	public AContainer(Category category, ItemStack item, String id, RecipeType recipeType, ItemStack[] recipe) {
		super(category, item, id, recipeType, recipe);

		createPreset(id, getInventoryTitle(), this::constructMenu);

		registerBlockHandler(id, (p, b, tool, reason) -> {
			BlockMenu inv = BlockStorage.getInventory(b);
			if (inv != null) {
				for (int slot : getInputSlots()) {
					if (inv.getItemInSlot(slot) != null) {
						b.getWorld().dropItemNaturally(b.getLocation(), inv.getItemInSlot(slot));
						inv.replaceExistingItem(slot, null);
					}
				}

				for (int slot : getOutputSlots()) {
					if (inv.getItemInSlot(slot) != null) {
						b.getWorld().dropItemNaturally(b.getLocation(), inv.getItemInSlot(slot));
						inv.replaceExistingItem(slot, null);
					}
				}
			}

			progress.remove(b);
			processing.remove(b);
			return true;
		});

		this.registerDefaultRecipes();
	}

	public AContainer(Category category, ItemStack item, String id, RecipeType recipeType, ItemStack[] recipe) {
		super(category, item, id, recipeType, recipe);

		createPreset(id, getInventoryTitle(), this::constructMenu);

		registerBlockHandler(id, new SlimefunBlockHandler() {

			@Override
			public boolean onBreak(Player p, Block b, SlimefunItem item, UnregisterReason reason) {
				BlockMenu inv = BlockStorage.getInventory(b);
				if (inv != null) {
					for (int slot : getInputSlots()) {
						if (inv.getItemInSlot(slot) != null) {
							b.getWorld().dropItemNaturally(b.getLocation(), inv.getItemInSlot(slot));
							inv.replaceExistingItem(slot, null);
						}
					}

					for (int slot : getOutputSlots()) {
						if (inv.getItemInSlot(slot) != null) {
							b.getWorld().dropItemNaturally(b.getLocation(), inv.getItemInSlot(slot));
							inv.replaceExistingItem(slot, null);
						}
					}
				}

				progress.remove(b);
				processing.remove(b);
				return true;
			}
		});

		this.registerDefaultRecipes();
	}

Replace Anonymous With Lambda me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AContainer.AContainer.registerBlockHandler.new SlimefunBlockHandler with (p, b, tool, reason) -> {BlockMenu inv=BlockStorage.getInventory(b); in method public AContainer(category Category, item ItemStack, id String, recipeType RecipeType, recipe ItemStack[]) from class me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AContainer


	public AFarm(Category category, ItemStack item, String id, RecipeType recipeType, ItemStack[] recipe) {
		super(category, item, id, recipeType, recipe);

		new BlockMenuPreset(id, getInventoryTitle()) {

			@Override
			public void init() {
				constructMenu(this);
			}

			@Override
			public boolean canOpen(Block b, Player p) {
				return p.hasPermission("slimefun.inventory.bypass") || CSCoreLib.getLib().getProtectionManager().canAccessChest(p.getUniqueId(), b, true);
			}

			@Override
			public int[] getSlotsAccessedByItemTransport(ItemTransportFlow flow) {
				if (flow == ItemTransportFlow.WITHDRAW) return getOutputSlots();
				return new int[0];
			}
		};

		registerBlockHandler(id, (p, b, tool, reason) -> {
			BlockMenu inv = BlockStorage.getInventory(b);
			if (inv != null) {
				for (int slot : getOutputSlots()) {
					if (inv.getItemInSlot(slot) != null) {
						b.getWorld().dropItemNaturally(b.getLocation(), inv.getItemInSlot(slot));
						inv.replaceExistingItem(slot, null);
					}
				}
			}
			return true;
		});
	}

	public AFarm(Category category, ItemStack item, String id, RecipeType recipeType, ItemStack[] recipe) {
		super(category, item, id, recipeType, recipe);

		new BlockMenuPreset(id, getInventoryTitle()) {

			@Override
			public void init() {
				constructMenu(this);
			}

			@Override
			public boolean canOpen(Block b, Player p) {
				return p.hasPermission("slimefun.inventory.bypass") || CSCoreLib.getLib().getProtectionManager().canAccessChest(p.getUniqueId(), b, true);
			}

			@Override
			public int[] getSlotsAccessedByItemTransport(ItemTransportFlow flow) {
				if (flow == ItemTransportFlow.WITHDRAW) return getOutputSlots();
				return new int[0];
			}
		};

		registerBlockHandler(id, new SlimefunBlockHandler() {

			@Override
			public boolean onBreak(Player p, Block b, SlimefunItem item, UnregisterReason reason) {
				BlockMenu inv = BlockStorage.getInventory(b);
				if (inv != null) {
					for (int slot : getOutputSlots()) {
						if (inv.getItemInSlot(slot) != null) {
							b.getWorld().dropItemNaturally(b.getLocation(), inv.getItemInSlot(slot));
							inv.replaceExistingItem(slot, null);
						}
					}
				}
				return true;
			}
		});
	}

Replace Anonymous With Lambda me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AFarm.AFarm.registerBlockHandler.new SlimefunBlockHandler with (p, b, tool, reason) -> {BlockMenu inv=BlockStorage.getInventory(b); in method public AFarm(category Category, item ItemStack, id String, recipeType RecipeType, recipe ItemStack[]) from class me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AFarm


	public AGenerator(Category category, ItemStack item, String id, RecipeType recipeType, ItemStack[] recipe) {
		super(category, item, id, recipeType, recipe);

		new BlockMenuPreset(id, getInventoryTitle()) {

			@Override
			public void init() {
				constructMenu(this);
			}

			@Override
			public boolean canOpen(Block b, Player p) {
				return p.hasPermission("slimefun.inventory.bypass") || CSCoreLib.getLib().getProtectionManager().canAccessChest(p.getUniqueId(), b, true);
			}

			@Override
			public int[] getSlotsAccessedByItemTransport(ItemTransportFlow flow) {
				if (flow == ItemTransportFlow.INSERT) return getInputSlots();
				else return getOutputSlots();
			}
		};

		registerBlockHandler(id, (p, b, tool, reason) -> {
			BlockMenu inv = BlockStorage.getInventory(b);
			if (inv != null) {
				for (int slot : getInputSlots()) {
					if (inv.getItemInSlot(slot) != null) {
						b.getWorld().dropItemNaturally(b.getLocation(), inv.getItemInSlot(slot));
						inv.replaceExistingItem(slot, null);
					}
				}
				for (int slot : getOutputSlots()) {
					if (inv.getItemInSlot(slot) != null) {
						b.getWorld().dropItemNaturally(b.getLocation(), inv.getItemInSlot(slot));
						inv.replaceExistingItem(slot, null);
					}
				}
			}
			progress.remove(b.getLocation());
			processing.remove(b.getLocation());
			return true;
		});

		this.registerDefaultRecipes();
	}

	public AGenerator(Category category, ItemStack item, String id, RecipeType recipeType, ItemStack[] recipe) {
		super(category, item, id, recipeType, recipe);

		new BlockMenuPreset(id, getInventoryTitle()) {

			@Override
			public void init() {
				constructMenu(this);
			}

			@Override
			public boolean canOpen(Block b, Player p) {
				return p.hasPermission("slimefun.inventory.bypass") || CSCoreLib.getLib().getProtectionManager().canAccessChest(p.getUniqueId(), b, true);
			}

			@Override
			public int[] getSlotsAccessedByItemTransport(ItemTransportFlow flow) {
				if (flow == ItemTransportFlow.INSERT) return getInputSlots();
				else return getOutputSlots();
			}
		};

		registerBlockHandler(id, new SlimefunBlockHandler() {

			@Override
			public boolean onBreak(Player p, Block b, SlimefunItem item, UnregisterReason reason) {
				BlockMenu inv = BlockStorage.getInventory(b);
				if (inv != null) {
					for (int slot : getInputSlots()) {
						if (inv.getItemInSlot(slot) != null) {
							b.getWorld().dropItemNaturally(b.getLocation(), inv.getItemInSlot(slot));
							inv.replaceExistingItem(slot, null);
						}
					}
					for (int slot : getOutputSlots()) {
						if (inv.getItemInSlot(slot) != null) {
							b.getWorld().dropItemNaturally(b.getLocation(), inv.getItemInSlot(slot));
							inv.replaceExistingItem(slot, null);
						}
					}
				}
				progress.remove(b.getLocation());
				processing.remove(b.getLocation());
				return true;
			}
		});

		this.registerDefaultRecipes();
	}

Replace Anonymous With Lambda me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AGenerator.AGenerator.registerBlockHandler.new SlimefunBlockHandler with (p, b, tool, reason) -> {BlockMenu inv=BlockStorage.getInventory(b); in method public AGenerator(category Category, item ItemStack, id String, recipeType RecipeType, recipe ItemStack[]) from class me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AGenerator


	public AReactor(Category category, ItemStack item, String id, RecipeType recipeType, ItemStack[] recipe) {
		super(category, item, id, recipeType, recipe);

		new BlockMenuPreset(id, getInventoryTitle()) {

			@Override
			public void init() {
				constructMenu(this);
			}

			@Override
			public void newInstance(final BlockMenu menu, final Block b) {
				try {
					if (BlockStorage.getLocationInfo(b.getLocation(), "reactor-mode") == null){
						BlockStorage.addBlockInfo(b, "reactor-mode", "generator");
					}

					if (!BlockStorage.hasBlockInfo(b) || BlockStorage.getLocationInfo(b.getLocation(), "reactor-mode").equals("generator")) {
						menu.replaceExistingItem(4, new CustomItem(CustomSkull.getItem("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOTM0M2NlNThkYTU0Yzc5OTI0YTJjOTMzMWNmYzQxN2ZlOGNjYmJlYTliZTQ1YTdhYzg1ODYwYTZjNzMwIn19fQ=="), "&7Focus: &eElectricity", "", "&6Your Reactor will focus on Power Generation", "&6If your Energy Network doesn't need Power", "&6it will not produce any either", "", "&7> Click to change the Focus to &eProduction"));
						menu.addMenuClickHandler(4, (p, slot, item, action) -> {
							BlockStorage.addBlockInfo(b, "reactor-mode", "production");
							newInstance(menu, b);
							return false;
						});
					}
					else {
						menu.replaceExistingItem(4, new CustomItem(SlimefunItems.PLUTONIUM, "&7Focus: &eProduction", "", "&6Your Reactor will focus on producing goods", "&6If your Energy Network doesn't need Power", "&6it will continue to run and simply will", "&6not generate any Power in the mean time", "", "&7> Click to change the Focus to &ePower Generation"));
						menu.addMenuClickHandler(4, (p, slot, item, action) -> {
							BlockStorage.addBlockInfo(b, "reactor-mode", "generator");
							newInstance(menu, b);
							return false;
						});
					}

					BlockMenu port = getAccessPort(b.getLocation());
					if (port != null) {
						menu.replaceExistingItem(infoSlot, new CustomItem(new ItemStack(Material.GREEN_WOOL), "&7Access Port", "", "&6Detected", "", "&7> Click to view Access Port"));
						menu.addMenuClickHandler(infoSlot, (p, slot, item, action) -> {
							port.open(p);
							newInstance(menu, b);

							return false;
						});
					}
					else {
						menu.replaceExistingItem(infoSlot, new CustomItem(new ItemStack(Material.RED_WOOL), "&7Access Port", "", "&cNot detected", "", "&7Access Port must be", "&7placed 3 blocks above", "&7a reactor!"));
						menu.addMenuClickHandler(infoSlot, (p, slot, item, action) -> {
							newInstance(menu, b);
							menu.open(p);
							return false;
						});
					}

				} catch(Exception x) {
					Slimefun.getLogger().log(Level.SEVERE, "An Error occured when creating a Reactor Menu for Slimefun " + Slimefun.getVersion(), x);
				}
			}

			@Override
			public boolean canOpen(Block b, Player p) {
				return p.hasPermission("slimefun.inventory.bypass") || CSCoreLib.getLib().getProtectionManager().canAccessChest(p.getUniqueId(), b, true);
			}

			@Override
			public int[] getSlotsAccessedByItemTransport(ItemTransportFlow flow) {
				return new int[0];
			}
		};

		registerBlockHandler(id, (p, b, tool, reason) -> {
			BlockMenu inv = BlockStorage.getInventory(b);
			if (inv != null) {
				for (int slot : getFuelSlots()) {
					if (inv.getItemInSlot(slot) != null) {
						b.getWorld().dropItemNaturally(b.getLocation(), inv.getItemInSlot(slot));
						inv.replaceExistingItem(slot, null);
					}
				}

				for (int slot : getCoolantSlots()) {
					if (inv.getItemInSlot(slot) != null) {
						b.getWorld().dropItemNaturally(b.getLocation(), inv.getItemInSlot(slot));
						inv.replaceExistingItem(slot, null);
					}
				}

				for (int slot : getOutputSlots()) {
					if (inv.getItemInSlot(slot) != null) {
						b.getWorld().dropItemNaturally(b.getLocation(), inv.getItemInSlot(slot));
						inv.replaceExistingItem(slot, null);
					}
				}
			}

			progress.remove(b.getLocation());
			processing.remove(b.getLocation());
			ReactorHologram.remove(b.getLocation());
			return true;
		});

		this.registerDefaultRecipes();
	}

	public AReactor(Category category, ItemStack item, String id, RecipeType recipeType, ItemStack[] recipe) {
		super(category, item, id, recipeType, recipe);

		new BlockMenuPreset(id, getInventoryTitle()) {

			@Override
			public void init() {
				constructMenu(this);
			}

			@Override
			public void newInstance(final BlockMenu menu, final Block b) {
				try {
					if (BlockStorage.getLocationInfo(b.getLocation(), "reactor-mode") == null){
						BlockStorage.addBlockInfo(b, "reactor-mode", "generator");
					}

					if (!BlockStorage.hasBlockInfo(b) || BlockStorage.getLocationInfo(b.getLocation(), "reactor-mode").equals("generator")) {
						menu.replaceExistingItem(4, new CustomItem(CustomSkull.getItem("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOTM0M2NlNThkYTU0Yzc5OTI0YTJjOTMzMWNmYzQxN2ZlOGNjYmJlYTliZTQ1YTdhYzg1ODYwYTZjNzMwIn19fQ=="), "&7Focus: &eElectricity", "", "&6Your Reactor will focus on Power Generation", "&6If your Energy Network doesn't need Power", "&6it will not produce any either", "", "&7> Click to change the Focus to &eProduction"));
						menu.addMenuClickHandler(4, (p, slot, item, action) -> {
							BlockStorage.addBlockInfo(b, "reactor-mode", "production");
							newInstance(menu, b);
							return false;
						});
					}
					else {
						menu.replaceExistingItem(4, new CustomItem(SlimefunItems.PLUTONIUM, "&7Focus: &eProduction", "", "&6Your Reactor will focus on producing goods", "&6If your Energy Network doesn't need Power", "&6it will continue to run and simply will", "&6not generate any Power in the mean time", "", "&7> Click to change the Focus to &ePower Generation"));
						menu.addMenuClickHandler(4, (p, slot, item, action) -> {
							BlockStorage.addBlockInfo(b, "reactor-mode", "generator");
							newInstance(menu, b);
							return false;
						});
					}

					BlockMenu port = getAccessPort(b.getLocation());
					if (port != null) {
						menu.replaceExistingItem(infoSlot, new CustomItem(new ItemStack(Material.GREEN_WOOL), "&7Access Port", "", "&6Detected", "", "&7> Click to view Access Port"));
						menu.addMenuClickHandler(infoSlot, (p, slot, item, action) -> {
							port.open(p);
							newInstance(menu, b);

							return false;
						});
					}
					else {
						menu.replaceExistingItem(infoSlot, new CustomItem(new ItemStack(Material.RED_WOOL), "&7Access Port", "", "&cNot detected", "", "&7Access Port must be", "&7placed 3 blocks above", "&7a reactor!"));
						menu.addMenuClickHandler(infoSlot, (p, slot, item, action) -> {
							newInstance(menu, b);
							menu.open(p);
							return false;
						});
					}

				} catch(Exception x) {
					Slimefun.getLogger().log(Level.SEVERE, "An Error occured when creating a Reactor Menu for Slimefun " + Slimefun.getVersion(), x);
				}
			}

			@Override
			public boolean canOpen(Block b, Player p) {
				return p.hasPermission("slimefun.inventory.bypass") || CSCoreLib.getLib().getProtectionManager().canAccessChest(p.getUniqueId(), b, true);
			}

			@Override
			public int[] getSlotsAccessedByItemTransport(ItemTransportFlow flow) {
				return new int[0];
			}
		};

		registerBlockHandler(id, new SlimefunBlockHandler() {

			@Override
			public boolean onBreak(Player p, Block b, SlimefunItem item, UnregisterReason reason) {
				BlockMenu inv = BlockStorage.getInventory(b);
				if (inv != null) {
					for (int slot : getFuelSlots()) {
						if (inv.getItemInSlot(slot) != null) {
							b.getWorld().dropItemNaturally(b.getLocation(), inv.getItemInSlot(slot));
							inv.replaceExistingItem(slot, null);
						}
					}

					for (int slot : getCoolantSlots()) {
						if (inv.getItemInSlot(slot) != null) {
							b.getWorld().dropItemNaturally(b.getLocation(), inv.getItemInSlot(slot));
							inv.replaceExistingItem(slot, null);
						}
					}

					for (int slot : getOutputSlots()) {
						if (inv.getItemInSlot(slot) != null) {
							b.getWorld().dropItemNaturally(b.getLocation(), inv.getItemInSlot(slot));
							inv.replaceExistingItem(slot, null);
						}
					}
				}

				progress.remove(b.getLocation());
				processing.remove(b.getLocation());
				ReactorHologram.remove(b.getLocation());
				return true;
			}
		});

		this.registerDefaultRecipes();
	}

Replace Anonymous With Lambda me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AReactor.AReactor.registerBlockHandler.new SlimefunBlockHandler with (p, b, tool, reason) -> {BlockMenu inv=BlockStorage.getInventory(b); in method public AReactor(category Category, item ItemStack, id String, recipeType RecipeType, recipe ItemStack[]) from class me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AReactor


	public ReactorAccessPort(Category category, ItemStack item, String name, RecipeType recipeType, ItemStack[] recipe) {
		super(category, item, name, recipeType, recipe);

		new BlockMenuPreset(name, getInventoryTitle()) {

			@Override
			public void init() {
				constructMenu(this);
			}

			@Override
			public boolean canOpen(Block b, Player p) {
				if(p.hasPermission("slimefun.inventory.bypass") || SlimefunPlugin.getProtectionManager().hasPermission(p, b.getLocation(), Action.ACCESS_INVENTORIES)) {
					AReactor reactor = getReactor(b.getLocation());
					if (reactor != null) {
						boolean empty = true;
						BlockMenu bm = getReactorMenu(b.getLocation());

						if (bm != null) {
							for (int slot: reactor.getCoolantSlots()) {
								if (bm.getItemInSlot(slot) != null) {
									empty = false;
								}
							}

							for (int slot: reactor.getFuelSlots()) {
								if (bm.getItemInSlot(slot) != null) {
									empty = false;
								}
							}

							if(!empty || !p.isSneaking()) {
								//reactor is not empty, lets view it's inventory instead.
								bm.open(p);
								return false;
							}

						}

						return true;

					}
				}

				return false;
			}

			@Override
			public int[] getSlotsAccessedByItemTransport(ItemTransportFlow flow) {
				if (flow == ItemTransportFlow.INSERT) return getInputSlots();
				else return getOutputSlots();
			}

			@Override
			public int[] getSlotsAccessedByItemTransport(BlockMenu menu, ItemTransportFlow flow, ItemStack item) {
				if (flow == ItemTransportFlow.INSERT) {
					if (SlimefunManager.isItemSimiliar(item, SlimefunItems.REACTOR_COOLANT_CELL, true)) return getCoolantSlots();
					else if (SlimefunManager.isItemSimiliar(item, SlimefunItems.NETHER_ICE_COOLANT_CELL, true)) return getCoolantSlots();
					else return getFuelSlots();
				}
				else return getOutputSlots();
			}
		};

		registerBlockHandler(name, (p, b, tool, reason) -> {
			BlockMenu inv = BlockStorage.getInventory(b);

			if (inv != null) {
				for (int slot : getFuelSlots()) {
					if (inv.getItemInSlot(slot) != null) {
						b.getWorld().dropItemNaturally(b.getLocation(), inv.getItemInSlot(slot));
						inv.replaceExistingItem(slot, null);
					}
				}

				for (int slot : getCoolantSlots()) {
					if (inv.getItemInSlot(slot) != null) {
						b.getWorld().dropItemNaturally(b.getLocation(), inv.getItemInSlot(slot));
						inv.replaceExistingItem(slot, null);
					}
				}

				for (int slot : getOutputSlots()) {
					if (inv.getItemInSlot(slot) != null) {
						b.getWorld().dropItemNaturally(b.getLocation(), inv.getItemInSlot(slot));
						inv.replaceExistingItem(slot, null);
					}
				}
			}
			return true;
		});
	}

	public ReactorAccessPort(Category category, ItemStack item, String name, RecipeType recipeType, ItemStack[] recipe) {
		super(category, item, name, recipeType, recipe);

		new BlockMenuPreset(name, getInventoryTitle()) {

			@Override
			public void init() {
				constructMenu(this);
			}

			@Override
			public boolean canOpen(Block b, Player p) {
				if(p.hasPermission("slimefun.inventory.bypass") || SlimefunPlugin.getProtectionManager().hasPermission(p, b.getLocation(), Action.ACCESS_INVENTORIES)) {
					AReactor reactor = getReactor(b.getLocation());
					if (reactor != null) {
						boolean empty = true;
						BlockMenu bm = getReactorMenu(b.getLocation());

						if (bm != null) {
							for (int slot: reactor.getCoolantSlots()) {
								if (bm.getItemInSlot(slot) != null) {
									empty = false;
								}
							}

							for (int slot: reactor.getFuelSlots()) {
								if (bm.getItemInSlot(slot) != null) {
									empty = false;
								}
							}

							if(!empty || !p.isSneaking()) {
								//reactor is not empty, lets view it's inventory instead.
								bm.open(p);
								return false;
							}

						}

						return true;

					}
				}

				return false;
			}

			@Override
			public int[] getSlotsAccessedByItemTransport(ItemTransportFlow flow) {
				if (flow == ItemTransportFlow.INSERT) return getInputSlots();
				else return getOutputSlots();
			}

			@Override
			public int[] getSlotsAccessedByItemTransport(BlockMenu menu, ItemTransportFlow flow, ItemStack item) {
				if (flow == ItemTransportFlow.INSERT) {
					if (SlimefunManager.isItemSimiliar(item, SlimefunItems.REACTOR_COOLANT_CELL, true)) return getCoolantSlots();
					else if (SlimefunManager.isItemSimiliar(item, SlimefunItems.NETHER_ICE_COOLANT_CELL, true)) return getCoolantSlots();
					else return getFuelSlots();
				}
				else return getOutputSlots();
			}
		};

		registerBlockHandler(name, new SlimefunBlockHandler() {

			@Override
			public boolean onBreak(Player p, Block b, SlimefunItem item, UnregisterReason reason) {
				BlockMenu inv = BlockStorage.getInventory(b);

				if (inv != null) {
					for (int slot : getFuelSlots()) {
						if (inv.getItemInSlot(slot) != null) {
							b.getWorld().dropItemNaturally(b.getLocation(), inv.getItemInSlot(slot));
							inv.replaceExistingItem(slot, null);
						}
					}

					for (int slot : getCoolantSlots()) {
						if (inv.getItemInSlot(slot) != null) {
							b.getWorld().dropItemNaturally(b.getLocation(), inv.getItemInSlot(slot));
							inv.replaceExistingItem(slot, null);
						}
					}

					for (int slot : getOutputSlots()) {
						if (inv.getItemInSlot(slot) != null) {
							b.getWorld().dropItemNaturally(b.getLocation(), inv.getItemInSlot(slot));
							inv.replaceExistingItem(slot, null);
						}
					}
				}
				return true;
			}
		});
	}

Replace Anonymous With Lambda me.mrCookieSlime.Slimefun.Objects.SlimefunItem.machines.ReactorAccessPort.ReactorAccessPort.registerBlockHandler.new SlimefunBlockHandler with (p, b, tool, reason) -> {BlockMenu inv=BlockStorage.getInventory(b); in method public ReactorAccessPort(category Category, item ItemStack, name String, recipeType RecipeType, recipe ItemStack[]) from class me.mrCookieSlime.Slimefun.Objects.SlimefunItem.machines.ReactorAccessPort


	public AnimalGrowthAccelerator(Category category, ItemStack item, String name, RecipeType recipeType, ItemStack[] recipe) {
		super(category, item, name, recipeType, recipe);
		createPreset(getID(), "&bGrowth Accelerator", this::constructMenu);

		registerBlockHandler(name, (p, b, tool, reason) -> {
			AnimalGrowthAcceleratorHologram.remove(b);
			BlockMenu inv = BlockStorage.getInventory(b);
			if (inv != null) {
				for (int slot : getInputSlots()) {
					if (inv.getItemInSlot(slot) != null) {
						b.getWorld().dropItemNaturally(b.getLocation(), inv.getItemInSlot(slot));
						inv.replaceExistingItem(slot, null);
					}
				}
			}
			return true;
		});
	}

	public AnimalGrowthAccelerator(Category category, ItemStack item, String name, RecipeType recipeType, ItemStack[] recipe) {
		super(category, item, name, recipeType, recipe);
		createPreset(getID(), "&bGrowth Accelerator", this::constructMenu);

		registerBlockHandler(name, new SlimefunBlockHandler() {

			@Override
			public boolean onBreak(Player p, Block b, SlimefunItem item, UnregisterReason reason) {
				AnimalGrowthAcceleratorHologram.remove(b);
				BlockMenu inv = BlockStorage.getInventory(b);
				if (inv != null) {
					for (int slot : getInputSlots()) {
						if (inv.getItemInSlot(slot) != null) {
							b.getWorld().dropItemNaturally(b.getLocation(), inv.getItemInSlot(slot));
							inv.replaceExistingItem(slot, null);
						}
					}
				}
				return true;
			}
		});
	}

Replace Anonymous With Lambda me.mrCookieSlime.Slimefun.Objects.SlimefunItem.machines.electric.AnimalGrowthAccelerator.AnimalGrowthAccelerator.registerBlockHandler.new SlimefunBlockHandler with (p, b, tool, reason) -> {AnimalGrowthAcceleratorHologram.remove(b); in method public AnimalGrowthAccelerator(category Category, item ItemStack, name String, recipeType RecipeType, recipe ItemStack[]) from class me.mrCookieSlime.Slimefun.Objects.SlimefunItem.machines.electric.AnimalGrowthAccelerator


	public AutoBreeder(Category category, ItemStack item, String name, RecipeType recipeType, ItemStack[] recipe) {
		super(category, item, name, recipeType, recipe);

		new BlockMenuPreset(name, "&6Auto Breeder") {

			@Override
			public void init() {
				constructMenu(this);
			}

			@Override
			public boolean canOpen(Block b, Player p) {
				return p.hasPermission("slimefun.inventory.bypass") || CSCoreLib.getLib().getProtectionManager().canAccessChest(p.getUniqueId(), b, true);
			}

			@Override
			public int[] getSlotsAccessedByItemTransport(ItemTransportFlow flow) {
				if (flow == ItemTransportFlow.INSERT) return getInputSlots();
				return new int[0];
			}
		};

		registerBlockHandler(name, (p, b, tool, reason) -> {
			AutoBreederHologram.remove(b);
			BlockMenu inv = BlockStorage.getInventory(b);
			if (inv != null) {
				for (int slot : getInputSlots()) {
					if (inv.getItemInSlot(slot) != null) {
						b.getWorld().dropItemNaturally(b.getLocation(), inv.getItemInSlot(slot));
						inv.replaceExistingItem(slot, null);
					}
				}
			}
			return true;
		});
	}

	public AutoBreeder(Category category, ItemStack item, String name, RecipeType recipeType, ItemStack[] recipe) {
		super(category, item, name, recipeType, recipe);

		new BlockMenuPreset(name, "&6Auto Breeder") {

			@Override
			public void init() {
				constructMenu(this);
			}

			@Override
			public boolean canOpen(Block b, Player p) {
				return p.hasPermission("slimefun.inventory.bypass") || CSCoreLib.getLib().getProtectionManager().canAccessChest(p.getUniqueId(), b, true);
			}

			@Override
			public int[] getSlotsAccessedByItemTransport(ItemTransportFlow flow) {
				if (flow == ItemTransportFlow.INSERT) return getInputSlots();
				return new int[0];
			}
		};

		registerBlockHandler(name, new SlimefunBlockHandler() {

			@Override
			public boolean onBreak(Player p, Block b, SlimefunItem item, UnregisterReason reason) {
				AutoBreederHologram.remove(b);
				BlockMenu inv = BlockStorage.getInventory(b);
				if (inv != null) {
					for (int slot : getInputSlots()) {
						if (inv.getItemInSlot(slot) != null) {
							b.getWorld().dropItemNaturally(b.getLocation(), inv.getItemInSlot(slot));
							inv.replaceExistingItem(slot, null);
						}
					}
				}
				return true;
			}
		});
	}

Replace Anonymous With Lambda me.mrCookieSlime.Slimefun.Objects.SlimefunItem.machines.electric.AutoBreeder.AutoBreeder.registerBlockHandler.new SlimefunBlockHandler with (p, b, tool, reason) -> {AutoBreederHologram.remove(b); in method public AutoBreeder(category Category, item ItemStack, name String, recipeType RecipeType, recipe ItemStack[]) from class me.mrCookieSlime.Slimefun.Objects.SlimefunItem.machines.electric.AutoBreeder


	public CropGrowthAccelerator(Category category, ItemStack item, String name, RecipeType recipeType, ItemStack[] recipe) {
		super(category, item, name, recipeType, recipe);
		createPreset(getID(), "&bGrowth Accelerator", this::constructMenu);

		registerBlockHandler(name, (p, b, tool, reason) -> {
			BlockMenu inv = BlockStorage.getInventory(b);
			if (inv != null) {
				for (int slot: getInputSlots()) {
					if (inv.getItemInSlot(slot) != null) {
						b.getWorld().dropItemNaturally(b.getLocation(), inv.getItemInSlot(slot));
						inv.replaceExistingItem(slot, null);
					}
				}
			}
			return true;
		});
	}

	public CropGrowthAccelerator(Category category, ItemStack item, String name, RecipeType recipeType, ItemStack[] recipe) {
		super(category, item, name, recipeType, recipe);
		createPreset(getID(), "&bGrowth Accelerator", this::constructMenu);

		registerBlockHandler(name, new SlimefunBlockHandler() {

			@Override
			public boolean onBreak(Player p, Block b, SlimefunItem item, UnregisterReason reason) {
				BlockMenu inv = BlockStorage.getInventory(b);
				if (inv != null) {
					for (int slot: getInputSlots()) {
						if (inv.getItemInSlot(slot) != null) {
							b.getWorld().dropItemNaturally(b.getLocation(), inv.getItemInSlot(slot));
							inv.replaceExistingItem(slot, null);
						}
					}
				}
				return true;
			}
		});
	}

Replace Anonymous With Lambda me.mrCookieSlime.Slimefun.Objects.SlimefunItem.machines.electric.CropGrowthAccelerator.CropGrowthAccelerator.registerBlockHandler.new SlimefunBlockHandler with (p, b, tool, reason) -> {BlockMenu inv=BlockStorage.getInventory(b); in method public CropGrowthAccelerator(category Category, item ItemStack, name String, recipeType RecipeType, recipe ItemStack[]) from class me.mrCookieSlime.Slimefun.Objects.SlimefunItem.machines.electric.CropGrowthAccelerator


	public ElectricSmeltery(Category category, ItemStack item, String name, RecipeType recipeType, ItemStack[] recipe) {
		super(category, item, name, recipeType, recipe);

		new BlockMenuPreset(name, getInventoryTitle()) {

			@Override
			public void init() {
				constructMenu(this);
			}

			@Override
			public boolean canOpen(Block b, Player p) {
				return p.hasPermission("slimefun.inventory.bypass") || CSCoreLib.getLib().getProtectionManager().canAccessChest(p.getUniqueId(), b, true);
			}

			@Override
			public int[] getSlotsAccessedByItemTransport(ItemTransportFlow flow) {
				return new int[0];
			}

			@Override
			public int[] getSlotsAccessedByItemTransport(BlockMenu menu, ItemTransportFlow flow, ItemStack item) {
				if (flow == ItemTransportFlow.WITHDRAW) return getOutputSlots();

				List<Integer> slots = new ArrayList<>();

				for (int slot : getInputSlots()) {
					if (SlimefunManager.isItemSimiliar(menu.getItemInSlot(slot), item, true)) {
						slots.add(slot);
					}
				}

				if (slots.isEmpty()) {
					return getInputSlots();
				}
				else {
					Collections.sort(slots, new RecipeSorter(menu));

					int[] array = new int[slots.size()];

					for (int i = 0; i < slots.size(); i++) {
						array[i] = slots.get(i);
					}

					return array;
				}
			}
		};

		registerBlockHandler(name, (p, b, tool, reason) -> {
			BlockMenu inv = BlockStorage.getInventory(b);
			if (inv != null) {
				for (int slot : getInputSlots()) {
					if (inv.getItemInSlot(slot) != null) {
						b.getWorld().dropItemNaturally(b.getLocation(), inv.getItemInSlot(slot));
						inv.replaceExistingItem(slot, null);
					}
				}
				for (int slot : getOutputSlots()) {
					if (inv.getItemInSlot(slot) != null) {
						b.getWorld().dropItemNaturally(b.getLocation(), inv.getItemInSlot(slot));
						inv.replaceExistingItem(slot, null);
					}
				}
			}
			progress.remove(b);
			processing.remove(b);
			return true;
		});

		this.registerDefaultRecipes();
	}

	public ElectricSmeltery(Category category, ItemStack item, String name, RecipeType recipeType, ItemStack[] recipe) {
		super(category, item, name, recipeType, recipe);

		new BlockMenuPreset(name, getInventoryTitle()) {

			@Override
			public void init() {
				constructMenu(this);
			}

			@Override
			public boolean canOpen(Block b, Player p) {
				return p.hasPermission("slimefun.inventory.bypass") || CSCoreLib.getLib().getProtectionManager().canAccessChest(p.getUniqueId(), b, true);
			}

			@Override
			public int[] getSlotsAccessedByItemTransport(ItemTransportFlow flow) {
				return new int[0];
			}

			@Override
			public int[] getSlotsAccessedByItemTransport(BlockMenu menu, ItemTransportFlow flow, ItemStack item) {
				if (flow == ItemTransportFlow.WITHDRAW) return getOutputSlots();

				List<Integer> slots = new ArrayList<>();

				for (int slot : getInputSlots()) {
					if (SlimefunManager.isItemSimiliar(menu.getItemInSlot(slot), item, true)) {
						slots.add(slot);
					}
				}

				if (slots.isEmpty()) {
					return getInputSlots();
				}
				else {
					Collections.sort(slots, new RecipeSorter(menu));

					int[] array = new int[slots.size()];

					for (int i = 0; i < slots.size(); i++) {
						array[i] = slots.get(i);
					}

					return array;
				}
			}
		};

		registerBlockHandler(name, new SlimefunBlockHandler() {

			@Override
			public boolean onBreak(Player p, Block b, SlimefunItem item, UnregisterReason reason) {
				BlockMenu inv = BlockStorage.getInventory(b);
				if (inv != null) {
					for (int slot : getInputSlots()) {
						if (inv.getItemInSlot(slot) != null) {
							b.getWorld().dropItemNaturally(b.getLocation(), inv.getItemInSlot(slot));
							inv.replaceExistingItem(slot, null);
						}
					}
					for (int slot : getOutputSlots()) {
						if (inv.getItemInSlot(slot) != null) {
							b.getWorld().dropItemNaturally(b.getLocation(), inv.getItemInSlot(slot));
							inv.replaceExistingItem(slot, null);
						}
					}
				}
				progress.remove(b);
				processing.remove(b);
				return true;
			}
		});

		this.registerDefaultRecipes();
	}

Replace Anonymous With Lambda me.mrCookieSlime.Slimefun.Objects.SlimefunItem.machines.electric.ElectricSmeltery.ElectricSmeltery.registerBlockHandler.new SlimefunBlockHandler with (p, b, tool, reason) -> {BlockMenu inv=BlockStorage.getInventory(b); in method public ElectricSmeltery(category Category, item ItemStack, name String, recipeType RecipeType, recipe ItemStack[]) from class me.mrCookieSlime.Slimefun.Objects.SlimefunItem.machines.electric.ElectricSmeltery


	@Override
	public BlockBreakHandler getItemHandler() {
		return (e, item, fortune, drops) -> {
			if (SlimefunManager.isItemSimiliar(item, SlimefunItems.EXPLOSIVE_PICKAXE, true)) {
				e.getBlock().getWorld().createExplosion(e.getBlock().getLocation(), 0.0F);
				e.getBlock().getWorld().playSound(e.getBlock().getLocation(), Sound.ENTITY_GENERIC_EXPLODE, 1F, 1F);
				for (int x = -1; x <= 1; x++) {
					for (int y = -1; y <= 1; y++) {
						for (int z = -1; z <= 1; z++) {
							Block b = e.getBlock().getRelative(x, y, z);

							if (b.getType() != Material.AIR && !b.isLiquid() && !StringUtils.equals(b.getType().toString(), blacklist) && SlimefunPlugin.getProtectionManager().hasPermission(e.getPlayer(), b.getLocation(), Action.BREAK_BLOCK)) {
								if (SlimefunPlugin.getHooks().isCoreProtectInstalled()) {
									SlimefunPlugin.getHooks().getCoreProtectAPI().logRemoval(e.getPlayer().getName(), b.getLocation(), b.getType(), b.getBlockData());
								}

								b.getWorld().playEffect(b.getLocation(), Effect.STEP_SOUND, b.getType());
								SlimefunItem sfItem = BlockStorage.check(b);
								boolean allow = false;

								if (sfItem != null && !(sfItem instanceof HandledBlock)) {
									if (SlimefunPlugin.getUtilities().blockHandlers.containsKey(sfItem.getID())) {
										allow = SlimefunPlugin.getUtilities().blockHandlers.get(sfItem.getID()).onBreak(e.getPlayer(), e.getBlock(), sfItem, UnregisterReason.PLAYER_BREAK);
									}
									if (allow) {
										drops.add(BlockStorage.retrieve(e.getBlock()));
									}
								}
								else if (b.getType() == Material.PLAYER_HEAD) {
									b.breakNaturally();
								}
								else if (b.getType().name().endsWith("_SHULKER_BOX")) {
									b.breakNaturally();
								}
								else {
									for (ItemStack drop: b.getDrops()) {
										b.getWorld().dropItemNaturally(b.getLocation(), (b.getType().toString().endsWith("_ORE") && b.getType() != Material.IRON_ORE && b.getType() != Material.GOLD_ORE) ? new CustomItem(drop, fortune): drop);
									}
									b.setType(Material.AIR);
								}

								damageItem(e.getPlayer(), item);
							}
						}
					}
				}

				return true;
			}
			else return false;
		};
	}

	@Override
	public void register(boolean slimefun) {
		addItemHandler(new BlockBreakHandler() {

			@Override
			public boolean onBlockBreak(BlockBreakEvent e, ItemStack item, int fortune, List<ItemStack> drops) {
				if (SlimefunManager.isItemSimiliar(item, SlimefunItems.EXPLOSIVE_SHOVEL, true)) {
					e.getBlock().getWorld().createExplosion(e.getBlock().getLocation(), 0.0F);
					e.getBlock().getWorld().playSound(e.getBlock().getLocation(), Sound.ENTITY_GENERIC_EXPLODE, 1F, 1F);

					for (int x = -1; x <= 1; x++) {
						for (int y = -1; y <= 1; y++) {
							for (int z = -1; z <= 1; z++) {
								Block b = e.getBlock().getRelative(x, y, z);
								boolean correctType = false;

								for (Material mat : MaterialTools.getShovelItems()) {
									if (b.getType() == mat) {
										correctType = true;
										break;
									}
								}

								if (correctType && SlimefunPlugin.getProtectionManager().hasPermission(e.getPlayer(), b.getLocation(), Action.BREAK_BLOCK)) {
									if (SlimefunPlugin.getHooks().isCoreProtectInstalled()) {
										SlimefunPlugin.getHooks().getCoreProtectAPI().logRemoval(e.getPlayer().getName(), b.getLocation(), b.getType(), b.getBlockData());
									}

									b.getWorld().playEffect(b.getLocation(), Effect.STEP_SOUND, b.getType());
									for (ItemStack drop: b.getDrops()) {
										b.getWorld().dropItemNaturally(b.getLocation(), drop);
									}
									b.setType(Material.AIR);

									damageItem(e.getPlayer(), item);
								}
							}
						}
					}

					return true;
				}
				else return false;
			}
		});

		super.register(slimefun);
		damageOnUse = ((Boolean) Slimefun.getItemValue(getID(), "damage-on-use"));
	}

Replace Anonymous With Lambda me.mrCookieSlime.Slimefun.Objects.SlimefunItem.items.ExplosiveShovel.register.addItemHandler.new BlockBreakHandler with (e, item, fortune, drops) -> {if(SlimefunManager.isItemSimiliar(item,SlimefunItems.EXPLOSIVE_PICKAXE,true)){e.getBlock().getWorld().createExplosion(e.getBlock().getLocation(),0.0F); in method public getItemHandler() : BlockBreakHandler from class me.mrCookieSlime.Slimefun.Objects.SlimefunItem.items.ExplosivePickaxe


	public static void openCategory(final Player p, final Category category, final boolean survival, final int selected_page, final boolean book) {
		if (category == null) return;

		if (book && category.getItems().size() < 250) {
			List<TellRawMessage> pages = new ArrayList<>();
			List<String> texts = new ArrayList<>();
			List<String> tooltips = new ArrayList<>();
			List<PlayerRunnable> actions = new ArrayList<>();

			for (final SlimefunItem item: category.getItems()) {
				if (Slimefun.hasPermission(p, item, false)) {
					if (Slimefun.isEnabled(p, item, false)) {
						if (survival && !Slimefun.hasUnlocked(p, item, false) && item.getResearch() != null) {
						    final Research research = item.getResearch();

							texts.add(ChatColor.translateAlternateColorCodes('&', shorten("&7", StringUtils.formatItemName(item.getItem(), false))));
							tooltips.add(ChatColor.translateAlternateColorCodes('&', StringUtils.formatItemName(item.getItem(), false) + "\n&c&lLOCKED\n\n&7Cost: " + (p.getLevel() >= research.getCost() ? "&b": "&4") + research.getCost() + " Levels\n\n&a> Click to unlock"));
							actions.add(new PlayerRunnable(2) {

								@Override
								public void run(final Player p) {
									if (!Research.isResearching(p)) {
										if (research.canUnlock(p)) {
											PlayerProfile profile = PlayerProfile.fromUUID(p.getUniqueId());

											if (profile.hasUnlocked(research)) {
												openCategory(p, category, true, selected_page, book);
											}
											else {
												if (!(p.getGameMode() == GameMode.CREATIVE && SlimefunPlugin.getSettings().researchesFreeInCreative)) {
													p.setLevel(p.getLevel() - research.getCost());
												}

												if (p.getGameMode() == GameMode.CREATIVE) {
													research.unlock(p, true);

													Bukkit.getScheduler().scheduleSyncDelayedTask(SlimefunPlugin.instance, () -> openCategory(p, category, survival, selected_page, book), 1L);
												}
												else {
													research.unlock(p, false);

													Bukkit.getScheduler().scheduleSyncDelayedTask(SlimefunPlugin.instance, () -> openCategory(p, category, survival, selected_page, book), 103L);
												}
											}
										} else Messages.local.sendTranslation(p, "messages.not-enough-xp", true);
									}
								}
							});
						}
						else {
							texts.add(ChatColor.translateAlternateColorCodes('&', shorten("&a", StringUtils.formatItemName(item.getItem(), false))));

							StringBuilder tooltip = new StringBuilder();

							tooltip.append(StringUtils.formatItemName(item.getItem(), false));

							if (item.getItem().hasItemMeta() && item.getItem().getItemMeta().hasLore()) {
								for (String line : item.getItem().getItemMeta().getLore()) {
									tooltip.append("\n" + line);
								}
							}

							tooltip.append(ChatColor.translateAlternateColorCodes('&', "\n\n&e&oClick for more Info"));

							tooltips.add(tooltip.toString());
							actions.add(new PlayerRunnable(2) {

								@Override
								public void run(Player p) {
									displayItem(p, item.getItem(), true, book, 0);
								}
							});
						}
					}
				}
				else {
					texts.add(ChatColor.translateAlternateColorCodes('&', shorten("&4", StringUtils.formatItemName(item.getItem(), false))));
					tooltips.add(ChatColor.translateAlternateColorCodes('&', "&cNo Permission!"));
					actions.add(null);
				}
			}

			for (int i = 0; i < texts.size(); i = i + 10) {
				TellRawMessage page = new TellRawMessage();
				page.addText(ChatColor.translateAlternateColorCodes('&', "&b&l- Slimefun Guide -\n\n"));
				for (int j = i; j < texts.size() && j < i + 10; j++) {
					page.addText(texts.get(j) + "\n");
					if (tooltips.get(j) != null) page.addHoverEvent(HoverAction.SHOW_TEXT, tooltips.get(j));
					if (actions.get(j) != null) page.addClickEvent(actions.get(j));
				}
				page.addText("\n");
				page.addText(ChatColor.translateAlternateColorCodes('&', "&6\u21E6 &lBack"));
				page.addHoverEvent(HoverAction.SHOW_TEXT, ChatColor.translateAlternateColorCodes('&', "&eClick to go back to the Category Overview"));
				page.addClickEvent(new PlayerRunnable(2) {
					@Override
					public void run(final Player p) {
						Bukkit.getScheduler().scheduleSyncDelayedTask(SlimefunPlugin.instance, () -> openMainMenu(p, survival, true, 1), 1L);
					}
				});
				pages.add(page);
			}

			new CustomBookOverlay("Slimefun Guide", "mrCookieSlime", pages.toArray(new TellRawMessage[pages.size()])).open(p);
		}
		else {
			final ChestMenu menu = new ChestMenu("Slimefun Guide");

			menu.setEmptySlotsClickable(false);
			menu.addMenuOpeningHandler(pl -> pl.playSound(pl.getLocation(), Sound.ENTITY_BAT_TAKEOFF, 0.7F, 0.7F));

			int index = 9;
			final int pages = (category.getItems().size() - 1) / category_size + 1;
			for (int i = 0; i < 4; i++) {
				menu.addItem(i, new CustomItem(new ItemStack(Material.GRAY_STAINED_GLASS_PANE), " "));
				menu.addMenuClickHandler(i, (pl, slot, item, action) -> false);
			}

			menu.addItem(4, new CustomItem(new ItemStack(Material.ENCHANTED_BOOK), "&7\u21E6 Back"));
			menu.addMenuClickHandler(4, (pl, slot, item, action) -> {
				openMainMenu(pl, survival, book, 1);
				return false;
			});

			for (int i = 5; i < 9; i++) {
				menu.addItem(i, new CustomItem(new ItemStack(Material.GRAY_STAINED_GLASS_PANE), " "));
				menu.addMenuClickHandler(i, (pl, slot, item, action) -> false);
			}

			for (int i = 45; i < 54; i++) {
				menu.addItem(i, new CustomItem(new ItemStack(Material.GRAY_STAINED_GLASS_PANE), " "));
				menu.addMenuClickHandler(i, (pl, slot, item, action) -> false);
			}

			menu.addItem(46, new CustomItem(new ItemStack(Material.LIME_STAINED_GLASS_PANE), "&r\u21E6 Previous Page", "", "&7(" + selected_page + " / " + pages + ")"));
			menu.addMenuClickHandler(46, (pl, slot, item, action) -> {
				int next = selected_page - 1;
				if (next < 1) next = pages;
				if (next != selected_page) openCategory(pl, category, survival, next, book);
				return false;
			});

			menu.addItem(52, new CustomItem(new ItemStack(Material.LIME_STAINED_GLASS_PANE), "&rNext Page \u21E8", "", "&7(" + selected_page + " / " + pages + ")"));
			menu.addMenuClickHandler(52, (pl, slot, item, action) -> {
				int next = selected_page + 1;
				if (next > pages) next = 1;
				if (next != selected_page) openCategory(pl, category, survival, next, book);
				return false;
			});

			int categoryIndex = category_size * (selected_page - 1);
			for (int i = 0; i < category_size; i++) {
				int target = categoryIndex + i;
				if (target >= category.getItems().size()) break;
				final SlimefunItem sfitem = category.getItems().get(target);
				if (Slimefun.isEnabled(p, sfitem, false)) {
					if (survival && !Slimefun.hasUnlocked(p, sfitem.getItem(), false) && sfitem.getResearch() != null) {
						if (Slimefun.hasPermission(p, sfitem, false)) {
						    final Research research = sfitem.getResearch();
							menu.addItem(index, new CustomItem(Material.BARRIER, "&r" + StringUtils.formatItemName(sfitem.getItem(), false), "&4&lLOCKED", "", "&a> Click to unlock", "", "&7Cost: &b" + research.getCost() + " Level"));
							menu.addMenuClickHandler(index, (pl, slot, item, action) -> {
								if (!Research.isResearching(pl)) {
									if (research.canUnlock(pl)) {
										PlayerProfile profile = PlayerProfile.fromUUID(p.getUniqueId());

										if (profile.hasUnlocked(research)) {
											openCategory(p, category, true, selected_page, book);
										}
										else {
											if (!(pl.getGameMode() == GameMode.CREATIVE && SlimefunPlugin.getSettings().researchesFreeInCreative)) {
												pl.setLevel(pl.getLevel() - research.getCost());
											}

											if (pl.getGameMode() == GameMode.CREATIVE) {
												research.unlock(pl, SlimefunPlugin.getSettings().researchesFreeInCreative);
												openCategory(pl, category, survival, selected_page, book);
											}
											else {
												research.unlock(pl, false);
												Bukkit.getScheduler().scheduleSyncDelayedTask(SlimefunPlugin.instance, () -> openCategory(pl, category, survival, selected_page, book), 103L);
											}
										}
									}
									else Messages.local.sendTranslation(pl, "messages.not-enough-xp", true);
								}
								return false;
							});

							index++;
						}
						else {
							menu.addItem(index, new CustomItem(Material.BARRIER, StringUtils.formatItemName(sfitem.getItem(), false), new String[] {"", "&rYou do not have Permission", "&rto access this Item"}));
							menu.addMenuClickHandler(index, (pl, slot, item, action) -> false);
							index++;
						}
					}
					else {
						menu.addItem(index, sfitem.getItem());
						menu.addMenuClickHandler(index, (pl, slot, item, action) -> {
							if (survival) displayItem(pl, item, true, book, 0);
							else pl.getInventory().addItem(item);
							return false;
						});
						index++;
					}
				}
			}

			menu.open(p);
		}

		if (survival) {
			addToHistory(p, category);
		}
	}

	public static void openCategory(final Player p, final Category category, final boolean survival, final int selected_page, final boolean book) {
		if (category == null) return;

		if (book && category.getItems().size() < 250) {
			List<TellRawMessage> pages = new ArrayList<>();
			List<String> texts = new ArrayList<>();
			List<String> tooltips = new ArrayList<>();
			List<PlayerRunnable> actions = new ArrayList<>();

			for (final SlimefunItem item: category.getItems()) {
				if (Slimefun.hasPermission(p, item, false)) {
					if (Slimefun.isEnabled(p, item, false)) {
						if (survival && !Slimefun.hasUnlocked(p, item, false) && item.getResearch() != null) {
						    final Research research = item.getResearch();

							texts.add(ChatColor.translateAlternateColorCodes('&', shorten("&7", StringUtils.formatItemName(item.getItem(), false))));
							tooltips.add(ChatColor.translateAlternateColorCodes('&', StringUtils.formatItemName(item.getItem(), false) + "\n&c&lLOCKED\n\n&7Cost: " + (p.getLevel() >= research.getCost() ? "&b": "&4") + research.getCost() + " Levels\n\n&a> Click to unlock"));
							actions.add(new PlayerRunnable(2) {

								@Override
								public void run(final Player p) {
									if (!Research.isResearching(p)) {
										if (research.canUnlock(p)) {
											PlayerProfile profile = PlayerProfile.fromUUID(p.getUniqueId());

											if (profile.hasUnlocked(research)) {
												openCategory(p, category, true, selected_page, book);
											}
											else {
												if (!(p.getGameMode() == GameMode.CREATIVE && SlimefunStartup.instance.getSettings().researchesFreeInCreative)) {
													p.setLevel(p.getLevel() - research.getCost());
												}

												if (p.getGameMode() == GameMode.CREATIVE) {
													research.unlock(p, true);

													Bukkit.getScheduler().scheduleSyncDelayedTask(SlimefunStartup.instance, () -> openCategory(p, category, survival, selected_page, book), 1L);
												}
												else {
													research.unlock(p, false);

													Bukkit.getScheduler().scheduleSyncDelayedTask(SlimefunStartup.instance, () -> openCategory(p, category, survival, selected_page, book), 103L);
												}
											}
										} else Messages.local.sendTranslation(p, "messages.not-enough-xp", true);
									}
								}
							});
						}
						else {
							texts.add(ChatColor.translateAlternateColorCodes('&', shorten("&a", StringUtils.formatItemName(item.getItem(), false))));

							StringBuilder tooltip = new StringBuilder();

							tooltip.append(StringUtils.formatItemName(item.getItem(), false));

							if (item.getItem().hasItemMeta() && item.getItem().getItemMeta().hasLore()) {
								for (String line : item.getItem().getItemMeta().getLore()) {
									tooltip.append("\n" + line);
								}
							}

							tooltip.append(ChatColor.translateAlternateColorCodes('&', "\n\n&e&oClick for more Info"));

							tooltips.add(tooltip.toString());
							actions.add(new PlayerRunnable(2) {

								@Override
								public void run(Player p) {
									displayItem(p, item.getItem(), true, book, 0);
								}
							});
						}
					}
				}
				else {
					texts.add(ChatColor.translateAlternateColorCodes('&', shorten("&4", StringUtils.formatItemName(item.getItem(), false))));
					tooltips.add(ChatColor.translateAlternateColorCodes('&', "&cNo Permission!"));
					actions.add(null);
				}
			}

			for (int i = 0; i < texts.size(); i = i + 10) {
				TellRawMessage page = new TellRawMessage();
				page.addText(ChatColor.translateAlternateColorCodes('&', "&b&l- Slimefun Guide -\n\n"));
				for (int j = i; j < texts.size() && j < i + 10; j++) {
					page.addText(texts.get(j) + "\n");
					if (tooltips.get(j) != null) page.addHoverEvent(HoverAction.SHOW_TEXT, tooltips.get(j));
					if (actions.get(j) != null) page.addClickEvent(actions.get(j));
				}
				page.addText("\n");
				page.addText(ChatColor.translateAlternateColorCodes('&', "&6\u21E6 &lBack"));
				page.addHoverEvent(HoverAction.SHOW_TEXT, ChatColor.translateAlternateColorCodes('&', "&eClick to go back to the Category Overview"));
				page.addClickEvent(new PlayerRunnable(2) {
					@Override
					public void run(final Player p) {
						Bukkit.getScheduler().scheduleSyncDelayedTask(SlimefunStartup.instance, () -> openMainMenu(p, survival, true, 1), 1L);
					}
				});
				pages.add(page);
			}

			new CustomBookOverlay("Slimefun Guide", "mrCookieSlime", pages.toArray(new TellRawMessage[pages.size()])).open(p);
		}
		else {
			final ChestMenu menu = new ChestMenu("Slimefun Guide");

			menu.setEmptySlotsClickable(false);
			menu.addMenuOpeningHandler(pl -> pl.playSound(pl.getLocation(), Sound.ENTITY_BAT_TAKEOFF, 0.7F, 0.7F));

			int index = 9;
			final int pages = (category.getItems().size() - 1) / category_size + 1;
			for (int i = 0; i < 4; i++) {
				menu.addItem(i, new CustomItem(new ItemStack(Material.GRAY_STAINED_GLASS_PANE), " "));
				menu.addMenuClickHandler(i, (pl, slot, item, action) -> false);
			}

			menu.addItem(4, new CustomItem(new ItemStack(Material.ENCHANTED_BOOK), "&7\u21E6 Back"));
			menu.addMenuClickHandler(4, (pl, slot, item, action) -> {
				openMainMenu(pl, survival, book, 1);
				return false;
			});

			for (int i = 5; i < 9; i++) {
				menu.addItem(i, new CustomItem(new ItemStack(Material.GRAY_STAINED_GLASS_PANE), " "));
				menu.addMenuClickHandler(i, (pl, slot, item, action) -> false);
			}

			for (int i = 45; i < 54; i++) {
				menu.addItem(i, new CustomItem(new ItemStack(Material.GRAY_STAINED_GLASS_PANE), " "));
				menu.addMenuClickHandler(i, (pl, slot, item, action) -> false);
			}

			menu.addItem(46, new CustomItem(new ItemStack(Material.LIME_STAINED_GLASS_PANE), "&r\u21E6 Previous Page", "", "&7(" + selected_page + " / " + pages + ")"));
			menu.addMenuClickHandler(46, (pl, slot, item, action) -> {
				int next = selected_page - 1;
				if (next < 1) next = pages;
				if (next != selected_page) openCategory(pl, category, survival, next, book);
				return false;
			});

			menu.addItem(52, new CustomItem(new ItemStack(Material.LIME_STAINED_GLASS_PANE), "&rNext Page \u21E8", "", "&7(" + selected_page + " / " + pages + ")"));
			menu.addMenuClickHandler(52, (pl, slot, item, action) -> {
				int next = selected_page + 1;
				if (next > pages) next = 1;
				if (next != selected_page) openCategory(pl, category, survival, next, book);
				return false;
			});

			int categoryIndex = category_size * (selected_page - 1);
			for (int i = 0; i < category_size; i++) {
				int target = categoryIndex + i;
				if (target >= category.getItems().size()) break;
				final SlimefunItem sfitem = category.getItems().get(target);
				if (Slimefun.isEnabled(p, sfitem, false)) {
					if (survival && !Slimefun.hasUnlocked(p, sfitem.getItem(), false) && sfitem.getResearch() != null) {
						if (Slimefun.hasPermission(p, sfitem, false)) {
						    final Research research = sfitem.getResearch();
							menu.addItem(index, new CustomItem(Material.BARRIER, "&r" + StringUtils.formatItemName(sfitem.getItem(), false), "&4&lLOCKED", "", "&a> Click to unlock", "", "&7Cost: &b" + research.getCost() + " Level"));
							menu.addMenuClickHandler(index, (pl, slot, item, action) -> {
								if (!Research.isResearching(pl)) {
									if (research.canUnlock(pl)) {
										PlayerProfile profile = PlayerProfile.fromUUID(p.getUniqueId());

										if (profile.hasUnlocked(research)) {
											openCategory(p, category, true, selected_page, book);
										}
										else {
											if (!(pl.getGameMode() == GameMode.CREATIVE && SlimefunStartup.instance.getSettings().researchesFreeInCreative)) {
												pl.setLevel(pl.getLevel() - research.getCost());
											}

											if (pl.getGameMode() == GameMode.CREATIVE) {
												research.unlock(pl, SlimefunStartup.instance.getSettings().researchesFreeInCreative);
												openCategory(pl, category, survival, selected_page, book);
											}
											else {
												research.unlock(pl, false);
												Bukkit.getScheduler().scheduleSyncDelayedTask(SlimefunStartup.instance, () -> openCategory(pl, category, survival, selected_page, book), 103L);
											}
										}
									}
									else Messages.local.sendTranslation(pl, "messages.not-enough-xp", true);
								}
								return false;
							});

							index++;
						}
						else {
							menu.addItem(index, new CustomItem(Material.BARRIER, StringUtils.formatItemName(sfitem.getItem(), false), new String[] {"", "&rYou do not have Permission", "&rto access this Item"}));
							menu.addMenuClickHandler(index, (pl, slot, item, action) -> false);
							index++;
						}
					}
					else {
						menu.addItem(index, sfitem.getItem());
						menu.addMenuClickHandler(index, (pl, slot, item, action) -> {
							if (survival) displayItem(pl, item, true, book, 0);
							else pl.getInventory().addItem(item);
							return false;
						});
						index++;
					}
				}
			}

			menu.open(p);
		}

		if (survival) {
			addToHistory(p, category);
		}
	}

Replace Anonymous With Lambda me.mrCookieSlime.Slimefun.SlimefunGuide.openCategory.add.new PlayerRunnable with (pl, slot, item, action) -> {if(!Research.isResearching(pl)){if(research.canUnlock(pl)){PlayerProfile profile=PlayerProfile.fromUUID(p.getUniqueId()); in method public openCategory(p Player, category Category, survival boolean, selected_page int, book boolean) : void from class me.mrCookieSlime.Slimefun.SlimefunGuide


	public static void openCategory(final Player p, final Category category, final boolean survival, final int selected_page, final boolean book) {
		if (category == null) return;

		if (book && category.getItems().size() < 250) {
			List<TellRawMessage> pages = new ArrayList<>();
			List<String> texts = new ArrayList<>();
			List<String> tooltips = new ArrayList<>();
			List<PlayerRunnable> actions = new ArrayList<>();

			for (final SlimefunItem item: category.getItems()) {
				if (Slimefun.hasPermission(p, item, false)) {
					if (Slimefun.isEnabled(p, item, false)) {
						if (survival && !Slimefun.hasUnlocked(p, item, false) && item.getResearch() != null) {
						    final Research research = item.getResearch();

							texts.add(ChatColor.translateAlternateColorCodes('&', shorten("&7", StringUtils.formatItemName(item.getItem(), false))));
							tooltips.add(ChatColor.translateAlternateColorCodes('&', StringUtils.formatItemName(item.getItem(), false) + "\n&c&lLOCKED\n\n&7Cost: " + (p.getLevel() >= research.getCost() ? "&b": "&4") + research.getCost() + " Levels\n\n&a> Click to unlock"));
							actions.add(new PlayerRunnable(2) {

								@Override
								public void run(final Player p) {
									if (!Research.isResearching(p)) {
										if (research.canUnlock(p)) {
											PlayerProfile profile = PlayerProfile.fromUUID(p.getUniqueId());

											if (profile.hasUnlocked(research)) {
												openCategory(p, category, true, selected_page, book);
											}
											else {
												if (!(p.getGameMode() == GameMode.CREATIVE && SlimefunStartup.instance.getSettings().researchesFreeInCreative)) {
													p.setLevel(p.getLevel() - research.getCost());
												}

												if (p.getGameMode() == GameMode.CREATIVE) {
													research.unlock(p, true);

													Bukkit.getScheduler().scheduleSyncDelayedTask(SlimefunStartup.instance, () -> openCategory(p, category, survival, selected_page, book), 1L);
												}
												else {
													research.unlock(p, false);

													Bukkit.getScheduler().scheduleSyncDelayedTask(SlimefunStartup.instance, () -> openCategory(p, category, survival, selected_page, book), 103L);
												}
											}
										} else Messages.local.sendTranslation(p, "messages.not-enough-xp", true);
									}
								}
							});
						}
						else {
							texts.add(ChatColor.translateAlternateColorCodes('&', shorten("&a", StringUtils.formatItemName(item.getItem(), false))));

							StringBuilder tooltip = new StringBuilder();

							tooltip.append(StringUtils.formatItemName(item.getItem(), false));

							if (item.getItem().hasItemMeta() && item.getItem().getItemMeta().hasLore()) {
								for (String line : item.getItem().getItemMeta().getLore()) {
									tooltip.append("\n" + line);
								}
							}

							tooltip.append(ChatColor.translateAlternateColorCodes('&', "\n\n&e&oClick for more Info"));

							tooltips.add(tooltip.toString());
							actions.add(new PlayerRunnable(2) {

								@Override
								public void run(Player p) {
									displayItem(p, item.getItem(), true, book, 0);
								}
							});
						}
					}
				}
				else {
					texts.add(ChatColor.translateAlternateColorCodes('&', shorten("&4", StringUtils.formatItemName(item.getItem(), false))));
					tooltips.add(ChatColor.translateAlternateColorCodes('&', "&cNo Permission!"));
					actions.add(null);
				}
			}

			for (int i = 0; i < texts.size(); i = i + 10) {
				TellRawMessage page = new TellRawMessage();
				page.addText(ChatColor.translateAlternateColorCodes('&', "&b&l- Slimefun Guide -\n\n"));
				for (int j = i; j < texts.size() && j < i + 10; j++) {
					page.addText(texts.get(j) + "\n");
					if (tooltips.get(j) != null) page.addHoverEvent(HoverAction.SHOW_TEXT, tooltips.get(j));
					if (actions.get(j) != null) page.addClickEvent(actions.get(j));
				}
				page.addText("\n");
				page.addText(ChatColor.translateAlternateColorCodes('&', "&6\u21E6 &lBack"));
				page.addHoverEvent(HoverAction.SHOW_TEXT, ChatColor.translateAlternateColorCodes('&', "&eClick to go back to the Category Overview"));
				page.addClickEvent(new PlayerRunnable(2) {
					@Override
					public void run(final Player p) {
						Bukkit.getScheduler().scheduleSyncDelayedTask(SlimefunStartup.instance, () -> openMainMenu(p, survival, true, 1), 1L);
					}
				});
				pages.add(page);
			}

			new CustomBookOverlay("Slimefun Guide", "mrCookieSlime", pages.toArray(new TellRawMessage[pages.size()])).open(p);
		}
		else {
			final ChestMenu menu = new ChestMenu("Slimefun Guide");

			menu.setEmptySlotsClickable(false);
			menu.addMenuOpeningHandler(pl -> pl.playSound(pl.getLocation(), Sound.ENTITY_BAT_TAKEOFF, 0.7F, 0.7F));

			int index = 9;
			final int pages = (category.getItems().size() - 1) / category_size + 1;
			for (int i = 0; i < 4; i++) {
				menu.addItem(i, new CustomItem(new ItemStack(Material.GRAY_STAINED_GLASS_PANE), " "));
				menu.addMenuClickHandler(i, (pl, slot, item, action) -> false);
			}

			menu.addItem(4, new CustomItem(new ItemStack(Material.ENCHANTED_BOOK), "&7\u21E6 Back"));
			menu.addMenuClickHandler(4, (pl, slot, item, action) -> {
				openMainMenu(pl, survival, book, 1);
				return false;
			});

			for (int i = 5; i < 9; i++) {
				menu.addItem(i, new CustomItem(new ItemStack(Material.GRAY_STAINED_GLASS_PANE), " "));
				menu.addMenuClickHandler(i, (pl, slot, item, action) -> false);
			}

			for (int i = 45; i < 54; i++) {
				menu.addItem(i, new CustomItem(new ItemStack(Material.GRAY_STAINED_GLASS_PANE), " "));
				menu.addMenuClickHandler(i, (pl, slot, item, action) -> false);
			}

			menu.addItem(46, new CustomItem(new ItemStack(Material.LIME_STAINED_GLASS_PANE), "&r\u21E6 Previous Page", "", "&7(" + selected_page + " / " + pages + ")"));
			menu.addMenuClickHandler(46, (pl, slot, item, action) -> {
				int next = selected_page - 1;
				if (next < 1) next = pages;
				if (next != selected_page) openCategory(pl, category, survival, next, book);
				return false;
			});

			menu.addItem(52, new CustomItem(new ItemStack(Material.LIME_STAINED_GLASS_PANE), "&rNext Page \u21E8", "", "&7(" + selected_page + " / " + pages + ")"));
			menu.addMenuClickHandler(52, (pl, slot, item, action) -> {
				int next = selected_page + 1;
				if (next > pages) next = 1;
				if (next != selected_page) openCategory(pl, category, survival, next, book);
				return false;
			});

			int category_index = category_size * (selected_page - 1);
			for (int i = 0; i < category_size; i++) {
				int target = category_index + i;
				if (target >= category.getItems().size()) break;
				final SlimefunItem sfitem = category.getItems().get(target);
				if (Slimefun.isEnabled(p, sfitem, false)) {
					if (survival && !Slimefun.hasUnlocked(p, sfitem.getItem(), false) && sfitem.getResearch() != null) {
						if (Slimefun.hasPermission(p, sfitem, false)) {
						    final Research research = sfitem.getResearch();
							menu.addItem(index, new CustomItem(Material.BARRIER, "&r" + StringUtils.formatItemName(sfitem.getItem(), false), "&4&lLOCKED", "", "&a> Click to unlock", "", "&7Cost: &b" + research.getCost() + " Level"));
							menu.addMenuClickHandler(index, (pl, slot, item, action) -> {
								if (!Research.isResearching(pl)) {
									if (research.canUnlock(pl)) {
										PlayerProfile profile = PlayerProfile.fromUUID(p.getUniqueId());

										if (profile.hasUnlocked(research)) {
											openCategory(p, category, true, selected_page, book);
										}
										else {
											if (!(pl.getGameMode() == GameMode.CREATIVE && SlimefunStartup.instance.getSettings().researchesFreeInCreative)) {
												pl.setLevel(pl.getLevel() - research.getCost());
											}

											if (pl.getGameMode() == GameMode.CREATIVE) {
												research.unlock(pl, SlimefunStartup.instance.getSettings().researchesFreeInCreative);
												openCategory(pl, category, survival, selected_page, book);
											}
											else {
												research.unlock(pl, false);
												Bukkit.getScheduler().scheduleSyncDelayedTask(SlimefunStartup.instance, () -> openCategory(pl, category, survival, selected_page, book), 103L);
											}
										}
									}
									else Messages.local.sendTranslation(pl, "messages.not-enough-xp", true);
								}
								return false;
							});

							index++;
						}
						else {
							menu.addItem(index, new CustomItem(Material.BARRIER, StringUtils.formatItemName(sfitem.getItem(), false), new String[] {"", "&rYou do not have Permission", "&rto access this Item"}));
							menu.addMenuClickHandler(index, (pl, slot, item, action) -> false);
							index++;
						}
					}
					else {
						menu.addItem(index, sfitem.getItem());
						menu.addMenuClickHandler(index, (pl, slot, item, action) -> {
							if (survival) displayItem(pl, item, true, book, 0);
							else pl.getInventory().addItem(item);
							return false;
						});
						index++;
					}
				}
			}

			menu.open(p);
		}

		if (survival) {
			addToHistory(p, category);
		}
	}

	public static void openCategory(final Player p, final Category category, final boolean survival, final int selected_page, final boolean book) {
		if (category == null) return;

		if (book && category.getItems().size() < 250) {
			List<TellRawMessage> pages = new ArrayList<>();
			List<String> texts = new ArrayList<>();
			List<String> tooltips = new ArrayList<>();
			List<PlayerRunnable> actions = new ArrayList<>();

			for (final SlimefunItem item: category.getItems()) {
				if (Slimefun.hasPermission(p, item, false)) {
					if (Slimefun.isEnabled(p, item, false)) {
						if (survival && !Slimefun.hasUnlocked(p, item, false) && item.getResearch() != null) {
						    final Research research = item.getResearch();

							texts.add(ChatColor.translateAlternateColorCodes('&', shorten("&7", StringUtils.formatItemName(item.getItem(), false))));
							tooltips.add(ChatColor.translateAlternateColorCodes('&', StringUtils.formatItemName(item.getItem(), false) + "\n&c&lLOCKED\n\n&7Cost: " + (p.getLevel() >= research.getCost() ? "&b": "&4") + research.getCost() + " Levels\n\n&a> Click to unlock"));
							actions.add(new PlayerRunnable(2) {

								@Override
								public void run(final Player p) {
									if (!Research.isResearching(p)) {
										if (research.canUnlock(p)) {
											PlayerProfile profile = PlayerProfile.fromUUID(p.getUniqueId());

											if (profile.hasUnlocked(research)) {
												openCategory(p, category, true, selected_page, book);
											}
											else {
												if (!(p.getGameMode() == GameMode.CREATIVE && SlimefunStartup.instance.getSettings().RESEARCHES_FREE_IN_CREATIVE)) {
													p.setLevel(p.getLevel() - research.getCost());
												}

												if (p.getGameMode() == GameMode.CREATIVE) {
													research.unlock(p, true);

													Bukkit.getScheduler().scheduleSyncDelayedTask(SlimefunStartup.instance, () -> openCategory(p, category, survival, selected_page, book), 1L);
												}
												else {
													research.unlock(p, false);

													Bukkit.getScheduler().scheduleSyncDelayedTask(SlimefunStartup.instance, () -> openCategory(p, category, survival, selected_page, book), 103L);
												}
											}
										} else Messages.local.sendTranslation(p, "messages.not-enough-xp", true);
									}
								}
							});
						}
						else {
							texts.add(ChatColor.translateAlternateColorCodes('&', shorten("&a", StringUtils.formatItemName(item.getItem(), false))));

							StringBuilder tooltip = new StringBuilder();

							tooltip.append(StringUtils.formatItemName(item.getItem(), false));

							if (item.getItem().hasItemMeta() && item.getItem().getItemMeta().hasLore()) {
								for (String line : item.getItem().getItemMeta().getLore()) {
									tooltip.append("\n" + line);
								}
							}

							tooltip.append(ChatColor.translateAlternateColorCodes('&', "\n\n&e&oClick for more Info"));

							tooltips.add(tooltip.toString());
							actions.add(new PlayerRunnable(2) {

								@Override
								public void run(Player p) {
									displayItem(p, item.getItem(), true, book, 0);
								}
							});
						}
					}
				}
				else {
					texts.add(ChatColor.translateAlternateColorCodes('&', shorten("&4", StringUtils.formatItemName(item.getItem(), false))));
					tooltips.add(ChatColor.translateAlternateColorCodes('&', "&cNo Permission!"));
					actions.add(null);
				}
			}

			for (int i = 0; i < texts.size(); i = i + 10) {
				TellRawMessage page = new TellRawMessage();
				page.addText(ChatColor.translateAlternateColorCodes('&', "&b&l- Slimefun Guide -\n\n"));
				for (int j = i; j < texts.size() && j < i + 10; j++) {
					page.addText(texts.get(j) + "\n");
					if (tooltips.get(j) != null) page.addHoverEvent(HoverAction.SHOW_TEXT, tooltips.get(j));
					if (actions.get(j) != null) page.addClickEvent(actions.get(j));
				}
				page.addText("\n");
				page.addText(ChatColor.translateAlternateColorCodes('&', "&6\u21E6 &lBack"));
				page.addHoverEvent(HoverAction.SHOW_TEXT, ChatColor.translateAlternateColorCodes('&', "&eClick to go back to the Category Overview"));
				page.addClickEvent(new PlayerRunnable(2) {
					@Override
					public void run(final Player p) {
						Bukkit.getScheduler().scheduleSyncDelayedTask(SlimefunStartup.instance, () -> openMainMenu(p, survival, true, 1), 1L);
					}
				});
				pages.add(page);
			}

			new CustomBookOverlay("Slimefun Guide", "mrCookieSlime", pages.toArray(new TellRawMessage[pages.size()])).open(p);
		}
		else {
			final ChestMenu menu = new ChestMenu("Slimefun Guide");

			menu.setEmptySlotsClickable(false);
			menu.addMenuOpeningHandler(pl -> pl.playSound(pl.getLocation(), Sound.ENTITY_BAT_TAKEOFF, 0.7F, 0.7F));

			int index = 9;
			final int pages = (category.getItems().size() - 1) / category_size + 1;
			for (int i = 0; i < 4; i++) {
				menu.addItem(i, new CustomItem(new ItemStack(Material.GRAY_STAINED_GLASS_PANE), " "));
				menu.addMenuClickHandler(i, (pl, slot, item, action) -> false);
			}

			menu.addItem(4, new CustomItem(new ItemStack(Material.ENCHANTED_BOOK), "&7\u21E6 Back"));
			menu.addMenuClickHandler(4, (pl, slot, item, action) -> {
				openMainMenu(pl, survival, book, 1);
				return false;
			});

			for (int i = 5; i < 9; i++) {
				menu.addItem(i, new CustomItem(new ItemStack(Material.GRAY_STAINED_GLASS_PANE), " "));
				menu.addMenuClickHandler(i, (pl, slot, item, action) -> false);
			}

			for (int i = 45; i < 54; i++) {
				menu.addItem(i, new CustomItem(new ItemStack(Material.GRAY_STAINED_GLASS_PANE), " "));
				menu.addMenuClickHandler(i, (pl, slot, item, action) -> false);
			}

			menu.addItem(46, new CustomItem(new ItemStack(Material.LIME_STAINED_GLASS_PANE), "&r\u21E6 Previous Page", "", "&7(" + selected_page + " / " + pages + ")"));
			menu.addMenuClickHandler(46, (pl, slot, item, action) -> {
				int next = selected_page - 1;
				if (next < 1) next = pages;
				if (next != selected_page) openCategory(pl, category, survival, next, book);
				return false;
			});

			menu.addItem(52, new CustomItem(new ItemStack(Material.LIME_STAINED_GLASS_PANE), "&rNext Page \u21E8", "", "&7(" + selected_page + " / " + pages + ")"));
			menu.addMenuClickHandler(52, (pl, slot, item, action) -> {
				int next = selected_page + 1;
				if (next > pages) next = 1;
				if (next != selected_page) openCategory(pl, category, survival, next, book);
				return false;
			});

			int category_index = category_size * (selected_page - 1);
			for (int i = 0; i < category_size; i++) {
				int target = category_index + i;
				if (target >= category.getItems().size()) break;
				final SlimefunItem sfitem = category.getItems().get(target);
				if (Slimefun.isEnabled(p, sfitem, false)) {
					if (survival && !Slimefun.hasUnlocked(p, sfitem.getItem(), false) && sfitem.getResearch() != null) {
						if (Slimefun.hasPermission(p, sfitem, false)) {
						    final Research research = sfitem.getResearch();
							menu.addItem(index, new CustomItem(Material.BARRIER, "&r" + StringUtils.formatItemName(sfitem.getItem(), false), "&4&lLOCKED", "", "&a> Click to unlock", "", "&7Cost: &b" + research.getCost() + " Level"));
							menu.addMenuClickHandler(index, (pl, slot, item, action) -> {
								if (!Research.isResearching(pl)) {
									if (research.canUnlock(pl)) {
										PlayerProfile profile = PlayerProfile.fromUUID(p.getUniqueId());

										if (profile.hasUnlocked(research)) {
											openCategory(p, category, true, selected_page, book);
										}
										else {
											if (!(pl.getGameMode() == GameMode.CREATIVE && SlimefunStartup.instance.getSettings().RESEARCHES_FREE_IN_CREATIVE)) {
												pl.setLevel(pl.getLevel() - research.getCost());
											}

											if (pl.getGameMode() == GameMode.CREATIVE) {
												research.unlock(pl, SlimefunStartup.instance.getSettings().RESEARCHES_FREE_IN_CREATIVE);
												openCategory(pl, category, survival, selected_page, book);
											}
											else {
												research.unlock(pl, false);
												Bukkit.getScheduler().scheduleSyncDelayedTask(SlimefunStartup.instance, () -> openCategory(pl, category, survival, selected_page, book), 103L);
											}
										}
									}
									else Messages.local.sendTranslation(pl, "messages.not-enough-xp", true);
								}
								return false;
							});

							index++;
						}
						else {
							menu.addItem(index, new CustomItem(Material.BARRIER, StringUtils.formatItemName(sfitem.getItem(), false), new String[] {"", "&rYou do not have Permission", "&rto access this Item"}));
							menu.addMenuClickHandler(index, (pl, slot, item, action) -> false);
							index++;
						}
					}
					else {
						menu.addItem(index, sfitem.getItem());
						menu.addMenuClickHandler(index, (pl, slot, item, action) -> {
							if (survival) displayItem(pl, item, true, book, 0);
							else pl.getInventory().addItem(item);
							return false;
						});
						index++;
					}
				}
			}

			menu.open(p);
		}

		if (survival) {
			addToHistory(p, category);
		}
	}


	public static void openCategory(final Player p, final Category category, final boolean survival, final int selected_page, final boolean book) {
		if (category == null) return;

		if (book && category.getItems().size() < 250) {
			List<TellRawMessage> pages = new ArrayList<>();
			List<String> texts = new ArrayList<>();
			List<String> tooltips = new ArrayList<>();
			List<PlayerRunnable> actions = new ArrayList<>();

			for (final SlimefunItem item: category.getItems()) {
				if (Slimefun.hasPermission(p, item, false)) {
					if (Slimefun.isEnabled(p, item, false)) {
						if (survival && !Slimefun.hasUnlocked(p, item, false) && item.getResearch() != null) {
						    final Research research = item.getResearch();

							texts.add(ChatColor.translateAlternateColorCodes('&', shorten("&7", StringUtils.formatItemName(item.getItem(), false))));
							tooltips.add(ChatColor.translateAlternateColorCodes('&', StringUtils.formatItemName(item.getItem(), false) + "\n&c&lLOCKED\n\n&7Cost: " + (p.getLevel() >= research.getCost() ? "&b": "&4") + research.getCost() + " Levels\n\n&a> Click to unlock"));
							actions.add(new PlayerRunnable(2) {

								@Override
								public void run(final Player p) {
									if (!Research.isResearching(p)) {
										if (research.canUnlock(p)) {
											PlayerProfile profile = PlayerProfile.fromUUID(p.getUniqueId());

											if (profile.hasUnlocked(research)) {
												openCategory(p, category, true, selected_page, book);
											}
											else {
												if (!(p.getGameMode() == GameMode.CREATIVE && SlimefunStartup.instance.getSettings().RESEARCHES_FREE_IN_CREATIVE)) {
													p.setLevel(p.getLevel() - research.getCost());
												}

												if (p.getGameMode() == GameMode.CREATIVE) {
													research.unlock(p, true);

													Bukkit.getScheduler().scheduleSyncDelayedTask(SlimefunStartup.instance, () -> openCategory(p, category, survival, selected_page, book), 1L);
												}
												else {
													research.unlock(p, false);

													Bukkit.getScheduler().scheduleSyncDelayedTask(SlimefunStartup.instance, () -> openCategory(p, category, survival, selected_page, book), 103L);
												}
											}
										} else Messages.local.sendTranslation(p, "messages.not-enough-xp", true);
									}
								}
							});
						}
						else {
							texts.add(ChatColor.translateAlternateColorCodes('&', shorten("&a", StringUtils.formatItemName(item.getItem(), false))));

							StringBuilder tooltip = new StringBuilder();

							tooltip.append(StringUtils.formatItemName(item.getItem(), false));

							if (item.getItem().hasItemMeta() && item.getItem().getItemMeta().hasLore()) {
								for (String line : item.getItem().getItemMeta().getLore()) {
									tooltip.append("\n" + line);
								}
							}

							tooltip.append(ChatColor.translateAlternateColorCodes('&', "\n\n&e&oClick for more Info"));

							tooltips.add(tooltip.toString());
							actions.add(new PlayerRunnable(2) {

								@Override
								public void run(Player p) {
									displayItem(p, item.getItem(), true, book, 0);
								}
							});
						}
					}
				}
				else {
					texts.add(ChatColor.translateAlternateColorCodes('&', shorten("&4", StringUtils.formatItemName(item.getItem(), false))));
					tooltips.add(ChatColor.translateAlternateColorCodes('&', "&cNo Permission!"));
					actions.add(null);
				}
			}

			for (int i = 0; i < texts.size(); i = i + 10) {
				TellRawMessage page = new TellRawMessage();
				page.addText(ChatColor.translateAlternateColorCodes('&', "&b&l- Slimefun Guide -\n\n"));
				for (int j = i; j < texts.size() && j < i + 10; j++) {
					page.addText(texts.get(j) + "\n");
					if (tooltips.get(j) != null) page.addHoverEvent(HoverAction.SHOW_TEXT, tooltips.get(j));
					if (actions.get(j) != null) page.addClickEvent(actions.get(j));
				}
				page.addText("\n");
				page.addText(ChatColor.translateAlternateColorCodes('&', "&6\u21E6 &lBack"));
				page.addHoverEvent(HoverAction.SHOW_TEXT, ChatColor.translateAlternateColorCodes('&', "&eClick to go back to the Category Overview"));
				page.addClickEvent(new PlayerRunnable(2) {
					@Override
					public void run(final Player p) {
						Bukkit.getScheduler().scheduleSyncDelayedTask(SlimefunStartup.instance, () -> openMainMenu(p, survival, true, 1), 1L);
					}
				});
				pages.add(page);
			}

			new CustomBookOverlay("Slimefun Guide", "mrCookieSlime", pages.toArray(new TellRawMessage[pages.size()])).open(p);
		}
		else {
			final ChestMenu menu = new ChestMenu("Slimefun Guide");

			menu.setEmptySlotsClickable(false);
			menu.addMenuOpeningHandler(pl -> pl.playSound(pl.getLocation(), Sound.ENTITY_BAT_TAKEOFF, 0.7F, 0.7F));

			int index = 9;
			final int pages = (category.getItems().size() - 1) / category_size + 1;
			for (int i = 0; i < 4; i++) {
				menu.addItem(i, new CustomItem(new ItemStack(Material.GRAY_STAINED_GLASS_PANE), " "));
				menu.addMenuClickHandler(i, (pl, slot, item, action) -> false);
			}

			menu.addItem(4, new CustomItem(new ItemStack(Material.ENCHANTED_BOOK), "&7\u21E6 Back"));
			menu.addMenuClickHandler(4, (pl, slot, item, action) -> {
				openMainMenu(pl, survival, book, 1);
				return false;
			});

			for (int i = 5; i < 9; i++) {
				menu.addItem(i, new CustomItem(new ItemStack(Material.GRAY_STAINED_GLASS_PANE), " "));
				menu.addMenuClickHandler(i, (pl, slot, item, action) -> false);
			}

			for (int i = 45; i < 54; i++) {
				menu.addItem(i, new CustomItem(new ItemStack(Material.GRAY_STAINED_GLASS_PANE), " "));
				menu.addMenuClickHandler(i, (pl, slot, item, action) -> false);
			}

			menu.addItem(46, new CustomItem(new ItemStack(Material.LIME_STAINED_GLASS_PANE), "&r\u21E6 Previous Page", "", "&7(" + selected_page + " / " + pages + ")"));
			menu.addMenuClickHandler(46, (pl, slot, item, action) -> {
				int next = selected_page - 1;
				if (next < 1) next = pages;
				if (next != selected_page) openCategory(pl, category, survival, next, book);
				return false;
			});

			menu.addItem(52, new CustomItem(new ItemStack(Material.LIME_STAINED_GLASS_PANE), "&rNext Page \u21E8", "", "&7(" + selected_page + " / " + pages + ")"));
			menu.addMenuClickHandler(52, (pl, slot, item, action) -> {
				int next = selected_page + 1;
				if (next > pages) next = 1;
				if (next != selected_page) openCategory(pl, category, survival, next, book);
				return false;
			});

			int categoryIndex = category_size * (selected_page - 1);
			for (int i = 0; i < category_size; i++) {
				int target = categoryIndex + i;
				if (target >= category.getItems().size()) break;
				final SlimefunItem sfitem = category.getItems().get(target);
				if (Slimefun.isEnabled(p, sfitem, false)) {
					if (survival && !Slimefun.hasUnlocked(p, sfitem.getItem(), false) && sfitem.getResearch() != null) {
						if (Slimefun.hasPermission(p, sfitem, false)) {
						    final Research research = sfitem.getResearch();
							menu.addItem(index, new CustomItem(Material.BARRIER, "&r" + StringUtils.formatItemName(sfitem.getItem(), false), "&4&lLOCKED", "", "&a> Click to unlock", "", "&7Cost: &b" + research.getCost() + " Level"));
							menu.addMenuClickHandler(index, (pl, slot, item, action) -> {
								if (!Research.isResearching(pl)) {
									if (research.canUnlock(pl)) {
										PlayerProfile profile = PlayerProfile.fromUUID(p.getUniqueId());

										if (profile.hasUnlocked(research)) {
											openCategory(p, category, true, selected_page, book);
										}
										else {
											if (!(pl.getGameMode() == GameMode.CREATIVE && SlimefunStartup.instance.getSettings().RESEARCHES_FREE_IN_CREATIVE)) {
												pl.setLevel(pl.getLevel() - research.getCost());
											}

											if (pl.getGameMode() == GameMode.CREATIVE) {
												research.unlock(pl, SlimefunStartup.instance.getSettings().RESEARCHES_FREE_IN_CREATIVE);
												openCategory(pl, category, survival, selected_page, book);
											}
											else {
												research.unlock(pl, false);
												Bukkit.getScheduler().scheduleSyncDelayedTask(SlimefunStartup.instance, () -> openCategory(pl, category, survival, selected_page, book), 103L);
											}
										}
									}
									else Messages.local.sendTranslation(pl, "messages.not-enough-xp", true);
								}
								return false;
							});

							index++;
						}
						else {
							menu.addItem(index, new CustomItem(Material.BARRIER, StringUtils.formatItemName(sfitem.getItem(), false), new String[] {"", "&rYou do not have Permission", "&rto access this Item"}));
							menu.addMenuClickHandler(index, (pl, slot, item, action) -> false);
							index++;
						}
					}
					else {
						menu.addItem(index, sfitem.getItem());
						menu.addMenuClickHandler(index, (pl, slot, item, action) -> {
							if (survival) displayItem(pl, item, true, book, 0);
							else pl.getInventory().addItem(item);
							return false;
						});
						index++;
					}
				}
			}

			menu.open(p);
		}

		if (survival) {
			addToHistory(p, category);
		}
	}

	public static void openCategory(final Player p, final Category category, final boolean survival, final int selected_page, final boolean book) {
		if (category == null) return;

		if (book && category.getItems().size() < 250) {
			List<TellRawMessage> pages = new ArrayList<>();
			List<String> texts = new ArrayList<>();
			List<String> tooltips = new ArrayList<>();
			List<PlayerRunnable> actions = new ArrayList<>();

			for (final SlimefunItem item: category.getItems()) {
				if (Slimefun.hasPermission(p, item, false)) {
					if (Slimefun.isEnabled(p, item, false)) {
						if (survival && !Slimefun.hasUnlocked(p, item, false) && item.getResearch() != null) {
						    final Research research = item.getResearch();

							texts.add(ChatColor.translateAlternateColorCodes('&', shorten("&7", StringUtils.formatItemName(item.getItem(), false))));
							tooltips.add(ChatColor.translateAlternateColorCodes('&', StringUtils.formatItemName(item.getItem(), false) + "\n&c&lLOCKED\n\n&7Cost: " + (p.getLevel() >= research.getCost() ? "&b": "&4") + research.getCost() + " Levels\n\n&a> Click to unlock"));
							actions.add(new PlayerRunnable(2) {

								@Override
								public void run(final Player p) {
									if (!Research.isResearching(p)) {
										if (research.canUnlock(p)) {
											PlayerProfile profile = PlayerProfile.fromUUID(p.getUniqueId());

											if (profile.hasUnlocked(research)) {
												openCategory(p, category, true, selected_page, book);
											}
											else {
												if (!(p.getGameMode() == GameMode.CREATIVE && SlimefunStartup.instance.getSettings().Researches_FREE_IN_CREATIVE)) {
													p.setLevel(p.getLevel() - research.getCost());
												}

												if (p.getGameMode() == GameMode.CREATIVE) {
													research.unlock(p, true);

													Bukkit.getScheduler().scheduleSyncDelayedTask(SlimefunStartup.instance, () -> openCategory(p, category, survival, selected_page, book), 1L);
												}
												else {
													research.unlock(p, false);

													Bukkit.getScheduler().scheduleSyncDelayedTask(SlimefunStartup.instance, () -> openCategory(p, category, survival, selected_page, book), 103L);
												}
											}
										} else Messages.local.sendTranslation(p, "messages.not-enough-xp", true);
									}
								}
							});
						}
						else {
							texts.add(ChatColor.translateAlternateColorCodes('&', shorten("&a", StringUtils.formatItemName(item.getItem(), false))));

							StringBuilder tooltip = new StringBuilder();

							tooltip.append(StringUtils.formatItemName(item.getItem(), false));

							if (item.getItem().hasItemMeta() && item.getItem().getItemMeta().hasLore()) {
								for (String line : item.getItem().getItemMeta().getLore()) {
									tooltip.append("\n" + line);
								}
							}

							tooltip.append(ChatColor.translateAlternateColorCodes('&', "\n\n&e&oClick for more Info"));

							tooltips.add(tooltip.toString());
							actions.add(new PlayerRunnable(2) {

								@Override
								public void run(Player p) {
									displayItem(p, item.getItem(), true, book, 0);
								}
							});
						}
					}
				}
				else {
					texts.add(ChatColor.translateAlternateColorCodes('&', shorten("&4", StringUtils.formatItemName(item.getItem(), false))));
					tooltips.add(ChatColor.translateAlternateColorCodes('&', "&cNo Permission!"));
					actions.add(null);
				}
			}

			for (int i = 0; i < texts.size(); i = i + 10) {
				TellRawMessage page = new TellRawMessage();
				page.addText(ChatColor.translateAlternateColorCodes('&', "&b&l- Slimefun Guide -\n\n"));
				for (int j = i; j < texts.size() && j < i + 10; j++) {
					page.addText(texts.get(j) + "\n");
					if (tooltips.get(j) != null) page.addHoverEvent(HoverAction.SHOW_TEXT, tooltips.get(j));
					if (actions.get(j) != null) page.addClickEvent(actions.get(j));
				}
				page.addText("\n");
				page.addText(ChatColor.translateAlternateColorCodes('&', "&6\u21E6 &lBack"));
				page.addHoverEvent(HoverAction.SHOW_TEXT, ChatColor.translateAlternateColorCodes('&', "&eClick to go back to the Category Overview"));
				page.addClickEvent(new PlayerRunnable(2) {
					@Override
					public void run(final Player p) {
						Bukkit.getScheduler().scheduleSyncDelayedTask(SlimefunStartup.instance, () -> openMainMenu(p, survival, true, 1), 1L);
					}
				});
				pages.add(page);
			}

			new CustomBookOverlay("Slimefun Guide", "mrCookieSlime", pages.toArray(new TellRawMessage[pages.size()])).open(p);
		}
		else {
			final ChestMenu menu = new ChestMenu("Slimefun Guide");

			menu.setEmptySlotsClickable(false);
			menu.addMenuOpeningHandler(pl -> pl.playSound(pl.getLocation(), Sound.ENTITY_BAT_TAKEOFF, 0.7F, 0.7F));

			int index = 9;
			final int pages = (category.getItems().size() - 1) / category_size + 1;
			for (int i = 0; i < 4; i++) {
				menu.addItem(i, new CustomItem(new ItemStack(Material.GRAY_STAINED_GLASS_PANE), " "));
				menu.addMenuClickHandler(i, (pl, slot, item, action) -> false);
			}

			menu.addItem(4, new CustomItem(new ItemStack(Material.ENCHANTED_BOOK), "&7\u21E6 Back"));
			menu.addMenuClickHandler(4, (pl, slot, item, action) -> {
				openMainMenu(pl, survival, book, 1);
				return false;
			});

			for (int i = 5; i < 9; i++) {
				menu.addItem(i, new CustomItem(new ItemStack(Material.GRAY_STAINED_GLASS_PANE), " "));
				menu.addMenuClickHandler(i, (pl, slot, item, action) -> false);
			}

			for (int i = 45; i < 54; i++) {
				menu.addItem(i, new CustomItem(new ItemStack(Material.GRAY_STAINED_GLASS_PANE), " "));
				menu.addMenuClickHandler(i, (pl, slot, item, action) -> false);
			}

			menu.addItem(46, new CustomItem(new ItemStack(Material.LIME_STAINED_GLASS_PANE), "&r\u21E6 Previous Page", "", "&7(" + selected_page + " / " + pages + ")"));
			menu.addMenuClickHandler(46, (pl, slot, item, action) -> {
				int next = selected_page - 1;
				if (next < 1) next = pages;
				if (next != selected_page) openCategory(pl, category, survival, next, book);
				return false;
			});

			menu.addItem(52, new CustomItem(new ItemStack(Material.LIME_STAINED_GLASS_PANE), "&rNext Page \u21E8", "", "&7(" + selected_page + " / " + pages + ")"));
			menu.addMenuClickHandler(52, (pl, slot, item, action) -> {
				int next = selected_page + 1;
				if (next > pages) next = 1;
				if (next != selected_page) openCategory(pl, category, survival, next, book);
				return false;
			});

			int categoryIndex = category_size * (selected_page - 1);
			for (int i = 0; i < category_size; i++) {
				int target = categoryIndex + i;
				if (target >= category.getItems().size()) break;
				final SlimefunItem sfitem = category.getItems().get(target);
				if (Slimefun.isEnabled(p, sfitem, false)) {
					if (survival && !Slimefun.hasUnlocked(p, sfitem.getItem(), false) && sfitem.getResearch() != null) {
						if (Slimefun.hasPermission(p, sfitem, false)) {
						    final Research research = sfitem.getResearch();
							menu.addItem(index, new CustomItem(Material.BARRIER, "&r" + StringUtils.formatItemName(sfitem.getItem(), false), "&4&lLOCKED", "", "&a> Click to unlock", "", "&7Cost: &b" + research.getCost() + " Level"));
							menu.addMenuClickHandler(index, (pl, slot, item, action) -> {
								if (!Research.isResearching(pl)) {
									if (research.canUnlock(pl)) {
										PlayerProfile profile = PlayerProfile.fromUUID(p.getUniqueId());

										if (profile.hasUnlocked(research)) {
											openCategory(p, category, true, selected_page, book);
										}
										else {
											if (!(pl.getGameMode() == GameMode.CREATIVE && SlimefunStartup.instance.getSettings().Researches_FREE_IN_CREATIVE)) {
												pl.setLevel(pl.getLevel() - research.getCost());
											}

											if (pl.getGameMode() == GameMode.CREATIVE) {
												research.unlock(pl, SlimefunStartup.instance.getSettings().Researches_FREE_IN_CREATIVE);
												openCategory(pl, category, survival, selected_page, book);
											}
											else {
												research.unlock(pl, false);
												Bukkit.getScheduler().scheduleSyncDelayedTask(SlimefunStartup.instance, () -> openCategory(pl, category, survival, selected_page, book), 103L);
											}
										}
									}
									else Messages.local.sendTranslation(pl, "messages.not-enough-xp", true);
								}
								return false;
							});

							index++;
						}
						else {
							menu.addItem(index, new CustomItem(Material.BARRIER, StringUtils.formatItemName(sfitem.getItem(), false), new String[] {"", "&rYou do not have Permission", "&rto access this Item"}));
							menu.addMenuClickHandler(index, (pl, slot, item, action) -> false);
							index++;
						}
					}
					else {
						menu.addItem(index, sfitem.getItem());
						menu.addMenuClickHandler(index, (pl, slot, item, action) -> {
							if (survival) displayItem(pl, item, true, book, 0);
							else pl.getInventory().addItem(item);
							return false;
						});
						index++;
					}
				}
			}

			menu.open(p);
		}

		if (survival) {
			addToHistory(p, category);
		}
	}