diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 281ca6f74..c1e8c171c 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -63,6 +63,7 @@ Sxw1212 Taugeshtu tigerw (Tiger Wang) tonibm19 +TooAngel UltraCoderRU Warmist WebFreak001 diff --git a/Server/Plugins/APIDump/APIDesc.lua b/Server/Plugins/APIDump/APIDesc.lua index ab31ad6b2..a55c2cade 100644 --- a/Server/Plugins/APIDump/APIDesc.lua +++ b/Server/Plugins/APIDump/APIDesc.lua @@ -6345,6 +6345,23 @@ These ItemGrids are available in the API and can be manipulated by the plugins, }, Notes = "Adds the specified damage (1 by default) to the specified item. Removes the item and returns true if the item reached its max damage and was destroyed.", }, + FindItem = + { + Params = + { + { + Name = "RecipeItem", + Type = "cItem", + }, + }, + Returns = + { + { + Type = "cItem", + }, + }, + Notes = "Finds an item in the shield, hotbar and inventory slots matching `ItemType` and `ItemDamage`. The actual item is returned, if none is found `nullptr`. This can be used to validate that the player has a specific type of item.", + }, GetArmorGrid = { Returns = @@ -7496,6 +7513,23 @@ This class represents a 2D array of items. It is used as the underlying storage Notes = "Destroys the item in the specified slot", }, }, + FindItem = + { + Params = + { + { + Name = "RecipeItem", + Type = "cItem", + }, + }, + Returns = + { + { + Type = "cItem", + }, + }, + Notes = "Finds an item within the grid matching `ItemType` and `ItemDamage`. The actual item is returned, if none is found `nullptr`.", + }, GetFirstEmptySlot = { Returns = diff --git a/Server/Protocol/1.12.2/base.recipes.txt b/Server/Protocol/1.12.2/base.recipes.txt new file mode 100644 index 000000000..e5c52fa8b --- /dev/null +++ b/Server/Protocol/1.12.2/base.recipes.txt @@ -0,0 +1,434 @@ +# recipeId minecraftName + +11 yellow_wool +12 yellow_terracotta +13 yellow_stained_glass_pane +14 yellow_stained_glass +15 yellow_dye_from_sunflower +16 yellow_dye_from_dandelion +17 yellow_concrete_powder +18 yellow_carpet +19 yellow_bed_from_white_bed +20 yellow_bed +21 yellow_banner +22 writable_book +23 wooden_sword +24 wooden_shovel +25 wooden_pressure_plate +26 wooden_pickaxe +27 wooden_hoe +28 oak_door +29 oak_button +30 wooden_axe +31 white_terracotta +32 white_stained_glass_pane +33 white_stained_glass +34 white_concrete_powder +35 white_carpet +36 white_bed +37 white_banner +38 wheat +39 tripwire_hook +40 trapped_chest +41 oak_trapdoor +42 torch +43 tnt_minecart +44 tnt +45 sugar +46 white_wool_from_string +47 stone_bricks +48 stone_sword +49 stone_stairs +50 stone_slab +51 stone_shovel +52 stone_pressure_plate +53 stone_pickaxe +54 stone_hoe +55 stone_button +56 stone_brick_stairs +57 stone_brick_slab +58 stone_axe +59 sticky_piston +60 stick +61 spruce_stairs +62 spruce_slab +63 spruce_planks +64 spruce_fence_gate +65 spruce_fence +66 spruce_door +67 spruce_boat +68 spectral_arrow +69 glistering_melon_slice +70 snow +71 snow_block +72 smooth_sandstone +73 smooth_red_sandstone +74 slime_ball +75 slime_block +76 oak_sign +77 shield +78 shears +79 sea_lantern +80 sandstone_stairs +81 sandstone_slab +82 sandstone +83 repeater +84 redstone_torch +85 redstone_lamp +86 redstone_block +87 redstone +88 red_wool +89 red_terracotta +90 red_stained_glass_pane +91 red_stained_glass +92 red_sandstone_stairs +93 red_sandstone_slab +94 red_sandstone +95 red_nether_bricks +96 red_dye_from_tulip +97 red_dye_from_rose_bush +98 red_dye_from_poppy +99 red_dye_from_beetroot +100 red_concrete_powder +101 red_carpet +102 red_bed_from_white_bed +103 red_bed +104 red_banner +105 rail +106 rabbit_stew_from_red_mushroom +107 rabbit_stew_from_brown_mushroom +108 quartz_stairs +109 quartz_slab +110 quartz_block +111 purpur_stairs +112 purpur_slab +113 purpur_pillar +114 purpur_block +115 purple_wool +116 purple_terracotta +117 purple_stained_glass_pane +118 purple_stained_glass +119 purpur_shulker_box +120 purple_dye +121 purple_concrete_powder +122 purple_carpet +123 purple_bed_from_white_bed +124 purple_bed +125 purple_banner +126 pumpkin_seeds +127 pumpkin_pie +128 prismarine_bricks +129 prismarine +130 polished_granite +131 polished_diorite +132 polished_andesite +133 piston +134 pink_wool +135 pink_terracotta +136 pink_stained_glass_pane +137 pink_stained_glass +138 pink_dye_from_red_white_dye +139 pink_tulip +140 peony +141 pink_concrete_powder +142 pink_carpet +143 pink_bed_from_white_bed +144 pink_bed +145 pink_banner +146 quartz_pillar +147 paper +148 painting +149 orange_wool +150 orange_terracotta +151 orange_stained_glass_pane +152 orange_stained_glass +153 orange_dye_from_red_yellow +154 orange_dye_from_orange_tulip +155 orange_concrete_powder +156 orange_carpet +157 orange_bed_from_white_bed +158 orange_bed +159 orange_banner +160 observer +161 oak_stairs +162 oak_slab +163 oak_planks +164 note_block +165 nether_wart_block +166 nether_brick_stairs +167 nether_brick_slab +168 nether_brick_fence +169 nether_bricks +170 mushroom_stew +171 mossy_stone_bricks +172 mossy_cobblestone_wall +173 mossy_cobblestone +174 minecart +175 melon_seeds +176 melon +177 map +178 magma_cream +179 magma_block +180 magenta_wool +181 magenta_terracotta +182 magenta_stained_glass_pane +183 magenta_stained_glass +184 magenta_dye_from_purple_and_pink +185 magenta_dye_from_lilac +186 magenta_dye_from_blue_red_pink +187 magenta_dye_from_blue_red_white_dye +188 magenta_dye_from_allium +189 magenta_concrete_powder +190 magenta_carpet +191 magenta_bed_from_white_bed +192 magenta_bed +193 magenta_banner +194 jack_o_lantern +195 lime_wool +196 lime_terracotta +197 lime_stained_glass_pane +198 lime_stained_glass +199 lime_dye +200 lime_concrete_powder +201 lime_carpet +202 lime_bed_from_white_bed +203 lime_bed +204 lime_banner +205 light_weighted_pressure_plate +206 light_gray_wool +207 light_gray_terracotta +208 light_gray_stained_glass_pane +209 light_gray_stained_glass +210 light_gray_dye_from_white_tulip +211 light_gray_dye_from_oxeye_daisy +212 light_gray_dye_from_gray_white_dye +213 light_gray_dye_from_black_white_dye +214 light_gray_dye_from_azure_bluet +215 light_gray_concrete_powder +216 light_gray_carpet +217 light_gray_bed_from_white_bed +218 light_gray_bed +219 light_gray_banner +220 light_blue_wool +221 light_blue_terracotta +222 light_blue_stained_glass_pane +223 light_blue_stained_glass +224 light_blue_dye_from_blue_white_dye +225 light_blue_dye_from_blue_orchid +226 light_blue_concrete_powder +227 light_blue_carpet +228 light_blue_bed_from_white_bed +229 light_blue_bed +230 light_blue_banner +231 lever +232 leather_leggings +233 leather_helmet +234 leather_chestplate +235 leather_boots +236 leather +237 lead +238 lapis_lazuli +239 lapis_block +240 ladder +241 jungle_slab +242 jungle_stairs +243 jungle_planks +244 jungle_fence_gate +245 jungle_fence +246 jungle_door +247 jungle_boat +248 jukebox +249 item_frame +250 iron_trapdoor +251 iron_sword +252 iron_shovel +253 iron_pickaxe +254 iron_nugget +255 iron_leggings +256 iron_ingot_from_iron_block +257 iron_ingot_from_nuggets +258 iron_hoe +259 iron_helmet +260 iron_door +261 iron_chestplate +262 iron_boots +263 iron_block +264 iron_bars +265 iron_axe +266 hopper_minecart +267 hopper +268 heavy_weighted_pressure_plate +269 hay_block +270 green_wool +271 green_terracotta +272 green_stained_glass_pane +273 green_stained_glass +274 green_concrete_powder +275 green_carpet +276 green_bed_from_white_bed +277 green_bed +278 green_banner +279 gray_wool +280 gray_terracotta +281 gray_stained_glass_pane +282 gray_stained_glass +283 gray_dye +284 gray_concrete_powder +285 gray_carpet +286 gray_bed_from_white_bed +287 gray_bed +288 gray_banner +289 granite +290 golden_sword +291 golden_shovel +292 powered_rail +293 golden_pickaxe +294 golden_leggings +295 golden_hoe +296 golden_helmet +297 golden_chestplate +298 golden_carrot +299 golden_boots +300 golden_axe +301 golden_apple +302 gold_nugget +303 gold_ingot_from_gold_block +304 gold_ingot +305 gold_block +306 glowstone +307 glass_pane +308 glass_bottle +309 furnace_minecart +310 furnace +311 flower_pot +312 flint_and_steel +313 fishing_rod +314 fire_charge +315 fermented_spider_eye +316 oak_fence_gate +317 oak_fence +318 ender_eye +319 ender_chest +320 end_rod +321 end_crystal +322 end_stone_bricks +323 enchanting_table +324 emerald_block +325 emerald +326 dropper +327 dispenser +328 diorite +329 diamond_sword +330 diamond_shovel +331 diamond_pickaxe +332 diamond_leggings +333 diamond_hoe +334 diamond_helmet +335 diamond_chestplate +336 diamond_boots +337 diamond_block +338 diamond_axe +339 diamond +340 detector_rail +341 daylight_detector +342 dark_prismarine +343 dark_oak_slab +344 dark_oak_stairs +345 dark_oak_planks +346 dark_oak_fence_gate +347 dark_oak_fence +348 dark_oak_door +349 dark_oak_boat +350 cyan_wool +351 cyan_terracotta +352 cyan_stained_glass_pane +353 cyan_stained_glass +354 cyan_dye +355 cyan_concrete_powder +356 cyan_carpet +357 cyan_bed_from_white_bed +358 cyan_bed +359 cyan_banner +360 crafting_table +361 cookie +362 compass +363 comparator +364 cobblestone_wall +365 cobblestone_slab +366 coarse_dirt +367 coal_block +368 coal +369 clock +370 clay +371 chiseled_stone_bricks +372 chiseled_sandstone +373 chiseled_red_sandstone +374 chiseled_quartz_block +375 chest_minecart +376 chest +377 cauldron +378 carrot_on_a_stick +379 cake +380 bucket +381 brown_wool +382 brown_terracotta +383 brown_stained_glass_pane +384 brown_stained_glass +385 brown_concrete_powder +386 brown_carpet +387 brown_bed_from_white_bed +388 brown_bed +389 brown_banner +390 brick_stairs +391 brick_slab +392 bricks +393 brewing_stand +394 bread +395 bowl +396 bow +397 bookshelf +398 book +399 bone_meal +400 bone_meal_from_bone_block +401 bone_block +402 oak_boat +403 blue_wool +404 blue_terracotta +405 blue_stained_glass_pane +406 blue_stained_glass +407 blue_concrete_powder +408 blue_carpet +409 blue_bed_from_white_bed +410 blue_bed +411 blue_banner +412 blaze_powder +413 black_wool +414 black_terracotta +415 black_stained_glass_pane +416 black_stained_glass +417 black_concrete_powder +418 black_carpet +419 black_bed_from_white_bed +420 black_bed +421 black_banner +422 birch_slab +423 birch_stairs +424 birch_planks +425 birch_fence_gate +426 birch_fence +427 birch_door +428 birch_boat +429 beetroot_soup +430 beacon +431 arrow +432 armor_stand +433 anvil +434 andesite +435 activator_rail +436 acacia_slab +437 acacia_stairs +438 acacia_planks +439 acacia_fence_gate +440 acacia_fence +441 acacia_door +442 acacia_boat diff --git a/Server/crafting.txt b/Server/crafting.txt index c85943996..e1a07d96b 100644 --- a/Server/crafting.txt +++ b/Server/crafting.txt @@ -43,19 +43,19 @@ # Need to list each of the four log types, otherwise all logs would get converted into apple planks (^0) -AcaciaPlanks, 4 = AcaciaLog, * -BirchPlanks, 4 = BirchLog, * -Chest = Planks^-1, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 -DarkOakPlanks, 4 = DarkOakLog, * -EnderChest = EyeOfEnder, 2:2 | Obsidian, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 -Furnace = Cobblestone, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 -JunglePlanks, 4 = JungleLog, * -OakPlanks, 4 = OakLog, * -SprucePlanks, 4 = SpruceLog, * -Stick, 4 = Planks^-1, 2:2, 2:3 -Torch, 4 = Stick, 1:2 | Coal^-1, 1:1 -TrappedChest = TripWireHook, * | Chest, * -Workbench = Planks^-1, 1:1, 1:2, 2:1, 2:2 +acacia_planks: AcaciaPlanks, 4 = AcaciaLog, * +birch_planks: BirchPlanks, 4 = BirchLog, * +chest: Chest = Planks^-1, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 +dark_oak_planks: DarkOakPlanks, 4 = DarkOakLog, * +ender_chest: EnderChest = EyeOfEnder, 2:2 | Obsidian, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 +furnace: Furnace = Cobblestone, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 +jungle_planks: JunglePlanks, 4 = JungleLog, * +oak_planks: OakPlanks, 4 = OakLog, * +spruce_planks: SprucePlanks, 4 = SpruceLog, * +stick: Stick, 4 = Planks^-1, 2:2, 2:3 +torch: Torch, 4 = Stick, 1:2 | Coal^-1, 1:1 +trapped_chest: TrappedChest = TripWireHook, * | Chest, * +crafting_table: Workbench = Planks^-1, 1:1, 1:2, 2:1, 2:2 @@ -64,110 +64,110 @@ Workbench = Planks^-1, 1:1, 1:2, 2:1, 2:2 #******************************************************# # Blocks # -Andesite, 2 = Diorite, * | Cobblestone, * -BoneBlock = BoneMeal, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 -BookShelf = Planks^-1, 1:1, 2:1, 3:1, 1:3, 2:3, 3:3 | Book, 1:2, 2:2, 3:2 -BrickBlock = Brick, 1:1, 1:2, 2:1, 2:2 -ChiseledQuartzBlock = QuartzSlab, 1:1, 1:2 -ChiseledRedSandstone = RedSandstoneSlab, 1:1, 1:2 -ChiseledStoneBrick = StoneBrickSlab, 1:1, 1:2 -ClayBlock = Clay, 1:1, 1:2, 2:1, 2:2 -CoalBlock = Coal, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 -CoarsedDirt, 4 = Dirt, 1:1, 2:2 | Gravel, 1:2, 2:1 +andesite: Andesite, 2 = Diorite, * | Cobblestone, * +bone_block: BoneBlock = BoneMeal, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 +bookshelf: BookShelf = Planks^-1, 1:1, 2:1, 3:1, 1:3, 2:3, 3:3 | Book, 1:2, 2:2, 3:2 +bricks: BrickBlock = Brick, 1:1, 1:2, 2:1, 2:2 +chiseled_quartz_block: ChiseledQuartzBlock = QuartzSlab, 1:1, 1:2 +chiseled_red_sandstone: ChiseledRedSandstone = RedSandstoneSlab, 1:1, 1:2 +chiseled_stone_bricks: ChiseledStoneBrick = StoneBrickSlab, 1:1, 1:2 +clay: ClayBlock = Clay, 1:1, 1:2, 2:1, 2:2 +coal_block: CoalBlock = Coal, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 +coarse_dirt: CoarsedDirt, 4 = Dirt, 1:1, 2:2 | Gravel, 1:2, 2:1 CoarsedDirt, 4 = Gravel, 1:1, 2:2 | Dirt, 1:2, 2:1 -DarkPrismarine = PrismarineShard, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | Inksac, 2:2 -DiamondBlock = Diamond, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 -Diorite, 2 = Cobblestone, * | NetherQuartz, * -EmeraldBlock = Emerald, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 -EndstoneBrick, 4 = Endstone, 1:1, 1:2, 2:1, 2:2 -Glowstone = GlowstoneDust, 1:1, 1:2, 2:1, 2:2 -GoldBlock = GoldIngot, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 -Granite, 2 = Diorite, * | NetherQuartz, * -HayBale = Wheat, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 -IronBlock = IronIngot, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 -JackOLantern = Pumpkin, 1:1 | Torch, 1:2 -LapisBlock = LapisLazuli, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 -Leather = RabbitHide, 1:1, 1:2, 2:1, 2:2 -MossyCobblestone = Cobblestone, * | Vines, * -MossyStoneBrick = Stonebrick, * | Vines, * -NetherBrickBlock = NetherBrick, 1:1, 1:2, 2:1, 2:2 -NetherWartBlock = NetherWart, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 -OrnamentSandstone = SandstoneSlab, 1:1, 1:2 -PillarQuartzBlock, 2 = QuartzBlock, 1:1, 1:2 -PolishedAndesite, 4 = Andesite, 1:1, 1:2, 2:1, 2:2 -PolishedDiorite, 4 = Diorite, 1:1, 1:2, 2:1, 2:2 -PolishedGranite, 4 = Granite, 1:1, 1:2, 2:1, 2:2 -Prismarine = PrismarineShard, 1:1, 1:2, 2:1, 2:2 -PrismarineBricks = PrismarineShard, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 -PurpurBlock, 4 = PoppedChorusFruit, 1:1, 1:2, 2:1, 2:2 -PurpurPillar, 1 = PurpurSlab, 1:1, 1:2 -QuartzBlock = NetherQuartz, 1:1, 1:2, 2:1, 2:2 -RedNetherBrick = NetherBrick, 1:1, 2:2 | NetherWart, 1:2, 2:1 +dark_prismarine: DarkPrismarine = PrismarineShard, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | Inksac, 2:2 +diamond_block: DiamondBlock = Diamond, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 +diorite: Diorite, 2 = Cobblestone, * | NetherQuartz, * +emerald_block: EmeraldBlock = Emerald, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 +end_stone_bricks: EndstoneBrick, 4 = Endstone, 1:1, 1:2, 2:1, 2:2 +glowstone: Glowstone = GlowstoneDust, 1:1, 1:2, 2:1, 2:2 +gold_block: GoldBlock = GoldIngot, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 +granite: Granite, 2 = Diorite, * | NetherQuartz, * +hay_block: HayBale = Wheat, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 +iron_block: IronBlock = IronIngot, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 +jack_o_lantern: JackOLantern = Pumpkin, 1:1 | Torch, 1:2 +lapis_block: LapisBlock = LapisLazuli, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 +leather: Leather = RabbitHide, 1:1, 1:2, 2:1, 2:2 +mossy_cobblestone: MossyCobblestone = Cobblestone, * | Vines, * +mossy_stone_bricks: MossyStoneBrick = Stonebrick, * | Vines, * +nether_bricks: NetherBrickBlock = NetherBrick, 1:1, 1:2, 2:1, 2:2 +nether_wart_block: NetherWartBlock = NetherWart, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 +chiseled_sandstone: OrnamentSandstone = SandstoneSlab, 1:1, 1:2 +quartz_pillar: PillarQuartzBlock, 2 = QuartzBlock, 1:1, 1:2 +polished_andesite: PolishedAndesite, 4 = Andesite, 1:1, 1:2, 2:1, 2:2 +polished_diorite: PolishedDiorite, 4 = Diorite, 1:1, 1:2, 2:1, 2:2 +polished_granite: PolishedGranite, 4 = Granite, 1:1, 1:2, 2:1, 2:2 +prismarine: Prismarine = PrismarineShard, 1:1, 1:2, 2:1, 2:2 +prismarine_bricks: PrismarineBricks = PrismarineShard, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 +purpur_block: PurpurBlock, 4 = PoppedChorusFruit, 1:1, 1:2, 2:1, 2:2 +purpur_pillar: PurpurPillar, 1 = PurpurSlab, 1:1, 1:2 +quartz_block: QuartzBlock = NetherQuartz, 1:1, 1:2, 2:1, 2:2 +red_nether_bricks: RedNetherBrick = NetherBrick, 1:1, 2:2 | NetherWart, 1:2, 2:1 RedNetherBrick = NetherWart, 1:1, 2:2 | NetherBrick, 1:2, 2:1 -RedSandstone = RedSand, 1:1, 1:2, 2:1, 2:2 -RedstoneBlock = RedstoneDust, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 -Sandstone = Sand, 1:1, 1:2, 2:1, 2:2 -SeaLantern = PrismarineShard, 1:1, 1:3, 3:1, 3:3 | PrismarineCrystals, 1:2, 2:1, 2:2, 2:3, 3:2 -SlimeBlock = Slimeball, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 -SmoothRedSandstone, 4 = RedSandstone, 1:1, 1:2, 2:1, 2:2 -SmoothSandstone, 4 = Sandstone, 1:1, 1:2, 2:1, 2:2 -SnowBlock = SnowBall, 1:1, 1:2, 2:1, 2:2 -StoneBrick, 4 = Stone, 1:1, 1:2, 2:1, 2:2 -TNT = Gunpowder, 1:1, 3:1, 2:2, 1:3, 3:3 | Sand, 2:1, 1:2, 3:2, 2:3 +red_sandstone: RedSandstone = RedSand, 1:1, 1:2, 2:1, 2:2 +redstone_block: RedstoneBlock = RedstoneDust, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 +sandstone: Sandstone = Sand, 1:1, 1:2, 2:1, 2:2 +sea_lantern: SeaLantern = PrismarineShard, 1:1, 1:3, 3:1, 3:3 | PrismarineCrystals, 1:2, 2:1, 2:2, 2:3, 3:2 +slime_block: SlimeBlock = Slimeball, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 +smooth_red_sandstone: SmoothRedSandstone, 4 = RedSandstone, 1:1, 1:2, 2:1, 2:2 +smooth_sandstone: SmoothSandstone, 4 = Sandstone, 1:1, 1:2, 2:1, 2:2 +snow_block: SnowBlock = SnowBall, 1:1, 1:2, 2:1, 2:2 +stone_bricks: StoneBrick, 4 = Stone, 1:1, 1:2, 2:1, 2:2 +tnt: TNT = Gunpowder, 1:1, 3:1, 2:2, 1:3, 3:3 | Sand, 2:1, 1:2, 3:2, 2:3 Wool = String, 1:1, 1:2, 2:1, 2:2 # Slabs: -AcaciaWoodSlab, 6 = AcaciaPlanks, 1:1, 2:1, 3:1 -BirchWoodSlab, 6 = BirchPlanks, 1:1, 2:1, 3:1 -BrickSlab, 6 = BrickBlock, 1:1, 2:1, 3:1 -CobblestoneSlab, 6 = Cobblestone, 1:1, 2:1, 3:1 -DarkOakWoodSlab, 6 = DarkOakPlanks, 1:1, 2:1, 3:1 -JungleWoodSlab, 6 = JunglePlanks, 1:1, 2:1, 3:1 -NetherBrickSlab, 6 = NetherBrickBlock, 1:1, 2:1, 3:1 -OakWoodSlab, 6 = OakPlanks, 1:1, 2:1, 3:1 -PurpurSlab, 6 = PurpurBlock, 1:1, 2:1, 3:1 -Quartzslab, 6 = QuartzBlock, 1:1, 2:1, 3:1 -RedSandstoneSlab, 6 = RedSandstone^-1, 1:1, 2:1, 3:1 -SandstoneSlab, 6 = OrnamentSandstone, 1:1, 2:1, 3:1 +acacia_slab: AcaciaWoodSlab, 6 = AcaciaPlanks, 1:1, 2:1, 3:1 +birch_slab: BirchWoodSlab, 6 = BirchPlanks, 1:1, 2:1, 3:1 +brick_slab: BrickSlab, 6 = BrickBlock, 1:1, 2:1, 3:1 +cobblestone_slab: CobblestoneSlab, 6 = Cobblestone, 1:1, 2:1, 3:1 +dark_oak_slab: DarkOakWoodSlab, 6 = DarkOakPlanks, 1:1, 2:1, 3:1 +jungle_slab: JungleWoodSlab, 6 = JunglePlanks, 1:1, 2:1, 3:1 +nether_brick_slab: NetherBrickSlab, 6 = NetherBrickBlock, 1:1, 2:1, 3:1 +oak_slab: OakWoodSlab, 6 = OakPlanks, 1:1, 2:1, 3:1 +purpur_slab: PurpurSlab, 6 = PurpurBlock, 1:1, 2:1, 3:1 +quartz_slab: Quartzslab, 6 = QuartzBlock, 1:1, 2:1, 3:1 +red_sandstone_slab: RedSandstoneSlab, 6 = RedSandstone^-1, 1:1, 2:1, 3:1 +sandstone_slab: SandstoneSlab, 6 = OrnamentSandstone, 1:1, 2:1, 3:1 SandstoneSlab, 6 = Sandstone, 1:1, 2:1, 3:1 SandstoneSlab, 6 = SmoothSandstone, 1:1, 2:1, 3:1 -SnowLayer, 6 = SnowBlock, 1:1, 2:1, 3:1 -SpruceWoodSlab, 6 = SprucePlanks, 1:1, 2:1, 3:1 -StonebrickSlab, 6 = StoneBrick, 1:1, 2:1, 3:1 -StoneSlab, 6 = Stone, 1:1, 2:1, 3:1 +snow: SnowLayer, 6 = SnowBlock, 1:1, 2:1, 3:1 +spruce_slab: SpruceWoodSlab, 6 = SprucePlanks, 1:1, 2:1, 3:1 +stone_brick_slab: StonebrickSlab, 6 = StoneBrick, 1:1, 2:1, 3:1 +stone_slab: StoneSlab, 6 = Stone, 1:1, 2:1, 3:1 # Stairs: -AcaciaWoodStairs, 4 = AcaciaPlanks, 1:1, 1:2, 2:2, 1:3, 2:3, 3:3 +acacia_stairs: AcaciaWoodStairs, 4 = AcaciaPlanks, 1:1, 1:2, 2:2, 1:3, 2:3, 3:3 AcaciaWoodStairs, 4 = AcaciaPlanks, 3:1, 2:2, 3:2, 1:3, 2:3, 3:3 -BirchWoodStairs, 4 = BirchPlanks, 1:1, 1:2, 2:2, 1:3, 2:3, 3:3 +birch_stairs: BirchWoodStairs, 4 = BirchPlanks, 1:1, 1:2, 2:2, 1:3, 2:3, 3:3 BirchWoodStairs, 4 = BirchPlanks, 3:1, 2:2, 3:2, 1:3, 2:3, 3:3 -BrickStairs, 4 = BrickBlock, 1:1, 1:2, 2:2, 1:3, 2:3, 3:3 +brick_stairs: BrickStairs, 4 = BrickBlock, 1:1, 1:2, 2:2, 1:3, 2:3, 3:3 BrickStairs, 4 = BrickBlock, 3:1, 2:2, 3:2, 1:3, 2:3, 3:3 -cobblestoneStairs, 4 = Cobblestone, 1:1, 1:2, 2:2, 1:3, 2:3, 3:3 +stone_stairs: cobblestoneStairs, 4 = Cobblestone, 1:1, 1:2, 2:2, 1:3, 2:3, 3:3 cobblestoneStairs, 4 = Cobblestone, 3:1, 2:2, 3:2, 1:3, 2:3, 3:3 -DarkOakWoodStairs, 4 = DarkOakPlanks, 1:1, 1:2, 2:2, 1:3, 2:3, 3:3 +dark_oak_stairs: DarkOakWoodStairs, 4 = DarkOakPlanks, 1:1, 1:2, 2:2, 1:3, 2:3, 3:3 DarkOakWoodStairs, 4 = DarkOakPlanks, 3:1, 2:2, 3:2, 1:3, 2:3, 3:3 -JungleWoodStairs, 4 = JunglePlanks, 1:1, 1:2, 2:2, 1:3, 2:3, 3:3 +jungle_stairs: JungleWoodStairs, 4 = JunglePlanks, 1:1, 1:2, 2:2, 1:3, 2:3, 3:3 JungleWoodStairs, 4 = JunglePlanks, 3:1, 2:2, 3:2, 1:3, 2:3, 3:3 -NetherBrickStairs, 4 = NetherBrickBlock, 1:1, 1:2, 2:2, 1:3, 2:3, 3:3 +nether_brick_stairs: NetherBrickStairs, 4 = NetherBrickBlock, 1:1, 1:2, 2:2, 1:3, 2:3, 3:3 NetherBrickStairs, 4 = NetherBrickBlock, 3:1, 2:2, 3:2, 1:3, 2:3, 3:3 -PurpurStairs, 4 = PurpurBlock, 1:1, 1:2, 2:2, 1:3, 2:3, 3:3 +purpur_stairs: PurpurStairs, 4 = PurpurBlock, 1:1, 1:2, 2:2, 1:3, 2:3, 3:3 PurpurStairs, 4 = PurpurBlock, 3:1, 2:2, 3:2, 1:3, 2:3, 3:3 -QuartzStairs, 4 = QuartzBlock, 1:1, 1:2, 2:2, 1:3, 2:3, 3:3 +quartz_stairs: QuartzStairs, 4 = QuartzBlock, 1:1, 1:2, 2:2, 1:3, 2:3, 3:3 QuartzStairs, 4 = QuartzBlock, 3:1, 2:2, 3:2, 1:3, 2:3, 3:3 -RedSandstoneStairs, 4 = RedSandstone^-1, 1:1, 1:2, 2:2, 1:3, 2:3, 3:3 +red_sandstone_stairs: RedSandstoneStairs, 4 = RedSandstone^-1, 1:1, 1:2, 2:2, 1:3, 2:3, 3:3 RedSandstoneStairs, 4 = RedSandstone^-1, 3:1, 2:2, 3:2, 1:3, 2:3, 3:3 -SandstoneStairs, 4 = OrnamentSandstone, 1:1, 1:2, 2:2, 1:3, 2:3, 3:3 +sandstone_stairs: SandstoneStairs, 4 = OrnamentSandstone, 1:1, 1:2, 2:2, 1:3, 2:3, 3:3 SandstoneStairs, 4 = OrnamentSandstone, 3:1, 2:2, 3:2, 1:3, 2:3, 3:3 SandstoneStairs, 4 = Sandstone, 1:1, 1:2, 2:2, 1:3, 2:3, 3:3 SandstoneStairs, 4 = Sandstone, 3:1, 2:2, 3:2, 1:3, 2:3, 3:3 SandstoneStairs, 4 = SmoothSandstone, 1:1, 1:2, 2:2, 1:3, 2:3, 3:3 SandstoneStairs, 4 = SmoothSandstone, 3:1, 2:2, 3:2, 1:3, 2:3, 3:3 -SpruceWoodStairs, 4 = SprucePlanks, 1:1, 1:2, 2:2, 1:3, 2:3, 3:3 +spruce_stairs: SpruceWoodStairs, 4 = SprucePlanks, 1:1, 1:2, 2:2, 1:3, 2:3, 3:3 SpruceWoodStairs, 4 = SprucePlanks, 3:1, 2:2, 3:2, 1:3, 2:3, 3:3 -StoneBrickStairs, 4 = StoneBrick, 1:1, 1:2, 2:2, 1:3, 2:3, 3:3 +stone_brick_stairs: StoneBrickStairs, 4 = StoneBrick, 1:1, 1:2, 2:2, 1:3, 2:3, 3:3 StoneBrickStairs, 4 = StoneBrick, 3:1, 2:2, 3:2, 1:3, 2:3, 3:3 -WoodStairs, 4 = OakPlanks, 1:1, 1:2, 2:2, 1:3, 2:3, 3:3 +oak_stairs: WoodStairs, 4 = OakPlanks, 1:1, 1:2, 2:2, 1:3, 2:3, 3:3 WoodStairs, 4 = OakPlanks, 3:1, 2:2, 3:2, 1:3, 2:3, 3:3 @@ -177,49 +177,49 @@ WoodStairs, 4 = OakPlanks, 3:1, 2:2, 3:2, 1:3, 2:3, 3:3 # # Axes: -DiamondAxe = Stick, 2:2, 2:3 | Diamond, 2:1, 1:1, 1:2 +diamond_axe: DiamondAxe = Stick, 2:2, 2:3 | Diamond, 2:1, 1:1, 1:2 DiamondAxe = Stick, 2:2, 2:3 | Diamond, 2:1, 3:1, 3:2 -GoldenAxe = Stick, 2:2, 2:3 | GoldIngot, 2:1, 1:1, 1:2 +golden_axe: GoldenAxe = Stick, 2:2, 2:3 | GoldIngot, 2:1, 1:1, 1:2 GoldenAxe = Stick, 2:2, 2:3 | GoldIngot, 2:1, 3:1, 3:2 -IronAxe = Stick, 2:2, 2:3 | IronIngot, 2:1, 1:1, 1:2 +iron_axe: IronAxe = Stick, 2:2, 2:3 | IronIngot, 2:1, 1:1, 1:2 IronAxe = Stick, 2:2, 2:3 | IronIngot, 2:1, 3:1, 3:2 -StoneAxe = Stick, 2:2, 2:3 | Cobblestone, 2:1, 1:1, 1:2 +stone_axe: StoneAxe = Stick, 2:2, 2:3 | Cobblestone, 2:1, 1:1, 1:2 StoneAxe = Stick, 2:2, 2:3 | Cobblestone, 2:1, 3:1, 3:2 -WoodenAxe = Stick, 2:2, 2:3 | Planks^-1, 2:1, 1:1, 1:2 +wooden_axe: WoodenAxe = Stick, 2:2, 2:3 | Planks^-1, 2:1, 1:1, 1:2 WoodenAxe = Stick, 2:2, 2:3 | Planks^-1, 2:1, 3:1, 3:2 # Pickaxes: -DiamondPickaxe = Stick, 2:2, 2:3 | Diamond, 1:1, 2:1, 3:1 -GoldenPickaxe = Stick, 2:2, 2:3 | GoldIngot, 1:1, 2:1, 3:1 -IronPickaxe = Stick, 2:2, 2:3 | IronIngot, 1:1, 2:1, 3:1 -StonePickaxe = Stick, 2:2, 2:3 | Cobblestone, 1:1, 2:1, 3:1 -WoodenPickaxe = Stick, 2:2, 2:3 | Planks^-1, 1:1, 2:1, 3:1 +diamond_pickaxe: DiamondPickaxe = Stick, 2:2, 2:3 | Diamond, 1:1, 2:1, 3:1 +golden_pickaxe: GoldenPickaxe = Stick, 2:2, 2:3 | GoldIngot, 1:1, 2:1, 3:1 +iron_pickaxe: IronPickaxe = Stick, 2:2, 2:3 | IronIngot, 1:1, 2:1, 3:1 +stone_pickaxe: StonePickaxe = Stick, 2:2, 2:3 | Cobblestone, 1:1, 2:1, 3:1 +wooden_pickaxe: WoodenPickaxe = Stick, 2:2, 2:3 | Planks^-1, 1:1, 2:1, 3:1 # Shovels: -DiamondShovel = Stick, 2:2, 2:3 | Diamond, 2:1 -GoldenShovel = Stick, 2:2, 2:3 | GoldIngot, 2:1 -IronShovel = Stick, 2:2, 2:3 | IronIngot, 2:1 -StoneShovel = Stick, 2:2, 2:3 | Cobblestone, 2:1 -WoodenShovel = Stick, 2:2, 2:3 | Planks^-1, 2:1 +diamond_shovel: DiamondShovel = Stick, 2:2, 2:3 | Diamond, 2:1 +golden_shovel: GoldenShovel = Stick, 2:2, 2:3 | GoldIngot, 2:1 +iron_shovel: IronShovel = Stick, 2:2, 2:3 | IronIngot, 2:1 +stone_shovel: StoneShovel = Stick, 2:2, 2:3 | Cobblestone, 2:1 +wooden_shovel: WoodenShovel = Stick, 2:2, 2:3 | Planks^-1, 2:1 # Hoes: -DiamondHoe = Stick, 2:2, 2:3 | Diamond, 2:1, *:1 -GoldenHoe = Stick, 2:2, 2:3 | GoldIngot, 2:1, *:1 -IronHoe = Stick, 2:2, 2:3 | IronIngot, 2:1, *:1 -StoneHoe = Stick, 2:2, 2:3 | Cobblestone, 2:1, *:1 -WoodenHoe = Stick, 2:2, 2:3 | Planks^-1, 2:1, *:1 +diamond_hoe: DiamondHoe = Stick, 2:2, 2:3 | Diamond, 2:1, *:1 +golden_hoe: GoldenHoe = Stick, 2:2, 2:3 | GoldIngot, 2:1, *:1 +iron_hoe: IronHoe = Stick, 2:2, 2:3 | IronIngot, 2:1, *:1 +stone_hoe: StoneHoe = Stick, 2:2, 2:3 | Cobblestone, 2:1, *:1 +wooden_hoe: WoodenHoe = Stick, 2:2, 2:3 | Planks^-1, 2:1, *:1 -Bucket = IronIngot, 1:1, 2:2, 3:1 -Compass = IronIngot, 2:1, 1:2, 3:2, 2:3 | RedstoneDust, 2:2 -EmptyMap = Paper, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | Compass, 2:2 -FireCharge, 3 = BlazePowder, * | Coal, * | Gunpowder, * -FishingRod = Stick, 1:3, 2:2, 3:1 | String, 3:2, 3:3 +bucket: Bucket = IronIngot, 1:1, 2:2, 3:1 +compass: Compass = IronIngot, 2:1, 1:2, 3:2, 2:3 | RedstoneDust, 2:2 +map: EmptyMap = Paper, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | Compass, 2:2 +fire_charge: FireCharge, 3 = BlazePowder, * | Coal, * | Gunpowder, * +fishing_rod: FishingRod = Stick, 1:3, 2:2, 3:1 | String, 3:2, 3:3 FishingRod = Stick, 3:3, 2:2, 1:1 | String, 1:2, 1:3 -Lead, 2 = String, 1:1, 1:2, 2:1, 3:3 | Slimeball, 2:2 -Lighter = IronIngot, * | Flint, * -Shears = IronIngot, 1:1, 2:2 +lead: Lead, 2 = String, 1:1, 1:2, 2:1, 3:3 | Slimeball, 2:2 +flint_and_steel: Lighter = IronIngot, * | Flint, * +shears: Shears = IronIngot, 1:1, 2:2 Shears = IronIngot, 2:1, 1:2 -Watch = GoldIngot, 2:1, 1:2, 3:2, 2:3 | RedstoneDust, 2:2 +clock: Watch = GoldIngot, 2:1, 1:2, 3:2, 2:3 | RedstoneDust, 2:2 @@ -228,15 +228,15 @@ Watch = GoldIngot, 2:1, 1:2, 3:2, 2:3 | RedstoneDust, 2:2 #******************************************************# # Weapons # -Arrow, 4 = Flint, 1:1 | Stick, 1:2 | Feather, 1:3 -Bow = Stick, 2:1, 1:2, 2:3 | String, 3:1, 3:2, 3:3 +arrow: Arrow, 4 = Flint, 1:1 | Stick, 1:2 | Feather, 1:3 +bow: Bow = Stick, 2:1, 1:2, 2:3 | String, 3:1, 3:2, 3:3 Bow = Stick, 2:1, 3:2, 2:3 | String, 1:1, 1:2, 1:3 -DiamondSword = Stick, 2:3 | Diamond, 2:1, 2:2 -GoldenSword = Stick, 2:3 | GoldIngot, 2:1, 2:2 -IronSword = Stick, 2:3 | IronIngot, 2:1, 2:2 -SpectralArrow, 2 = Arrow, 2:2 | GlowstoneDust, 1:2, 2:1, 2:3, 3:2 -StoneSword = Stick, 2:3 | Cobblestone, 2:1, 2:2 -WoodenSword = Stick, 2:3 | Planks^-1, 2:1, 2:2 +diamond_sword: DiamondSword = Stick, 2:3 | Diamond, 2:1, 2:2 +golden_sword: GoldenSword = Stick, 2:3 | GoldIngot, 2:1, 2:2 +iron_sword: IronSword = Stick, 2:3 | IronIngot, 2:1, 2:2 +spectral_arrow: SpectralArrow, 2 = Arrow, 2:2 | GlowstoneDust, 1:2, 2:1, 2:3, 3:2 +stone_sword: StoneSword = Stick, 2:3 | Cobblestone, 2:1, 2:2 +wooden_sword: WoodenSword = Stick, 2:3 | Planks^-1, 2:1, 2:2 @@ -248,31 +248,31 @@ WoodenSword = Stick, 2:3 | Planks^-1, 2:1, 2:2 # # Helmets: -DiamondHelmet = Diamond, 1:1, 2:1, 3:1, 1:2, 3:2 -GoldenHelmet = GoldIngot, 1:1, 2:1, 3:1, 1:2, 3:2 -IronHelmet = IronIngot, 1:1, 2:1, 3:1, 1:2, 3:2 -LeatherHelmet = Leather, 1:1, 2:1, 3:1, 1:2, 3:2 +diamond_helmet: DiamondHelmet = Diamond, 1:1, 2:1, 3:1, 1:2, 3:2 +golden_helmet: GoldenHelmet = GoldIngot, 1:1, 2:1, 3:1, 1:2, 3:2 +iron_helmet: IronHelmet = IronIngot, 1:1, 2:1, 3:1, 1:2, 3:2 +leather_helmet: LeatherHelmet = Leather, 1:1, 2:1, 3:1, 1:2, 3:2 # Chestplates: -DiamondChestplate = Diamond, 1:1, 3:1, 1:2, 2:2, 3:2, 1:3, 2:3, 3:3 -GoldenChestplate = GoldIngot, 1:1, 3:1, 1:2, 2:2, 3:2, 1:3, 2:3, 3:3 -IronChestplate = IronIngot, 1:1, 3:1, 1:2, 2:2, 3:2, 1:3, 2:3, 3:3 -LeatherChestplate = Leather, 1:1, 3:1, 1:2, 2:2, 3:2, 1:3, 2:3, 3:3 +diamond_chestplate: DiamondChestplate = Diamond, 1:1, 3:1, 1:2, 2:2, 3:2, 1:3, 2:3, 3:3 +golden_chestplate: GoldenChestplate = GoldIngot, 1:1, 3:1, 1:2, 2:2, 3:2, 1:3, 2:3, 3:3 +iron_chestplate: IronChestplate = IronIngot, 1:1, 3:1, 1:2, 2:2, 3:2, 1:3, 2:3, 3:3 +leather_chestplate: LeatherChestplate = Leather, 1:1, 3:1, 1:2, 2:2, 3:2, 1:3, 2:3, 3:3 # Leggings: -DiamondLeggings = Diamond, 1:1, 2:1, 3:1, 1:2, 3:2, 1:3, 3:3 -GoldenLeggings = GoldIngot, 1:1, 2:1, 3:1, 1:2, 3:2, 1:3, 3:3 -IronLeggings = IronIngot, 1:1, 2:1, 3:1, 1:2, 3:2, 1:3, 3:3 -LeatherPants = Leather, 1:1, 2:1, 3:1, 1:2, 3:2, 1:3, 3:3 +diamond_leggings: DiamondLeggings = Diamond, 1:1, 2:1, 3:1, 1:2, 3:2, 1:3, 3:3 +golden_leggings: GoldenLeggings = GoldIngot, 1:1, 2:1, 3:1, 1:2, 3:2, 1:3, 3:3 +iron_leggings: IronLeggings = IronIngot, 1:1, 2:1, 3:1, 1:2, 3:2, 1:3, 3:3 +leather_leggings: LeatherPants = Leather, 1:1, 2:1, 3:1, 1:2, 3:2, 1:3, 3:3 # Boots: -DiamondBoots = Diamond, 1:1, 3:1, 1:2, 3:2 -GoldenBoots = GoldIngot, 1:1, 3:1, 1:2, 3:2 -IronBoots = IronIngot, 1:1, 3:1, 1:2, 3:2 -LeatherBoots = Leather, 1:1, 3:1, 1:2, 3:2 +diamond_boots: DiamondBoots = Diamond, 1:1, 3:1, 1:2, 3:2 +golden_boots: GoldenBoots = GoldIngot, 1:1, 3:1, 1:2, 3:2 +iron_boots: IronBoots = IronIngot, 1:1, 3:1, 1:2, 3:2 +leather_boots: LeatherBoots = Leather, 1:1, 3:1, 1:2, 3:2 # Shield: -Shield = IronIngot, 2:1 | Planks^-1, 1:1, 3:1, 1:2, 2:2, 3:2, 2:3 +shield: Shield = IronIngot, 2:1 | Planks^-1, 1:1, 3:1, 1:2, 2:2, 3:2, 2:3 @@ -280,22 +280,22 @@ Shield = IronIngot, 2:1 | Planks^-1, 1:1, 3:1, 1:2, 2:2, 3:2, 2:3 #******************************************************# # Transportation # -AcaciaBoat = AcaciaPlanks, 1:1, 3:1, 1:2, 2:2, 3:2 -ActivatorRail, 6 = IronIngot, 1:1, 1:2, 1:3, 3:1, 3:2, 3:3 | Stick, 2:1, 2:3 | RedstoneTorchon, 2:2 -BirchBoat = BirchPlanks, 1:1, 3:1, 1:2, 2:2, 3:2 -CarrotOnAStick = FishingRod, 1:2 | Carrot, 2:3 -DarkOakBoat = DarkOakPlanks, 1:1, 3:1, 1:2, 2:2, 3:2 -DetectorRail, 6 = IronIngot, 1:1, 3:1, 1:2, 3:2, 1:3, 3:3 | StonePlate, 2:2 | RedstoneDust, 2:3 -hopperminecart = Minecart, * | Hopper, * -JungleBoat = JunglePlanks, 1:1, 3:1, 1:2, 2:2, 3:2 -Minecart = IronIngot, 1:1, 3:1, 1:2, 2:2, 3:2 -OakBoat = OakPlanks, 1:1, 3:1, 1:2, 2:2, 3:2 -PoweredMinecart = Minecart, * | Furnace, * -PoweredRail, 6 = GoldIngot, 1:1, 3:1, 1:2, 3:2, 1:3, 3:3 | Stick, 2:2 | RedstoneDust, 2:3 -Rails, 16 = IronIngot, 1:1, 3:1, 1:2, 3:2, 1:3, 3:3 | Stick, 2:2 -SpruceBoat = SprucePlanks, 1:1, 3:1, 1:2, 2:2, 3:2 -StorageMinecart = Minecart, * | Chest, * -TNTMinecart = Minecart, * | TNT, * +acacia_boat: AcaciaBoat = AcaciaPlanks, 1:1, 3:1, 1:2, 2:2, 3:2 +activator_rail: ActivatorRail, 6 = IronIngot, 1:1, 1:2, 1:3, 3:1, 3:2, 3:3 | Stick, 2:1, 2:3 | RedstoneTorchon, 2:2 +birch_boat: BirchBoat = BirchPlanks, 1:1, 3:1, 1:2, 2:2, 3:2 +carrot_on_a_stick: CarrotOnAStick = FishingRod, 1:2 | Carrot, 2:3 +dark_oak_boat: DarkOakBoat = DarkOakPlanks, 1:1, 3:1, 1:2, 2:2, 3:2 +detector_rail: DetectorRail, 6 = IronIngot, 1:1, 3:1, 1:2, 3:2, 1:3, 3:3 | StonePlate, 2:2 | RedstoneDust, 2:3 +hopper_minecart: hopperminecart = Minecart, * | Hopper, * +jungle_boat: JungleBoat = JunglePlanks, 1:1, 3:1, 1:2, 2:2, 3:2 +minecart: Minecart = IronIngot, 1:1, 3:1, 1:2, 2:2, 3:2 +oak_boat: OakBoat = OakPlanks, 1:1, 3:1, 1:2, 2:2, 3:2 +furnace_minecart: PoweredMinecart = Minecart, * | Furnace, * +powered_rail: PoweredRail, 6 = GoldIngot, 1:1, 3:1, 1:2, 3:2, 1:3, 3:3 | Stick, 2:2 | RedstoneDust, 2:3 +rail: Rails, 16 = IronIngot, 1:1, 3:1, 1:2, 3:2, 1:3, 3:3 | Stick, 2:2 +spruce_boat: SpruceBoat = SprucePlanks, 1:1, 3:1, 1:2, 2:2, 3:2 +chest_minecart: StorageMinecart = Minecart, * | Chest, * +tnt_minecart: TNTMinecart = Minecart, * | TNT, * @@ -303,35 +303,35 @@ TNTMinecart = Minecart, * | TNT, * #******************************************************# # Mechanisms # -AcaciaDoor, 3 = AcaciaPlanks, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3 -BirchDoor, 3 = BirchPlanks, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3 -Comparator = RedstoneTorchOn, 2:1, 1:2, 3:2 | NetherQuartz, 2:2 | Stone, 1:3, 2:3, 3:3 -DarkOakDoor, 3 = DarkOakPlanks, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3 -DaylightSensor = Glass, 1:1, 2:1, 3:1 | NetherQuartz, 1:2, 2:2, 3:2 | WoodenSlab^-1, 1:3, 2:3, 3:3 -Dispenser = Cobblestone, 1:1, 1:2, 1:3, 2:1, 3:1, 3:2, 3:3 | RedstoneDust, 2:3 | Bow, 2:2 -Dropper = Cobblestone, 1:1, 2:1, 3:1, 1:2, 1:3, 3:2, 3:3 | RedstoneDust, 2:3 -heavyweightedpressureplate = IronIngot, 1:1, 2:1 -Hopper = IronIngot, 1:1, 3:1, 1:2, 3:2, 2:3 | Chest, 2:2 -IronDoor, 3 = IronIngot, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3 -IronTrapDoor = IronIngot, 1:1, 1:2, 2:1, 2:2 -Jukebox = Planks^-1, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | Diamond, 2:2 -JungleDoor, 3 = JunglePlanks, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3 -Lever = Cobblestone, 1:2 | Stick, 1:1 -lightweightedpressureplate = GoldIngot, 1:1, 2:1 -NoteBlock = Planks^-1, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | RedstoneDust, 2:2 -Piston = Planks^-1, 1:1, 2:1, 3:1 | RedstoneDust, 2:3 | Cobblestone, 1:2, 3:2, 1:3, 3:3 | IronIngot, 2:2 -RedstoneLamp = RedstoneDust, 2:1, 1:2, 3:2, 2:3 | Glowstone, 2:2 -RedstoneTorchOn = Stick, 1:2 | RedstoneDust, 1:1 -Repeater = Stone, 1:2, 2:2, 3:2 | RedstoneTorchOn, 1:1, 3:1 | RedstoneDust, 2:1 -PurpleShulkerBox = ShulkerShell, 2:1, 2:3 | Chest, 2:2 -SpruceDoor, 3 = SprucePlanks, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3 -StickyPiston = Piston, * | SlimeBall, * -StoneButton = Stone, 1:1 -StonePlate = Stone, 1:1, 2:1 -TrapDoor, 2 = Planks^-1, 1:1, 2:1, 3:1, 1:2, 2:2, 3:2 -TripwireHook, 2 = Planks^-1, 2:3 | stick, 2:2 | IronIngot, 2:1 +acacia_door: AcaciaDoor, 3 = AcaciaPlanks, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3 +birch_door: BirchDoor, 3 = BirchPlanks, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3 +comparator: Comparator = RedstoneTorchOn, 2:1, 1:2, 3:2 | NetherQuartz, 2:2 | Stone, 1:3, 2:3, 3:3 +dark_oak_door: DarkOakDoor, 3 = DarkOakPlanks, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3 +daylight_detector: DaylightSensor = Glass, 1:1, 2:1, 3:1 | NetherQuartz, 1:2, 2:2, 3:2 | WoodenSlab^-1, 1:3, 2:3, 3:3 +dispenser: Dispenser = Cobblestone, 1:1, 1:2, 1:3, 2:1, 3:1, 3:2, 3:3 | RedstoneDust, 2:3 | Bow, 2:2 +dropper: Dropper = Cobblestone, 1:1, 2:1, 3:1, 1:2, 1:3, 3:2, 3:3 | RedstoneDust, 2:3 +heavy_weighted_pressure_plate: heavyweightedpressureplate = IronIngot, 1:1, 2:1 +hopper: Hopper = IronIngot, 1:1, 3:1, 1:2, 3:2, 2:3 | Chest, 2:2 +iron_door: IronDoor, 3 = IronIngot, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3 +iron_trapdoor: IronTrapDoor = IronIngot, 1:1, 1:2, 2:1, 2:2 +jukebox: Jukebox = Planks^-1, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | Diamond, 2:2 +jungle_door: JungleDoor, 3 = JunglePlanks, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3 +lever: Lever = Cobblestone, 1:2 | Stick, 1:1 +light_weighted_pressure_plate: lightweightedpressureplate = GoldIngot, 1:1, 2:1 +note_block: NoteBlock = Planks^-1, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | RedstoneDust, 2:2 +piston: Piston = Planks^-1, 1:1, 2:1, 3:1 | RedstoneDust, 2:3 | Cobblestone, 1:2, 3:2, 1:3, 3:3 | IronIngot, 2:2 +redstone_lamp: RedstoneLamp = RedstoneDust, 2:1, 1:2, 3:2, 2:3 | Glowstone, 2:2 +redstone_torch: RedstoneTorchOn = Stick, 1:2 | RedstoneDust, 1:1 +repeater: Repeater = Stone, 1:2, 2:2, 3:2 | RedstoneTorchOn, 1:1, 3:1 | RedstoneDust, 2:1 +purpur_shulker_box: PurpleShulkerBox = ShulkerShell, 2:1, 2:3 | Chest, 2:2 +spruce_door: SpruceDoor, 3 = SprucePlanks, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3 +sticky_piston: StickyPiston = Piston, * | SlimeBall, * +stone_button: StoneButton = Stone, 1:1 +stone_pressure_plate: StonePlate = Stone, 1:1, 2:1 +oak_trapdoor: TrapDoor, 2 = Planks^-1, 1:1, 2:1, 3:1, 1:2, 2:2, 3:2 +tripwire_hook: TripwireHook, 2 = Planks^-1, 2:3 | stick, 2:2 | IronIngot, 2:1 WoodenButton = Planks^-1, 1:1 -WoodenDoor, 3 = OakPlanks, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3 +oak_button: WoodenDoor, 3 = OakPlanks, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3 WoodPlate = Planks^-1, 1:1, 2:1 @@ -341,21 +341,21 @@ WoodPlate = Planks^-1, 1:1, 2:1 #******************************************************# # Food # -Bowl, 4 = Planks^-1, 1:1, 2:2, 3:1 -Bread = Wheat, 1:1, 2:1, 3:1 -Cake = MilkBucket, 1:1, 2:1, 3:1 | Sugar, 1:2, 3:2 | Egg, 2:2 | Wheat, 1:3, 2:3, 3:3 -Cookie, 8 = Wheat, *, * | CocoaBeans, * -GoldenApple = RedApple, 2:2 | GoldIngot, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 -MelonBlock = MelonSlice, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 -MelonSeeds = MelonSlice, * -MushroomStew = Bowl, * | BrownMushroom, * | RedMushroom, * -BeetrootSoup = Bowl, 2:3 | Beetroot, 1:1, 1:2, 2:1, 2:2, 3:1, 3:2 -PumpkinPie = Pumpkin, * | Sugar, * | egg, * -PumpkinSeeds, 4 = Pumpkin, * -RabbitStew = Cooked Rabbit, 2:1 | Carrot, 1:2 | BakedPotato, 2:2 | BrownMushroom, 3:2 | Bowl, 2:3 -RabbitStew = Cooked Rabbit, 2:1 | Carrot, 1:2 | BakedPotato, 2:2 | RedMushroom, 3:2 | Bowl, 2:3 -Sugar = Sugarcane, * -Wheat, 9 = Haybale, * +bowl: Bowl, 4 = Planks^-1, 1:1, 2:2, 3:1 +bread: Bread = Wheat, 1:1, 2:1, 3:1 +cake: Cake = MilkBucket, 1:1, 2:1, 3:1 | Sugar, 1:2, 3:2 | Egg, 2:2 | Wheat, 1:3, 2:3, 3:3 +cookie: Cookie, 8 = Wheat, *, * | CocoaBeans, * +golden_apple: GoldenApple = RedApple, 2:2 | GoldIngot, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 +melon: MelonBlock = MelonSlice, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 +melon_seeds: MelonSeeds = MelonSlice, * +mushroom_stew: MushroomStew = Bowl, * | BrownMushroom, * | RedMushroom, * +beetroot_soup: BeetrootSoup = Bowl, 2:3 | Beetroot, 1:1, 1:2, 2:1, 2:2, 3:1, 3:2 +pumpkin_pie: PumpkinPie = Pumpkin, * | Sugar, * | egg, * +pumpkin_seeds: PumpkinSeeds, 4 = Pumpkin, * +rabbit_stew_from_brown_mushroom: RabbitStew = Cooked Rabbit, 2:1 | Carrot, 1:2 | BakedPotato, 2:2 | BrownMushroom, 3:2 | Bowl, 2:3 +rabbit_stew_from_red_mushroom: RabbitStew = Cooked Rabbit, 2:1 | Carrot, 1:2 | BakedPotato, 2:2 | RedMushroom, 3:2 | Bowl, 2:3 +sugar: Sugar = Sugarcane, * +wheat: Wheat, 9 = Haybale, * @@ -366,71 +366,71 @@ Wheat, 9 = Haybale, * # # Minerals: -Clay, 4 = ClayBlock, * -Coal, 9 = CoalBlock, * -Diamond, 9 = DiamondBlock, * -Emerald, 9 = EmeraldBlock, * -GoldIngot, 9 = GoldBlock, * -IronIngot = IronNugget, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 -IronIngot, 9 = IronBlock, * -LapisLazuli, 9 = LapisBlock, * -RedstoneDust, 9 = RedstoneBlock, * -SlimeBall, 9 = SlimeBlock, * +terracotta: Clay, 4 = ClayBlock, * +coal: Coal, 9 = CoalBlock, * +diamond: Diamond, 9 = DiamondBlock, * +emerald: Emerald, 9 = EmeraldBlock, * +gold_ingot_from_gold_block: GoldIngot, 9 = GoldBlock, * +iron_ingot_from_nuggets: IronIngot = IronNugget, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 +iron_ingot_from_iron_block: IronIngot, 9 = IronBlock, * +lapis_lazuli: LapisLazuli, 9 = LapisBlock, * +redstone: RedstoneDust, 9 = RedstoneBlock, * +slime_ball: SlimeBall, 9 = SlimeBlock, * -AcaciaFence, 3 = AcaciaPlanks, 1:1, 1:2, 3:1, 3:2 | Stick, 2:1, 2:2 -AcaciaFenceGate = Stick, 1:1, 1:2, 3:1, 3:2 | AcaciaPlanks, 2:1, 2:2 -Anvil = IronBlock, 1:1, 2:1, 3:1 | IronIngot, 2:2, 1:3, 2:3, 3:3 -ArmorStand = Stick, 1:1, 1:3, 2:1, 2:2, 3:1, 3:3 | StoneSlab, 2:3 -Beacon = Glass, 1:1, 1:2, 2:1, 3:1, 3:2 | Obsidian, 1:3, 2:3, 3:3 | NetherStar, 2:2 -BirchFence, 3 = BirchPlanks, 1:1, 1:2, 3:1, 3:2 | Stick, 2:1, 2:2 -BirchFenceGate = Stick, 1:1, 1:2, 3:1, 3:2 | BirchPlanks, 2:1, 2:2 -Bookandquill = Book, * | feather, * | inksac, * -Book = Paper, *, *, * | leather, * -Cobblestonewall, 6 = cobblestone, 1:2, 1:3, 2:2, 2:3, 3:2, 3:3 -DarkOakFence, 3 = DarkOakPlanks, 1:1, 1:2, 3:1, 3:2 | Stick, 2:1, 2:2 -DarkOakFenceGate = Stick, 1:1, 1:2, 3:1, 3:2 | DarkOakPlanks, 2:1, 2:2 -EndCrystal = Glass, 1:1, 1:2, 1:3, 2:1, 3:1, 3:2, 3:3 | EyeOfEnder, 2:2 | GhastTear, 2:3 -EndRod, 4 = BlazeRod, 1:1 | PoppedChorusFruit, 1:2 -EyeOfEnder = EnderPearl, * | BlazePowder, * -Fence, 3 = OakPlanks, 1:1, 1:2, 3:1, 3:2 | Stick, 2:1, 2:2 -FenceGate = Stick, 1:1, 1:2, 3:1, 3:2 | OakPlanks, 2:1, 2:2 -FlowerPot = Brick, 1:2, 2:3, 3:2 -GlassPane, 16 = Glass, 1:1, 2:1, 3:1, 1:2, 2:2, 3:2 -GoldIngot = GoldNugget, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 -IronBars, 16 = IronIngot, 1:1, 2:1, 3:1, 1:2, 2:2, 3:2 -IronNugget, 9 = IronIngot, * -ItemFrame = Stick, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | Leather, 2:2 -JungleFence, 3 = JunglePlanks, 1:1, 1:2, 3:1, 3:2 | Stick, 2:1, 2:2 -JungleFenceGate = Stick, 1:1, 1:2, 3:1, 3:2 | JunglePlanks, 2:1, 2:2 -Ladder, 3 = Stick, 1:1, 3:1, 1:2, 2:2, 3:2, 1:3, 3:3 -mossycobblestonewall, 6 = mossycobblestone, 1:2, 1:3, 2:2, 2:3, 3:2, 3:3 -NetherBrickFence, 6 = NetherBrickBlock, 1:1, 2:1, 3:1, 1:2, 2:2, 3:2 -Painting = Stick, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | Wool^-1, 2:2 -Paper, 3 = Sugarcane, 1:1, 2:1, 3:1 -Sign, 3 = Planks^-1, 1:1, 2:1, 3:1, 1:2, 2:2, 3:2 | Stick, 2:3 -SpruceFence, 3 = SprucePlanks, 1:1, 1:2, 3:1, 3:2 | Stick, 2:1, 2:2 -SpruceFenceGate = Stick, 1:1, 1:2, 3:1, 3:2 | SprucePlanks, 2:1, 2:2 +acacia_fence: AcaciaFence, 3 = AcaciaPlanks, 1:1, 1:2, 3:1, 3:2 | Stick, 2:1, 2:2 +acacia_fence_gate: AcaciaFenceGate = Stick, 1:1, 1:2, 3:1, 3:2 | AcaciaPlanks, 2:1, 2:2 +anvil: Anvil = IronBlock, 1:1, 2:1, 3:1 | IronIngot, 2:2, 1:3, 2:3, 3:3 +armor_stand: ArmorStand = Stick, 1:1, 1:3, 2:1, 2:2, 3:1, 3:3 | StoneSlab, 2:3 +beacon: Beacon = Glass, 1:1, 1:2, 2:1, 3:1, 3:2 | Obsidian, 1:3, 2:3, 3:3 | NetherStar, 2:2 +birch_fence: BirchFence, 3 = BirchPlanks, 1:1, 1:2, 3:1, 3:2 | Stick, 2:1, 2:2 +birch_fence_gate: BirchFenceGate = Stick, 1:1, 1:2, 3:1, 3:2 | BirchPlanks, 2:1, 2:2 +writable_book: Bookandquill = Book, * | feather, * | inksac, * +book: Book = Paper, *, *, * | leather, * +cobblestone_wall: Cobblestonewall, 6 = cobblestone, 1:2, 1:3, 2:2, 2:3, 3:2, 3:3 +dark_oak_fence: DarkOakFence, 3 = DarkOakPlanks, 1:1, 1:2, 3:1, 3:2 | Stick, 2:1, 2:2 +dark_oak_fence_gate: DarkOakFenceGate = Stick, 1:1, 1:2, 3:1, 3:2 | DarkOakPlanks, 2:1, 2:2 +end_crystal: EndCrystal = Glass, 1:1, 1:2, 1:3, 2:1, 3:1, 3:2, 3:3 | EyeOfEnder, 2:2 | GhastTear, 2:3 +end_rod: EndRod, 4 = BlazeRod, 1:1 | PoppedChorusFruit, 1:2 +ender_eye: EyeOfEnder = EnderPearl, * | BlazePowder, * +oak_fence: Fence, 3 = OakPlanks, 1:1, 1:2, 3:1, 3:2 | Stick, 2:1, 2:2 +oak_fence_gate: FenceGate = Stick, 1:1, 1:2, 3:1, 3:2 | OakPlanks, 2:1, 2:2 +flower_pot: FlowerPot = Brick, 1:2, 2:3, 3:2 +glass_pane: GlassPane, 16 = Glass, 1:1, 2:1, 3:1, 1:2, 2:2, 3:2 +gold_ingot: GoldIngot = GoldNugget, 1:1, 1:2, 1:3, 2:1, 2:2, 2:3, 3:1, 3:2, 3:3 +iron_bars: IronBars, 16 = IronIngot, 1:1, 2:1, 3:1, 1:2, 2:2, 3:2 +iron_nugget: IronNugget, 9 = IronIngot, * +item_frame: ItemFrame = Stick, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | Leather, 2:2 +jungle_fence: JungleFence, 3 = JunglePlanks, 1:1, 1:2, 3:1, 3:2 | Stick, 2:1, 2:2 +jungle_fence_gate: JungleFenceGate = Stick, 1:1, 1:2, 3:1, 3:2 | JunglePlanks, 2:1, 2:2 +ladder: Ladder, 3 = Stick, 1:1, 3:1, 1:2, 2:2, 3:2, 1:3, 3:3 +mossy_cobblestone_wall: mossycobblestonewall, 6 = mossycobblestone, 1:2, 1:3, 2:2, 2:3, 3:2, 3:3 +nether_brick_fence: NetherBrickFence, 6 = NetherBrickBlock, 1:1, 2:1, 3:1, 1:2, 2:2, 3:2 +painting: Painting = Stick, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | Wool^-1, 2:2 +paper: Paper, 3 = Sugarcane, 1:1, 2:1, 3:1 +oak_sign: Sign, 3 = Planks^-1, 1:1, 2:1, 3:1, 1:2, 2:2, 3:2 | Stick, 2:3 +spruce_fence: SpruceFence, 3 = SprucePlanks, 1:1, 1:2, 3:1, 3:2 | Stick, 2:1, 2:2 +spruce_fence_gate: SpruceFenceGate = Stick, 1:1, 1:2, 3:1, 3:2 | SprucePlanks, 2:1, 2:2 # These are just the basic ones, you can add various shapes and stuff to each of them # ToDo: Add the various shapes (saved in NBT-Tags, not in meta) # Banners: -BlackBanner = Stick, 2:3 | BlackWool, 1:1, 1:2, 2:1, 2:2, 2:1, 2:2 -BlueBanner = Stick, 2:3 | BlueWool, 1:1, 1:2, 2:1, 2:2, 2:1, 2:2 -BrownBanner = Stick, 2:3 | BrownWool, 1:1, 1:2, 2:1, 2:2, 2:1, 2:2 -CyanBanner = Stick, 2:3 | CyanWool, 1:1, 1:2, 2:1, 2:2, 2:1, 2:2 -GrayBanner = Stick, 2:3 | GrayWool, 1:1, 1:2, 2:1, 2:2, 2:1, 2:2 -GreenBanner = Stick, 2:3 | GreenWool, 1:1, 1:2, 2:1, 2:2, 2:1, 2:2 -LightBlueBanner = Stick, 2:3 | LightBlueWool, 1:1, 1:2, 2:1, 2:2, 2:1, 2:2 -LightGrayBanner = Stick, 2:3 | LightGrayWool, 1:1, 1:2, 2:1, 2:2, 2:1, 2:2 -LimeBanner = Stick, 2:3 | LimeWool, 1:1, 1:2, 2:1, 2:2, 2:1, 2:2 -MagentaBanner = Stick, 2:3 | MagentaWool, 1:1, 1:2, 2:1, 2:2, 2:1, 2:2 -OrangeBanner = Stick, 2:3 | OrangeWool, 1:1, 1:2, 2:1, 2:2, 2:1, 2:2 -PinkBanner = Stick, 2:3 | PinkWool, 1:1, 1:2, 2:1, 2:2, 2:1, 2:2 -PurpleBanner = Stick, 2:3 | PurpleWool, 1:1, 1:2, 2:1, 2:2, 2:1, 2:2 -RedBanner = Stick, 2:3 | RedWool, 1:1, 1:2, 2:1, 2:2, 2:1, 2:2 -WhiteBanner = Stick, 2:3 | WhiteWool, 1:1, 1:2, 2:1, 2:2, 2:1, 2:2 -YellowBanner = Stick, 2:3 | YellowWool, 1:1, 1:2, 2:1, 2:2, 2:1, 2:2 +black_banner: BlackBanner = Stick, 2:3 | BlackWool, 1:1, 1:2, 2:1, 2:2, 2:1, 2:2 +blue_banner: BlueBanner = Stick, 2:3 | BlueWool, 1:1, 1:2, 2:1, 2:2, 2:1, 2:2 +brown_banner: BrownBanner = Stick, 2:3 | BrownWool, 1:1, 1:2, 2:1, 2:2, 2:1, 2:2 +cyan_banner: CyanBanner = Stick, 2:3 | CyanWool, 1:1, 1:2, 2:1, 2:2, 2:1, 2:2 +gray_banner: GrayBanner = Stick, 2:3 | GrayWool, 1:1, 1:2, 2:1, 2:2, 2:1, 2:2 +green_banner: GreenBanner = Stick, 2:3 | GreenWool, 1:1, 1:2, 2:1, 2:2, 2:1, 2:2 +light_blue_banner: LightBlueBanner = Stick, 2:3 | LightBlueWool, 1:1, 1:2, 2:1, 2:2, 2:1, 2:2 +light_gray_banner: LightGrayBanner = Stick, 2:3 | LightGrayWool, 1:1, 1:2, 2:1, 2:2, 2:1, 2:2 +lime_banner: LimeBanner = Stick, 2:3 | LimeWool, 1:1, 1:2, 2:1, 2:2, 2:1, 2:2 +magenta_banner: MagentaBanner = Stick, 2:3 | MagentaWool, 1:1, 1:2, 2:1, 2:2, 2:1, 2:2 +orange_banner: OrangeBanner = Stick, 2:3 | OrangeWool, 1:1, 1:2, 2:1, 2:2, 2:1, 2:2 +pink_banner: PinkBanner = Stick, 2:3 | PinkWool, 1:1, 1:2, 2:1, 2:2, 2:1, 2:2 +purple_banner: PurpleBanner = Stick, 2:3 | PurpleWool, 1:1, 1:2, 2:1, 2:2, 2:1, 2:2 +red_banner: RedBanner = Stick, 2:3 | RedWool, 1:1, 1:2, 2:1, 2:2, 2:1, 2:2 +white_banner: WhiteBanner = Stick, 2:3 | WhiteWool, 1:1, 1:2, 2:1, 2:2, 2:1, 2:2 +yellow_banner: YellowBanner = Stick, 2:3 | YellowWool, 1:1, 1:2, 2:1, 2:2, 2:1, 2:2 @@ -440,28 +440,28 @@ YellowBanner = Stick, 2:3 | YellowWool, 1:1, 1:2, 2:1, 2:2, 2:1, 2:2 # Dyes # -RedDye, 1 = Beetroot, * -RedDye, 2 = Rose, * +red_dye_from_beetroot: RedDye, 1 = Beetroot, * +red_dye_from_rose_bush: RedDye, 2 = Rose, * WhiteDye, 3 = Bone, * -YellowDye, 2 = Dandelion, * +yellow_dye_from_dandelion: YellowDye, 2 = Dandelion, * # Color mixing, duals: -CyanDye, 2 = GreenDye, * | BlueDye, * -GrayDye, 2 = BlackDye, * | WhiteDye, * -LimeDye, 2 = GreenDye, * | WhiteDye, * -LtBlueDye, 2 = BlueDye, * | WhiteDye, * -LtGrayDye, 2 = GrayDye, * | WhiteDye, * -MagentaDye, 2 = PurpleDye, * | PinkDye, * -OrangeDye, 2 = YellowDye, * | RedDye, * -PinkDye, 2 = RedDye, * | WhiteDye, * -PurpleDye, 2 = RedDye, * | BlueDye, * +cyan_dye: CyanDye, 2 = GreenDye, * | BlueDye, * +gray_dye: GrayDye, 2 = BlackDye, * | WhiteDye, * +lime_dye: LimeDye, 2 = GreenDye, * | WhiteDye, * +light_blue_dye_from_blue_white_dye: LtBlueDye, 2 = BlueDye, * | WhiteDye, * +light_gray_dye_from_gray_white_dye: LtGrayDye, 2 = GrayDye, * | WhiteDye, * +magenta_dye_from_purple_and_pink: MagentaDye, 2 = PurpleDye, * | PinkDye, * +orange_dye_from_red_yellow: OrangeDye, 2 = YellowDye, * | RedDye, * +pink_dye_from_red_white_dye: PinkDye, 2 = RedDye, * | WhiteDye, * +purple_dye: PurpleDye, 2 = RedDye, * | BlueDye, * # triplets: -LtGrayDye, 3 = BlackDye, * | WhiteDye, *, * -MagentaDye, 3 = BlueDye, * | PinkDye, * | RedDye, * +light_gray_dye_from_black_white_dye: LtGrayDye, 3 = BlackDye, * | WhiteDye, *, * +magenta_dye_from_blue_red_pink: MagentaDye, 3 = BlueDye, * | PinkDye, * | RedDye, * # quads: -MagentaDye, 4 = BlueDye, * | WhiteDye, * | RedDye, *, * +magenta_dye_from_blue_red_white_dye: MagentaDye, 4 = BlueDye, * | WhiteDye, * | RedDye, *, * @@ -469,21 +469,21 @@ MagentaDye, 4 = BlueDye, * | WhiteDye, * | RedDye, *, * #******************************************************# # Concrete Powder: # -White_Concrete_Powder = Sand, 1:1, 3:1, 1:3, 3:3 | Gravel, 2:1, 1:2, 3:2, 2:3 | BoneMeal, 2:2 -Orange_Concrete_Powder = Sand, 1:1, 3:1, 1:3, 3:3 | Gravel, 2:1, 1:2, 3:2, 2:3 | OrangeDye, 2:2 -Magenta_Concrete_Powder = Sand, 1:1, 3:1, 1:3, 3:3 | Gravel, 2:1, 1:2, 3:2, 2:3 | MagentaDye, 2:2 -Light_Blue_Concrete_Powder = Sand, 1:1, 3:1, 1:3, 3:3 | Gravel, 2:1, 1:2, 3:2, 2:3 | LightBlueDye, 2:2 -Yellow_Concrete_Powder = Sand, 1:1, 3:1, 1:3, 3:3 | Gravel, 2:1, 1:2, 3:2, 2:3 | YellowDye, 2:2 -Lime_Concrete_Powder = Sand, 1:1, 3:1, 1:3, 3:3 | Gravel, 2:1, 1:2, 3:2, 2:3 | LimeDye, 2:2 -Pink_Concrete_Powder = Sand, 1:1, 3:1, 1:3, 3:3 | Gravel, 2:1, 1:2, 3:2, 2:3 | PinkDye, 2:2 -Gray_Concrete_Powder = Sand, 1:1, 3:1, 1:3, 3:3 | Gravel, 2:1, 1:2, 3:2, 2:3 | GrayDye, 2:2 -Light_Gray_Concrete_Powder = Sand, 1:1, 3:1, 1:3, 3:3 | Gravel, 2:1, 1:2, 3:2, 2:3 | LightGrayDye, 2:2 -Cyan_Concrete_Powder = Sand, 1:1, 3:1, 1:3, 3:3 | Gravel, 2:1, 1:2, 3:2, 2:3 | CyanDye, 2:2 -Blue_Concrete_Powder = Sand, 1:1, 3:1, 1:3, 3:3 | Gravel, 2:1, 1:2, 3:2, 2:3 | BlueDye, 2:2 -Brown_Concrete_Powder = Sand, 1:1, 3:1, 1:3, 3:3 | Gravel, 2:1, 1:2, 3:2, 2:3 | BrownDye, 2:2 -Green_Concrete_Powder = Sand, 1:1, 3:1, 1:3, 3:3 | Gravel, 2:1, 1:2, 3:2, 2:3 | GreenDye, 2:2 -Red_Concrete_Powder = Sand, 1:1, 3:1, 1:3, 3:3 | Gravel, 2:1, 1:2, 3:2, 2:3 | RedDye, 2:2 -Black_Concrete_Powder = Sand, 1:1, 3:1, 1:3, 3:3 | Gravel, 2:1, 1:2, 3:2, 2:3 | BlackDye, 2:2 +white_concrete_powder: White_Concrete_Powder = Sand, 1:1, 3:1, 1:3, 3:3 | Gravel, 2:1, 1:2, 3:2, 2:3 | BoneMeal, 2:2 +orange_concrete_powder: Orange_Concrete_Powder = Sand, 1:1, 3:1, 1:3, 3:3 | Gravel, 2:1, 1:2, 3:2, 2:3 | OrangeDye, 2:2 +magenta_concrete_powder: Magenta_Concrete_Powder = Sand, 1:1, 3:1, 1:3, 3:3 | Gravel, 2:1, 1:2, 3:2, 2:3 | MagentaDye, 2:2 +light_blue_concrete_powder: Light_Blue_Concrete_Powder = Sand, 1:1, 3:1, 1:3, 3:3 | Gravel, 2:1, 1:2, 3:2, 2:3 | LightBlueDye, 2:2 +yellow_concrete_powder: Yellow_Concrete_Powder = Sand, 1:1, 3:1, 1:3, 3:3 | Gravel, 2:1, 1:2, 3:2, 2:3 | YellowDye, 2:2 +lime_concrete_powder: Lime_Concrete_Powder = Sand, 1:1, 3:1, 1:3, 3:3 | Gravel, 2:1, 1:2, 3:2, 2:3 | LimeDye, 2:2 +pink_concrete_powder: Pink_Concrete_Powder = Sand, 1:1, 3:1, 1:3, 3:3 | Gravel, 2:1, 1:2, 3:2, 2:3 | PinkDye, 2:2 +gray_concrete_powder: Gray_Concrete_Powder = Sand, 1:1, 3:1, 1:3, 3:3 | Gravel, 2:1, 1:2, 3:2, 2:3 | GrayDye, 2:2 +light_gray_concrete_powder: Light_Gray_Concrete_Powder = Sand, 1:1, 3:1, 1:3, 3:3 | Gravel, 2:1, 1:2, 3:2, 2:3 | LightGrayDye, 2:2 +cyan_concrete_powder: Cyan_Concrete_Powder = Sand, 1:1, 3:1, 1:3, 3:3 | Gravel, 2:1, 1:2, 3:2, 2:3 | CyanDye, 2:2 +blue_concrete_powder: Blue_Concrete_Powder = Sand, 1:1, 3:1, 1:3, 3:3 | Gravel, 2:1, 1:2, 3:2, 2:3 | BlueDye, 2:2 +brown_concrete_powder: Brown_Concrete_Powder = Sand, 1:1, 3:1, 1:3, 3:3 | Gravel, 2:1, 1:2, 3:2, 2:3 | BrownDye, 2:2 +green_concrete_powder: Green_Concrete_Powder = Sand, 1:1, 3:1, 1:3, 3:3 | Gravel, 2:1, 1:2, 3:2, 2:3 | GreenDye, 2:2 +red_concrete_powder: Red_Concrete_Powder = Sand, 1:1, 3:1, 1:3, 3:3 | Gravel, 2:1, 1:2, 3:2, 2:3 | RedDye, 2:2 +black_concrete_powder: Black_Concrete_Powder = Sand, 1:1, 3:1, 1:3, 3:3 | Gravel, 2:1, 1:2, 3:2, 2:3 | BlackDye, 2:2 #******************************************************# # Colored shulker boxes: @@ -748,118 +748,118 @@ YellowShulkerBox = YellowShulkerBox, * | YellowDye, * #******************************************************# # Colored wool: # -BlackWool = WhiteWool, * | BlackDye, * -BlueWool = WhiteWool, * | BlueDye, * -BrownWool = WhiteWool, * | BrownDye, * -CyanWool = WhiteWool, * | CyanDye, * -GrayWool = WhiteWool, * | GrayDye, * -GreenWool = WhiteWool, * | GreenDye, * -LightBlueWool = WhiteWool, * | LightBlueDye, * -LightGrayWool = WhiteWool, * | LightGrayDye, * -LimeWool = WhiteWool, * | LimeDye, * -MagentaWool = WhiteWool, * | MagentaDye, * -OrangeWool = WhiteWool, * | OrangeDye, * -PinkWool = WhiteWool, * | PinkDye, * -PurpleWool = WhiteWool, * | PurpleDye, * -RedWool = WhiteWool, * | RedDye, * +black_wool: BlackWool = WhiteWool, * | BlackDye, * +blue_wool: BlueWool = WhiteWool, * | BlueDye, * +brown_wool: BrownWool = WhiteWool, * | BrownDye, * +cyan_wool: CyanWool = WhiteWool, * | CyanDye, * +gray_wool: GrayWool = WhiteWool, * | GrayDye, * +green_wool: GreenWool = WhiteWool, * | GreenDye, * +light_blue_wool: LightBlueWool = WhiteWool, * | LightBlueDye, * +light_gray_wool: LightGrayWool = WhiteWool, * | LightGrayDye, * +lime_wool: LimeWool = WhiteWool, * | LimeDye, * +magenta_wool: MagentaWool = WhiteWool, * | MagentaDye, * +orange_wool: OrangeWool = WhiteWool, * | OrangeDye, * +pink_wool: PinkWool = WhiteWool, * | PinkDye, * +purple_wool: PurpleWool = WhiteWool, * | PurpleDye, * +red_wool: RedWool = WhiteWool, * | RedDye, * WhiteWool = Wool^-1, * | BoneMeal, * -YellowWool = WhiteWool, * | YellowDye, * +yellow_wool: YellowWool = WhiteWool, * | YellowDye, * -BlackCarpet, 3 = BlackWool, 1:1, 2:1 -BlueCarpet, 3 = BlueWool, 1:1, 2:1 -BrownCarpet, 3 = BrownWool, 1:1, 2:1 -CyanCarpet, 3 = CyanWool, 1:1, 2:1 -GrayCarpet, 3 = GrayWool, 1:1, 2:1 -GreenCarpet, 3 = GreenWool, 1:1, 2:1 -LightBlueCarpet, 3 = LightBlueWool, 1:1, 2:1 -LightGrayCarpet, 3 = LightGrayWool, 1:1, 2:1 -LimeCarpet, 3 = LimeWool, 1:1, 2:1 -MagentaCarpet, 3 = MagentaWool, 1:1, 2:1 -OrangeCarpet, 3 = OrangeWool, 1:1, 2:1 -PinkCarpet, 3 = PinkWool, 1:1, 2:1 -PurpleCarpet, 3 = PurpleWool, 1:1, 2:1 -RedCarpet, 3 = RedWool, 1:1, 2:1 -WhiteCarpet, 3 = WhiteWool, 1:1, 2:1 -YellowCarpet, 3 = YellowWool, 1:1, 2:1 +black_carpet: BlackCarpet, 3 = BlackWool, 1:1, 2:1 +blue_carpet: BlueCarpet, 3 = BlueWool, 1:1, 2:1 +brown_carpet: BrownCarpet, 3 = BrownWool, 1:1, 2:1 +cyan_carpet: CyanCarpet, 3 = CyanWool, 1:1, 2:1 +gray_carpet: GrayCarpet, 3 = GrayWool, 1:1, 2:1 +green_carpet: GreenCarpet, 3 = GreenWool, 1:1, 2:1 +light_blue_carpet: LightBlueCarpet, 3 = LightBlueWool, 1:1, 2:1 +light_gray_carpet: LightGrayCarpet, 3 = LightGrayWool, 1:1, 2:1 +lime_carpet: LimeCarpet, 3 = LimeWool, 1:1, 2:1 +magenta_carpet: MagentaCarpet, 3 = MagentaWool, 1:1, 2:1 +orange_carpet: OrangeCarpet, 3 = OrangeWool, 1:1, 2:1 +pink_carpet: PinkCarpet, 3 = PinkWool, 1:1, 2:1 +purple_carpet: PurpleCarpet, 3 = PurpleWool, 1:1, 2:1 +red_carpet: RedCarpet, 3 = RedWool, 1:1, 2:1 +white_carpet: WhiteCarpet, 3 = WhiteWool, 1:1, 2:1 +yellow_carpet: YellowCarpet, 3 = YellowWool, 1:1, 2:1 #******************************************************# # Stained Glass: # -BlackStainedGlass, 8 = Glass, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | BlackDye, 2:2 -BlueStainedGlass, 8 = Glass, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | BlueDye, 2:2 -BrownStainedGlass, 8 = Glass, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | BrownDye, 2:2 -CyanStainedGlass, 8 = Glass, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | CyanDye, 2:2 -GrayStainedGlass, 8 = Glass, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | GrayDye, 2:2 -GreenStainedGlass, 8 = Glass, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | GreenDye, 2:2 -LightBlueStainedGlass, 8 = Glass, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | LightBlueDye, 2:2 -LightGrayStainedGlass, 8 = Glass, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | LightGrayDye, 2:2 -LimeStainedGlass, 8 = Glass, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | LimeDye, 2:2 -MagentaStainedGlass, 8 = Glass, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | MagentaDye, 2:2 -OrangeStainedGlass, 8 = Glass, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | OrangeDye, 2:2 -PinkStainedGlass, 8 = Glass, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | PinkDye, 2:2 -RedStainedGlass, 8 = Glass, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | RedDye, 2:2 -VioletStainedGlass, 8 = Glass, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | VioletDye, 2:2 -WhiteStainedGlass, 8 = Glass, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | BoneMeal, 2:2 -YellowStainedGlass, 8 = Glass, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | YellowDye, 2:2 +black_stained_glass: BlackStainedGlass, 8 = Glass, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | BlackDye, 2:2 +blue_stained_glass: BlueStainedGlass, 8 = Glass, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | BlueDye, 2:2 +brown_stained_glass: BrownStainedGlass, 8 = Glass, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | BrownDye, 2:2 +cyan_stained_glass: CyanStainedGlass, 8 = Glass, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | CyanDye, 2:2 +gray_stained_glass: GrayStainedGlass, 8 = Glass, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | GrayDye, 2:2 +green_stained_glass: GreenStainedGlass, 8 = Glass, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | GreenDye, 2:2 +light_blue_stained_glass: LightBlueStainedGlass, 8 = Glass, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | LightBlueDye, 2:2 +light_gray_stained_glass: LightGrayStainedGlass, 8 = Glass, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | LightGrayDye, 2:2 +lime_stained_glass: LimeStainedGlass, 8 = Glass, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | LimeDye, 2:2 +magenta_stained_glass: MagentaStainedGlass, 8 = Glass, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | MagentaDye, 2:2 +orange_stained_glass: OrangeStainedGlass, 8 = Glass, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | OrangeDye, 2:2 +pink_stained_glass: PinkStainedGlass, 8 = Glass, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | PinkDye, 2:2 +red_stained_glass: RedStainedGlass, 8 = Glass, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | RedDye, 2:2 +purple_stained_glass: VioletStainedGlass, 8 = Glass, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | VioletDye, 2:2 +white_stained_glass: WhiteStainedGlass, 8 = Glass, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | BoneMeal, 2:2 +yellow_stained_glass: YellowStainedGlass, 8 = Glass, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | YellowDye, 2:2 #******************************************************# # Stained Glass Pane: # -BlackStainedGlassPane , 16 = BlackStainedGlass, 1:2, 1:3, 2:2, 2:3, 3:2, 3:3 -BlueStainedGlassPane, 16 = BlueStainedGlass, 1:2, 1:3, 2:2, 2:3, 3:2, 3:3 -BrownStainedGlassPane, 16 = BrownStainedGlass, 1:2, 1:3, 2:2, 2:3, 3:2, 3:3 -CyanStainedGlassPane, 16 = CyanStainedGlass, 1:2, 1:3, 2:2, 2:3, 3:2, 3:3 -GrayStainedGlassPane, 16 = GrayStainedGlass, 1:2, 1:3, 2:2, 2:3, 3:2, 3:3 -GreenStainedGlassPane, 16 = GreenStainedGlass, 1:2, 1:3, 2:2, 2:3, 3:2, 3:3 -LightBlueStainedGlassPane, 16 = LightBlueStainedGlass, 1:2, 1:3, 2:2, 2:3, 3:2, 3:3 -LightGrayStainedGlassPane, 16 = LightGrayStainedGlass, 1:2, 1:3, 2:2, 2:3, 3:2, 3:3 -LimeStainedGlassPane, 16 = LimeStainedGlass, 1:2, 1:3, 2:2, 2:3, 3:2, 3:3 -MagentaStainedGlassPane, 16 = MagentaStainedGlass, 1:2, 1:3, 2:2, 2:3, 3:2, 3:3 -OrangeStainedGlassPane, 16 = OrangeStainedGlass, 1:2, 1:3, 2:2, 2:3, 3:2, 3:3 -PinkStainedGlassPane, 16 = PinkStainedGlass, 1:2, 1:3, 2:2, 2:3, 3:2, 3:3 -RedStainedGlassPane, 16 = RedStainedGlass, 1:2, 1:3, 2:2, 2:3, 3:2, 3:3 -VioletStainedGlassPane, 16 = VioletStainedGlass, 1:2, 1:3, 2:2, 2:3, 3:2, 3:3 -WhiteStainedGlassPane, 16 = WhiteStainedGlass, 1:2, 1:3, 2:2, 2:3, 3:2, 3:3 -YellowStainedGlassPane, 16 = YellowStainedGlass, 1:2, 1:3, 2:2, 2:3, 3:2, 3:3 +black_stained_glass_pane: BlackStainedGlassPane , 16 = BlackStainedGlass, 1:2, 1:3, 2:2, 2:3, 3:2, 3:3 +blue_stained_glass_pane: BlueStainedGlassPane, 16 = BlueStainedGlass, 1:2, 1:3, 2:2, 2:3, 3:2, 3:3 +brown_stained_glass_pane: BrownStainedGlassPane, 16 = BrownStainedGlass, 1:2, 1:3, 2:2, 2:3, 3:2, 3:3 +cyan_stained_glass_pane: CyanStainedGlassPane, 16 = CyanStainedGlass, 1:2, 1:3, 2:2, 2:3, 3:2, 3:3 +gray_stained_glass_pane: GrayStainedGlassPane, 16 = GrayStainedGlass, 1:2, 1:3, 2:2, 2:3, 3:2, 3:3 +green_stained_glass_pane: GreenStainedGlassPane, 16 = GreenStainedGlass, 1:2, 1:3, 2:2, 2:3, 3:2, 3:3 +light_blue_stained_glass_pane: LightBlueStainedGlassPane, 16 = LightBlueStainedGlass, 1:2, 1:3, 2:2, 2:3, 3:2, 3:3 +light_gray_stained_glass_pane: LightGrayStainedGlassPane, 16 = LightGrayStainedGlass, 1:2, 1:3, 2:2, 2:3, 3:2, 3:3 +lime_stained_glass_pane: LimeStainedGlassPane, 16 = LimeStainedGlass, 1:2, 1:3, 2:2, 2:3, 3:2, 3:3 +magenta_stained_glass_pane: MagentaStainedGlassPane, 16 = MagentaStainedGlass, 1:2, 1:3, 2:2, 2:3, 3:2, 3:3 +orange_stained_glass_pane: OrangeStainedGlassPane, 16 = OrangeStainedGlass, 1:2, 1:3, 2:2, 2:3, 3:2, 3:3 +pink_stained_glass_pane: PinkStainedGlassPane, 16 = PinkStainedGlass, 1:2, 1:3, 2:2, 2:3, 3:2, 3:3 +red_stained_glass_pane: RedStainedGlassPane, 16 = RedStainedGlass, 1:2, 1:3, 2:2, 2:3, 3:2, 3:3 +purple_stained_glass_pane: VioletStainedGlassPane, 16 = VioletStainedGlass, 1:2, 1:3, 2:2, 2:3, 3:2, 3:3 +white_stained_glass_pane: WhiteStainedGlassPane, 16 = WhiteStainedGlass, 1:2, 1:3, 2:2, 2:3, 3:2, 3:3 +yellow_stained_glass_pane: YellowStainedGlassPane, 16 = YellowStainedGlass, 1:2, 1:3, 2:2, 2:3, 3:2, 3:3 #******************************************************# # Stained Clay: # -BlackStainedClay, 8 = HardenedClay, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | BlackDye, 2:2 -BlueStainedClay, 8 = HardenedClay, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | BlueDye, 2:2 -BrownStainedClay, 8 = HardenedClay, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | BrownDye, 2:2 -CyanStainedClay, 8 = HardenedClay, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | CyanDye, 2:2 -GrayStainedClay, 8 = HardenedClay, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | GrayDye, 2:2 -GreenStainedClay, 8 = HardenedClay, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | GreenDye, 2:2 -LightBlueStainedClay, 8 = HardenedClay, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | LightBlueDye, 2:2 -LightGrayStainedClay, 8 = HardenedClay, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | LightGrayDye, 2:2 -LimeStainedClay, 8 = HardenedClay, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | LimeDye, 2:2 -MagentaStainedClay, 8 = HardenedClay, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | MagentaDye, 2:2 -OrangeStainedClay, 8 = HardenedClay, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | OrangeDye, 2:2 -PinkStainedClay, 8 = HardenedClay, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | PinkDye, 2:2 +black_terracotta: BlackStainedClay, 8 = HardenedClay, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | BlackDye, 2:2 +blue_terracotta: BlueStainedClay, 8 = HardenedClay, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | BlueDye, 2:2 +brown_terracotta: BrownStainedClay, 8 = HardenedClay, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | BrownDye, 2:2 +cyan_terracotta: CyanStainedClay, 8 = HardenedClay, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | CyanDye, 2:2 +gray_terracotta: GrayStainedClay, 8 = HardenedClay, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | GrayDye, 2:2 +green_terracotta: GreenStainedClay, 8 = HardenedClay, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | GreenDye, 2:2 +light_blue_terracotta: LightBlueStainedClay, 8 = HardenedClay, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | LightBlueDye, 2:2 +light_gray_terracotta: LightGrayStainedClay, 8 = HardenedClay, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | LightGrayDye, 2:2 +lime_terracotta: LimeStainedClay, 8 = HardenedClay, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | LimeDye, 2:2 +magenta_terracotta: MagentaStainedClay, 8 = HardenedClay, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | MagentaDye, 2:2 +orange_terracotta: OrangeStainedClay, 8 = HardenedClay, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | OrangeDye, 2:2 +pink_terracotta: PinkStainedClay, 8 = HardenedClay, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | PinkDye, 2:2 RedStainedClay, 8 = HardenedClay, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | RedDye, 2:2 -VioletStainedClay, 8 = HardenedClay, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | VioletDye, 2:2 +purple_terracotta: VioletStainedClay, 8 = HardenedClay, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | VioletDye, 2:2 WhiteStainedClay, 8 = HardenedClay, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | BoneMeal, 2:2 -YellowStainedClay, 8 = HardenedClay, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | YellowDye, 2:2 +yellow_terracotta: YellowStainedClay, 8 = HardenedClay, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 | YellowDye, 2:2 #******************************************************# # Enchantment & Brewing # -BlazePowder, 2 = BlazeRod, * -BrewingStand = Cobblestone, 1:2, 2:2, 3:2 | BlazeRod, 2:1 -Cauldron = IronIngot, 1:1, 3:1, 1:2, 3:2, 1:3, 2:3, 3:3 -EnchantmentTable = Obsidian, 1:3, 2:3, 3:3, 2:2 | Diamond, 1:2, 3:2 | Book, 2:1 -FermentedSpiderEye = SpiderEye, * | Sugar, * | BrownMushroom, * -GlassBottle, 3 = Glass, 1:1, 2:2, 3:1 -GlisteringMelon = MelonSlice, 2:2 | GoldNugget, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 -GoldenCarrot = Carrot, 2:2 | GoldNugget, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 -GoldNugget, 9 = GoldIngot, * -MagmaCream = SlimeBall, * | BlazePowder, * +blaze_powder: BlazePowder, 2 = BlazeRod, * +brewing_stand: BrewingStand = Cobblestone, 1:2, 2:2, 3:2 | BlazeRod, 2:1 +cauldron: Cauldron = IronIngot, 1:1, 3:1, 1:2, 3:2, 1:3, 2:3, 3:3 +enchanting_table: EnchantmentTable = Obsidian, 1:3, 2:3, 3:3, 2:2 | Diamond, 1:2, 3:2 | Book, 2:1 +fermented_spider_eye: FermentedSpiderEye = SpiderEye, * | Sugar, * | BrownMushroom, * +glass_bottle: GlassBottle, 3 = Glass, 1:1, 2:2, 3:1 +glistering_melon_slice: GlisteringMelon = MelonSlice, 2:2 | GoldNugget, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 +golden_carrot: GoldenCarrot = Carrot, 2:2 | GoldNugget, 1:1, 1:2, 1:3, 2:1, 2:3, 3:1, 3:2, 3:3 +gold_nugget: GoldNugget, 9 = GoldIngot, * +magma_cream: MagmaCream = SlimeBall, * | BlazePowder, * #******************************************************# # Dyed Armor # Do not modify -LeatherHelmet = LeatherHelmet^-1, * | Dye^-1, * +leather_helmet: LeatherHelmet = LeatherHelmet^-1, * | Dye^-1, * LeatherHelmet = LeatherHelmet^-1, * | Dye^-1, * | Dye^-1, * LeatherHelmet = LeatherHelmet^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * LeatherHelmet = LeatherHelmet^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * @@ -868,7 +868,7 @@ LeatherHelmet = LeatherHelmet^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1 LeatherHelmet = LeatherHelmet^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * LeatherHelmet = LeatherHelmet^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * -LeatherChestplate = LeatherChestplate^-1, * | Dye^-1, * +leather_chestplate: LeatherChestplate = LeatherChestplate^-1, * | Dye^-1, * LeatherChestplate = LeatherChestplate^-1, * | Dye^-1, * | Dye^-1, * LeatherChestplate = LeatherChestplate^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * LeatherChestplate = LeatherChestplate^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * @@ -877,7 +877,7 @@ LeatherChestplate = LeatherChestplate^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * LeatherChestplate = LeatherChestplate^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * LeatherChestplate = LeatherChestplate^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * -LeatherPants = LeatherPants^-1, * | Dye^-1, * +leather_leggings: LeatherPants = LeatherPants^-1, * | Dye^-1, * LeatherPants = LeatherPants^-1, * | Dye^-1, * | Dye^-1, * LeatherPants = LeatherPants^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * LeatherPants = LeatherPants^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * @@ -886,7 +886,7 @@ LeatherPants = LeatherPants^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, LeatherPants = LeatherPants^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * LeatherPants = LeatherPants^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * -LeatherBoots = LeatherBoots^-1, * | Dye^-1, * +leather_boots: LeatherBoots = LeatherBoots^-1, * | Dye^-1, * LeatherBoots = LeatherBoots^-1, * | Dye^-1, * | Dye^-1, * LeatherBoots = LeatherBoots^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * LeatherBoots = LeatherBoots^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * | Dye^-1, * diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index 3cad17849..9fbc9f89d 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -14,6 +14,8 @@ #include "BlockEntities/ChestEntity.h" #include "BlockEntities/CommandBlockEntity.h" #include "BlockEntities/SignEntity.h" +#include "UI/InventoryWindow.h" +#include "UI/CraftingWindow.h" #include "UI/Window.h" #include "UI/AnvilWindow.h" #include "UI/BeaconWindow.h" @@ -1692,7 +1694,7 @@ void cClientHandle::HandleWindowClick(UInt8 a_WindowID, Int16 a_SlotNum, eClickA LOGWARNING("Player \"%s\" clicked in a non-existent window. Ignoring", m_Username.c_str()); return; } - + m_Player->AddKnownItem(a_HeldItem); Window->Clicked(*m_Player, a_WindowID, a_SlotNum, a_ClickAction, a_HeldItem); } @@ -3129,6 +3131,46 @@ void cClientHandle::SendUseBed(const cEntity & a_Entity, int a_BlockX, int a_Blo +void cClientHandle::SendUnlockRecipe(UInt32 a_RecipeId) +{ + m_Protocol->SendUnlockRecipe(a_RecipeId); +} + + + + + +void cClientHandle::SendInitRecipes(UInt32 a_RecipeId) +{ + m_Protocol->SendInitRecipes(a_RecipeId); +} + + + + + +void cClientHandle::HandleCraftRecipe(UInt32 a_RecipeId) +{ + auto * Window = m_Player->GetWindow(); + if (Window == nullptr) + { + return; + } + + if (Window->GetWindowType() == cWindow::wtInventory) + { + static_cast(Window)->LoadRecipe(*m_Player, a_RecipeId); + } + else if (Window->GetWindowType() == cWindow::wtWorkbench) + { + static_cast(Window)->LoadRecipe(*m_Player, a_RecipeId); + } +} + + + + + void cClientHandle::SendWeather(eWeather a_Weather) { m_Protocol->SendWeather(a_Weather); diff --git a/src/ClientHandle.h b/src/ClientHandle.h index 8495fb239..1d988b137 100644 --- a/src/ClientHandle.h +++ b/src/ClientHandle.h @@ -221,6 +221,13 @@ public: // tolua_export void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity); void SendUpdateSign (int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4); void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ); + + /** Send a newly discovered recipe to show the notification and unlock in the recipe book */ + void SendUnlockRecipe (UInt32 a_RecipeId); + + /** Send already known recipes without notification but visible in the recipe book */ + void SendInitRecipes (UInt32 a_RecipeId); + void SendWeather (eWeather a_Weather); void SendWholeInventory (const cWindow & a_Window); void SendWindowClose (const cWindow & a_Window); @@ -371,6 +378,9 @@ public: // tolua_export void HandleWindowClick (UInt8 a_WindowID, Int16 a_SlotNum, eClickAction a_ClickAction, const cItem & a_HeldItem); void HandleWindowClose (UInt8 a_WindowID); + /** Called when a recipe from the recipe book is selected */ + void HandleCraftRecipe (UInt32 a_RecipeId); + /** Called when the protocol has finished logging the user in. Return true to allow the user in; false to kick them. */ diff --git a/src/CraftingRecipes.cpp b/src/CraftingRecipes.cpp index bdc98e151..7cd41ec97 100644 --- a/src/CraftingRecipes.cpp +++ b/src/CraftingRecipes.cpp @@ -268,6 +268,7 @@ void cCraftingRecipe::Dump(void) cCraftingRecipes::cCraftingRecipes(void) { LoadRecipes(); + PopulateRecipeNameMap(); } @@ -283,6 +284,72 @@ cCraftingRecipes::~cCraftingRecipes() +bool cCraftingRecipes::IsNewCraftableRecipe(const cRecipe * a_Recipe, const cItem & a_Item, const std::set & a_KnownItems) +{ + bool ContainsNewItem = false; + for (const auto & Ingredient : a_Recipe->m_Ingredients) + { + if ( + (Ingredient.m_Item.m_ItemType == a_Item.m_ItemType) && + ( + (Ingredient.m_Item.m_ItemDamage == a_Item.m_ItemDamage) || + (Ingredient.m_Item.m_ItemDamage == -1) + ) + ) + { + ContainsNewItem = true; + } + if (a_KnownItems.find(Ingredient.m_Item) == a_KnownItems.end()) + { + return false; + } + } + return ContainsNewItem; +} + + + + + +std::vector cCraftingRecipes::FindNewRecipesForItem(const cItem & a_Item, const std::set & a_KnownItems) +{ + std::vector Recipes; + for (UInt32 i = 0; i < m_Recipes.size(); i++) + { + if (m_Recipes[i]->m_RecipeName.empty()) + { + continue; + } + if (IsNewCraftableRecipe(m_Recipes[i], a_Item, a_KnownItems)) + { + Recipes.push_back(i); + } + } + return Recipes; +} + + + + + +const std::map & cCraftingRecipes::GetRecipeNameMap() +{ + return m_RecipeNameMap; +} + + + + + +cCraftingRecipes::cRecipe * cCraftingRecipes::GetRecipeById(UInt32 a_RecipeId) +{ + return m_Recipes[a_RecipeId]; +} + + + + + void cCraftingRecipes::GetRecipe(cPlayer & a_Player, cCraftingGrid & a_CraftingGrid, cCraftingRecipe & a_Recipe) { // Allow plugins to intercept recipes using a pre-craft hook: @@ -355,6 +422,21 @@ void cCraftingRecipes::LoadRecipes(void) +void cCraftingRecipes::PopulateRecipeNameMap(void) +{ + for (UInt32 i = 0; i < m_Recipes.size(); i++) + { + if (!m_Recipes[i]->m_RecipeName.empty()) + { + m_RecipeNameMap.emplace(m_Recipes[i]->m_RecipeName, i); + } + } +} + + + + + void cCraftingRecipes::ClearRecipes(void) { for (cRecipes::iterator itr = m_Recipes.begin(); itr != m_Recipes.end(); ++itr) @@ -384,8 +466,15 @@ void cCraftingRecipes::AddRecipeLine(int a_LineNum, const AString & a_RecipeLine std::unique_ptr Recipe = cpp14::make_unique(); + AStringVector RecipeSplit = StringSplit(Sides[0], ":"); + const auto * resultPart = &RecipeSplit[0]; + if (RecipeSplit.size() > 1) + { + resultPart = &RecipeSplit[1]; + Recipe->m_RecipeName = RecipeSplit[0]; + } // Parse the result: - AStringVector ResultSplit = StringSplit(Sides[0], ","); + AStringVector ResultSplit = StringSplit(*resultPart, ","); if (ResultSplit.empty()) { LOGWARNING("crafting.txt: line %d: Result is empty, ignoring the recipe.", a_LineNum); @@ -1059,7 +1148,3 @@ void cCraftingRecipes::HandleDyedLeather(const cItem * a_CraftingGrid, cCrafting a_Recipe->m_Result.m_ItemColor.SetColor(result_red, result_green, result_blue); } } - - - - diff --git a/src/CraftingRecipes.h b/src/CraftingRecipes.h index 9659e53fc..7e4ac86ae 100644 --- a/src/CraftingRecipes.h +++ b/src/CraftingRecipes.h @@ -10,10 +10,6 @@ #include "Item.h" - - - - // fwd: cPlayer.h class cPlayer; @@ -104,7 +100,20 @@ protected: +/** +The crafting recipes are the configurations to build a result item out of a set +of ingredient items. +The recipes are configured in the `crafting.txt`. When populating the crafting +grid in game (inventory or crafting table), the items are compared to the +ingredients to find a matching recipe and show and craft the result. + +Each recipe is defined via the result, the ingredients and the minecraft recipe +name. + +To handle the crafting recipes internally efficient the vector index of the +`cRecipes` is used as `RecipeId`. +*/ class cCraftingRecipes { public: @@ -117,7 +126,8 @@ public: /** Returns the recipe for current crafting grid. Doesn't modify the grid. Clears a_Recipe if no recipe found. */ void GetRecipe(cPlayer & a_Player, cCraftingGrid & a_CraftingGrid, cCraftingRecipe & a_Recipe); -protected: + /** Find recipes and returns the RecipeIds which contain the new item and all ingredients are in the known items */ + std::vector FindNewRecipesForItem(const cItem & a_Item, const std::set & a_KnownItems); struct cRecipeSlot { @@ -132,11 +142,21 @@ protected: { cRecipeSlots m_Ingredients; cItem m_Result; + AString m_RecipeName; // Size of the regular items in the recipe; "anywhere" items are excluded: int m_Width; int m_Height; } ; + + /** Returns the recipe by id */ + cRecipe * GetRecipeById(UInt32 a_RecipeId); + + /** Gets a map of all recipes with name and recipe id */ + const std::map & GetRecipeNameMap(); + +protected: + typedef std::vector cRecipes; cRecipes m_Recipes; @@ -170,8 +190,22 @@ protected: /** Searches for anything dye related for leather, calculates the appropriate color value, and sets the resulting value. */ void HandleDyedLeather(const cItem * a_CraftingGrid, cCraftingRecipes::cRecipe * a_Recipe, int a_GridStride, int a_GridWidth, int a_GridHeight); + +private: + /** Mapping the minecraft recipe names to the internal cuberite recipe Ids */ + std::map m_RecipeNameMap; + + /** + Checks if all ingredients of the a_Recipe are within the a_KnownItems list and + if the a_NewItem is part of the ingredients. + This makes sure to only find 'newly discovered' recipes. + */ + bool IsNewCraftableRecipe( + const cRecipe * a_Recipe, + const cItem & a_NewItem, + const std::set & a_KnownItems + ); + + /** Populates the RecipeNameMap */ + void PopulateRecipeNameMap(void); } ; - - - - diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index d5d9f49af..df410575e 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -31,6 +31,8 @@ #include "../JsonUtils.h" #include "json/json.h" +#include "../CraftingRecipes.h" + // 6000 ticks or 5 minutes #define PLAYER_INVENTORY_SAVE_INTERVAL 6000 @@ -194,6 +196,18 @@ bool cPlayer::Initialize(OwnedEntity a_Self, cWorld & a_World) cPluginManager::Get()->CallHookSpawnedEntity(*GetWorld(), *this); + if (m_KnownRecipes.empty()) + { + m_ClientHandle->SendInitRecipes(0); + } + else + { + for (const auto KnownRecipe : m_KnownRecipes) + { + m_ClientHandle->SendInitRecipes(KnownRecipe); + } + } + return true; } @@ -201,6 +215,47 @@ bool cPlayer::Initialize(OwnedEntity a_Self, cWorld & a_World) +void cPlayer::AddKnownItem(const cItem & a_Item) +{ + if (a_Item.m_ItemType < 0) + { + return; + } + + auto Response = m_KnownItems.insert(a_Item.CopyOne()); + if (!Response.second) + { + // The item was already known, bail out: + return; + } + + // Process the recipes that got unlocked by this newly-known item: + auto Recipes = cRoot::Get()->GetCraftingRecipes()->FindNewRecipesForItem(a_Item, m_KnownItems); + for (const auto & RecipeId : Recipes) + { + AddKnownRecipe(RecipeId); + } +} + + + + + +void cPlayer::AddKnownRecipe(UInt32 a_RecipeId) +{ + auto Response = m_KnownRecipes.insert(a_RecipeId); + if (!Response.second) + { + // The recipe was already known, bail out: + return; + } + m_ClientHandle->SendUnlockRecipe(a_RecipeId); +} + + + + + cPlayer::~cPlayer(void) { if (!cRoot::Get()->GetPluginManager()->CallHookPlayerDestroyed(*this)) @@ -2229,6 +2284,26 @@ bool cPlayer::LoadFromFile(const AString & a_FileName, cWorldPtr & a_World) m_CurrentXp = root.get("xpCurrent", 0).asInt(); m_IsFlying = root.get("isflying", 0).asBool(); + Json::Value & JSON_KnownItems = root["knownItems"]; + for (UInt32 i = 0; i < JSON_KnownItems.size(); i++) + { + cItem Item; + Item.FromJson(JSON_KnownItems[i]); + m_KnownItems.insert(Item); + } + + const auto & RecipeNameMap = cRoot::Get()->GetCraftingRecipes()->GetRecipeNameMap(); + + Json::Value & JSON_KnownRecipes = root["knownRecipes"]; + for (UInt32 i = 0; i < JSON_KnownRecipes.size(); i++) + { + auto RecipeId = RecipeNameMap.find(JSON_KnownRecipes[i].asString()); + if (RecipeId != RecipeNameMap.end()) + { + m_KnownRecipes.insert(RecipeId->second); + } + } + m_GameMode = static_cast(root.get("gamemode", eGameMode_NotSet).asInt()); if (m_GameMode == eGameMode_Creative) @@ -2327,10 +2402,27 @@ bool cPlayer::SaveToDisk() Json::Value JSON_EnderChestInventory; cEnderChestEntity::SaveToJson(JSON_EnderChestInventory, m_EnderChestContents); + Json::Value JSON_KnownItems; + for (const auto & KnownItem : m_KnownItems) + { + Json::Value JSON_Item; + KnownItem.GetJson(JSON_Item); + JSON_KnownItems.append(JSON_Item); + } + + Json::Value JSON_KnownRecipes; + for (auto KnownRecipe : m_KnownRecipes) + { + auto Recipe = cRoot::Get()->GetCraftingRecipes()->GetRecipeById(KnownRecipe); + JSON_KnownRecipes.append(Recipe->m_RecipeName); + } + Json::Value root; root["position"] = JSON_PlayerPosition; root["rotation"] = JSON_PlayerRotation; root["inventory"] = JSON_Inventory; + root["knownItems"] = JSON_KnownItems; + root["knownRecipes"] = JSON_KnownRecipes; root["equippedItemSlot"] = m_Inventory.GetEquippedSlotNum(); root["enderchestinventory"] = JSON_EnderChestInventory; root["health"] = m_Health; @@ -3095,13 +3187,3 @@ float cPlayer::GetExplosionExposureRate(Vector3d a_ExplosionPosition, float a_Ex return Super::GetExplosionExposureRate(a_ExplosionPosition, a_ExlosionPower) / 30.0f; } - - - - - - - - - - diff --git a/src/Entities/Player.h b/src/Entities/Player.h index 11d448b11..c52d6bbdc 100644 --- a/src/Entities/Player.h +++ b/src/Entities/Player.h @@ -600,6 +600,10 @@ public: /** get player explosion exposure rate */ virtual float GetExplosionExposureRate(Vector3d a_ExplosionPosition, float a_ExlosionPower) override; + /** Adds an Item to the list of known items. + If the item is already known, does nothing. */ + void AddKnownItem(const cItem & a_Item); + protected: typedef std::vector > AStringVectorVector; @@ -753,6 +757,12 @@ protected: /** The main hand of the player */ eMainHand m_MainHand; + /** List on known recipes as Ids */ + std::set m_KnownRecipes; + + /** List of known items as Ids */ + std::set m_KnownItems; + virtual void DoMoveToWorld(const cEntity::sWorldChangeInfo & a_WorldChangeInfo) override; /** Sets the speed and sends it to the client, so that they are forced to move so. */ @@ -795,4 +805,8 @@ private: If he is not on ground it also gets divided by 5. */ float GetDigSpeed(BLOCKTYPE a_Block); + /** Add the recipe Id to the known recipes. + If the recipe is already known, does nothing. */ + void AddKnownRecipe(UInt32 RecipeId); + } ; // tolua_export diff --git a/src/Inventory.cpp b/src/Inventory.cpp index 42c243f17..6509dfe5d 100644 --- a/src/Inventory.cpp +++ b/src/Inventory.cpp @@ -105,6 +105,8 @@ int cInventory::HowManyCanFit(const cItem & a_ItemStack, int a_BeginSlotNum, int int cInventory::AddItem(const cItem & a_Item, bool a_AllowNewStacks) { + m_Owner.AddKnownItem(a_Item); + cItem ToAdd(a_Item); int res = 0; @@ -207,6 +209,26 @@ int cInventory::RemoveItem(const cItem & a_ItemStack) +cItem * cInventory::FindItem(const cItem & a_RecipeItem) +{ + cItem * Item = m_ShieldSlots.FindItem(a_RecipeItem); + if (Item != nullptr) + { + return Item; + } + Item = m_HotbarSlots.FindItem(a_RecipeItem); + if (Item != nullptr) + { + return Item; + } + + return m_InventorySlots.FindItem(a_RecipeItem); +} + + + + + bool cInventory::RemoveOneEquippedItem(void) { if (m_HotbarSlots.GetSlot(m_EquippedSlotNum).IsEmpty()) @@ -863,7 +885,3 @@ void cInventory::OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum) SendSlot(Base + a_SlotNum); } - - - - diff --git a/src/Inventory.h b/src/Inventory.h index 7436d7528..7221ded00 100644 --- a/src/Inventory.h +++ b/src/Inventory.h @@ -88,6 +88,9 @@ public: Returns the number of items that were removed. */ int RemoveItem(const cItem & a_ItemStack); + /** Finds an item based on ItemType and ItemDamage (<- defines the itemType, too) */ + cItem * FindItem(const cItem & a_RecipeItem); + /** Removes one item out of the currently equipped item stack, returns true if successful, false if empty-handed */ bool RemoveOneEquippedItem(void); @@ -210,7 +213,3 @@ protected: // cItemGrid::cListener override: virtual void OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum) override; }; // tolua_export - - - - diff --git a/src/Item.h b/src/Item.h index 175f044b5..2f7b1a238 100644 --- a/src/Item.h +++ b/src/Item.h @@ -169,6 +169,31 @@ public: AStringVector m_LoreTable; // Exported in ManualBindings.cpp + /** + Compares two items for the same type or category. Type of item is defined + via `m_ItemType` and `m_ItemDamage`. Some items (e.g. planks) have the same + `m_ItemType` and the wood kind is defined via `m_ItemDamage`. `-1` is used + as placeholder for all kinds (e.g. all kind of planks). + + Items are different when the `ItemType` is different or the `ItemDamage` + is different and unequal -1. + */ + struct sItemCompare + { + bool operator() (const cItem & a_Lhs, const cItem & a_Rhs) const + { + if (a_Lhs.m_ItemType != a_Rhs.m_ItemType) + { + return (a_Lhs.m_ItemType < a_Rhs.m_ItemType); + } + if ((a_Lhs.m_ItemDamage == -1) || (a_Rhs.m_ItemDamage == -1)) + { + return false; // -1 is a wildcard, damage of -1 alway compares equal + } + return (a_Lhs.m_ItemDamage < a_Rhs.m_ItemDamage); + } + }; + // tolua_begin int m_RepairCost; diff --git a/src/ItemGrid.cpp b/src/ItemGrid.cpp index 045f083c8..790f078fc 100644 --- a/src/ItemGrid.cpp +++ b/src/ItemGrid.cpp @@ -440,6 +440,31 @@ int cItemGrid::RemoveItem(const cItem & a_ItemStack) +cItem * cItemGrid::FindItem(const cItem & a_RecipeItem) +{ + if (!m_Slots.IsStorageAllocated()) + { + return nullptr; + } + + for (int i = 0; i < m_Slots.size(); i++) + { + // Items are equal if none is greater the other + auto compare = cItem::sItemCompare{}; + if (!compare(a_RecipeItem, m_Slots[i]) && + !compare(m_Slots[i], a_RecipeItem)) + { + return &m_Slots[i]; + } + } + + return nullptr; +} + + + + + int cItemGrid::ChangeSlotCount(int a_SlotNum, int a_AddToCount) { if (!IsValidSlotNum(a_SlotNum)) @@ -825,7 +850,3 @@ void cItemGrid::TriggerListeners(int a_SlotNum) } // for itr - m_Listeners[] m_IsInTriggerListeners = false; } - - - - diff --git a/src/ItemGrid.h b/src/ItemGrid.h index ee2dc79f3..52cfbc84a 100644 --- a/src/ItemGrid.h +++ b/src/ItemGrid.h @@ -102,6 +102,9 @@ public: Returns the number of items that were removed. */ int RemoveItem(const cItem & a_ItemStack); + /** Finds an item based on ItemType and ItemDamage (<- defines the itemType, too) */ + cItem * FindItem(const cItem & a_RecipeItem); + /** Adds (or subtracts, if a_AddToCount is negative) to the count of items in the specified slot. If the slot is empty, ignores the call. Returns the new count. @@ -198,6 +201,3 @@ protected: int AddItemToSlot(const cItem & a_ItemStack, int a_Slot, int a_Num, int a_MaxStack); } ; // tolua_end - - - diff --git a/src/Protocol/CMakeLists.txt b/src/Protocol/CMakeLists.txt index e197853cb..40eecde07 100644 --- a/src/Protocol/CMakeLists.txt +++ b/src/Protocol/CMakeLists.txt @@ -14,6 +14,7 @@ target_sources( Protocol_1_13.cpp ProtocolPalettes.cpp ProtocolRecognizer.cpp + RecipeMapper.cpp Authenticator.h ChunkDataSerializer.h @@ -29,4 +30,5 @@ target_sources( Protocol_1_13.h ProtocolPalettes.h ProtocolRecognizer.h + RecipeMapper.h ) diff --git a/src/Protocol/Packetizer.cpp b/src/Protocol/Packetizer.cpp index 6afea8a36..12bfcc0dd 100644 --- a/src/Protocol/Packetizer.cpp +++ b/src/Protocol/Packetizer.cpp @@ -121,6 +121,7 @@ AString cPacketizer::PacketTypeToStr(cProtocol::ePacketType a_PacketType) case cProtocol::pktTimeUpdate: return "pktTimeUpdate"; case cProtocol::pktTitle: return "pktTitle"; case cProtocol::pktUnloadChunk: return "pktUnloadChunk"; + case cProtocol::pktUnlockRecipe: return "pktUnlockRecipe"; case cProtocol::pktUpdateBlockEntity: return "pktUpdateBlockEntity"; case cProtocol::pktUpdateHealth: return "pktUpdateHealth"; case cProtocol::pktUpdateScore: return "pktUpdateScore"; @@ -134,7 +135,3 @@ AString cPacketizer::PacketTypeToStr(cProtocol::ePacketType a_PacketType) } return Printf("Unknown packet type: 0x%02x", a_PacketType); } - - - - diff --git a/src/Protocol/Protocol.h b/src/Protocol/Protocol.h index 12382b954..e1d901321 100644 --- a/src/Protocol/Protocol.h +++ b/src/Protocol/Protocol.h @@ -132,6 +132,7 @@ public: pktTimeUpdate, pktTitle, pktUnloadChunk, + pktUnlockRecipe, pktUpdateBlockEntity, pktUpdateHealth, pktUpdateScore, @@ -225,6 +226,8 @@ public: virtual void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity) = 0; virtual void SendUpdateSign (int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) = 0; virtual void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ) = 0; + virtual void SendUnlockRecipe (UInt32 a_RecipeID) = 0; + virtual void SendInitRecipes (UInt32 a_RecipeID) = 0; virtual void SendWeather (eWeather a_Weather) = 0; virtual void SendWholeInventory (const cWindow & a_Window) = 0; virtual void SendWindowClose (const cWindow & a_Window) = 0; diff --git a/src/Protocol/ProtocolRecognizer.cpp b/src/Protocol/ProtocolRecognizer.cpp index 73f8e0ff1..3f3982c90 100644 --- a/src/Protocol/ProtocolRecognizer.cpp +++ b/src/Protocol/ProtocolRecognizer.cpp @@ -51,6 +51,7 @@ AString cProtocolRecognizer::GetVersionTextFromInt(int a_ProtocolVersion) case PROTO_VERSION_1_11_1: return "1.11.1"; case PROTO_VERSION_1_12: return "1.12"; case PROTO_VERSION_1_12_1: return "1.12.1"; + case PROTO_VERSION_1_12_2: return "1.12.2"; case PROTO_VERSION_1_13: return "1.13"; } ASSERT(!"Unknown protocol version"); @@ -921,6 +922,26 @@ void cProtocolRecognizer::SendUseBed(const cEntity & a_Entity, int a_BlockX, int +void cProtocolRecognizer::SendUnlockRecipe(UInt32 a_RecipeID) +{ + ASSERT(m_Protocol != nullptr); + m_Protocol->SendUnlockRecipe(a_RecipeID); +} + + + + + +void cProtocolRecognizer::SendInitRecipes(UInt32 a_RecipeID) +{ + ASSERT(m_Protocol != nullptr); + m_Protocol->SendInitRecipes(a_RecipeID); +} + + + + + void cProtocolRecognizer::SendWeather(eWeather a_Weather) { ASSERT(m_Protocol != nullptr); diff --git a/src/Protocol/ProtocolRecognizer.h b/src/Protocol/ProtocolRecognizer.h index f82dab08a..c5d180b44 100644 --- a/src/Protocol/ProtocolRecognizer.h +++ b/src/Protocol/ProtocolRecognizer.h @@ -127,6 +127,8 @@ public: virtual void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity) override; virtual void SendUpdateSign (int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) override; virtual void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ) override; + virtual void SendUnlockRecipe (UInt32 a_RecipeID) override; + virtual void SendInitRecipes (UInt32 a_RecipeID) override; virtual void SendWeather (eWeather a_Weather) override; virtual void SendWholeInventory (const cWindow & a_Window) override; virtual void SendWindowClose (const cWindow & a_Window) override; diff --git a/src/Protocol/Protocol_1_12.cpp b/src/Protocol/Protocol_1_12.cpp index dba85435b..6998f73bf 100644 --- a/src/Protocol/Protocol_1_12.cpp +++ b/src/Protocol/Protocol_1_12.cpp @@ -25,6 +25,7 @@ Implements the 1.12 protocol classes: #include "../Root.h" #include "../Server.h" #include "../ClientHandle.h" +#include "../CraftingRecipes.h" #include "../Bindings/PluginManager.h" #include "../JsonUtils.h" @@ -1007,6 +1008,7 @@ UInt32 cProtocol_1_12::GetPacketID(cProtocol::ePacketType a_Packet) case pktTeleportEntity: return 0x4b; case pktTimeUpdate: return 0x46; case pktTitle: return 0x47; + case pktUnlockRecipe: return 0x30; case pktUpdateBlockEntity: return 0x09; case pktUpdateHealth: return 0x40; case pktUpdateScore: return 0x44; @@ -1019,10 +1021,27 @@ UInt32 cProtocol_1_12::GetPacketID(cProtocol::ePacketType a_Packet) +void cProtocol_1_12::HandleCraftRecipe(cByteBuffer & a_ByteBuffer) +{ + HANDLE_READ(a_ByteBuffer, ReadBEUInt8, UInt8, WindowID); + HANDLE_READ(a_ByteBuffer, ReadVarInt, UInt32, RecipeID); + HANDLE_READ(a_ByteBuffer, ReadBool, bool, MakeAll); + auto CuberiteRecipeId = cRoot::Get()->GetRecipeMapper()->GetCuberiteRecipeId(RecipeID, m_Client->GetProtocolVersion()); + if (CuberiteRecipeId.has_value()) + { + m_Client->HandleCraftRecipe(CuberiteRecipeId.value()); + } +} + + + + + void cProtocol_1_12::HandlePacketCraftingBookData(cByteBuffer & a_ByteBuffer) { + // TODO not yet used, not sure if it is needed + // https://wiki.vg/index.php?title=Protocol&oldid=14204#Crafting_Book_Data a_ByteBuffer.SkipRead(a_ByteBuffer.GetReadableSpace() - 1); - m_Client->GetPlayer()->SendMessageInfo("The green crafting book feature is not implemented yet."); } @@ -1170,6 +1189,7 @@ UInt32 cProtocol_1_12_1::GetPacketID(ePacketType a_Packet) case pktRespawn: return 0x35; case pktScoreboardObjective: return 0x42; case pktSpawnPosition: return 0x46; + case pktUnlockRecipe: return 0x31; case pktUpdateHealth: return 0x41; case pktUpdateScore: return 0x45; case pktUseBed: return 0x30; @@ -1277,7 +1297,7 @@ bool cProtocol_1_12_1::HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketT case 0x0f: HandlePacketPlayerLook(a_ByteBuffer); return true; case 0x10: HandlePacketVehicleMove(a_ByteBuffer); return true; case 0x11: HandlePacketBoatSteer(a_ByteBuffer); return true; - case 0x12: break; // Craft Recipe Request - not yet implemented + case 0x12: HandleCraftRecipe(a_ByteBuffer); return true; case 0x13: HandlePacketPlayerAbilities(a_ByteBuffer); return true; case 0x14: HandlePacketBlockDig(a_ByteBuffer); return true; case 0x15: HandlePacketEntityAction(a_ByteBuffer); return true; @@ -1397,3 +1417,55 @@ void cProtocol_1_12_2::SendKeepAlive(UInt32 a_PingID) cPacketizer Pkt(*this, pktKeepAlive); Pkt.WriteBEInt64(a_PingID); } + + + + + +void cProtocol_1_12_2::SendUnlockRecipe(UInt32 a_RecipeID) +{ + ASSERT(m_State == 3); // In game mode? + + auto ProtocolRecipeId = cRoot::Get()->GetRecipeMapper()->GetProtocolRecipeId(a_RecipeID, m_Client->GetProtocolVersion()); + if (ProtocolRecipeId.has_value()) + { + cPacketizer Pkt(*this, pktUnlockRecipe); + Pkt.WriteVarInt32(1); + Pkt.WriteBool(true); + Pkt.WriteBool(false); + Pkt.WriteVarInt32(1); + Pkt.WriteVarInt32(ProtocolRecipeId.value()); + } +} + + + + + +void cProtocol_1_12_2::SendInitRecipes(UInt32 a_RecipeID) +{ + ASSERT(m_State == 3); // In game mode? + + auto ProtocolRecipeId = cRoot::Get()->GetRecipeMapper()->GetProtocolRecipeId(a_RecipeID, m_Client->GetProtocolVersion()); + if (!ProtocolRecipeId.has_value()) + { + return; + } + + cPacketizer Pkt(*this, pktUnlockRecipe); + Pkt.WriteVarInt32(0); + Pkt.WriteBool(true); + Pkt.WriteBool(false); + if (a_RecipeID == 0) + { + Pkt.WriteVarInt32(0); + Pkt.WriteVarInt32(0); + } + else + { + Pkt.WriteVarInt32(1); + Pkt.WriteVarInt32(ProtocolRecipeId.value()); + Pkt.WriteVarInt32(1); + Pkt.WriteVarInt32(ProtocolRecipeId.value()); + } +} diff --git a/src/Protocol/Protocol_1_12.h b/src/Protocol/Protocol_1_12.h index 38c025e9e..c1b81955a 100644 --- a/src/Protocol/Protocol_1_12.h +++ b/src/Protocol/Protocol_1_12.h @@ -20,7 +20,7 @@ Declares the 1.12 protocol classes: #include "Protocol_1_11.h" - +#include "RecipeMapper.h" @@ -36,6 +36,7 @@ public: protected: virtual bool HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType) override; virtual void HandlePacketAdvancementTab(cByteBuffer & a_ByteBuffer); + virtual void HandleCraftRecipe(cByteBuffer & a_ByteBuffer); virtual void HandlePacketCraftingBookData(cByteBuffer & a_ByteBuffer); virtual void HandlePacketStatusRequest(cByteBuffer & a_ByteBuffer) override; virtual void WriteEntityMetadata(cPacketizer & a_Pkt, const cEntity & a_Entity) override; @@ -86,8 +87,6 @@ protected: virtual void HandlePacketKeepAlive(cByteBuffer & a_ByteBuffer) override; virtual void HandlePacketStatusRequest(cByteBuffer & a_ByteBuffer) override; virtual void SendKeepAlive(UInt32 a_PingID) override; + virtual void SendUnlockRecipe(UInt32 a_RecipeID) override; + virtual void SendInitRecipes(UInt32 a_RecipeID) override; }; - - - - diff --git a/src/Protocol/Protocol_1_13.cpp b/src/Protocol/Protocol_1_13.cpp index fc048fe70..1dcecaa4b 100644 --- a/src/Protocol/Protocol_1_13.cpp +++ b/src/Protocol/Protocol_1_13.cpp @@ -140,6 +140,7 @@ UInt32 cProtocol_1_13::GetPacketID(ePacketType a_PacketType) case pktTimeUpdate: return 0x4a; case pktTitle: return 0x4b; case pktUnloadChunk: return 0x1f; + case pktUnlockRecipe: return 0x32; case pktUpdateHealth: return 0x44; case pktUpdateScore: return 0x48; case pktUpdateSign: return GetPacketID(pktUpdateBlockEntity); diff --git a/src/Protocol/Protocol_1_8.cpp b/src/Protocol/Protocol_1_8.cpp index b5d78e457..469f01c39 100644 --- a/src/Protocol/Protocol_1_8.cpp +++ b/src/Protocol/Protocol_1_8.cpp @@ -1587,6 +1587,26 @@ void cProtocol_1_8_0::SendUseBed(const cEntity & a_Entity, int a_BlockX, int a_B +void cProtocol_1_8_0::SendUnlockRecipe(UInt32 a_RecipeID) +{ + // Client doesn't support this feature + return; +} + + + + + +void cProtocol_1_8_0::SendInitRecipes(UInt32 a_RecipeID) +{ + // Client doesn't support this feature + return; +} + + + + + void cProtocol_1_8_0::SendWeather(eWeather a_Weather) { ASSERT(m_State == 3); // In game mode? diff --git a/src/Protocol/Protocol_1_8.h b/src/Protocol/Protocol_1_8.h index 42903a921..a8232104b 100644 --- a/src/Protocol/Protocol_1_8.h +++ b/src/Protocol/Protocol_1_8.h @@ -114,6 +114,8 @@ public: virtual void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity) override; virtual void SendUpdateSign (int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4) override; virtual void SendUseBed (const cEntity & a_Entity, int a_BlockX, int a_BlockY, int a_BlockZ) override; + virtual void SendUnlockRecipe (UInt32 a_RecipeID) override; + virtual void SendInitRecipes (UInt32 a_RecipeID) override; virtual void SendWeather (eWeather a_Weather) override; virtual void SendWholeInventory (const cWindow & a_Window) override; virtual void SendWindowClose (const cWindow & a_Window) override; diff --git a/src/Protocol/Protocol_1_9.cpp b/src/Protocol/Protocol_1_9.cpp index 8327eaf40..784c26f34 100644 --- a/src/Protocol/Protocol_1_9.cpp +++ b/src/Protocol/Protocol_1_9.cpp @@ -567,6 +567,12 @@ UInt32 cProtocol_1_9_0::GetPacketID(cProtocol::ePacketType a_Packet) case pktWindowItems: return 0x14; case pktWindowOpen: return 0x13; case pktWindowProperty: return 0x15; + + // Unsupported packets + case pktUnlockRecipe: + { + break; + } } UNREACHABLE("Unsupported outgoing packet type"); } diff --git a/src/Protocol/RecipeMapper.cpp b/src/Protocol/RecipeMapper.cpp new file mode 100644 index 000000000..2757fdfd6 --- /dev/null +++ b/src/Protocol/RecipeMapper.cpp @@ -0,0 +1,128 @@ +#include "Globals.h" +#include "RecipeMapper.h" +#include "../Root.h" + +cRecipeMapper::cRecipeMapper(void) +{ + AString path = "Protocol"; + auto contents = cFile::GetFolderContents(path); + for (const auto & content: contents) + { + auto fullName = path + cFile::PathSeparator() + content; + if (cFile::IsFolder(fullName)) + { + loadRecipes(content); + } + } +} + + + + + +void cRecipeMapper::loadRecipes(const AString & a_ProtocolVersion) +{ + cFile f; + if (!f.Open("Protocol/" + a_ProtocolVersion + "/base.recipes.txt", cFile::fmRead)) + { + LOGWARNING("Cannot open file \"Protocol/%s/base.recipes.txt\", no recipe book recipes will be available!", a_ProtocolVersion); + return; + } + AString Everything; + if (!f.ReadRestOfFile(Everything)) + { + LOGWARNING("Cannot read file \"Protocol/%s/base.recipes.txt\", no recipe book recipes will be available!", a_ProtocolVersion); + return; + } + f.Close(); + + // Split it into lines, then process each line as a single recipe: + AStringVector Split = StringSplit(Everything, "\n"); + m_ProtocolVersionMap[a_ProtocolVersion] = {}; + const auto & RecipeNameMap = cRoot::Get()->GetCraftingRecipes()->GetRecipeNameMap(); + + int LineNum = 1; + for (AStringVector::const_iterator itr = Split.begin(); itr != Split.end(); ++itr, ++LineNum) + { + // Remove anything after a '#' sign and trim away the whitespace: + AString Recipe = TrimString(itr->substr(0, itr->find('#'))); + if (Recipe.empty()) + { + // Empty recipe + continue; + } + AddRecipeLine(a_ProtocolVersion, LineNum, Recipe, RecipeNameMap); + } + LOG("Loaded %s %zu recipe book", a_ProtocolVersion, m_ProtocolVersionMap[a_ProtocolVersion].size()); +} + + + + + +cRecipeMapper::~cRecipeMapper() +{ +} + + + + + +void cRecipeMapper::AddRecipeLine(const AString & a_ProtocolVersion, int a_LineNum, const AString & a_RecipeLine, const std::map & a_RecipeNameMap) +{ + AStringVector Sides = StringSplit(a_RecipeLine, " "); + UInt32 Id; + if (Sides.size() != 2) + { + LOGINFO("Recipe incompletely configured %s", a_RecipeLine); + return; + } + StringToInteger(Sides[0], Id); + + auto RecipeIndex = a_RecipeNameMap.find(Sides[1]); + if (RecipeIndex == a_RecipeNameMap.end()) + { + return; + } + m_ProtocolVersionMap[a_ProtocolVersion].emplace(Id, RecipeIndex->second); +} + + + + + +std::optional cRecipeMapper::GetProtocolRecipeId(UInt32 a_RecipeId, UInt32 a_ProtocolVersion) +{ + auto ProtocolMap = m_ProtocolVersionMap.find(cRoot::Get()->GetProtocolVersionTextFromInt(static_cast(a_ProtocolVersion))); + if (ProtocolMap == m_ProtocolVersionMap.end()) + { + return {}; + } + for (const auto & item: ProtocolMap->second) + { + if (item.second == a_RecipeId) + { + return item.first; + } + } + return {}; +} + + + + + +std::optional cRecipeMapper::GetCuberiteRecipeId(UInt32 a_ProtocolRecipeId, UInt32 a_ProtocolVersion) +{ + auto ProtocolMap = m_ProtocolVersionMap.find(cRoot::Get()->GetProtocolVersionTextFromInt(static_cast(a_ProtocolVersion))); + if (ProtocolMap == m_ProtocolVersionMap.end()) + { + return {}; + } + auto Element = ProtocolMap->second.find(a_ProtocolRecipeId); + if (Element != ProtocolMap->second.end()) + { + return Element->second; + } + return {}; +} diff --git a/src/Protocol/RecipeMapper.h b/src/Protocol/RecipeMapper.h new file mode 100644 index 000000000..1cac62f92 --- /dev/null +++ b/src/Protocol/RecipeMapper.h @@ -0,0 +1,35 @@ +#pragma once + +#include "../CraftingRecipes.h" +#include + +/** +The RecipeMapper handles the translation of crafting recipes into protocol +specific recipe Ids. +The crafting recipes are identified by the RecipeId. +The actual configuration is stored in the protocol specific configuration +directory, e.g. `Server/Protocol/1.12.2/base.recipes.txt` +*/ +class cRecipeMapper +{ +public: + cRecipeMapper(void); + ~cRecipeMapper(); + + /** Translates the cuberite RecipeId to the protocol specific RecipeId */ + std::optional GetProtocolRecipeId(UInt32 a_RecipeId, UInt32 a_ProtocolVersion); + + /** Translates the protocol specific RecipeId to the cuberite RecipeId */ + std::optional GetCuberiteRecipeId(UInt32 a_ProtocolRecipeId, UInt32 a_ProtocolVersion); + +private: + /** A mapping for each protocol from the protocol specific RecipeId and the cuberite RecipeId */ + std::map> m_ProtocolVersionMap; + + /** Load Recipes from the protocol specific mapping file */ + void loadRecipes(const AString & a_ProtocolVersion); + + /** Handles a single line of the protocol specific mapping file */ + void AddRecipeLine(const AString & a_ProtocolVersion, int a_LineNum, const AString & a_RecipeLine, const std::map & a_RecipeNameMap); + +}; diff --git a/src/Root.cpp b/src/Root.cpp index 0cece9e6d..b3e7f61ee 100644 --- a/src/Root.cpp +++ b/src/Root.cpp @@ -24,6 +24,7 @@ #include "BrewingRecipes.h" #include "FurnaceRecipe.h" #include "CraftingRecipes.h" +#include "Protocol/RecipeMapper.h" #include "Bindings/PluginManager.h" #include "MonsterConfig.h" #include "Entities/Player.h" @@ -213,6 +214,7 @@ void cRoot::Start(std::unique_ptr a_OverridesRepo) m_RankManager.reset(new cRankManager()); m_RankManager->Initialize(*m_MojangAPI); m_CraftingRecipes = new cCraftingRecipes(); + m_RecipeMapper.reset(new cRecipeMapper()); m_FurnaceRecipe = new cFurnaceRecipe(); m_BrewingRecipes.reset(new cBrewingRecipes()); diff --git a/src/Root.h b/src/Root.h index 6c84e6bf7..2393871da 100644 --- a/src/Root.h +++ b/src/Root.h @@ -18,6 +18,7 @@ class cItem; class cMonsterConfig; class cBrewingRecipes; class cCraftingRecipes; +class cRecipeMapper; class cFurnaceRecipe; class cWebAdmin; class cPluginManager; @@ -89,6 +90,7 @@ public: cMonsterConfig * GetMonsterConfig(void) { return m_MonsterConfig; } cCraftingRecipes * GetCraftingRecipes(void) { return m_CraftingRecipes; } // tolua_export + cRecipeMapper * GetRecipeMapper(void) { return m_RecipeMapper.get(); } cFurnaceRecipe * GetFurnaceRecipe (void) { return m_FurnaceRecipe; } // Exported in ManualBindings.cpp with quite a different signature cBrewingRecipes * GetBrewingRecipes (void) { return m_BrewingRecipes.get(); } // Exported in ManualBindings.cpp @@ -229,6 +231,7 @@ private: cMonsterConfig * m_MonsterConfig; cCraftingRecipes * m_CraftingRecipes; + std::unique_ptr m_RecipeMapper; cFurnaceRecipe * m_FurnaceRecipe; std::unique_ptr m_BrewingRecipes; cWebAdmin * m_WebAdmin; @@ -275,8 +278,3 @@ private: static void InputThread(cRoot & a_Params); }; // tolua_export - - - - - diff --git a/src/UI/CraftingWindow.cpp b/src/UI/CraftingWindow.cpp index 34599788c..d72e13729 100644 --- a/src/UI/CraftingWindow.cpp +++ b/src/UI/CraftingWindow.cpp @@ -59,3 +59,9 @@ void cCraftingWindow::DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & + +void cCraftingWindow::LoadRecipe(cPlayer & a_Player, UInt32 a_RecipeId) +{ + auto slotAreaCrafting = static_cast(m_SlotAreas[0]); + slotAreaCrafting->LoadRecipe(a_Player, a_RecipeId); +} diff --git a/src/UI/CraftingWindow.h b/src/UI/CraftingWindow.h index 75026dc67..b0de69704 100644 --- a/src/UI/CraftingWindow.h +++ b/src/UI/CraftingWindow.h @@ -25,8 +25,7 @@ public: cCraftingWindow(); virtual void DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply) override; + + /** Loads the given Recipe into the crafting grid */ + void LoadRecipe(cPlayer & a_Player, UInt32 a_RecipeId); }; - - - - diff --git a/src/UI/InventoryWindow.cpp b/src/UI/InventoryWindow.cpp index 3c787ff7c..a3122d2d9 100644 --- a/src/UI/InventoryWindow.cpp +++ b/src/UI/InventoryWindow.cpp @@ -72,3 +72,9 @@ void cInventoryWindow::DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer + +void cInventoryWindow::LoadRecipe(cPlayer & a_Player, UInt32 a_RecipeId) +{ + auto slotAreaCrafting = static_cast(m_SlotAreas[0]); + slotAreaCrafting->LoadRecipe(a_Player, a_RecipeId); +} diff --git a/src/UI/InventoryWindow.h b/src/UI/InventoryWindow.h index 108f58fa0..052439f40 100644 --- a/src/UI/InventoryWindow.h +++ b/src/UI/InventoryWindow.h @@ -26,10 +26,8 @@ public: virtual void DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply) override; + /** Loads the given Recipe into the crafting grid */ + void LoadRecipe(cPlayer & a_Player, UInt32 a_RecipeId); protected: cPlayer & m_Player; }; - - - - diff --git a/src/UI/SlotArea.cpp b/src/UI/SlotArea.cpp index 0bbfb4b12..1552d4bfe 100644 --- a/src/UI/SlotArea.cpp +++ b/src/UI/SlotArea.cpp @@ -665,6 +665,7 @@ void cSlotAreaCrafting::ShiftClickedResult(cPlayer & a_Player) { return; } + a_Player.AddKnownItem(Result); cItem * PlayerSlots = GetPlayerSlots(a_Player) + 1; for (;;) { @@ -780,6 +781,70 @@ void cSlotAreaCrafting::HandleCraftItem(const cItem & a_Result, cPlayer & a_Play +void cSlotAreaCrafting::LoadRecipe(cPlayer & a_Player, UInt32 a_RecipeId) +{ + if (a_RecipeId == 0) + { + return; + } + auto Recipe = cRoot::Get()->GetCraftingRecipes()->GetRecipeById(a_RecipeId); + + int NumItems = 0; + ClearCraftingGrid(a_Player); + + for (auto itrS = Recipe->m_Ingredients.begin(); itrS != Recipe->m_Ingredients.end(); ++itrS) + { + cItem * FoundItem = a_Player.GetInventory().FindItem(itrS->m_Item); + if (FoundItem == nullptr) + { + ClearCraftingGrid(a_Player); + break; + } + cItem Item = FoundItem->CopyOne(); + ++NumItems; + int pos = 1 + itrS->x + m_GridSize * itrS->y; + // Assuming there are ether shaped or unshaped recipes, no mixed ones + if ((itrS->x == -1) && (itrS->y == -1)) + { + pos = NumItems; + } + // Handle x wildcard + else if (itrS->x == -1) + { + for (int i = 0; i < m_GridSize; i++) + { + pos = 1 + i + m_GridSize * itrS->y; + auto itemCheck = GetSlot(pos, a_Player); + if (itemCheck->IsEmpty()) + { + break; + } + } + } + SetSlot(pos, a_Player, Item); + a_Player.GetInventory().RemoveItem(Item); + } +} + + + + + +void cSlotAreaCrafting::ClearCraftingGrid(cPlayer & a_Player) +{ + for (int pos = 1; pos <= m_GridSize * m_GridSize; pos++) + { + auto Item = GetSlot(pos, a_Player); + if (Item->m_ItemCount > 0) + { + a_Player.GetInventory().AddItem(*Item); + SetSlot(pos, a_Player, cItem()); + } + } +} + + + //////////////////////////////////////////////////////////////////////////////// // cSlotAreaAnvil: @@ -2749,8 +2814,3 @@ void cSlotAreaHorse::DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bo --a_ItemStack.m_ItemCount; } } - - - - - diff --git a/src/UI/SlotArea.h b/src/UI/SlotArea.h index 86c0afd51..d363a72e6 100644 --- a/src/UI/SlotArea.h +++ b/src/UI/SlotArea.h @@ -273,6 +273,11 @@ public: // Distributing items into this area is completely disabled virtual void DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots, bool a_BackFill) override; + /** Clear the crafting grid */ + void ClearCraftingGrid(cPlayer & a_Player); + + /** Loads the given Recipe into the crafting grid */ + void LoadRecipe(cPlayer & a_Player, UInt32 a_RecipeId); protected: /** Maps player's EntityID -> current recipe. @@ -555,7 +560,3 @@ public: private: cHorse & m_Horse; }; - - - -