local S = core.get_translator(core.get_current_modname())

doc.add_category("yams_doc:basics_category", {
    name = S("Basics"),
    description = S("Covers the basics of this game."),
    build_formspec = doc.entry_builders.text,
    sorting = "custom",
    sorting_data = {"yams_doc:intro", "yams_doc:health_damage",
                    "yams_doc:hunger", "yams_doc:mobs_basic",
                    "yams_doc:sprinting", "yams_doc:exp",
                    "yams_doc:awards"},
})

local intro_text = S("Welcome to yams!\n\n" ..
    "yams is a fork of Minetest Game with light RPG elements. It " ..
    "includes many mods developed by various members of the Minetest " ..
    "community as well as a few mods developed specifically for yams.\n\n" ..
    "This game assumes that you have experience playing Minetest Game or " ..
    "similar games. If you never played a game like this, playing Wuzzy's " ..
    "Tutorial game to learn the basics is recommended, as this game's " ..
    "manual assumes that you are familiar with the basic controls and game " ..
    "mechanics.\n\n" ..
    "Note that the game is not paused while viewing the help screens.\n\n" ..
    "I hope you enjoy playing yams!"
)

doc.add_entry("yams_doc:basics_category", "yams_doc:intro", {
    name = S("Introduction"),
    data = intro_text,
})

local health_text = S("Your current and maximum health is displayed within " ..
    "a red bar above the inventory hotbar. Receiving damage decreases your " ..
    "health.\n\n" ..
    "Some common ways of receiving damage include:\n" ..
    "- Getting hit by a monster or a projectile\n" ..
    "- Stepping into lava or fire\n" ..
    "- Falling from a high place\n" ..
    "- Drowning underwater\n" ..
    "- Starving\n\n" ..
    "The main way of recovering health is by eating food and maintaining a " ..
    "healthy level of satiation. More information about hunger is covered " ..
    "in the 'Hunger' page. For now, try to keep your Satiation bar as full " ..
    "as possible by finding or cooking food and eating regularly so that " ..
    "your health can recover. Taking damage will hinder health recovery, so " ..
    "it is important to avoid or flee from danger if your health is low.\n\n" ..
    "If your health reaches zero at any point, you die. " ..
    "When you die, you keep all your items and stats, but you lose " ..
    "some experience points. If you slept in a bed previously and the bed " ..
    "is still there, you respawn near that bed. Otherwise, you respawn " ..
    "at the world's spawn point. There is no limit to how many times you " ..
    "can respawn.\n\n" ..
    "You can increase your maximum health by leveling up and increasing " ..
    "your stats. More information on doing so is located in the 'Experience " ..
    "and Leveling Up' page. Increasing your maximum health will allow you " ..
    "to withstand more damage at once. Falling damage and drowning damage " ..
    "scale based on your maximum health, however."
)
    
doc.add_entry("yams_doc:basics_category", "yams_doc:health_damage", {
    name = S("Health and Damage"),
    data = health_text,
})

local hunger_text = S("The orange bar above the inventory hotbar is the " ..
    "Satiation bar, which represents how full you are.\n\n" ..
    "Satiation decreases over time, and it depletes faster if you are " ..
    "moving and digging. Eating food recovers satiation and prevents you " ..
    "from becoming too hungry.\n\n" ..
    "Some common methods of obtaining food include:\n" ..
    "- Picking fruit from trees\n" ..
    "- Gathering berries from bushes\n" ..
    "- Slaying animals and gathering their meat\n" ..
    "- Making a farm and growing food\n\n" ..
    "Certain types of food can be cooked in a furnace to increase the " ..
    "amount of satiation recovered, and there are many crafting recipes that " ..
    "can be used to make even better food. In addition to recovering " ..
    "satiation, some types of food may bestow additional effects when " ..
    "eaten. Normally, food cannot be eaten when you are completely full, " ..
    "but if you want to eat the food anyway, hold down the sneak button " ..
    "while attempting to eat it.\n\n" ..
    "If satiation is 5 or above, health recovers every few seconds as long " ..
    "as damage is not being received. The amount of health restored scales " ..
    "to your maximum health. Every time your health recovers naturally, " ..
    "your satiation decreases by 1.\n\n" ..
    "While satiation is below 5, health will not recover naturally. If " ..
    "satiation depletes completely, you will start taking damage over time " ..
    "until you eat some food or you die. Keep an eye on the Satiation bar " ..
    "and make sure to maintain your satiation, especially if your health " ..
    "is low and needs to recover.\n\n" ..
    "If you need to remain idle for an extended period of time, your " ..
    "satiation will not go below 4 as long as you do not move.\n\n" ..
    "The maximum level of satiation is 30, and it cannot be increased."
)

doc.add_entry("yams_doc:basics_category", "yams_doc:hunger", {
    name = S("Hunger"),
    data = hunger_text,
})

local sprinting_text = S("The green bar above the inventory hotbar is the " ..
    "Stamina bar, which represents how much energy you have for " ..
    "sprinting.\n\n" ..
    "Hold down the Aux1 button while moving forward in order to sprint. " ..
    "Sprinting cannot be performed while moving backward or sideways.\n\n" ..
    "While sprinting, you move faster and jump farther, but your stamina " ..
    "will also decrease over time. Let go of the Aux1 button or stop moving " ..
    "forward in order to stop sprinting.\n\n" ..
    "You will also stop sprinting once your stamina reaches 0. Stamina will " ..
    "recover over time, and the rate that stamina recovers scales to your " ..
    "maximum stamina. While your stamina is below 10, you cannot sprint. " ..
    "Sprinting will also deplete your satiation more quickly.\n\n" ..
    "You can increase your maximum stamina by increasing your Strength " ..
    "stat. Increasing your Dexterity stat also helps because the speed at " ..
    "which you sprint is based on your base movement speed. " ..
    "More information on increasing these stats is covered in the " ..
    "'Experience and Leveling Up' page.\n\n"
)

doc.add_entry("yams_doc:basics_category", "yams_doc:sprinting", {
    name = S("Sprinting"),
    data = sprinting_text,
})

local mobs_basic_text = S("While exploring the world, you may encounter " ..
    "creatures roaming around. These creatures are known as mobs.\n\n" ..
    "There are many types of mobs that can be encountered, and each type " ..
    "of mob behaves differently. Some mobs are hostile to players and " ..
    "will attack you when they are nearby, while other mobs are passive " ..
    "and will not react to nearby players unless attacked. Mobs that are " ..
    "generally hostile to players are known as monsters.\n\n" ..
    "Mobs gradually appear over time. This process is known as spawning. " ..
    "Many mobs only spawn within specific areas, during daytime or " ..
    "nighttime, or within bright or dark areas. Generally, monsters tend " ..
    "to spawn at night or within dark caves, while passive mobs such as " ..
    "cows and sheep tend to spawn on the surface during the day. Knowledge " ..
    "about how mobs spawn can be used to your advantage. In particular, " ..
    "sources of light, such as torches, can be used to prevent monsters " ..
    "from spawning by brightening the surrounding area.\n\n" ..
    "Mobs can be attacked by players using tools such as swords. Like " ..
    "players, mobs have a certain amount of health. When a mob is damaged, " ..
    "a health bar appears above it that shows how much health it has " ..
    "remaining. Stronger weapons will deal more damage to mobs than weaker " ..
    "ones. When a mob is defeated, every nearby player that dealt damage to " ..
    "the mob will gain experience points, and that mob may drop items that " ..
    "can be picked up. Mobs that are more difficult to defeat generally " ..
    "give more rewards.\n\n" ..
    "Many mobs, including monsters, will fight back. Mobs will damage the " ..
    "player if they get close enough while attacking, and some mobs may " ..
    "also fight using projectiles such as arrows. Despite the danger, " ..
    "defeating monsters is the primary way of gaining experience points. " ..
    "More information on experience points can be found in the 'Experience " ..
    "and Leveling Up' page. Note that passive mobs give a minimal amount " ..
    "of experience points.\n\n" ..
    "There are many passive mobs that the player can interact with. These " ..
    "mobs can be examined by right-clicking on them while sneaking. " ..
    "Examining a mob will display a description of it within the chat " ..
    "message area. Some items, such as food, can be used on passive mobs."
)

doc.add_entry("yams_doc:basics_category", "yams_doc:mobs_basic", {
    name = S("Encountering Mobs"),
    data = mobs_basic_text,
})

local exp_text = S("The lower-left corner of the screen displays your " ..
    "current level and your progress towards the next level.\n\n" ..
    "New players start at level 0. In order to level up, you need to earn " ..
    "experience points, or EXP. The main way of earning EXP is by defeating " ..
    "monsters, but there are other methods of gaining EXP. In particular, " ..
    "mining ores and chopping wood will also reward EXP.\n\n" ..
    "As you earn EXP, the percentage next to your current level will " ..
    "increase, and when it reaches 100%, you level up and gain a stat " ..
    "point. Stat points can be used to increase the four stats: " ..
    "Strength, Dexterity, Intelligence, and Constitution.\n\n" ..
    "Here is a short description of each stat:\n" ..
    "- Strength: mainly used in melee combat\n" ..
    "- Dexterity: mainly used in non-magical ranged combat\n" ..
    "- Intelligence: mainly used when utilizing magical weapons\n" ..
    "- Constitution: helps with the player's durability\n\n" ..
    "More details on each stat can be found within the pages located in " ..
    "the 'Combat' category.\n\n" ..
    "In order to spend stat points, open the inventory and click on the " ..
    "Level Up tab, then click the Upgrade button next to the stat that " ..
    "you want to increase. Increasing your stats will grant bonuses " ..
    "such as increased weapon damage and higher maximum health. These " ..
    "bonuses are listed next to each stat. Note that spending all your stat " ..
    "points on increasing the same stat has diminishing returns with each " ..
    "stat point spent.\n\n" ..
    "The amount of EXP needed to reach the next level increases every time " ..
    "you level up, but EXP earned from defeating monsters and mining ores " ..
    "scales based on how far you are from the world's surface. In other " ..
    "words, you will generally gain more EXP the deeper you go.\n\n" ..
    "When you die, you lose a percentage of your current progress towards " ..
    "the next level. This penalty is less severe at lower levels, and your " ..
    "level will never decrease no matter how many times you die."
)

doc.add_entry("yams_doc:basics_category", "yams_doc:exp", {
    name = S("Experience and Leveling Up"),
    data = exp_text,
})

local awards_text = S("Awards are achievements that can be earned by " ..
    "completing certain tasks. A list of awards included in yams can be " ..
    "found by clicking on the Awards tab within the inventory screen.\n\n" ..
    "Clicking on an award within the list will show the requirements for " ..
    "that award and your progress towards obtaining them.\n\n" ..
    "Some awards are hidden until other awards are achieved. Getting " ..
    "easier awards may reveal more difficult versions of those awards.\n\n" ..
    "A few awards are marked as secret, which means that the conditions " ..
    "for receiving them are hidden from players. Figuring out how to obtain " ..
    "a secret award is part of the challenge.\n\n" ..
    "Obtaining awards is optional, and there are no in-game rewards for " ..
    "doing so. Despite this, going after awards is a great way to learn " ..
    "more about yams. If you find yourself not knowing what to do, you " ..
    "can try obtaining as many awards as you can."
)

doc.add_entry("yams_doc:basics_category", "yams_doc:awards", {
    name = S("Awards"),
    data = awards_text,
})

doc.add_category("yams_doc:crafting_category", {
    name = S("Crafting and Inventory"),
    description = S("Covers crafting and inventory management."),
    build_formspec = doc.entry_builders.text,
    sorting = "custom",
    sorting_data = {"yams_doc:crafting_overview", "yams_doc:crafting_controls",
                    "yams_doc:craft_lookup", "yams_doc:bags"},
})

local crafting_overview_text = S("Crafting and inventory management in " ..
    "yams is similar to Minetest Game. This category covers a few features " ..
    "that yams adds to those aspects of the game, but the basics remain " ..
    "the same."
)

doc.add_entry("yams_doc:crafting_category", "yams_doc:crafting_overview", {
    name = S("Overview"),
    data = crafting_overview_text,
})

local inventory_controls_text = S("Luanti has many controls that makes it " ..
    "easier to manage inventories. The information on this page is taken " ..
    "from the Inventory page on the Luanti wiki, and this page serves as an " ..
    "in-game reference for that information. These controls are not " ..
    "exclusive to yams and will work with many other games.\n\n" ..
    "Note that the information in this section assumes that a keyboard and " ..
    "mouse are being used.\n\n" ..
    "Make sure to learn these controls, as inventory management is an " ..
    "important skill to have when playing yams.\n\n" ..
    "Remember that while viewing your inventory, items can be dropped into " ..
    "the world by clicking outside the inventory screen while the cursor is " ..
    "holding a stack of items.\n\n" ..
    "There are many ways to pick up a stack of items:\n" ..
    "- Left-clicking takes the entire stack\n" ..
    "- Right-clicking takes half of the stack, rounded up\n" ..
    "- Middle-clicking takes up to 10 items from the stack\n" ..
    "- Scrolling down on the mouse wheel while hovering over a stack takes " ..
    "one item from the stack\n\n" ..
    "Similarly, there are many ways to drop a stack into an item slot:\n" ..
    "- Left-clicking drops the entire stack\n" ..
    "- Right-clicking drops one item of the stack\n" ..
    "- Middle-clicking drops up to 10 items of the stack\n" ..
    "- Scrolling up on the mouse wheel drops one item of the stack\n\n" .. 
    "Additionally, an item stack can be dropped into multiple item slots in " ..
    "rapid succession by dragging a stack over those slots. The mouse " ..
    "button being held while dragging alters the behavior of this action:\n" ..
    "- The left mouse button splits the stack evenly between each slot\n" ..
    "- The right mouse button places one item in each slot\n" ..
    "- The middle mouse button places 10 items in each slot\n\n" ..
    "If there are multiple item slots with items of the same type, " ..
    "double-clicking any of those stacks while not holding anything will " ..
    "pick up all of those items at once. Up to a maximum of 99 items can " ..
    "be picked up this way. Alternatively, one can pick up an stack with " ..
    "the left mouse button and drag the cursor over any slots with the same " ..
    "type of item to add those items to the stack.\n\n" ..
    "When crafting an item, middle-clicking the output slot will craft the " ..
    "output 10 times. Moving the scroll wheel in either direction will also " ..
    "cause the output to be crafted.\n\n" ..
    "If holding Shift while clicking a mouse button on the output slot, the " ..
    "output is crafted a number of times depending on the mouse button " ..
    "being pressed:\n" ..
    "- Left-clicking crafts as many items as possible, up to 99\n" ..
    "- Right-clicking crafts the output once\n" ..
    "- Middle-clicking crafts the output 10 times\n" ..
    "- Scrolling the mouse wheel crafts the output once\n" ..
    "Using the Shift button to craft items this way also immediately places " ..
    "the result into an empty slot within your inventory if possible.\n\n" ..
    "When there are two different inventories on-screen, such as when " ..
    "managing a chest's inventory, holding Shift while clicking a stack " ..
    "will move that stack to the other inventory. This action can be " ..
    "combined with dragging to transfer multiple stacks between inventories " ..
    "quickly."
)

doc.add_entry("yams_doc:crafting_category", "yams_doc:crafting_controls", {
    name = S("Inventory Controls Reference"),
    data = inventory_controls_text,
})

local craft_lookup_text = S("The Craft Lookup tab within the inventory " ..
    "screen is the recipe database of yams.\n\n" ..
    "In order to see the recipes associated with a particular item, that " ..
    "item must be discovered first. To discover an item, either move it " ..
    "into your inventory, craft that item, or punch that item within the " ..
    "world. Make sure to discover as many items as possible.\n\n" ..
    "To view recipes associated with an item, first click that item in " ..
    "the bottom half of the screen. The < and > buttons on the " ..
    "bottom-right are used to change pages. There is a search box on the " ..
    "bottom-left that can be used to find a specific item, and the " ..
    "drop-down menu next to it can be used to narrow the search results. " ..
    "The 'Inventory' option within the drop-down menu, in particular, is " ..
    "used to only show items that are within your main inventory. " ..
    "Click the ? button to search for items, and click the X button to " ..
    "reset the search results and show every discovered item again.\n\n" ..
    "After clicking an item, one of the recipes associated with that item " ..
    "will be shown in the top half of the screen. The < and > buttons on " ..
    "the right can be used to browse through the other recipes.\n\n" ..
    "Many recipes are marked as 'recommended.' Recommended items can " ..
    "be essential for progressing through yams. If you are unsure about " ..
    "what to craft next, try crafting those items.\n\n" ..
    "On the top-left of the screen, either the text 'as result' or 'as " ..
    "ingredient' is shown next to the selected item's name. If 'as result' " ..
    "is shown, then the recipes shown will result in the selected item. " ..
    "If 'as ingredient' is shown, then the recipes shown use the selected " ..
    "item as an ingredient in order to make other items. To toggle " ..
    "between the two modes, click the selected item's image at the top-left " ..
    "of the screen.\n\n" ..
    "If an item within the shown recipe has already been discovered, " ..
    "clicking on it will show recipes that result in that item. Clicking " ..
    "on an output item which has been discovered already will show recipes " ..
    "that use that item. This can be helpful for figuring out the " ..
    "relationships between different items and recipes.\n\n" ..
    "Any undiscovered items within recipes are shown as an outline. Viewing " ..
    "recipes for those items by clicking on them is not possible.\n\n" ..
    "Some recipes have items with a 'G' on top of it. This means that any " ..
    "item belonging to the same group can be used to craft the output item. " ..
    "One common example is that many recipes that use wooden planks can use " ..
    "any type of wooden plank. Clicking on an item with a 'G' on top of it " ..
    "will display all discovered items that are part of the same group on " ..
    "the bottom half of the screen.\n\n" ..
    "A yellow number on top of an item indicates how many undiscovered " ..
    "items can be crafted using that item."
)

doc.add_entry("yams_doc:crafting_category", "yams_doc:craft_lookup", {
    name = S("Craft Lookup"),
    data = craft_lookup_text,
})

local bags_text = S("Bags are items that provide more inventory slots. " ..
    "They are equipped within the Bags tab on the inventory screen.\n\n" ..
    "Bags are obtained by crafting them. There are four bag sizes, and " ..
    "larger bags add more inventory slots than smaller ones. Bags can " ..
    "be upgraded by using a small bag together with some materials to " ..
    "craft a larger one.\n\n" ..
    "To equip a bag, go to the Bags tab and place a bag within any of " ..
    "the four slots on the right. The additional inventory slots can be " ..
    "accessed by clicking the button to the left of any slot with a bag " ..
    "in it. To go back to the previous screen, click the Main button on " ..
    "the bottom-right corner.\n\n" ..
    "In order to remove a bag from its slot or replace it with another " ..
    "bag, the inventory slots associated with that bag must be empty. If " ..
    "you cannot remove or replace a bag, make sure to check its inventory " ..
    "for any items within it.\n\n" ..
    "Since yams contains many types of useful items, having space to " ..
    "store all these items so that they can be used while exploring is " ..
    "important. It is recommended to make crafting bags a priority."
)

doc.add_entry("yams_doc:crafting_category", "yams_doc:bags", {
    name = S("Bags"),
    data = bags_text,
})

doc.add_category("yams_doc:combat_category", {
    name = S("Combat"),
    description = S("Covers information about combat."),
    build_formspec = doc.entry_builders.text,
    sorting = "custom",
    sorting_data = {"yams_doc:combat_overview", "yams_doc:armor",
                    "yams_doc:mana", "yams_doc:using_weapons",
                    "yams_doc:weapon_damage", "yams_doc:weapon_properties",
                    "yams_doc:elemental_damage"},
})

local combat_overview_text = S("The combat mechanics within yams are " ..
    "inspired by RPG games, and there are more factors to consider when " ..
    "fighting mobs. This category goes in-depth into the details of this " ..
    "game's combat. Knowledge of these details is essential, so take the " ..
    "time to read these help pages carefully."
)

doc.add_entry("yams_doc:combat_category", "yams_doc:combat_overview", {
    name = S("Overview"),
    data = combat_overview_text,
})

local armor_text = S("Armor reduces the damage that players take from " ..
    "combat against mobs.\n\n" ..
    "Pieces of armor can be obtained by crafting them. Obtained armor " ..
    "can be equipped within the Armor tab on the inventory screen. Place " ..
    "armor within any of the six slots on the left side.\n\n" ..
    "There are five different pieces of armor: helmets, chestplates, " ..
    "leggings, boots, and shields. All five pieces of armor can be worn " ..
    "at the same time, but two of the same type of armor piece cannot " ..
    "be equipped simultaneously.\n\n" ..
    "Except for shields, each piece of armor has a protection value, which " ..
    "is shown on its tooltip. This value is the percentage that damage is "..
    "reduced by while the piece of armor is being worn, and the protection " ..
    "values of all equipped armor are added together to form the total " ..
    "percentage of damage reduction. This value stacks multiplicatively " ..
    "with other forms of damage reduction, including the damage reduction " ..
    "bonus granted from increasing the Constitution stat.\n\n" ..
    "Shields work differently from other pieces of armor. Instead of " ..
    "reducing damage, shields give players the ability to occasionally " ..
    "block a monster's attack. Blocking attempts occur automatically when " ..
    "receiving combat damage. When an attack is blocked, no damage is " ..
    "taken. The chance of a shield blocking an attack is shown on its " ..
    "tooltip. Increasing the Constitution stat provides a bonus to this " ..
    "chance, and this bonus is added to the shield's block chance. This " ..
    "bonus is ineffective if a shield is not equipped. Note that wearing " ..
    "a shield incurs a penalty to one's movement speed.\n\n" ..
    "When taking damage with armor equipped or when blocking an attack, " ..
    "all pieces of armor that are being worn will have their durability " ..
    "reduced. Armor pieces will break once their durability is reduced to " ..
    "zero. The total durability of currently equipped armor is shown by " ..
    "the gray Armor bar, which is above the Health bar. The Armor bar does " ..
    "not appear if no armor is equipped.\n\n" ..
    "Many types of materials can be used to make pieces of armor. Armor " ..
    "made from better materials provides more protection and lasts longer. " ..
    "There is no bonus for equipping a full set of armor that is made from " ..
    "the same type of material.\n\n" ..
    "It is important to note that armor only protects from damage taken " ..
    "from mobs. Armor does not protect against other sources of damage, " ..
    "including fall damage, drowning, and starvation. Additionally, if an " ..
    "attack is not blocked, incoming damage cannot be reduced below 1."
)

doc.add_entry("yams_doc:combat_category", "yams_doc:armor", {
    name = S("Armor"),
    data = armor_text,
})

local mana_text = S("Mana is a resource used by magical weapons and tools. " ..
    "The blue Mana bar above your inventory hotbar shows how much mana " ..
    "you currently have.\n\n" ..
    "Tools that use mana will show the amount of required mana within " ..
    "their tooltips. When the tool is used, your mana will decrease by the " ..
    "stated amount. If you do not have enough mana, nothing will happen " ..
    "when you try to use the tool.\n\n" ..
    "Mana is restored over time. After using a tool that consumes mana, " ..
    "there is a short delay before mana starts to regenerate. Continuing " ..
    "to use mana will postpone mana regeneration further.\n\n" ..
    "Some items, including certain types of food, can also restore mana. " ..
    "There are also status effects which affect the rate of mana " ..
    "regeneration.\n\n" ..
    "Increasing the Intelligence stat will increase the maximum amount of " ..
    "mana that you can have. The speed of mana regeneration also scales " ..
    "with one's maximum mana, so players with a higher Intelligence stat " ..
    "will be able to use magical weapons and tools more often.\n\n"
)

doc.add_entry("yams_doc:combat_category", "yams_doc:mana", {
    name = S("Mana"),
    data = mana_text,
})

local weapons_text = S("There are many types of weapons within yams that " ..
    "can be crafted, and knowing how to effectively use these weapons is " ..
    "essential to survival.\n\n" ..
    "If using a melee weapon, such as a sword, it is important to remember " ..
    "that repeatedly clicking to attack is an ineffective way of doing " ..
    "damage. Not only does attacking in that way deal less damage, it also " ..
    "does not knock the enemy back. Instead, after every attack, wait until " ..
    "your weapon stops moving back towards you, then strike again. Attacks " ..
    "performed this way deal the most damage and knock the enemy backwards. " ..
    "Better melee weapons allow players to attack more frequently in " ..
    "addition to doing more damage.\n\n" ..
    "Ranged weapons, such as a bow, do not require proper timing to " ..
    "use. Simply point at the target and fire the weapon with the Punch " ..
    "button. In normal circumstances, ranged weapons always knock the " ..
    "enemy back. There is a short delay before the weapon can be used " ..
    "again, and each ranged weapon has a different cooldown. Some ranged " ..
    "weapons require the correct type of ammo to use, and a stack of this " ..
    "ammo must be placed in the hotbar. Other ranged weapons require mana " ..
    "to use, and some magical weapons can deal splash damage.\n\n" ..
    "Choose your weapons wisely based on the current situation. It is " ..
    "recommended to have a melee weapon and a ranged weapon ready when " ..
    "exploring unsafe areas."
)

doc.add_entry("yams_doc:combat_category", "yams_doc:using_weapons", {
    name = S("Using Weapons"),
    data = weapons_text,
})

local weapon_damage_text = S("Weapons have various properties, but the most " ..
    "important ones to know are the base damage, the primary stat, and the " ..
    "secondary stat. These properties are related with each other.\n\n" ..
    "The base damage is the amount of damage that a weapon does before any " ..
    "bonuses or penalties are applied. If the player is level 0 and there " ..
    "are no other factors affecting the damage being dealt, then the base " ..
    "damage is the damage that the weapon will inflict on the target.\n\n" ..
    "The primary stat is the stat that has the most influence on how much "..
    "damage a weapon does. This stat can be Strength, Dexterity, or " ..
    "Intelligence. Some weapons have a secondary stat, which also " ..
    "influences how much damage a weapon does, but it has less of an effect " ..
    "compared to the primary stat. All weapons have a primary stat, but " ..
    "many weapons do not have a secondary stat.\n\n" ..
    "When using stat points to increase Strength, Dexterity, or " ..
    "Intelligence, the weapon damage bonus that corresponds with that stat " ..
    "increases. This bonus increases a weapon's base damage by the given " ..
    "percentage, which results in more damage done to mobs. These bonuses " ..
    "do not apply to every weapon, however. The bonuses only apply to " ..
    "a weapon if its primary or secondary stat is the same as the stat " ..
    "associated with the bonus.\n\n" ..
    "For example, imagine that a player increases Strength to 5 while " ..
    "leaving the rest of their stats at zero. Having Strength at 5 gives a " ..
    "weapon damage bonus of 50%, and that bonus is applied to swords since " ..
    "their primary stat is Strength. This bonus is not applied to a magic " ..
    "wand because Intelligence is its primary stat, and Intelligence " ..
    "remains at zero. As a result, a sword with a base damage of 8 will " ..
    "now do 12 damage, but a magic wand that has a base damage of 6 will " ..
    "still do 6 damage.\n\n" ..
    "If a weapon has both a primary and secondary stat, then the weapon " ..
    "damage bonuses of both stats are taken into account. The calculation " ..
    "is more complicated, but it is sufficient to know that the primary " ..
    "stat has more influence on the resulting damage than the secondary " ..
    "stat.\n\n" ..
    "Damage bonuses from stats stack multiplicatively with other factors " ..
    "that affect the damage a player does."
)

doc.add_entry("yams_doc:combat_category", "yams_doc:weapon_damage", {
    name = S("Weapon Damage and Stat Bonuses"),
    data = weapon_damage_text,
})

local weapon_props_text = S("Below is a list of properties that weapons may " ..
    "have. These properties are shown within a weapon's tooltip.\n\n" ..
    "- Mana cost: The amount of mana required to use the weapon\n" ..
    "- Base damage: The damage the weapon does excluding any other factors\n" ..
    "- Element: The types of damage done with the weapon\n" ..
    "- Knockback: How far the weapon knocks back enemies\n" ..
    "- Ammo needed: The type of ammo needed to use the weapon\n" ..
    "- Repair with: The item used to restore the weapon's durability " ..
    "within the crafting grid\n" ..
    "- Primary stat: The player stat which influences the weapon's damage " ..
    "the most\n" ..
    "- Secondary stat: The player stat which influences the weapon's damage " ..
    "to a lesser extent\n\n" ..
    "Additionally, some tools that can be used as weapons have a warning " ..
    "within their tooltip stating that they are less durable when used as " ..
    "a weapon. These tools include pickaxes and shovels. While these tools " ..
    "can be used to fight mobs as a last resort, they will wear out more " ..
    "quickly when used in that way.\n\n"
)

doc.add_entry("yams_doc:combat_category", "yams_doc:weapon_properties", {
    name = S("Weapon Properties"),
    data = weapon_props_text,
})

local elemental_damage_text = S("Elemental damage is an important game " ..
    "mechanic in yams that needs to be taken into account when fighting " ..
    "certain mobs.\n\n" ..
    "Every weapon in yams is either a physical weapon or a magical weapon. " ..
    "Weapons also have a natural element. The natural elements are fire, " ..
    "ice, electric, mese, light, dark, and neutral. The neutral element is " ..
    "used for ordinary damage. When a weapon hits an enemy, both its " ..
    "physical nature and its element are used when determining how much " ..
    "damage to inflict on the enemy.\n\n" ..
    "The types of damage that a weapon inflicts are shown next to the word " ..
    "'Element' within its tooltip.\n\n" ..
    "Many mobs have resistances and weaknesses against certain elements. " ..
    "A mob that is resistant against an element will take less damage from " ..
    "attacks of that element, and they may also resist being knocked back. " ..
    "A mob that is weak against an element will take more damage from that " ..
    "element, and they may also be knocked back further. Mobs may also " ..
    "be strong or weak against either physical or magical damage. " ..
    "Note that mobs rarely resist or are weak to neutral damage. " ..
    "All mobs of the same type have identical elemental properties.\n\n" ..
    "The degree to which mobs resist or are weak to a particular type of " ..
    "attack varies. Some mobs may receive double damage when hit with a " ..
    "weakness, while other mobs may have less severe weaknesses. " ..
    "On the other hand, if a mob receives an attack that it is resistant " ..
    "to, it usually takes less damage from the attack, but the exact amount " ..
    "of damage reduction can vary. Some resistances are so strong that " ..
    "the mob will take zero damage from the attack or even absorb it. If " ..
    "a mob absorbs an attack, it regains health based on the amount of " ..
    "damage absorbed.\n\n" ..
    "Since the physical nature and the element of an attack are taken into " ..
    "account at the same time, it is possible to hit both a weakness and " ..
    "a resistance simultaneously. If this happens, the severity of the " ..
    "weakness and the strength of the resistance are applied together. " ..
    "Damage bonuses and penalties related to elemental damage " ..
    "stack multiplicatively with each other and with other factors that " ..
    "influence the damage a player inflicts.\n\n" ..
    "When hitting a mob that is resistant to your attack, shield icons will " ..
    "appear. If the color of those icons is gray, then the mob took reduced " ..
    "damage. Diamond shields indicate that the mob took no damage at all, " ..
    "and pink shields indicate that the mob absorbed the attack and " ..
    "regained health.\n\n" ..
    "Explosions are a special case. Explosions deal physical damage, but " ..
    "half of their damage is treated as fire damage, while the other half " ..
    "is treated as neutral damage."
)

doc.add_entry("yams_doc:combat_category", "yams_doc:elemental_damage", {
    name = S("Elemental Damage"),
    data = elemental_damage_text,
})

local status_effects_text = S("Status effects are temporary effects that " ..
    "can benefit or hinder players.\n\n" ..
    "Positive status effects, also known as buffs, are usually gained from " ..
    "items such as food. Negative status effects are usually received from " ..
    "enemy attacks. Those effects are also known as debuffs.\n\n" ..
    "Items that bestow status effects will have descriptions of those " ..
    "effects in their tooltips.\n\n" ..
    "Any status effects that are currently affecting you are shown on the " ..
    "right side of the screen. Status effects last for a limited amount " ..
    "of time, and the amount of time left is shown next to each status " ..
    "effect. Once the timer for a status effect expires, that effect is " ..
    "removed. There are also items that instantly remove status effects " ..
    "when used.\n\n" ..
    "Each status effect does something different. For more details on any " ..
    "status effects that you have seen before, consult the help pages " ..
    "within the 'Status Effects' category.\n\n" ..
    "Some status effects conflict with each other. If you gain a status " ..
    "effect that conflicts with one you already have, the newer effect " ..
    "replaces the older one. In particular, status effects that affect the " ..
    "same property, such as Attack Up and Attack Down, will override each " ..
    "other. Status effects that have the same base effect but different " ..
    "degrees of strength, such as Attack Up S and Attack Up M, will " ..
    "override each other as well. The strength of the effect that is " ..
    "currently active does not matter, so be careful not to accidentally " ..
    "replace a stronger effect with a weaker one.\n\n" ..
    "All status effects are removed when you die."
)

doc.add_entry("yams_doc:combat_category", "yams_doc:status_effects", {
    name = S("Status Effects"),
    data = status_effects_text,
})

local function unlock_world_info_page(dtime)
    local cat_name = "yams_doc:world_info_category"

    for _, player in ipairs(core.get_connected_players()) do
        local y = player:get_pos().y

        local page = nil
        local msg = nil

        if y < -20000 then
            page = "yams_doc:nether"
            msg = S("Help page unlocked: Nether")
        elseif y > 1024 then
            page = "yams_doc:cloudlands"
            msg = S("Help page unlocked: Cloudlands")
        end

        if page then
            local pname = player:get_player_name()

            if not doc.entry_revealed(pname, cat_name, page) then
                doc.mark_entry_as_revealed(pname, cat_name, page)

                msg = core.colorize('#00ffff', msg)
                core.chat_send_player(pname, msg)
            end
        end
    end
end

core.register_globalstep(unlock_world_info_page)

doc.add_category("yams_doc:world_info_category", {
    name = S("World Information"),
    description = S("Covers the various parts of the world."),
    build_formspec = doc.entry_builders.text,
    sorting = "custom",
    sorting_data = {"yams_doc:world_info_overview", "yams_doc:overworld",
                    "yams_doc:underground", "yams_doc:nether",
                    "yams_doc:cloudlands"},
    hide_entries_by_default = true,
})

local location_overview_text = S("A world created by this game will consist " ..
    "of several distinct layers that players can explore. This category " ..
    "provides some information about each part of the world.\n\n" ..
    "Help pages for certain areas are initially hidden, and they will " ..
    "be revealed once those areas are visited for the first time."
)

doc.add_entry("yams_doc:world_info_category", "yams_doc:world_info_overview", {
    name = S("Overview"),
    hidden = false,
    data = location_overview_text,
})

local overworld_text = S("The surface of the world is known as the " ..
    "Overworld. It is where players begin their journey.\n\n" ..
    "There are many biomes within the Overworld, including snowy tundras, " ..
    "dense rainforests, dry deserts, open grasslands, and vast oceans. " ..
    "Each biome has its own characteristics, and many blocks, plants, and " ..
    "mobs can only be found in certain biomes.\n\n" ..
    "The Overworld is tame during the day. Most passive mobs, including " ..
    "animals such as cows and sheep, spawn during the day. At night, " ..
    "however, the Overworld can be dangerous for unleveled players since " ..
    "monsters spawn within the darkness. Placing some torches to prevent " ..
    "monsters from spawning during the night is the primary way of keeping " ..
    "areas safe at night."
)

doc.add_entry("yams_doc:world_info_category", "yams_doc:overworld", {
    name = S("Overworld"),
    hidden = false,
    data = overworld_text,
})

local underground_text = S("Below the world's surface is a network of " ..
    "underground caves.\n\n" ..
    "It is suggested that players are at least level 1 before exploring " ..
    "the caves for the first time. Being familiar with the basics of " ..
    "combat is essential.\n\n" ..
    "Exploring the caves is the best way of obtaining plenty of ores. " ..
    "Better ores can be found the deeper you go. EXP is gained for mining " ..
    "ores, and the amount of EXP gained for doing so increases the deeper " ..
    "the ores are.\n\n" ..
    "Cave exploration is not without its dangers, however. Many monsters " ..
    "spawn underground within the darkness, and they can pose a threat to " ..
    "unprepared players. Like in the Overworld, lighting up the area will " ..
    "prevent monsters from spawning, so it is recommended to place torches " ..
    "while exploring the caves.\n\n" ..
    "Monsters become tougher the deeper you go, and some types of monsters " ..
    "only start appearing at certain depths. On the other hand, tougher " ..
    "monsters give more EXP and items when defeated.\n\n" ..
    "Dying by losing one's footing and falling too far is also a " ..
    "possibility. There are many tools that make traversing steep drops " ..
    "easier and safer, so try to utilize them as you explore the caves.\n\n" ..
    "While exploring the caves, you may find structures covered in mossy " ..
    "cobblestone. These structures are known as dungeons, and they house " ..
    "many monsters, but there is also a chance that treasure can be found " ..
    "within them.\n\n" ..
    "Deeper within the caves are vast caverns. Be careful if you think " ..
    "that you are entering one of these caverns. Preventing monsters from " ..
    "spawning in these areas is difficult because of how large these " ..
    "areas are, so it is very easy to become overwhelmed if one is not " ..
    "careful."
)

doc.add_entry("yams_doc:world_info_category", "yams_doc:underground", {
    name = S("Underground"),
    hidden = false,
    data = underground_text,
})

local nether_text = S("Note: this area is still being developed. Future " ..
    "updates may change this area significantly.\n\n" ..
    "The Nether is a realm of darkness that is accessed by going through " ..
    "a dark portal that was constructed according to the instructions " ..
    "within the Book of Portals.\n\n" ..
    "It is recommended that players are at least level 20 and have at least " ..
    "50% damage reduction before exploring the Nether.\n\n" ..
    "Within the Nether are dangerous monsters and oceans of lava. Unlike " ..
    "many other areas, light does not prevent monsters from spawning in " ..
    "the Nether. Monsters become stronger as players venture deeper " ..
    "into the Nether, but they will give more EXP too.\n\n" ..
    "With great danger comes great rewards. Monsters within the Nether give " ..
    "plenty of EXP, and there are some valuable items that can only be " ..
    "found within the Nether.\n\n" ..
    "As the Book of Portals implies, traveling 10 meters within the Nether " ..
    "then exiting through a different portal is roughly equivalent to " ..
    "traveling 80 meters within the Overworld. This can be used to travel " ..
    "great distances more quickly."
)

doc.add_entry("yams_doc:world_info_category", "yams_doc:nether", {
    name = S("Nether"),
    data = nether_text,
})

local cloudlands_text = S("Note: this area is still being developed. Future " ..
    "updates may change this area significantly.\n\n" ..
    "The Cloudlands is a realm of floating islands and landmasses high " ..
    "above the Overworld. The primary way of accessing this realms is by " ..
    "going through a blue portal that was constructed according to the " ..
    "instructions within the Book of Portals.\n\n" ..
    "It is recommended that players are at least level 25 and have at least " ..
    "50% damage reduction before exploring the Cloudlands.\n\n" ..
    "Many monsters that spawn within the Overworld will spawn within the " ..
    "Cloudlands as well, but they will be much tougher. As players ascend " ..
    "further, the monsters will become stronger and give more EXP.\n\n" ..
    "Some items can only be found within the Cloudlands."
)

doc.add_entry("yams_doc:world_info_category", "yams_doc:cloudlands", {
    name = S("Cloudlands"),
    data = cloudlands_text,
})

-- Mapping of status effects to the help pages they are associated with
local effect_mapping = {
    ["yams_effects:ailment_ward"] = "yams_doc:ailment_ward",
    ["yams_effects:attack_up_small"] = "yams_doc:attack_change",
    ["yams_effects:attack_up_medium"] = "yams_doc:attack_change",
    ["yams_effects:attack_up_large"] = "yams_doc:attack_change",
    ["yams_effects:attack_down_small"] = "yams_doc:attack_change",
    ["yams_effects:attack_down_medium"] = "yams_doc:attack_change",
    ["yams_effects:attack_down_large"] = "yams_doc:attack_change",
    ["yams_effects:defense_up_small"] = "yams_doc:defense_change",
    ["yams_effects:defense_up_medium"] = "yams_doc:defense_change",
    ["yams_effects:defense_up_large"] = "yams_doc:defense_change",
    ["yams_effects:defense_down_small"] = "yams_doc:defense_change",
    ["yams_effects:defense_down_medium"] = "yams_doc:defense_change",
    ["yams_effects:defense_down_large"] = "yams_doc:defense_change",
    ["yams_effects:health_regen_small"] = "yams_doc:health_regen",
    ["yams_effects:health_regen_medium"] = "yams_doc:health_regen",
    ["yams_effects:health_regen_large"] = "yams_doc:health_regen",
    ["yams_effects:high_jump_small"] = "yams_doc:high_jump",
    ["yams_effects:insight_small"] = "yams_doc:insight",
    ["yams_effects:insight_medium"] = "yams_doc:insight",
    ["yams_effects:insight_large"] = "yams_doc:insight",
    ["yams_effects:mana_regen_small"] = "yams_doc:mana_regen",
    ["yams_effects:mana_regen_medium"] = "yams_doc:mana_regen",
    ["yams_effects:mana_sap"] = "yams_doc:mana_sap",
    ["yams_effects:morale"] = "yams_doc:morale",
    ["yams_effects:plague"] = "yams_doc:plague",
    ["yams_effects:poison"] = "yams_doc:poison",
    ["yams_effects:poison_ward"] = "yams_doc:poison_ward",
    ["yams_effects:sap_ward"] = "yams_doc:sap_ward",
    ["yams_effects:speed_up_small"] = "yams_doc:speed_change",
    ["yams_effects:speed_up_medium"] = "yams_doc:speed_change",
    ["yams_effects:speed_up_large"] = "yams_doc:speed_change",
    ["yams_effects:speed_down_small"] = "yams_doc:speed_change",
    ["yams_effects:speed_down_medium"] = "yams_doc:speed_change",
    ["yams_effects:speed_down_large"] = "yams_doc:speed_change",
    ["yams_effects:stamina_regen_small"] = "yams_doc:stamina_regen",
    ["yams_effects:stamina_regen_medium"] = "yams_doc:stamina_regen",
    ["yams_effects:tough_skin"] = "yams_doc:tough_skin",
    ["yams_effects:well_fed_small"] = "yams_doc:well_fed",
    ["yams_effects:well_fed_medium"] = "yams_doc:well_fed",
    ["yams_effects:well_fed_large"] = "yams_doc:well_fed"
}

local function reveal_effect_impl(player, effect)
    if effect_mapping[effect] then
        local pname = player:get_player_name()
        local page = effect_mapping[effect]

        if not doc.entry_revealed(pname, "yams_doc:statuses_category", page) then
            doc.mark_entry_as_revealed(pname, "yams_doc:statuses_category", page)

            local def = doc.get_entry_definition("yams_doc:statuses_category", page)
            local msg = S("Help page revealed: @1", def.name)
            msg = core.colorize("#00ffff", msg)

            core.chat_send_player(pname, msg)
        end
    else
        core.log("warning", effect .. " has no help page")
    end
end

yams.register_on_player_status_effect(reveal_effect_impl)

doc.add_category("yams_doc:statuses_category", {
    name = S("Status Effects"),
    description = S("Covers status effects that have been discovered."),
    build_formspec = doc.entry_builders.text,
    sorting = "custom",
    sorting_data = {"yams_doc:statuses_overview", "yams_doc:ailment_ward",
                    "yams_doc:attack_change", "yams_doc:defense_change",
                    "yams_doc:health_regen", "yams_doc:high_jump",
                    "yams_doc:insight", "yams_doc:mana_regen",
                    "yams_doc:mana_sap", "yams_doc:morale", "yams_doc:plague",
                    "yams_doc:poison", "yams_doc:poison_ward",
                    "yams_doc:sap_ward", "yams_doc:speed_change",
                    "yams_doc:stamina_regen", "yams_doc:tough_skin",
                    "yams_doc:well_fed"},
    hide_entries_by_default = true,
})

local status_effects_overview_text = S("This category is a reference for " ..
    "every status effect in the game.\n\n" ..
    "Help pages for specific status effects will be unlocked when you " ..
    "receive those effects for the first time."
)

doc.add_entry("yams_doc:statuses_category", "yams_doc:statuses_overview", {
    name = S("Overview"),
    hidden = false,
    data = status_effects_overview_text,
})

local ailment_ward_text = S("Ailment Ward is a positive status effect that " ..
    "removes most negative status effects and protects against status " ..
    "effects from an enemy attack once.\n\n" ..
    "The effect is immediately removed once the player receives an attack " ..
    "that inflicts status effects. In exchange, every status effect that " ..
    "the attack would have inflicted is blocked. Attacks that do not " ..
    "inflict status effects do not remove the Ailment Ward effect.\n\n" ..
    "Like all status effects, the Ailment Ward effect can also expire " ..
    "naturally.\n\n" ..
    "Ailment Ward and other status effects that ward off negative effects, " ..
    "such as Poison Ward, can be active at the same time. When receiving " ..
    "negative status effects, Ailment Ward is removed only if at least " ..
    "one negative effect has not already been blocked by a different " ..
    "effect.\n\n" ..
    "Ailment Ward does not protect against negative status effects obtained " ..
    "from using certain items.\n\n"
)

doc.add_entry("yams_doc:statuses_category", "yams_doc:ailment_ward", {
    name = S("Ailment Ward"),
    data = ailment_ward_text,
})

local attack_status_text = S("The Attack Up status effect increases the " ..
    "amount of damage players deal to enemies, while the Attack Down " ..
    "status effect decreases the amount of damage dealt instead.\n\n" ..
    "Attack Up is a positive status effect, while Attack Down is a negative " ..
    "status effect.\n\n" ..
    "Both Attack Up and Attack Down have three tiers of strength: small " ..
    "(S), medium (M), and large (L). Higher tiers increase or decrease " ..
    "the amount of damage dealt by a higher amount.\n\n" ..
    "The exact values for each tier are listed below:\n" ..
    "- Small (S): 10% change\n" ..
    "- Medium (M): 25% change\n" ..
    "- Large (L): 50% change\n\n" ..
    "These status effects stack multiplicatively with other factors that " ..
    "modify a player's damage, including elemental resistances and weapon " ..
    "damage bonuses gained from one's stats.\n\n" ..
    "Attack Up and Attack Down conflict with each other, and both effects " ..
    "cannot be active at the same time. Two or more of the same effect, " ..
    "such as Attack Up S and Attack Up M, cannot be active at the same " ..
    "time as well. If a new effect that affects the player's damage " ..
    "is received while the player already has another one, the newer " ..
    "effect will replace the older one. The tier of the older effect " ..
    "does not matter."
)

doc.add_entry("yams_doc:statuses_category", "yams_doc:attack_change", {
    name = S("Attack Up / Down"),
    data = attack_status_text,
})

local defense_status_text = S("The Defense Up status effect decreases the " ..
    "amount of damage that players take from enemies, while the Defense " ..
    "Down status effect increases the amount of damage taken instead.\n\n" ..
    "Defense Up is a positive status effect, while Defense Down is a " ..
    "negative status effect.\n\n" ..
    "Both Defense Up and Defense Down have three tiers of strength: " ..
    "small (S), medium (M), and large (L). Higher tiers decrease or " ..
    "increase the amount of damage taken by a higher amount.\n\n" ..
    "The exact values for each tier are listed below:\n" ..
    "- Small (S): 10% change\n" ..
    "- Medium (M): 25% change\n" ..
    "- Large (L): 50% change\n\n" ..
    "These status effects stack multiplicatively with other factors that " ..
    "affect the amount of damage a player takes, including damage reduction " ..
    "from armor and the Constitution stat.\n\n" ..
    "Defense Up and Defense Down conflict with each other, and both effects " ..
    "cannot be active at the same time. Two or more of the same effect, " ..
    "such as Defense Up S and Defense Up M, cannot be active at the same " ..
    "time as well. If a new effect that affects the amount of damage a " ..
    "player takes is received while the player already has another one, " ..
    "the newer effect will replace the older one. The tier of the older " ..
    "effect does not matter.\n\n" ..
    "An exception to the above is that either Defense Up or Defense Down " ..
    "and the Tough Skin status effect can both be active simultaneously. " ..
    "The damage reduction from Tough Skin is applied after other modifiers " ..
    "that affect the amount of damage received, and the resulting damage " ..
    "cannot be reduced below 1.\n\n"
)

doc.add_entry("yams_doc:statuses_category", "yams_doc:defense_change", {
    name = S("Defense Up / Down"),
    data = defense_status_text,
})

local health_regen_text = S("Health Regen is a positive status effect that " ..
    "regenerates a player's health periodically.\n\n" ..
    "This status effect has three tiers of strength: small (S), medium (M), " ..
    "and large (L). Higher tiers restore health more often.\n\n" ..
    "The time interval values for each tier are listed below:\n" ..
    "- Small (S): every 10 seconds\n" ..
    "- Medium (M): every 5 seconds\n" ..
    "- Large (L): every 3 seconds\n\n" ..
    "The amount of health restored per interval is 10% of a player's " ..
    "maximum health. This restoration can occur alongside natural health " ..
    "recovery. Taking damage does not hinder health recovery from the " ..
    "Health Regen effect.\n\n" ..
    "Some status effects change the player's maximum health temporarily. " ..
    "The amount of health restored from Health Regen will change depending " ..
    "on what the player's maximum health is at the time.\n\n" ..
    "Only one Health Regen effect can be active on a player. If a new " ..
    "Health Regen effect is received, it will replace any existing Health " ..
    "Regen effect regardless of its tier.\n\n"
)

doc.add_entry("yams_doc:statuses_category", "yams_doc:health_regen", {
    name = S("Health Regen"),
    data = health_regen_text,
})

local high_jump_text = S("High Jump is a positive status effect that makes " ..
    "players jump higher.\n\n" ..
    "This status effect currently has only one tier of strength: small (S). " ..
    "Stronger versions of this effect will be added in future updates.\n\n" ..
    "The jump heights that each tier allows for are listed below:\n" ..
    "- Small (S): two blocks high\n\n" ..
    "Only one High Jump effect can be active on a player. If a new High " ..
    "Jump effect is received, it will replace any existing High Jump effect " ..
    "regardless of its tier.\n\n"
)

doc.add_entry("yams_doc:statuses_category", "yams_doc:high_jump", {
    name = S("High Jump"),
    data = high_jump_text,
})

local insight_text = S("Insight is a positive status effect that increases " ..
    "the amount of EXP that players earn from most sources.\n\n" ..
    "This status effect has three tiers of strength: small (S), medium (M), " ..
    "and large (L). Higher tiers increase the amount of EXP gained by a " ..
    "larger amount.\n\n" ..
    "The exact values for each tier are listed below:\n" ..
    "- Small (S): +25% more EXP\n" ..
    "- Medium (M): +50% more EXP\n" ..
    "- Large (L): +100% more EXP\n\n" ..
    "Insight stacks with other EXP gain bonuses additively.\n\n" ..
    "Only one Insight effect can be active on a player. If a new Insight " ..
    "effect is received, it will replace any existing Insight effect " ..
    "regardless of its tier. Insight and Well Fed can both be active at " ..
    "the same time."
)

doc.add_entry("yams_doc:statuses_category", "yams_doc:insight", {
    name = S("Insight"),
    data = insight_text,
})

local mana_regen_text = S("Mana Regen is a positive status effect that " ..
    "increases the speed of mana regeneration.\n\n" ..
    "This status effect has two tiers of strength: small (S) and medium " ..
    "(M). Higher tiers increase the speed of mana regeneration much more " ..
    "than lower tiers.\n\n" ..
    "The exact values for each tier are listed below:\n" ..
    "- Small (S): 50% faster\n" ..
    "- Medium (M): 100% faster\n\n" ..
    "This effect does not affect the delay that occurs after using a tool " ..
    "that consumes mana.\n\n" ..
    "Only one Mana Regen effect can be active on a player. If a new Mana " ..
    "Regen effect is received, it will replace any existing Mana Regen " ..
    "effect regardless of its tier.\n\n" ..
    "Mana Regen and Mana Sap conflict with each other. Receiving the Mana " ..
    "Sap effect will remove the Mana Regen effect, and applying the Mana " ..
    "Regen effect cures the Mana Sap effect."
)

doc.add_entry("yams_doc:statuses_category", "yams_doc:mana_regen", {
    name = S("Mana Regen"),
    data = mana_regen_text,
})

local mana_sap_text = S("Mana Sap is a negative status effect that slowly " ..
    "decreases a player's mana over time.\n\n" ..
    "Mana Sap and Mana Regen conflict with each other. Receiving the Mana " ..
    "Sap effect will remove the Mana Regen effect, and applying the Mana " ..
    "Regen effect cures the Mana Sap effect.\n\n" ..
    "The Sap Ward effect also cures Mana Sap, and it will block Mana Sap " ..
    "from being inflicted on the player once.\n\n" ..
    "After the Mana Sap effect expires or is removed, there is a short " ..
    "delay before mana starts regenerating again."
)

doc.add_entry("yams_doc:statuses_category", "yams_doc:mana_sap", {
    name = S("Mana Sap"),
    data = mana_sap_text,
})

local morale_text = S("Morale is a positive status effect that limits " ..
    "incoming combat damage from a single attack to 25% of a player's " ..
    "maximum health. \n\n" ..
    "Any combat damage that exceeds that limit is lowered to 25% of the " ..
    "player's maximum health, rounded up, before damaging the player.\n\n" ..
    "This damage limit is applied after other sources of damage reduction, " ..
    "including armor, the Constitution stat, and status effects such as " ..
    "Defense Up and Tough Skin.\n\n" ..
    "The Morale status effect allows players to survive extremely powerful " ..
    "attacks more easily, but it has no effect on weaker attacks, which " ..
    "may occur more frequently. It also only applies to combat damage. " ..
    "Other types of damage, such as fall damage, will still deal the full " ..
    "amount of damage to the player.\n\n" ..
    "Some status effects change the player's maximum health temporarily. " ..
    "The Morale status effect is always based on the player's original " ..
    "amount of maximum health, so temporary changes to a player's maximum " ..
    "health does not alter the maximum amount of damage that a player can " ..
    "take from a single attack while Morale is active.\n\n"
)

doc.add_entry("yams_doc:statuses_category", "yams_doc:morale", {
    name = S("Morale"),
    data = morale_text,
})

local plague_text = S("Plague is a negative status effect that temporarily " ..
    "reduces the player's maximum health.\n\n" ..
    "This status effect initially reduces a player's maximum health by 10%. " ..
    "Every time Plague is inflicted again while the player is already " ..
    "plagued, the player's maximum health is reduced by another 10%. This " ..
    "effect can stack multiple times, although the player's maximum health " ..
    "cannot be reduced below 1. This stacking is performed additively.\n\n" ..
    "When an attack that inflicts Plague hits a player, the player takes " ..
    "the damage first, then their maximum health is reduced. After the " ..
    "attack, if the player's health exceeds the new maximum value, it is " ..
    "lowered to that maximum. \n\n" ..
    "When a player is plagued, their health bar will be purple unless they " ..
    "are also poisoned at the same time.\n\n" ..
    "Once the Plague effect is removed, the player's maximum health will " ..
    "return to its normal value, and the number of stacks will reset. The " ..
    "player's current health will remain the same.\n\n" ..
    "Note that a player's natural health regeneration and some status " ..
    "effects scale based on the player's current amount of maximum health. " ..
    "Being plagued reduces the potency of these effects."
)

doc.add_entry("yams_doc:statuses_category", "yams_doc:plague", {
    name = S("Plague"),
    data = plague_text,
})

local poison_text = S("Poison is a negative status effect that damages the " ..
    "player periodically.\n\n" ..
    "The damage inflicted is equal to 5% of a player's maximum health, and " ..
    "this damage occurs every four seconds. Additionally, natural health " ..
    "regeneration does not occur while poisoned. Damage from poison cannot " ..
    "reduce the player's health below 1.\n\n" ..
    "Armor and other forms of damage reduction has no effect on damage " ..
    "from poison.\n\n" ..
    "When a player is poisoned, their health bar will be green.\n\n" ..
    "Some status effects change the player's maximum health temporarily. " ..
    "The Poison status effect is always based on the player's original " ..
    "amount of maximum health, so temporary changes to a player's maximum " ..
    "health does not change the amount of damage inflicted from being " ..
    "poisoned.\n\n" ..
    "The Poison Ward effect cures poison, and it will block Poison from " ..
    "being inflicted on the player once by an enemy attack."
)

doc.add_entry("yams_doc:statuses_category", "yams_doc:poison", {
    name = S("Poison"),
    data = poison_text,
})

local poison_ward_text = S("Poison Ward is a positive status effect that " ..
    "cures the Poison status effect and protects against poison from an " ..
    "enemy attack once.\n\n" ..
    "Poison Ward is immediately removed once the player receives a " ..
    "poisonous attack. In exchange, the player is protected from being " ..
    "poisoned by that attack. Attacks that do not poison the player do not " ..
    "remove the Poison Ward effect.\n\n" ..
    "Like all status effects, the Poison Ward effect can also expire " ..
    "naturally.\n\n" ..
    "Poison Ward and Ailment Ward can both be active at the same time. If " ..
    "a player receives a poisonous attack while both effects are active, " ..
    "the Poison Ward effect is removed, and the Ailment Ward effect " ..
    "remains on the player if that attack did not inflict additional " ..
    "status effects.\n\n" ..
    "Poison Ward does not protect against items that poison the player, " ..
    "including poisonous food, but the resulting poison can be cured " ..
    "afterwards."
)

doc.add_entry("yams_doc:statuses_category", "yams_doc:poison_ward", {
    name = S("Poison Ward"),
    data = poison_ward_text,
})

local sap_ward_text = S("Sap Ward is a positive status effect that cures " ..
    "the Mana Sap status effect and protects against Mana Sap from an enemy " ..
    "attack once.\n\n" ..
    "Sap Ward is immediately removed once the player receives an attack " ..
    "that inflicts Mana Sap. In exchange, the player is protected from " ..
    "receiving the Mana Sap status effect. Attacks that do not inflict " ..
    "Mana Sap do not remove the Sap Ward effect.\n\n" ..
    "Like all status effects, the Sap Ward effect can also expire " ..
    "naturally.\n\n" ..
    "Sap Ward and Ailment Ward can both be active at the same time. If a " ..
    "player receives an attack that inflicts Mana Sap while both effects " ..
    "are active, the Sap Ward effect is removed, and the Ailment Ward " ..
    "effect remains on the player if that attack did not inflict additional " ..
    "status effects.\n\n" ..
    "Sap Ward does not protect against items that inflict Mana Sap when " ..
    "used, but the resulting Mana Sap effect can be cured afterwards."
)

doc.add_entry("yams_doc:statuses_category", "yams_doc:sap_ward", {
    name = S("Sap Ward"),
    data = sap_ward_text,
})

local speed_status_text = S("The Speed Up status effect makes the player " ..
    "move faster, while the Speed Down status effect slows down the player " ..
    "instead.\n\n" ..
    "Speed Up is a positive status effect, while Speed Down is a negative " ..
    "status effect.\n\n" ..
    "Both Speed Up and Speed Down have three tiers of strength: small (S), " ..
    "medium (M), and large (L). Higher tiers change the player's movement " ..
    "speed by a greater amount.\n\n" ..
    "The exact values for each tier are listed below:\n" ..
    "- Small (S): 10% change\n" ..
    "- Medium (M): 25% change\n" ..
    "- Large (L): 50% change\n\n" ..
    "These status effects stack multiplicatively with other factors that " ..
    "affect a player's movement speed, including the Dexterity stat. It " ..
    "also affects the player's sprinting speed.\n\n" ..
    "Speed Up and Speed Down conflict with each other, and both effects " ..
    "cannot be active at the same time. Two or more of the same effect, " ..
    "such as Speed Up S and Speed Up M, cannot be active at the same time " ..
    "as well. If a new effect that affects the player's movement speed is " ..
    "received while the player already has another one, the newer effect " ..
    "will replace the older one. The tier of the older effect does not matter."
)

doc.add_entry("yams_doc:statuses_category", "yams_doc:speed_change", {
    name = S("Speed Up / Down"),
    data = speed_status_text,
})

local stamina_regen_text = S("Stamina Regen is a positive status effect " ..
    "that increases the speed of stamina regeneration.\n\n" ..
    "This status effect has two tiers of strength: small (S) and medium " ..
    "(M). Higher tiers increase the speed of stamina regeneration much more " ..
    "than lower tiers.\n\n" ..
    "The exact values for each tier are listed below:\n" ..
    "- Small (S): 50% faster\n" ..
    "- Medium (M): 100% faster\n\n" ..
    "Only one Stamina Regen effect can be active on a player. If a new " ..
    "Stamina Regen effect is received, it will replace any existing " ..
    "Stamina Regen effect regardless of its tier."
)

doc.add_entry("yams_doc:statuses_category", "yams_doc:stamina_regen", {
    name = S("Stamina Regen"),
    data = stamina_regen_text,
})

local tough_skin_text = S("Tough Skin is a positive status effect that " ..
    "reduces the damage of any incoming attacks by 1.\n\n" ..
    "This damage reduction is applied after any other sources of damage " ..
    "reduction, such as armor, the Constitution stat, and other status " ..
    "effects such as Defense Up.\n\n" ..
    "The resulting damage cannot be reduced below 1, and only combat damage " ..
    "is affected. Other sources of damage, such as fall damage, are " ..
    "unaffected by the Tough Skin effect.\n\n"
)

doc.add_entry("yams_doc:statuses_category", "yams_doc:tough_skin", {
    name = S("Tough Skin"),
    data = tough_skin_text,
})

local well_fed_text = S("Well Fed is a positive status effect that " ..
    "increases the amount of EXP that players earn from most sources.\n\n" ..
    "This status effect has three tiers of strength: small (S), medium (M), " ..
    "and large (L). Higher tiers increase the amount of EXP gained by a " ..
    "larger amount.\n\n" ..
    "The exact values for each tier are listed below:\n" ..
    "- Small (S): +10% more EXP\n" ..
    "- Medium (M): +25% more EXP\n" ..
    "- Large (L): +50% more EXP\n\n" ..
    "Well Fed stacks with other EXP gain bonuses additively.\n\n" ..
    "Only one Well Fed effect can be active on a player. If a new Well Fed " ..
    "effect is received, it will replace any existing Well Fed effect " ..
    "regardless of its tier. Well Fed and Insight can both be active at " ..
    "the same time."
)

doc.add_entry("yams_doc:statuses_category", "yams_doc:well_fed", {
    name = S("Well Fed"),
    data = well_fed_text,
})

-- Mapping of items to the help pages they are associated with
local item_mapping = {
    ["airtanks:breathing_tube"] = "yams_doc:airtanks",
    ["airtanks:bronze_tank"] = "yams_doc:airtanks",
    ["airtanks:bronze_tank_2"] = "yams_doc:airtanks",
    ["airtanks:bronze_tank_3"] = "yams_doc:airtanks",
    ["airtanks:compressor"] = "yams_doc:airtanks",
    ["airtanks:copper_tank"] = "yams_doc:airtanks",
    ["airtanks:copper_tank_2"] = "yams_doc:airtanks",
    ["airtanks:copper_tank_3"] = "yams_doc:airtanks",
    ["airtanks:empty_bronze_tank"] = "yams_doc:airtanks",
    ["airtanks:empty_bronze_tank_2"] = "yams_doc:airtanks",
    ["airtanks:empty_bronze_tank_3"] = "yams_doc:airtanks",
    ["airtanks:empty_copper_tank"] = "yams_doc:airtanks",
    ["airtanks:empty_copper_tank_2"] = "yams_doc:airtanks",
    ["airtanks:empty_copper_tank_3"] = "yams_doc:airtanks",
    ["airtanks:empty_steel_tank"] = "yams_doc:airtanks",
    ["airtanks:empty_steel_tank_2"] = "yams_doc:airtanks",
    ["airtanks:empty_steel_tank_3"] = "yams_doc:airtanks",
    ["airtanks:steel_tank"] = "yams_doc:airtanks",
    ["airtanks:steel_tank_2"] = "yams_doc:airtanks",
    ["airtanks:steel_tank_3"] = "yams_doc:airtanks",
    ["anvil:anvil"] = "yams_doc:anvil",
    ["anvil:hammer"] = "yams_doc:anvil",
    ["hopper:chute"] = "yams_doc:hoppers",
    ["hopper:hopper"] = "yams_doc:hoppers",
    ["hopper:hopper_side"] = "yams_doc:hoppers",
    ["hopper:sorter"] = "yams_doc:hoppers",
    ["screwdriver2:screwdriver"] = "yams_doc:screwdriver",
} 

local function reveal_item_page_impl(player, itemstack)
    local itemname = itemstack:get_name()

    if item_mapping[itemname] then
        local pname = player:get_player_name()
        local page = item_mapping[itemname]

        if not doc.entry_revealed(pname, "yams_doc:items_category", page) then
            doc.mark_entry_as_revealed(pname, "yams_doc:items_category", page)

            local def = doc.get_entry_definition("yams_doc:items_category", page)
            local msg = S("Help page revealed: @1", def.name)
            msg = core.colorize("#00ffff", msg)

            core.chat_send_player(pname, msg)
        end
    end
end

-- Reveal help pages for items when the player obtains them in some way
local function reveal_on_craft(itemstack, player, old_craft_grid, craft_inv)
    if player ~= nil then
        reveal_item_page_impl(player, itemstack)
    end

    return nil
end

core.register_on_craft(reveal_on_craft)

local function reveal_on_inv_put(player, action, inventory, inventory_info)
    if player ~= nil and action == "put" then
        reveal_item_page_impl(player, inventory_info.stack)
    end
end

core.register_on_player_inventory_action(reveal_on_inv_put)

doc.add_category("yams_doc:items_category", {
    name = S("Special Items"),
    description = S("Covers items that have special functionality."),
    build_formspec = doc.entry_builders.text,
    sorting = "custom",
    sorting_data = {
        "yams_doc:items_overview", "yams_doc:airtanks", "yams_doc:anvil",
        "yams_doc:hoppers", "yams_doc:screwdriver"
    },
    hide_entries_by_default = true,
})

local items_overview_text = S("This category contains information " ..
    "about certain items and tools that require more explanation.\n\n" ..
    "Help pages for those items will be unlocked when they are found or " ..
    "crafted."
)

doc.add_entry("yams_doc:items_category", "yams_doc:items_overview", {
    name = S("Overview"),
    hidden = false,
    data = items_overview_text,
})

local airtanks_text = S("Air tanks are used to restore your breath while " ..
    "underwater, allowing you to remain submerged for much longer without " ..
    "losing health.\n\n" ..
    "There are three types of air tanks that can be crafted: copper, " ..
    "bronze, and steel. Copper air tanks hold the least amount of air, " ..
    "while steel tanks hold the most. Multiple air tanks of the same type " ..
    "can be combined together to create a double or triple air tank with " ..
    "the corresponding amount of capacity.\n\n" ..
    "Crafted air tanks start out empty. To fill an air tank, an air " ..
    "compressor is required. Place the air compressor on a block, then " ..
    "interact with it using the Place key. Add fuel to the leftmost slot, " ..
    "then place the air tanks you want to fill within any of the 16 slots " ..
    "on the right. It takes some time and enough fuel for air tanks to fill " ..
    "completely.\n\n" ..
    "Air tanks can be used directly from the hotbar, but a breathing tube " ..
    "can be crafted and placed in the hotbar in order to automatically " ..
    "restore your breath when it becomes too low. For this to work, at " ..
    "least one air tank with some air must also be within the hotbar. Air " ..
    "tanks that are not within the hotbar cannot be used automatically.\n\n" ..
    "Air tanks lose some air every time they are used, and eventually they " ..
    "will become empty again."
)

doc.add_entry("yams_doc:items_category", "yams_doc:airtanks", {
    name = S("Air Tanks"),
    data = airtanks_text,
})

local anvil_text = S("The anvil is used to repair worn tools. To use the " ..
    "anvil, a steel hammer is required.\n\n" ..
    "To place a tool on the anvil, hold the tool and press the Place " ..
    "button while looking at the anvil. Once the tool has been placed on " ..
    "the anvil, hold the steel hammer and use it to strike the anvil. " ..
    "Continue striking the anvil until the tool has been fully repaired. " ..
    "To pick up the tool again, look at the anvil and either punch the " ..
    "anvil or press the Place button while your hand is empty.\n\n" ..
    "As you use the steel hammer, its durability will decrease. Tools made " ..
    "out of stronger materials, such as diamond and mithril, will wear out " ..
    "the hammer faster than tools made out of weaker materials.\n\n" ..
    "Some tools cannot be repaired using the anvil. This includes most " ..
    "tools that can be repaired by crafting. Additionally, steel hammers " ..
    "cannot be repaired.\n\n" ..
    "Anvils normally have an owner, and players can only use anvils that " ..
    "they own. The owner of an anvil is the player that placed the anvil. " ..
    "To craft a shared anvil, which is an anvil that can be used by " ..
    "any player, combine it with a piece of paper. To claim ownership of a " ..
    "shared anvil, place it in the crafting grid and pick up the resulting " ..
    "anvil.\n\n" ..
    "If needed, steel hammers can be used as weapons, and they can be used " ..
    "to mine stone and some types of ore."
)

doc.add_entry("yams_doc:items_category", "yams_doc:anvil", {
    name = S("Anvil and Hammer"),
    data = anvil_text,
})

local hopper_text = S("Some blocks, such as chests and furnaces, contain " ..
    "their own inventory slots. Hoppers can be used to move items between " ..
    "these types of blocks. Chutes allow the movement of items over longer " ..
    "distances, while sorters can redirect certain items to an alternate " ..
    "location.\n\n" ..
    "There are two types of hoppers: vertical hoppers and side hoppers.\n\n" ..
    "The normal type of hopper is the vertical hopper. Vertical hoppers " ..
    "take in items from above. If there is a chest or similar block above " ..
    "the hopper, then items will be taken from that block. Items can also " ..
    "be dropped directly into the hopper. Items that enter the hopper will " ..
    "be sent to the block below it. These items are sent through the " ..
    "narrow tube attached to the bottom of the hopper.\n\n" ..
    "Side hoppers work similarly to vertical hoppers. They take items from " ..
    "above, but they send items towards the side that the narrow tube is " ..
    "facing. The direction this tube faces depends on the side that " ..
    "the player is pointing at when placing the hopper.\n\n" ..
    "Both types of hoppers can be converted to the other type by placing " ..
    "the hopper in the crafting grid and taking out the result.\n\n" ..
    "Make sure to place blocks that should interact with a hopper in " ..
    "the correct positions. The block from which the hopper takes items " ..
    "must be placed above the hopper. The block that receives items " ..
    "from the hopper must be connected to the hopper's narrow tube.\n\n" ..
    "Hoppers have inventories that can be accessed by pressing the Place " ..
    "button while pointing at them. Normally, if a hopper cannot find a " ..
    "block to send items towards, it holds any items that it receives until " ..
    "it is able to send those items. This can also happen if the block " ..
    "which the hopper sends items towards is full or if the block cannot " ..
    "accept the items being received. While viewing a hopper's inventory, " ..
    "there is a button to the right that changes this behavior so that " ..
    "hoppers eject items instead of holding on to them. This behavior can " ..
    "be toggled.\n\n" ..
    "Transferring items into furnaces works differently compared to other " ..
    "blocks. If the hopper's narrow tube is attached to the furnace's top or " ..
    "bottom, then items are inserted into the slot where raw materials, " ..
    "such as ingots, are placed. On the other hand, hoppers that are " ..
    "attached to a side of the furnace insert items into the fuel slot.\n\n" ..
    "A hopper's inventory can be accessed by anyone regardless of who " ..
    "placed the hopper. Locked chests, however, can only interact with " ..
    "hoppers that are placed by the owner of those chests.\n\n" ..
    "Chutes are used to move items over longer distances. They can be used " ..
    "when there is some distance between the hopper and another block. " ..
    "Hoppers can connect to chutes, and many chutes can be placed in a " ..
    "row.\n\n" ..
    "Unlike hoppers, chutes cannot take items from adjacent blocks. Chutes " ..
    "need to receive items from a hopper first, although players can also " ..
    "place items in chutes manually. Items received by a chute are " ..
    "transferred in the direction that the chute's narrow tube is facing. " ..
    "The narrow tube has an arrow on it which shows the direction that " ..
    "items will be sent towards. The direction this tube faces depends on " ..
    "the side that the player is pointing at when placing the chute. " ..
    "Chutes behave similarly to hoppers when they cannot find a block to " ..
    "send items towards, and their inventories can also be accessed.\n\n" ..
    "Sorters are used to redirect certain items to an alternate location. " ..
    "Their behavior is similar to chutes, but they have two narrow tubes " ..
    "instead of one, and there is an arrow on the sorter that points to one " ..
    "of those tubes. Placing a sorter is similar to placing a chute.\n\n" ..
    "When viewing a sorter's inventory, there is a row of eight inventory " ..
    "slots with the word 'Filter' above it. If a sorter receives an item " ..
    "that matches any items in that row, the item gets sent through the " ..
    "narrow tube that the arrow on the sorter is pointing at. If the item " ..
    "does not match any of the items in the filter row, or if the block " ..
    "that the sorter is pointing towards cannot accept the item that is " ..
    "being given to it, it gets sent through the other narrow tube.\n\n" ..
    "To specify the items that a sorter should filter, place an item in " ..
    "the top row. The actual item will not be taken from you. If you do " ..
    "not want an item to be filtered anymore, simply remove the item from " ..
    "that row.\n\n" ..
    "Sorters have an alternate mode of operation that can be toggled by " ..
    "pressing the 'On' switch while viewing a sorter's inventory. In this " ..
    "mode, the types of items to be filtered cannot be specified. Instead, " ..
    "the sorter will attempt to send all items towards the narrow tube that " ..
    "the arrow on the sorter is pointing at. If it cannot do that for " ..
    "various reasons, such as the destination block being full, it will " ..
    "send items through the other narrow tube.\n\n" ..
    "The screwdriver can be used to rotate hoppers, chutes, and sorters " ..
    "after placing them.\n\n" ..
    "Hoppers, chutes, and sorters move items at a rate of one item per second."
)

doc.add_entry("yams_doc:items_category", "yams_doc:hoppers", {
    name = S("Hoppers"),
    data = hopper_text,
})

local screwdriver_text = S("The screwdriver is used to rotate certain " ..
    "blocks. Any blocks with a different appearance on one or more sides " ..
    "can be rotated. Some objects, such as hoppers, can also be rotated. " ..
    "There are two methods of rotation.\n\n" ..
    "Pressing the punch/dig button when pointing at a block will rotate the " ..
    "block by pushing the nearest edge away from you. This is based on the " ..
    "exact point on the block's face that you are pointing at. If you are " ..
    "pointing towards the left edge of the block, then the block will " ..
    "rotate to the left. Pointing towards the top edge will rotate the " ..
    "block away from you. Similar logic applies when pointing to the right " ..
    "and bottom edges of the block.\n\n" ..
    "When rotating a block in this way, the direction of rotation can be " ..
    "reversed by sneaking while doing so.\n\n" ..
    "Pressing the place/use button when pointing at a block will rotate the " ..
    "block clockwise around the face you are pointing at. The exact " ..
    "location on the block that you are pointing at does not matter.\n\n" ..
    "Some blocks, such as chests and furnaces, usually display a screen " ..
    "when pressing the place/use button. Holding the sneak button prevents " ..
    "this from happening and rotates the block instead."
)

doc.add_entry("yams_doc:items_category", "yams_doc:screwdriver", {
    name = S("Screwdriver"),
    data = screwdriver_text,
})
