diff --git a/ItemsAdder/tfmc_cooking/contents/chocolate.yml b/ItemsAdder/tfmc_cooking/contents/chocolate.yml new file mode 100644 index 0000000..923c58c --- /dev/null +++ b/ItemsAdder/tfmc_cooking/contents/chocolate.yml @@ -0,0 +1,85 @@ +# Chocolate (Cooking feat/chocolate). Made by scratch/new-foods/chocolate/bin/gen.py. Melted milk chocolate +# uses the pack's cooking_chocolate; the mould uses the pie tin's tray texture. +info: + namespace: tfmc_cooking +items: + roasted_cocoa_beans: + display_name: "Roasted Cocoa Beans" + resource: + material: PAPER + generate: false + model_path: item/chocolate/roasted_cocoa_beans + roasted_cocoa_beans_burnt: + display_name: "Burnt Cocoa Beans" + resource: + material: PAPER + generate: false + model_path: item/chocolate/roasted_cocoa_beans_burnt + cocoa_powder: + display_name: "Cocoa Powder" + resource: + material: PAPER + generate: false + model_path: item/chocolate/cocoa_powder + cocoa_powder_pile: + display_name: "Cocoa Powder (Milling Stone)" + resource: + material: PAPER + generate: false + model_path: item/bulk/cocoa_powder + hot_chocolate: + display_name: "Hot Chocolate" + resource: + material: POTION + generate: false + model_path: item/chocolate/hot_chocolate + item_flags: + - HIDE_POTION_EFFECTS + melted_dark_chocolate: + display_name: "Melted Dark Chocolate" + resource: + material: PAPER + generate: false + model_path: item/chocolate/melted_dark_chocolate + chocolate_mould: + display_name: "Chocolate Mould" + resource: + material: PAPER + generate: false + model_path: furniture/chocolate_mould + milk_chocolate_bar: + display_name: "Milk Chocolate Bar" + resource: + material: PAPER + generate: false + model_path: item/chocolate/milk_chocolate_bar + chocolate_mould_fill_milk_chocolate: + display_name: "Milk Chocolate (Mould, Poured)" + resource: + material: PAPER + generate: false + model_path: item/chocolate/mould_fill_milk_chocolate + chocolate_mould_bars_milk_chocolate: + display_name: "Milk Chocolate Bars (Mould)" + resource: + material: PAPER + generate: false + model_path: item/chocolate/mould_bars_milk_chocolate + dark_chocolate_bar: + display_name: "Dark Chocolate Bar" + resource: + material: PAPER + generate: false + model_path: item/chocolate/dark_chocolate_bar + chocolate_mould_fill_dark_chocolate: + display_name: "Dark Chocolate (Mould, Poured)" + resource: + material: PAPER + generate: false + model_path: item/chocolate/mould_fill_dark_chocolate + chocolate_mould_bars_dark_chocolate: + display_name: "Dark Chocolate Bars (Mould)" + resource: + material: PAPER + generate: false + model_path: item/chocolate/mould_bars_dark_chocolate diff --git a/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/furniture/chocolate_mould.json b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/furniture/chocolate_mould.json new file mode 100644 index 0000000..7446d89 --- /dev/null +++ b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/furniture/chocolate_mould.json @@ -0,0 +1,659 @@ +{ + "credit": "TFMC chocolate: a tin mould for four bars", + "textures": { + "0": "tfmc_cooking:furniture/tray", + "particle": "tfmc_cooking:furniture/tray" + }, + "elements": [ + { + "from": [ + 2.0, + 0, + 4.5 + ], + "to": [ + 14.0, + 0.5, + 11.5 + ], + "faces": { + "north": { + "uv": [ + 0, + 0, + 16, + 1 + ], + "texture": "#0" + }, + "south": { + "uv": [ + 0, + 0, + 16, + 1 + ], + "texture": "#0" + }, + "east": { + "uv": [ + 0, + 0, + 16, + 1 + ], + "texture": "#0" + }, + "west": { + "uv": [ + 0, + 0, + 16, + 1 + ], + "texture": "#0" + }, + "up": { + "uv": [ + 2.0, + 4.5, + 14.0, + 11.5 + ], + "texture": "#0" + }, + "down": { + "uv": [ + 2.0, + 4.5, + 14.0, + 11.5 + ], + "texture": "#0" + } + } + }, + { + "from": [ + 2.0, + 0.5, + 4.5 + ], + "to": [ + 14.0, + 1.5, + 5.0 + ], + "faces": { + "north": { + "uv": [ + 0, + 0, + 16, + 1 + ], + "texture": "#0" + }, + "south": { + "uv": [ + 0, + 0, + 16, + 1 + ], + "texture": "#0" + }, + "east": { + "uv": [ + 0, + 0, + 16, + 1 + ], + "texture": "#0" + }, + "west": { + "uv": [ + 0, + 0, + 16, + 1 + ], + "texture": "#0" + }, + "up": { + "uv": [ + 2.0, + 4.5, + 14.0, + 5.0 + ], + "texture": "#0" + }, + "down": { + "uv": [ + 2.0, + 4.5, + 14.0, + 5.0 + ], + "texture": "#0" + } + } + }, + { + "from": [ + 2.0, + 0.5, + 11.0 + ], + "to": [ + 14.0, + 1.5, + 11.5 + ], + "faces": { + "north": { + "uv": [ + 0, + 0, + 16, + 1 + ], + "texture": "#0" + }, + "south": { + "uv": [ + 0, + 0, + 16, + 1 + ], + "texture": "#0" + }, + "east": { + "uv": [ + 0, + 0, + 16, + 1 + ], + "texture": "#0" + }, + "west": { + "uv": [ + 0, + 0, + 16, + 1 + ], + "texture": "#0" + }, + "up": { + "uv": [ + 2.0, + 11.0, + 14.0, + 11.5 + ], + "texture": "#0" + }, + "down": { + "uv": [ + 2.0, + 11.0, + 14.0, + 11.5 + ], + "texture": "#0" + } + } + }, + { + "from": [ + 2.0, + 0.5, + 5.0 + ], + "to": [ + 2.5, + 1.5, + 11.0 + ], + "faces": { + "north": { + "uv": [ + 0, + 0, + 16, + 1 + ], + "texture": "#0" + }, + "south": { + "uv": [ + 0, + 0, + 16, + 1 + ], + "texture": "#0" + }, + "east": { + "uv": [ + 0, + 0, + 16, + 1 + ], + "texture": "#0" + }, + "west": { + "uv": [ + 0, + 0, + 16, + 1 + ], + "texture": "#0" + }, + "up": { + "uv": [ + 2.0, + 5.0, + 2.5, + 11.0 + ], + "texture": "#0" + }, + "down": { + "uv": [ + 2.0, + 5.0, + 2.5, + 11.0 + ], + "texture": "#0" + } + } + }, + { + "from": [ + 13.5, + 0.5, + 5.0 + ], + "to": [ + 14.0, + 1.5, + 11.0 + ], + "faces": { + "north": { + "uv": [ + 0, + 0, + 16, + 1 + ], + "texture": "#0" + }, + "south": { + "uv": [ + 0, + 0, + 16, + 1 + ], + "texture": "#0" + }, + "east": { + "uv": [ + 0, + 0, + 16, + 1 + ], + "texture": "#0" + }, + "west": { + "uv": [ + 0, + 0, + 16, + 1 + ], + "texture": "#0" + }, + "up": { + "uv": [ + 13.5, + 5.0, + 14.0, + 11.0 + ], + "texture": "#0" + }, + "down": { + "uv": [ + 13.5, + 5.0, + 14.0, + 11.0 + ], + "texture": "#0" + } + } + }, + { + "from": [ + 4.875, + 0.5, + 5.0 + ], + "to": [ + 5.375, + 1.4, + 11.0 + ], + "faces": { + "north": { + "uv": [ + 0, + 0, + 16, + 1 + ], + "texture": "#0" + }, + "south": { + "uv": [ + 0, + 0, + 16, + 1 + ], + "texture": "#0" + }, + "east": { + "uv": [ + 0, + 0, + 16, + 1 + ], + "texture": "#0" + }, + "west": { + "uv": [ + 0, + 0, + 16, + 1 + ], + "texture": "#0" + }, + "up": { + "uv": [ + 4.875, + 5.0, + 5.375, + 11.0 + ], + "texture": "#0" + }, + "down": { + "uv": [ + 4.875, + 5.0, + 5.375, + 11.0 + ], + "texture": "#0" + } + } + }, + { + "from": [ + 7.75, + 0.5, + 5.0 + ], + "to": [ + 8.25, + 1.4, + 11.0 + ], + "faces": { + "north": { + "uv": [ + 0, + 0, + 16, + 1 + ], + "texture": "#0" + }, + "south": { + "uv": [ + 0, + 0, + 16, + 1 + ], + "texture": "#0" + }, + "east": { + "uv": [ + 0, + 0, + 16, + 1 + ], + "texture": "#0" + }, + "west": { + "uv": [ + 0, + 0, + 16, + 1 + ], + "texture": "#0" + }, + "up": { + "uv": [ + 7.75, + 5.0, + 8.25, + 11.0 + ], + "texture": "#0" + }, + "down": { + "uv": [ + 7.75, + 5.0, + 8.25, + 11.0 + ], + "texture": "#0" + } + } + }, + { + "from": [ + 10.625, + 0.5, + 5.0 + ], + "to": [ + 11.125, + 1.4, + 11.0 + ], + "faces": { + "north": { + "uv": [ + 0, + 0, + 16, + 1 + ], + "texture": "#0" + }, + "south": { + "uv": [ + 0, + 0, + 16, + 1 + ], + "texture": "#0" + }, + "east": { + "uv": [ + 0, + 0, + 16, + 1 + ], + "texture": "#0" + }, + "west": { + "uv": [ + 0, + 0, + 16, + 1 + ], + "texture": "#0" + }, + "up": { + "uv": [ + 10.625, + 5.0, + 11.125, + 11.0 + ], + "texture": "#0" + }, + "down": { + "uv": [ + 10.625, + 5.0, + 11.125, + 11.0 + ], + "texture": "#0" + } + } + } + ], + "display": { + "thirdperson_righthand": { + "rotation": [ + 50, + 0, + 0 + ], + "translation": [ + 0, + 3.25, + 1.75 + ], + "scale": [ + 0.5, + 0.5, + 0.5 + ] + }, + "thirdperson_lefthand": { + "rotation": [ + 50, + 0, + 0 + ], + "translation": [ + 0, + 3.25, + 1.75 + ], + "scale": [ + 0.5, + 0.5, + 0.5 + ] + }, + "firstperson_righthand": { + "translation": [ + 0, + 5.75, + 0 + ], + "scale": [ + 0.6, + 0.6, + 0.6 + ] + }, + "firstperson_lefthand": { + "translation": [ + 0, + 5.75, + 0 + ], + "scale": [ + 0.6, + 0.6, + 0.6 + ] + }, + "ground": { + "translation": [ + 0, + 3.75, + 0 + ], + "scale": [ + 0.5, + 0.5, + 0.5 + ] + }, + "gui": { + "rotation": [ + 30, + -135, + 0 + ], + "translation": [ + 0, + 3, + 0 + ], + "scale": [ + 0.85, + 0.85, + 0.85 + ] + }, + "fixed": { + "rotation": [ + -90, + 0, + 0 + ], + "translation": [ + 0, + 0, + -14 + ], + "scale": [ + 1.8, + 1.8, + 1.8 + ] + } + } +} \ No newline at end of file diff --git a/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/bulk/cocoa_powder.json b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/bulk/cocoa_powder.json new file mode 100644 index 0000000..b47fc73 --- /dev/null +++ b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/bulk/cocoa_powder.json @@ -0,0 +1,1107 @@ +{ + "credit": "TFMC chocolate: the flour heap in cocoa", + "textures": { + "0": "tfmc_cooking:item/bulk/cocoa_powder", + "particle": "tfmc_cooking:item/bulk/cocoa_powder" + }, + "elements": [ + { + "from": [ + 0, + 0, + 0 + ], + "to": [ + 16, + 1, + 16 + ], + "faces": { + "north": { + "uv": [ + 0, + 1, + 16, + 2 + ], + "texture": "#0" + }, + "east": { + "uv": [ + 0, + 1, + 16, + 2 + ], + "texture": "#0" + }, + "south": { + "uv": [ + 0, + 1, + 16, + 2 + ], + "texture": "#0" + }, + "west": { + "uv": [ + 0, + 1, + 16, + 2 + ], + "texture": "#0" + }, + "up": { + "uv": [ + 0, + 0, + 16, + 16 + ], + "texture": "#0" + }, + "down": { + "uv": [ + 0, + 0, + 16, + 16 + ], + "texture": "#0" + } + } + }, + { + "from": [ + 1, + 0.5, + 4 + ], + "to": [ + 14, + 1.5, + 6 + ], + "rotation": { + "angle": 0, + "axis": "y", + "origin": [ + 0, + 0.5, + 0 + ] + }, + "faces": { + "north": { + "uv": [ + 2, + 1, + 15, + 2 + ], + "texture": "#0" + }, + "east": { + "uv": [ + 10, + 1, + 12, + 2 + ], + "texture": "#0" + }, + "south": { + "uv": [ + 1, + 1, + 14, + 2 + ], + "texture": "#0" + }, + "west": { + "uv": [ + 4, + 1, + 6, + 2 + ], + "texture": "#0" + }, + "up": { + "uv": [ + 1, + 4, + 14, + 6 + ], + "texture": "#0" + }, + "down": { + "uv": [ + 1, + 10, + 14, + 12 + ], + "texture": "#0" + } + } + }, + { + "from": [ + 3, + 0.5, + 2 + ], + "to": [ + 13, + 1.5, + 4 + ], + "rotation": { + "angle": 0, + "axis": "y", + "origin": [ + 0, + 0.5, + -2 + ] + }, + "faces": { + "north": { + "uv": [ + 3, + 1, + 13, + 2 + ], + "texture": "#0" + }, + "east": { + "uv": [ + 10, + 1, + 12, + 2 + ], + "texture": "#0" + }, + "south": { + "uv": [ + 3, + 1, + 13, + 2 + ], + "texture": "#0" + }, + "west": { + "uv": [ + 4, + 1, + 6, + 2 + ], + "texture": "#0" + }, + "up": { + "uv": [ + 3, + 4, + 13, + 6 + ], + "texture": "#0" + }, + "down": { + "uv": [ + 3, + 10, + 13, + 12 + ], + "texture": "#0" + } + } + }, + { + "from": [ + 2, + 0.5, + 6 + ], + "to": [ + 12, + 1.5, + 13 + ], + "rotation": { + "angle": 0, + "axis": "y", + "origin": [ + 0, + 0.5, + 4 + ] + }, + "faces": { + "north": { + "uv": [ + 4, + 1, + 14, + 2 + ], + "texture": "#0" + }, + "east": { + "uv": [ + 7, + 1, + 14, + 2 + ], + "texture": "#0" + }, + "south": { + "uv": [ + 2, + 1, + 12, + 2 + ], + "texture": "#0" + }, + "west": { + "uv": [ + 2, + 1, + 9, + 2 + ], + "texture": "#0" + }, + "up": { + "uv": [ + 2, + 2, + 12, + 9 + ], + "texture": "#0" + }, + "down": { + "uv": [ + 2, + 7, + 12, + 14 + ], + "texture": "#0" + } + } + }, + { + "from": [ + 12, + 0.5, + 6 + ], + "to": [ + 15, + 1.5, + 12 + ], + "rotation": { + "angle": 0, + "axis": "y", + "origin": [ + 11, + 0.5, + 4 + ] + }, + "faces": { + "north": { + "uv": [ + 12, + 1, + 15, + 2 + ], + "texture": "#0" + }, + "east": { + "uv": [ + 8, + 1, + 14, + 2 + ], + "texture": "#0" + }, + "south": { + "uv": [ + 1, + 1, + 4, + 2 + ], + "texture": "#0" + }, + "west": { + "uv": [ + 2, + 1, + 8, + 2 + ], + "texture": "#0" + }, + "up": { + "uv": [ + 1, + 2, + 4, + 8 + ], + "texture": "#0" + }, + "down": { + "uv": [ + 1, + 8, + 4, + 14 + ], + "texture": "#0" + } + } + }, + { + "from": [ + 3, + 1, + 6 + ], + "to": [ + 13, + 2, + 10 + ], + "rotation": { + "angle": 0, + "axis": "y", + "origin": [ + 3, + 0, + 6 + ] + }, + "faces": { + "north": { + "uv": [ + 0, + 0, + 10, + 1 + ], + "texture": "#0" + }, + "east": { + "uv": [ + 0, + 0, + 4, + 1 + ], + "texture": "#0" + }, + "south": { + "uv": [ + 0, + 0, + 10, + 1 + ], + "texture": "#0" + }, + "west": { + "uv": [ + 0, + 0, + 4, + 1 + ], + "texture": "#0" + }, + "up": { + "uv": [ + 0, + 0, + 10, + 4 + ], + "texture": "#0" + }, + "down": { + "uv": [ + 0, + 0, + 10, + 4 + ], + "texture": "#0" + } + } + }, + { + "from": [ + 8, + 1.5, + 7 + ], + "to": [ + 12, + 2.5, + 10 + ], + "rotation": { + "angle": 0, + "axis": "y", + "origin": [ + 3, + 0.5, + 6 + ] + }, + "faces": { + "north": { + "uv": [ + 1, + 0, + 5, + 1 + ], + "texture": "#0" + }, + "east": { + "uv": [ + 0, + 0, + 3, + 1 + ], + "texture": "#0" + }, + "south": { + "uv": [ + 5, + 0, + 9, + 1 + ], + "texture": "#0" + }, + "west": { + "uv": [ + 1, + 0, + 4, + 1 + ], + "texture": "#0" + }, + "up": { + "uv": [ + 5, + 1, + 9, + 4 + ], + "texture": "#0" + }, + "down": { + "uv": [ + 5, + 0, + 9, + 3 + ], + "texture": "#0" + } + } + }, + { + "from": [ + 6, + 1.5, + 7 + ], + "to": [ + 8, + 2.5, + 11 + ], + "rotation": { + "angle": 0, + "axis": "y", + "origin": [ + -2, + 0.5, + 6 + ] + }, + "faces": { + "north": { + "uv": [ + 0, + 0, + 2, + 1 + ], + "texture": "#0" + }, + "east": { + "uv": [ + 0, + 0, + 4, + 1 + ], + "texture": "#0" + }, + "south": { + "uv": [ + 8, + 0, + 10, + 1 + ], + "texture": "#0" + }, + "west": { + "uv": [ + 1, + 0, + 5, + 1 + ], + "texture": "#0" + }, + "up": { + "uv": [ + 8, + 1, + 10, + 5 + ], + "texture": "#0" + }, + "down": { + "uv": [ + 8, + 0, + 10, + 4 + ], + "texture": "#0" + } + } + }, + { + "from": [ + 6, + 2, + 6 + ], + "to": [ + 9, + 3, + 9 + ], + "rotation": { + "angle": 0, + "axis": "y", + "origin": [ + -2, + 1, + 6 + ] + }, + "faces": { + "north": { + "uv": [ + 0, + 0, + 3, + 1 + ], + "texture": "#0" + }, + "east": { + "uv": [ + 2, + 0, + 5, + 1 + ], + "texture": "#0" + }, + "south": { + "uv": [ + 8, + 0, + 11, + 1 + ], + "texture": "#0" + }, + "west": { + "uv": [ + 0, + 0, + 3, + 1 + ], + "texture": "#0" + }, + "up": { + "uv": [ + 8, + 0, + 11, + 3 + ], + "texture": "#0" + }, + "down": { + "uv": [ + 8, + 2, + 11, + 5 + ], + "texture": "#0" + } + } + }, + { + "from": [ + 5, + 1.5, + 5 + ], + "to": [ + 10, + 2.5, + 7 + ], + "rotation": { + "angle": 0, + "axis": "y", + "origin": [ + 1, + 0.5, + 3 + ] + }, + "faces": { + "north": { + "uv": [ + 1, + 0, + 6, + 1 + ], + "texture": "#0" + }, + "east": { + "uv": [ + 0, + 0, + 2, + 1 + ], + "texture": "#0" + }, + "south": { + "uv": [ + 4, + 0, + 9, + 1 + ], + "texture": "#0" + }, + "west": { + "uv": [ + 2, + 0, + 4, + 1 + ], + "texture": "#0" + }, + "up": { + "uv": [ + 4, + 2, + 9, + 4 + ], + "texture": "#0" + }, + "down": { + "uv": [ + 4, + 0, + 9, + 2 + ], + "texture": "#0" + } + } + }, + { + "from": [ + 4, + 1, + 4 + ], + "to": [ + 11, + 2, + 6 + ], + "rotation": { + "angle": 0, + "axis": "y", + "origin": [ + 2, + 0, + 3 + ] + }, + "faces": { + "north": { + "uv": [ + 1, + 0, + 8, + 1 + ], + "texture": "#0" + }, + "east": { + "uv": [ + 1, + 0, + 3, + 1 + ], + "texture": "#0" + }, + "south": { + "uv": [ + 2, + 0, + 9, + 1 + ], + "texture": "#0" + }, + "west": { + "uv": [ + 1, + 0, + 3, + 1 + ], + "texture": "#0" + }, + "up": { + "uv": [ + 2, + 1, + 9, + 3 + ], + "texture": "#0" + }, + "down": { + "uv": [ + 2, + 1, + 9, + 3 + ], + "texture": "#0" + } + } + }, + { + "from": [ + 6, + 1, + 3 + ], + "to": [ + 9, + 2, + 4 + ], + "rotation": { + "angle": 0, + "axis": "y", + "origin": [ + 2, + 0, + 1 + ] + }, + "faces": { + "north": { + "uv": [ + 3, + 0, + 6, + 1 + ], + "texture": "#0" + }, + "east": { + "uv": [ + 1, + 0, + 2, + 1 + ], + "texture": "#0" + }, + "south": { + "uv": [ + 4, + 0, + 7, + 1 + ], + "texture": "#0" + }, + "west": { + "uv": [ + 2, + 0, + 3, + 1 + ], + "texture": "#0" + }, + "up": { + "uv": [ + 4, + 2, + 7, + 3 + ], + "texture": "#0" + }, + "down": { + "uv": [ + 4, + 1, + 7, + 2 + ], + "texture": "#0" + } + } + }, + { + "from": [ + 5, + 1, + 10 + ], + "to": [ + 12, + 2, + 12 + ], + "rotation": { + "angle": 0, + "axis": "y", + "origin": [ + 3, + 0, + 9 + ] + }, + "faces": { + "north": { + "uv": [ + 1, + 0, + 8, + 1 + ], + "texture": "#0" + }, + "east": { + "uv": [ + 1, + 0, + 3, + 1 + ], + "texture": "#0" + }, + "south": { + "uv": [ + 2, + 0, + 9, + 1 + ], + "texture": "#0" + }, + "west": { + "uv": [ + 1, + 0, + 3, + 1 + ], + "texture": "#0" + }, + "up": { + "uv": [ + 2, + 1, + 9, + 3 + ], + "texture": "#0" + }, + "down": { + "uv": [ + 2, + 1, + 9, + 3 + ], + "texture": "#0" + } + } + } + ], + "display": { + "thirdperson_righthand": { + "rotation": [ + 50, + 0, + 0 + ], + "translation": [ + 0, + 3.25, + 1.75 + ], + "scale": [ + 0.5, + 0.5, + 0.5 + ] + }, + "thirdperson_lefthand": { + "rotation": [ + 50, + 0, + 0 + ], + "translation": [ + 0, + 3.25, + 1.75 + ], + "scale": [ + 0.5, + 0.5, + 0.5 + ] + }, + "firstperson_righthand": { + "translation": [ + 0, + 5.75, + 0 + ], + "scale": [ + 0.6, + 0.6, + 0.6 + ] + }, + "firstperson_lefthand": { + "translation": [ + 0, + 5.75, + 0 + ], + "scale": [ + 0.6, + 0.6, + 0.6 + ] + }, + "ground": { + "translation": [ + 0, + 3.75, + 0 + ], + "scale": [ + 0.5, + 0.5, + 0.5 + ] + }, + "gui": { + "rotation": [ + 29, + -143, + 0 + ], + "translation": [ + 0, + 1.75, + 0 + ], + "scale": [ + 0.5, + 0.5, + 0.5 + ] + }, + "fixed": { + "rotation": [ + -90, + 0, + 0 + ], + "translation": [ + 0, + 0, + -14 + ], + "scale": [ + 2, + 2, + 2 + ] + } + } +} \ No newline at end of file diff --git a/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/chocolate/cocoa_powder.json b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/chocolate/cocoa_powder.json new file mode 100644 index 0000000..1ec1825 --- /dev/null +++ b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/chocolate/cocoa_powder.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "tfmc_cooking:item/chocolate/cocoa_powder" + } +} \ No newline at end of file diff --git a/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/chocolate/dark_chocolate_bar.json b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/chocolate/dark_chocolate_bar.json new file mode 100644 index 0000000..e98a3e8 --- /dev/null +++ b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/chocolate/dark_chocolate_bar.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "tfmc_cooking:item/chocolate/dark_chocolate_bar" + } +} \ No newline at end of file diff --git a/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/chocolate/hot_chocolate.json b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/chocolate/hot_chocolate.json new file mode 100644 index 0000000..0fbc856 --- /dev/null +++ b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/chocolate/hot_chocolate.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "tfmc_cooking:item/chocolate/hot_chocolate" + } +} \ No newline at end of file diff --git a/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/chocolate/melted_dark_chocolate.json b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/chocolate/melted_dark_chocolate.json new file mode 100644 index 0000000..d5c9434 --- /dev/null +++ b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/chocolate/melted_dark_chocolate.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "tfmc_cooking:item/chocolate/melted_dark_chocolate" + } +} \ No newline at end of file diff --git a/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/chocolate/milk_chocolate_bar.json b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/chocolate/milk_chocolate_bar.json new file mode 100644 index 0000000..5013c3c --- /dev/null +++ b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/chocolate/milk_chocolate_bar.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "tfmc_cooking:item/chocolate/milk_chocolate_bar" + } +} \ No newline at end of file diff --git a/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/chocolate/mould_bars_dark_chocolate.json b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/chocolate/mould_bars_dark_chocolate.json new file mode 100644 index 0000000..083683a --- /dev/null +++ b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/chocolate/mould_bars_dark_chocolate.json @@ -0,0 +1,281 @@ +{ + "credit": "TFMC chocolate: four set bars lying in the mould", + "textures": { + "c": "tfmc_cooking:item/chocolate/dark_chocolate_solid", + "particle": "tfmc_cooking:item/chocolate/dark_chocolate_solid" + }, + "elements": [ + { + "from": [ + 2.5, + 0.5, + 5.0 + ], + "to": [ + 4.875, + 1.6, + 11.0 + ], + "faces": { + "north": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "south": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "east": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "west": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "up": { + "uv": [ + 4, + 0, + 12, + 16 + ], + "texture": "#c" + }, + "down": { + "uv": [ + 2.5, + 5.0, + 4.875, + 11.0 + ], + "texture": "#c" + } + } + }, + { + "from": [ + 5.375, + 0.5, + 5.0 + ], + "to": [ + 7.75, + 1.6, + 11.0 + ], + "faces": { + "north": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "south": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "east": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "west": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "up": { + "uv": [ + 4, + 0, + 12, + 16 + ], + "texture": "#c" + }, + "down": { + "uv": [ + 5.375, + 5.0, + 7.75, + 11.0 + ], + "texture": "#c" + } + } + }, + { + "from": [ + 8.25, + 0.5, + 5.0 + ], + "to": [ + 10.625, + 1.6, + 11.0 + ], + "faces": { + "north": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "south": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "east": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "west": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "up": { + "uv": [ + 4, + 0, + 12, + 16 + ], + "texture": "#c" + }, + "down": { + "uv": [ + 8.25, + 5.0, + 10.625, + 11.0 + ], + "texture": "#c" + } + } + }, + { + "from": [ + 11.125, + 0.5, + 5.0 + ], + "to": [ + 13.5, + 1.6, + 11.0 + ], + "faces": { + "north": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "south": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "east": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "west": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "up": { + "uv": [ + 4, + 0, + 12, + 16 + ], + "texture": "#c" + }, + "down": { + "uv": [ + 11.125, + 5.0, + 13.5, + 11.0 + ], + "texture": "#c" + } + } + } + ] +} \ No newline at end of file diff --git a/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/chocolate/mould_bars_milk_chocolate.json b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/chocolate/mould_bars_milk_chocolate.json new file mode 100644 index 0000000..ca24fdd --- /dev/null +++ b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/chocolate/mould_bars_milk_chocolate.json @@ -0,0 +1,281 @@ +{ + "credit": "TFMC chocolate: four set bars lying in the mould", + "textures": { + "c": "tfmc_cooking:item/chocolate/milk_chocolate_solid", + "particle": "tfmc_cooking:item/chocolate/milk_chocolate_solid" + }, + "elements": [ + { + "from": [ + 2.5, + 0.5, + 5.0 + ], + "to": [ + 4.875, + 1.6, + 11.0 + ], + "faces": { + "north": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "south": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "east": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "west": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "up": { + "uv": [ + 4, + 0, + 12, + 16 + ], + "texture": "#c" + }, + "down": { + "uv": [ + 2.5, + 5.0, + 4.875, + 11.0 + ], + "texture": "#c" + } + } + }, + { + "from": [ + 5.375, + 0.5, + 5.0 + ], + "to": [ + 7.75, + 1.6, + 11.0 + ], + "faces": { + "north": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "south": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "east": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "west": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "up": { + "uv": [ + 4, + 0, + 12, + 16 + ], + "texture": "#c" + }, + "down": { + "uv": [ + 5.375, + 5.0, + 7.75, + 11.0 + ], + "texture": "#c" + } + } + }, + { + "from": [ + 8.25, + 0.5, + 5.0 + ], + "to": [ + 10.625, + 1.6, + 11.0 + ], + "faces": { + "north": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "south": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "east": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "west": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "up": { + "uv": [ + 4, + 0, + 12, + 16 + ], + "texture": "#c" + }, + "down": { + "uv": [ + 8.25, + 5.0, + 10.625, + 11.0 + ], + "texture": "#c" + } + } + }, + { + "from": [ + 11.125, + 0.5, + 5.0 + ], + "to": [ + 13.5, + 1.6, + 11.0 + ], + "faces": { + "north": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "south": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "east": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "west": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "up": { + "uv": [ + 4, + 0, + 12, + 16 + ], + "texture": "#c" + }, + "down": { + "uv": [ + 11.125, + 5.0, + 13.5, + 11.0 + ], + "texture": "#c" + } + } + } + ] +} \ No newline at end of file diff --git a/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/chocolate/mould_fill_dark_chocolate.json b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/chocolate/mould_fill_dark_chocolate.json new file mode 100644 index 0000000..e55dac2 --- /dev/null +++ b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/chocolate/mould_fill_dark_chocolate.json @@ -0,0 +1,281 @@ +{ + "credit": "TFMC chocolate: melted chocolate poured into the mould", + "textures": { + "c": "tfmc_cooking:item/chocolate/dark_chocolate_melted", + "particle": "tfmc_cooking:item/chocolate/dark_chocolate_melted" + }, + "elements": [ + { + "from": [ + 2.5, + 0.5, + 5.0 + ], + "to": [ + 4.875, + 1.25, + 11.0 + ], + "faces": { + "north": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "south": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "east": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "west": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "up": { + "uv": [ + 0, + 0, + 16, + 16 + ], + "texture": "#c" + }, + "down": { + "uv": [ + 2.5, + 5.0, + 4.875, + 11.0 + ], + "texture": "#c" + } + } + }, + { + "from": [ + 5.375, + 0.5, + 5.0 + ], + "to": [ + 7.75, + 1.25, + 11.0 + ], + "faces": { + "north": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "south": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "east": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "west": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "up": { + "uv": [ + 0, + 0, + 16, + 16 + ], + "texture": "#c" + }, + "down": { + "uv": [ + 5.375, + 5.0, + 7.75, + 11.0 + ], + "texture": "#c" + } + } + }, + { + "from": [ + 8.25, + 0.5, + 5.0 + ], + "to": [ + 10.625, + 1.25, + 11.0 + ], + "faces": { + "north": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "south": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "east": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "west": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "up": { + "uv": [ + 0, + 0, + 16, + 16 + ], + "texture": "#c" + }, + "down": { + "uv": [ + 8.25, + 5.0, + 10.625, + 11.0 + ], + "texture": "#c" + } + } + }, + { + "from": [ + 11.125, + 0.5, + 5.0 + ], + "to": [ + 13.5, + 1.25, + 11.0 + ], + "faces": { + "north": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "south": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "east": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "west": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "up": { + "uv": [ + 0, + 0, + 16, + 16 + ], + "texture": "#c" + }, + "down": { + "uv": [ + 11.125, + 5.0, + 13.5, + 11.0 + ], + "texture": "#c" + } + } + } + ] +} \ No newline at end of file diff --git a/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/chocolate/mould_fill_milk_chocolate.json b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/chocolate/mould_fill_milk_chocolate.json new file mode 100644 index 0000000..e9de53a --- /dev/null +++ b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/chocolate/mould_fill_milk_chocolate.json @@ -0,0 +1,281 @@ +{ + "credit": "TFMC chocolate: melted chocolate poured into the mould", + "textures": { + "c": "tfmc_cooking:item/chocolate/milk_chocolate_melted", + "particle": "tfmc_cooking:item/chocolate/milk_chocolate_melted" + }, + "elements": [ + { + "from": [ + 2.5, + 0.5, + 5.0 + ], + "to": [ + 4.875, + 1.25, + 11.0 + ], + "faces": { + "north": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "south": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "east": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "west": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "up": { + "uv": [ + 0, + 0, + 16, + 16 + ], + "texture": "#c" + }, + "down": { + "uv": [ + 2.5, + 5.0, + 4.875, + 11.0 + ], + "texture": "#c" + } + } + }, + { + "from": [ + 5.375, + 0.5, + 5.0 + ], + "to": [ + 7.75, + 1.25, + 11.0 + ], + "faces": { + "north": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "south": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "east": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "west": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "up": { + "uv": [ + 0, + 0, + 16, + 16 + ], + "texture": "#c" + }, + "down": { + "uv": [ + 5.375, + 5.0, + 7.75, + 11.0 + ], + "texture": "#c" + } + } + }, + { + "from": [ + 8.25, + 0.5, + 5.0 + ], + "to": [ + 10.625, + 1.25, + 11.0 + ], + "faces": { + "north": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "south": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "east": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "west": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "up": { + "uv": [ + 0, + 0, + 16, + 16 + ], + "texture": "#c" + }, + "down": { + "uv": [ + 8.25, + 5.0, + 10.625, + 11.0 + ], + "texture": "#c" + } + } + }, + { + "from": [ + 11.125, + 0.5, + 5.0 + ], + "to": [ + 13.5, + 1.25, + 11.0 + ], + "faces": { + "north": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "south": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "east": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "west": { + "uv": [ + 0, + 0, + 16, + 2 + ], + "texture": "#c" + }, + "up": { + "uv": [ + 0, + 0, + 16, + 16 + ], + "texture": "#c" + }, + "down": { + "uv": [ + 11.125, + 5.0, + 13.5, + 11.0 + ], + "texture": "#c" + } + } + } + ] +} \ No newline at end of file diff --git a/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/chocolate/roasted_cocoa_beans.json b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/chocolate/roasted_cocoa_beans.json new file mode 100644 index 0000000..0ee8d56 --- /dev/null +++ b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/chocolate/roasted_cocoa_beans.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "tfmc_cooking:item/chocolate/roasted_cocoa_beans" + } +} \ No newline at end of file diff --git a/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/chocolate/roasted_cocoa_beans_burnt.json b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/chocolate/roasted_cocoa_beans_burnt.json new file mode 100644 index 0000000..c55ef85 --- /dev/null +++ b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/models/item/chocolate/roasted_cocoa_beans_burnt.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "tfmc_cooking:item/chocolate/roasted_cocoa_beans_burnt" + } +} \ No newline at end of file diff --git a/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/bulk/cocoa_powder.png b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/bulk/cocoa_powder.png new file mode 100644 index 0000000..4004884 Binary files /dev/null and b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/bulk/cocoa_powder.png differ diff --git a/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/chocolate/cocoa_powder.png b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/chocolate/cocoa_powder.png new file mode 100644 index 0000000..b082cb8 Binary files /dev/null and b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/chocolate/cocoa_powder.png differ diff --git a/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/chocolate/dark_chocolate_bar.png b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/chocolate/dark_chocolate_bar.png new file mode 100644 index 0000000..aeb553d Binary files /dev/null and b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/chocolate/dark_chocolate_bar.png differ diff --git a/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/chocolate/dark_chocolate_melted.png b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/chocolate/dark_chocolate_melted.png new file mode 100644 index 0000000..beb8445 Binary files /dev/null and b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/chocolate/dark_chocolate_melted.png differ diff --git a/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/chocolate/dark_chocolate_solid.png b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/chocolate/dark_chocolate_solid.png new file mode 100644 index 0000000..e44810d Binary files /dev/null and b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/chocolate/dark_chocolate_solid.png differ diff --git a/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/chocolate/hot_chocolate.png b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/chocolate/hot_chocolate.png new file mode 100644 index 0000000..0a99f20 Binary files /dev/null and b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/chocolate/hot_chocolate.png differ diff --git a/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/chocolate/melted_dark_chocolate.png b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/chocolate/melted_dark_chocolate.png new file mode 100644 index 0000000..3436557 Binary files /dev/null and b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/chocolate/melted_dark_chocolate.png differ diff --git a/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/chocolate/milk_chocolate_bar.png b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/chocolate/milk_chocolate_bar.png new file mode 100644 index 0000000..0e4f2e2 Binary files /dev/null and b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/chocolate/milk_chocolate_bar.png differ diff --git a/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/chocolate/milk_chocolate_melted.png b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/chocolate/milk_chocolate_melted.png new file mode 100644 index 0000000..23df881 Binary files /dev/null and b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/chocolate/milk_chocolate_melted.png differ diff --git a/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/chocolate/milk_chocolate_solid.png b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/chocolate/milk_chocolate_solid.png new file mode 100644 index 0000000..5707a42 Binary files /dev/null and b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/chocolate/milk_chocolate_solid.png differ diff --git a/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/chocolate/roasted_cocoa_beans.png b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/chocolate/roasted_cocoa_beans.png new file mode 100644 index 0000000..e5262b6 Binary files /dev/null and b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/chocolate/roasted_cocoa_beans.png differ diff --git a/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/chocolate/roasted_cocoa_beans_burnt.png b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/chocolate/roasted_cocoa_beans_burnt.png new file mode 100644 index 0000000..5f42d82 Binary files /dev/null and b/ItemsAdder/tfmc_cooking/resourcepack/assets/tfmc_cooking/textures/item/chocolate/roasted_cocoa_beans_burnt.png differ diff --git a/README.md b/README.md index 6678a06..05922a8 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ Cooking makes food an interactive part of everyday life. Players grow and gather - **Working kitchens** — fry, boil, prepare sauces and soups, and bake with cookware, heat sources, and fuelled ovens. Leaving food cooking too long can burn it. The frying pan fries eggs, grills mushrooms and pops chopped corn into popcorn: a cooking option can name the food a piece turns into once it is done (`output` in `types.yml`). - **Popcorn machine** — put up to 16 corn (one per right-click) and up to two toppings (caramel, sugar, butter, salt) in a popcorn machine and start it with an empty hand: the kettle rattles, kernels pop out and land on a rising heap behind the glass. Once it stops, a right-click takes out 4 popcorn per corn, each with its corn's stars and every topping (Salted Caramel Popcorn) (`popcorn-machines.yml`). Caramel is sugar and butter boiled in a cup of water in the saucepan and bottled (`condiments.yml`). +- **Chocolate** — cocoa beans roast in the frying pan and are ground on the milling stone into cocoa powder. Boil a cup of milk with cocoa powder and a sweetener in the saucepan and fill an empty cup with hot chocolate, which you drink and keep the cup (`returns` in `types.yml`). Add butter and take it out with a bowl as melted milk chocolate (a cup of water makes it dark), pour it into a chocolate mould and cut it into 4 bars with the knife (`crafting-stations.yml`). Vanilla, cinnamon and nutmeg boiled in with them flavour and name them, Cinnamon Hot Chocolate or Vanilla Milk Chocolate Bar (`extras` and `container` on the saucepan's `bottles` in `condiments.yml`); cinnamon and vanilla also top popcorn. - **Food preparation** — milling stones, mixing bowls, butter churns, sausage makers, and baking trays provide different ways to transform ingredients. - **Sandwiches** — lay a slice of bread on a cutting board, add spreads, cheese and vegetables, close it with another slice and pick it up. Its fillings name it, and its food, quality and freshness come from its layers (`sandwiches.yml`). Its layers also earn it bonuses such as Hearty, Buttered or Well-Rounded (`bonuses` in `sandwiches.yml`). Fried meat goes in too: fried beef makes it a Hamburger (a Cheeseburger with cheese), and fried pork with lettuce and tomato a BLT (`kinds` in `sandwiches.yml`). - **Pizzas** — place a pizza peel, put dough on it, spread a paste and add cheese, vegetables, fruit, sausage and spices, then carry the peel into a lit oven to bake. A baked pizza is taken off a slice at a time. Its toppings name it, and its food, quality and freshness come from its layers (`pizzas.yml`). Its toppings also earn it bonuses such as Saucy, Extra Cheesy or Well Seasoned (`bonuses` in `pizzas.yml`). diff --git a/src/main/java/net/tfminecraft/cooking/condiment/BottleRecipe.java b/src/main/java/net/tfminecraft/cooking/condiment/BottleRecipe.java index 8350d49..2a462e5 100644 --- a/src/main/java/net/tfminecraft/cooking/condiment/BottleRecipe.java +++ b/src/main/java/net/tfminecraft/cooking/condiment/BottleRecipe.java @@ -2,17 +2,26 @@ import java.util.ArrayList; import java.util.Collection; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; +import org.bukkit.Material; import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.inventory.ItemStack; +import net.tfminecraft.tlibs.TLibs; import net.tfminecraft.cooking.item.CookingPathHandler; import net.tfminecraft.cooking.item.FoodItem; +import net.tfminecraft.cooking.item.tag.TagTrack; +import net.tfminecraft.cooking.loader.TrackLoader; /** * A saucepan bottling from condiments.yml: what the saucepan holds (its liquid and exactly these ingredients) and the * food an empty glass bottle takes out once it has boiled long enough. Paths are Cooking food paths (c.paste(origin=Tomato)); - * the liquid {@value #WATER} is a cup of water, which isn't food. + * the liquid {@value #WATER} is a cup of water, which isn't food. Extras (vanilla in hot chocolate) may go in once each + * besides the ingredients and give the output their tags.yml track; a container other than a glass bottle (an empty + * cup, a bowl) takes the output instead. */ public final class BottleRecipe { /** The liquid line for a saucepan filled with a cup of water (bone stock). */ @@ -23,6 +32,11 @@ public final class BottleRecipe { private final List ingredients; private final int boilSeconds; private final String output; + /** Extra path -> the tags.yml track it gives the output. */ + private final Map extras = new LinkedHashMap<>(); + /** The item path that takes the output, or null for an empty glass bottle. */ + private final String container; + private final String containerName; public BottleRecipe(String id, ConfigurationSection config) { this.id = id; @@ -30,6 +44,17 @@ public BottleRecipe(String id, ConfigurationSection config) { this.ingredients = config.getStringList("ingredients"); this.boilSeconds = Math.max(0, config.getInt("boil-seconds", 30)); this.output = config.getString("output", ""); + ConfigurationSection extraSection = config.getConfigurationSection("extras"); + if (extraSection != null) { + for (String key : extraSection.getKeys(false)) { + ConfigurationSection extra = extraSection.getConfigurationSection(key); + if (extra == null || extra.getString("path", "").isBlank()) continue; + extras.put(extra.getString("path"), extra.getString("track", "")); + } + } + String path = config.getString("container", ""); + this.container = path.isBlank() ? null : path; + this.containerName = config.getString("container-name", container == null ? "an empty glass bottle" : "an empty cup"); } public String getId() { @@ -45,43 +70,83 @@ public String getOutput() { return output; } + /** How a player reads the container that takes the output ("an empty cup"). */ + public String getContainerName() { + return containerName; + } + + /** True when this held item takes the output: the recipe's container, or else a plain empty glass bottle. */ + public boolean takesContainer(ItemStack item) { + if (item == null) return false; + if (container == null) return item.getType() == Material.GLASS_BOTTLE; + return TLibs.getItemAPI().getChecker().checkItemWithPath(item, container); + } + + /** True when this held item is the container of some recipe (so it's for bottling, not an ingredient). */ + public boolean isContainer(ItemStack item) { + return container != null && takesContainer(item); + } + + /** Gives the output the track of each extra in the saucepan, at its first step (Vanilla Hot Chocolate). */ + public void applyExtras(FoodItem output, Collection present) { + for (String extra : sort(present).extras) { + TagTrack track = TrackLoader.getByString(extras.get(extra)); + if (track == null) continue; + track = new TagTrack(track); + track.setValue(0); + output.addOrModifyTrack(track); + } + } + /** True when the saucepan's liquid is this recipe's: the poured food, or a cup of water for {@value #WATER}. */ public boolean usesLiquid(FoodItem liquidFood, boolean water) { if (WATER.equalsIgnoreCase(liquid.trim())) return water; return CookingPathHandler.matches(liquidFood, liquid); } - /** True when this food is one of the recipe's ingredients not already in the saucepan. */ + /** True when this food is one of the recipe's ingredients or extras not already in the saucepan. */ public boolean takes(FoodItem candidate, Collection present) { - List open = unmatched(present); - if (open == null) return false; - for (String path : open) { - if (CookingPathHandler.matches(candidate, path)) return true; - } - return false; + Sorted sorted = sort(present); + if (!sorted.fits) return false; + if (firstMatch(sorted.open, candidate) != null) return true; + String extra = firstMatch(extras.keySet(), candidate); + return extra != null && !sorted.extras.contains(extra); } - /** The saucepan holds this liquid and exactly these ingredients, each once. */ + /** The saucepan holds this liquid and exactly these ingredients, each once, and any extras once each. */ public boolean matches(FoodItem liquidFood, boolean water, Collection present) { if (!usesLiquid(liquidFood, water)) return false; - List open = unmatched(present); - return open != null && open.isEmpty(); + Sorted sorted = sort(present); + return sorted.fits && sorted.open.isEmpty(); } - /** The ingredient paths no food in the saucepan fills yet, or null when something in it isn't part of the recipe. */ - private List unmatched(Collection present) { + /** + * Sorts what's in the saucepan into the ingredient paths still open and the extras in it. It doesn't fit when + * something is neither an open ingredient nor an extra not in yet. + */ + private Sorted sort(Collection present) { List open = new ArrayList<>(ingredients); + List used = new ArrayList<>(); + boolean fits = true; for (FoodItem food : present) { - String filled = null; - for (String path : open) { - if (CookingPathHandler.matches(food, path)) { - filled = path; - break; - } + String filled = firstMatch(open, food); + if (filled != null) { + open.remove(filled); + continue; } - if (filled == null) return null; - open.remove(filled); + String extra = firstMatch(extras.keySet(), food); + if (extra == null || used.contains(extra)) fits = false; + else used.add(extra); + } + return new Sorted(open, used, fits); + } + + private record Sorted(List open, List extras, boolean fits) {} + + private static String firstMatch(Collection paths, FoodItem food) { + for (String path : paths) { + if (CookingPathHandler.matches(food, path)) return path; } - return open; + return null; } } diff --git a/src/main/java/net/tfminecraft/cooking/condiment/CondimentConfig.java b/src/main/java/net/tfminecraft/cooking/condiment/CondimentConfig.java index e34fcac..3e622c2 100644 --- a/src/main/java/net/tfminecraft/cooking/condiment/CondimentConfig.java +++ b/src/main/java/net/tfminecraft/cooking/condiment/CondimentConfig.java @@ -12,6 +12,7 @@ import org.bukkit.Material; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.inventory.ItemStack; import net.tfminecraft.cooking.item.CookingPathHandler; import net.tfminecraft.cooking.item.FoodItem; @@ -110,6 +111,14 @@ public static boolean isSaucepanLiquid(FoodItem food) { return false; } + /** True for an item some bottling takes its output out with instead of a glass bottle (an empty cup, a bowl). */ + public static boolean isBottlingContainer(ItemStack item) { + for (BottleRecipe recipe : bottles) { + if (recipe.isContainer(item)) return true; + } + return false; + } + public static List bottles() { return bottles; } diff --git a/src/main/java/net/tfminecraft/cooking/cooking/SauceReference.java b/src/main/java/net/tfminecraft/cooking/cooking/SauceReference.java index 02b9ede..9713e8d 100644 --- a/src/main/java/net/tfminecraft/cooking/cooking/SauceReference.java +++ b/src/main/java/net/tfminecraft/cooking/cooking/SauceReference.java @@ -399,8 +399,9 @@ public void interact(FurnitureInteractEvent e) { } - if (item.getType() == Material.GLASS_BOTTLE && FoodItem.fromItem(item) == null) { - bottle(p); + if (FoodItem.fromItem(item) == null + && (item.getType() == Material.GLASS_BOTTLE || CondimentConfig.isBottlingContainer(item))) { + bottle(p, item); return; } FoodItem bottled = secondaries.containsKey("liquid") ? null : FoodItem.fromItem(item); @@ -624,8 +625,11 @@ private ItemStack convertForBottling(Player p, ItemStack item) { return p.getInventory().getItemInMainHand(); } - /** An empty glass bottle takes what the saucepan made (catsup, mustard, syrup) once it has boiled long enough. */ - private void bottle(Player p) { + /** + * An empty glass bottle takes what the saucepan made (catsup, mustard, syrup) once it has boiled long enough, or the + * recipe's own container does (an empty cup takes hot chocolate). + */ + private void bottle(Player p, ItemStack held) { if (!secondaries.containsKey("liquid")) { p.sendMessage("§7The saucepan is empty."); return; @@ -635,6 +639,10 @@ private void bottle(Player p) { p.sendMessage("§7Nothing in this saucepan goes in a bottle. Use a ladle for sauce."); return; } + if (!recipe.takesContainer(held)) { + p.sendMessage("§7Take this out with " + recipe.getContainerName() + "."); + return; + } if (boiled < recipe.getBoilSeconds()) { p.sendMessage("§7It needs to boil a while longer (" + (recipe.getBoilSeconds() - boiled) + "s)."); return; @@ -648,6 +656,7 @@ private void bottle(Player p) { inputs.addAll(slots.values()); CompositionResult composed = CompositionQualityResolver.compose(p, inputs, CompositionContext.SAUCE_SCOOP); CompositionApplier.apply(parsed.template, composed); + recipe.applyExtras(parsed.template, slots.values()); output = ItemBuilder.buildSingleWithQuality(parsed.template, null, composed.getFinalQuality()); } if (output == null) { diff --git a/src/main/java/net/tfminecraft/cooking/cup/DrinkConsumeListener.java b/src/main/java/net/tfminecraft/cooking/cup/DrinkConsumeListener.java index 7f0ac07..a292754 100644 --- a/src/main/java/net/tfminecraft/cooking/cup/DrinkConsumeListener.java +++ b/src/main/java/net/tfminecraft/cooking/cup/DrinkConsumeListener.java @@ -15,6 +15,7 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.PlayerInventory; +import net.tfminecraft.tlibs.TLibs; import net.tfminecraft.cooking.Cooking; import net.tfminecraft.cooking.cache.ItemCache; import net.tfminecraft.cooking.item.FoodItem; @@ -93,6 +94,40 @@ public void onDrink(PlayerItemConsumeEvent event) { }); } + /** + * A drink served in something other than a glass bottle (hot chocolate in a cup, types.yml returns) gives that back + * once it's drunk. FoodConsumeListener feeds the drinker; this only swaps what vanilla leaves in the slot. + */ + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onServedDrink(PlayerItemConsumeEvent event) { + ItemStack consumed = event.getItem(); + if (consumed == null || ItemCache.isCupOfMilk(consumed)) { + return; + } + FoodItem food = FoodItem.fromItem(consumed); + String returns = food == null ? null : food.getReturns(); + if (returns == null || returns.isBlank()) { + return; + } + Player player = event.getPlayer(); + PlayerActionContext context = PlayerActionContext.capture(player); + if (context == null) { + return; + } + int amountBefore = consumed.getAmount(); + int slot = event.getHand() == EquipmentSlot.OFF_HAND ? -1 : player.getInventory().getHeldItemSlot(); + Bukkit.getScheduler().runTask(Cooking.plugin, () -> { + if (!event.isCancelled() && context.isCurrent()) { + replaceWithEmptyCup(player, amountBefore, slot, () -> returned(returns), context::isCurrent); + } + }); + } + + private static ItemStack returned(String path) { + ItemStack item = TLibs.getItemAPI().getCreator().getItemFromPath(path); + return item == null ? null : item.clone(); + } + /** * Swaps the glass bottle vanilla leaves in the slot the cup was drunk from for an empty cup. * Only that slot, and only if it still holds the bottle: switching slots within the tick @@ -114,7 +149,7 @@ private static void replaceWithEmptyCup(Player player, int amountBefore, int slo return; } ItemStack empty = emptyCup.get(); - if (!current.getAsBoolean()) return; + if (empty == null || !current.getAsBoolean()) return; if (slot < 0) { inv.setItemInOffHand(empty); } else { diff --git a/src/main/java/net/tfminecraft/cooking/item/FoodItem.java b/src/main/java/net/tfminecraft/cooking/item/FoodItem.java index 89eafe1..f045fa2 100644 --- a/src/main/java/net/tfminecraft/cooking/item/FoodItem.java +++ b/src/main/java/net/tfminecraft/cooking/item/FoodItem.java @@ -37,6 +37,8 @@ public class FoodItem { private boolean mashable = false; private boolean edible = true; private boolean edibleWhenCooked = false; + /** What drinking it leaves in the hand instead of a glass bottle (types.yml returns: an empty cup), or null. */ + private String returns; private Integer catchSizeCm; private String seafoodCutType; private String customFishingId; @@ -88,6 +90,7 @@ public FoodItem(String key, ConfigurationSection config) { this.mashable = config.getBoolean("mashable", false); this.edible = config.getBoolean("edible", true); this.edibleWhenCooked = config.getBoolean("edible-when-cooked", false); + this.returns = config.getString("returns", null); this.typeLevelCarveSequence = config.getString("carve-sequence", null); String modelId = config.getString("model", null); @@ -161,6 +164,7 @@ public FoodItem(FoodItem other) { this.mashable = other.mashable; this.edible = other.edible; this.edibleWhenCooked = other.edibleWhenCooked; + this.returns = other.returns; this.catchSizeCm = other.catchSizeCm; this.seafoodCutType = other.seafoodCutType; this.customFishingId = other.customFishingId; @@ -271,6 +275,8 @@ public void updateAge() { public boolean shouldUpdate() { return update; } public boolean isValuable() { return valuable; } public boolean isMashable() { return mashable; } + /** The item path drinking it leaves instead of a glass bottle (ia.tfmc_cooking:empty_cup), or null for vanilla's. */ + public String getReturns() { return returns; } public void setMashable(boolean mashable) { this.mashable = mashable; } public boolean isEdible() { if (!edible) { diff --git a/src/main/java/net/tfminecraft/cooking/milling/MillingRecipe.java b/src/main/java/net/tfminecraft/cooking/milling/MillingRecipe.java index 9e83542..73f4ec9 100644 --- a/src/main/java/net/tfminecraft/cooking/milling/MillingRecipe.java +++ b/src/main/java/net/tfminecraft/cooking/milling/MillingRecipe.java @@ -153,4 +153,17 @@ public int getOutputAmount() { public String getRefundFood() { return inputFood == null || inputFood.isBlank() ? DEFAULT_REFUND_FOOD : inputFood; } + + /** + * The food line a broken stone rebuilds its input from when the recipe loads by a food path and names no + * input-food: that path without its c. prefix (ingredient(type=roasted_cocoa_beans;tags=cooked.1)), so the + * refund keeps the category and tags that let it load again. Null otherwise. + */ + public String getRefundPath() { + if (inputFood != null && !inputFood.isBlank()) return null; + if (inputMatcher == null) return null; + String path = inputMatcher.trim(); + if (!path.regionMatches(true, 0, "c.", 0, 2) || !path.contains("(")) return null; + return path.substring(2); + } } diff --git a/src/main/java/net/tfminecraft/cooking/milling/MillingStoneHandler.java b/src/main/java/net/tfminecraft/cooking/milling/MillingStoneHandler.java index dcd51ae..ccc0b8b 100644 --- a/src/main/java/net/tfminecraft/cooking/milling/MillingStoneHandler.java +++ b/src/main/java/net/tfminecraft/cooking/milling/MillingStoneHandler.java @@ -17,6 +17,7 @@ import net.tfminecraft.cooking.loader.FoodLoader; import net.tfminecraft.cooking.quality.OriginQualityResolver; import net.tfminecraft.cooking.utils.InventoryAdder; +import net.tfminecraft.cooking.utils.FoodParser; import net.tfminecraft.cooking.utils.ItemBuilder; import net.tfminecraft.interactiblefurniture.events.FurnitureBreakEvent; import net.tfminecraft.interactiblefurniture.events.FurnitureInteractEvent; @@ -205,12 +206,23 @@ private static ItemStack buildFlour(MillingRecipe recipe, int quality, Ingredien return built; } - /** What a loaded stone gives back: the recipe's refund item (sugar cane), or its input as food (wheat). */ + /** + * What a loaded stone gives back: the recipe's refund item (sugar cane), its input food path rebuilt (roasted cocoa + * beans), or its input as food (wheat). + */ private static ItemStack buildWheat(MillingRecipe recipe, int quality, IngredientLineage lineage) { if (recipe.getRefund() != null) { ItemStack refund = TLibs.getItemAPI().getCreator().getItemFromPath(recipe.getRefund()); return refund == null ? null : refund.clone(); } + if (recipe.getRefundPath() != null) { + FoodParser.Result parsed = FoodParser.parse(recipe.getRefundPath()); + if (parsed == null || parsed.template == null) return null; + FoodItem input = new FoodItem(parsed.template); + input.setOrigin(recipe.getOrigin()); + input.setLineage(lineage == null || lineage.isEmpty() ? IngredientLineage.ofMain(recipe.getOrigin()) : lineage); + return ItemBuilder.buildSingleWithQuality(input, quality); + } FoodItem template = FoodLoader.getByString(recipe.getRefundFood()); if (template == null) { return null; diff --git a/src/main/resources/condiments.yml b/src/main/resources/condiments.yml index c43d06f..8f2aea6 100644 --- a/src/main/resources/condiments.yml +++ b/src/main/resources/condiments.yml @@ -81,3 +81,112 @@ saucepan: - c.ingredient(type=butter) boil-seconds: 45 output: condiment(type=caramel;origin=Sugar;tags=freshness.0) + # Chocolate (types.yml cocoa_beans to chocolate_bar). Cocoa powder is ground on the milling stone from roasted beans. + # extras: optional, once each, besides the ingredients; each gives the output its tags.yml track, which names it + # (Cinnamon Hot Chocolate). A spice goes in like any spice, two at most (naming.yml addons). + # container: what takes the output out instead of an empty glass bottle; container-name is how a player is told. + # + # Hot chocolate: a cup of milk boiled with cocoa powder and a sweetener, taken out with an empty cup and drunk from + # it (types.yml returns gives the cup back). + hot_chocolate: + liquid: c.ingredient(type=cup_of_milk) + ingredients: + - c.ingredient(type=cocoa_powder) + - c.sweetener + extras: + vanilla: + path: c.spice(origin=Vanilla) + track: flavour_vanilla + cinnamon: + path: c.spice(origin=Cinnamon) + track: flavour_cinnamon + nutmeg: + path: c.spice(origin=Nutmeg) + track: flavour_nutmeg + boil-seconds: 30 + container: ia.tfmc_cooking:empty_cup + container-name: an empty cup + output: drink(type=hot_chocolate;origin=Cocoa;tags=freshness.0:warmth.0) + # Melted chocolate: cocoa powder, a sweetener and butter boiled in a cup of milk (Milk Chocolate) or of water (Dark + # Chocolate), taken out with a bowl and poured into a chocolate mould (crafting-stations.yml chocolate_mould). + # Butter from the churn is dairy and butter picked up is an ingredient, so each has its line. + milk_chocolate: + liquid: c.ingredient(type=cup_of_milk) + ingredients: + - c.ingredient(type=cocoa_powder) + - c.sweetener + - c.dairy(type=butter) + extras: + vanilla: + path: c.spice(origin=Vanilla) + track: flavour_vanilla + cinnamon: + path: c.spice(origin=Cinnamon) + track: flavour_cinnamon + nutmeg: + path: c.spice(origin=Nutmeg) + track: flavour_nutmeg + boil-seconds: 45 + container: v.bowl + container-name: a bowl + output: condiment(type=melted_chocolate;origin=Milk Chocolate;tags=freshness.0) + milk_chocolate_picked_up_butter: + liquid: c.ingredient(type=cup_of_milk) + ingredients: + - c.ingredient(type=cocoa_powder) + - c.sweetener + - c.ingredient(type=butter) + extras: + vanilla: + path: c.spice(origin=Vanilla) + track: flavour_vanilla + cinnamon: + path: c.spice(origin=Cinnamon) + track: flavour_cinnamon + nutmeg: + path: c.spice(origin=Nutmeg) + track: flavour_nutmeg + boil-seconds: 45 + container: v.bowl + container-name: a bowl + output: condiment(type=melted_chocolate;origin=Milk Chocolate;tags=freshness.0) + dark_chocolate: + liquid: water + ingredients: + - c.ingredient(type=cocoa_powder) + - c.sweetener + - c.dairy(type=butter) + extras: + vanilla: + path: c.spice(origin=Vanilla) + track: flavour_vanilla + cinnamon: + path: c.spice(origin=Cinnamon) + track: flavour_cinnamon + nutmeg: + path: c.spice(origin=Nutmeg) + track: flavour_nutmeg + boil-seconds: 45 + container: v.bowl + container-name: a bowl + output: condiment(type=melted_chocolate;origin=Dark Chocolate;tags=freshness.0) + dark_chocolate_picked_up_butter: + liquid: water + ingredients: + - c.ingredient(type=cocoa_powder) + - c.sweetener + - c.ingredient(type=butter) + extras: + vanilla: + path: c.spice(origin=Vanilla) + track: flavour_vanilla + cinnamon: + path: c.spice(origin=Cinnamon) + track: flavour_cinnamon + nutmeg: + path: c.spice(origin=Nutmeg) + track: flavour_nutmeg + boil-seconds: 45 + container: v.bowl + container-name: a bowl + output: condiment(type=melted_chocolate;origin=Dark Chocolate;tags=freshness.0) diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 4050983..70ff041 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -150,6 +150,9 @@ colours: - origin.cinnamon 8b4513 - origin.vanilla f5e6c8 - origin.nutmeg 6b3a1f + - origin.cocoa 5c3a21 + - origin.milk_chocolate 7b4a2d + - origin.dark_chocolate 3e2415 - origin.spice_leaf 2e7d32 - origin.mustard c9a227 - origin.potato d4a017 @@ -181,6 +184,7 @@ dictionary: garnish: "#0b5394Garnish" liquid: "#3d85c6Liquid" snack: "#e8c56bSnack" + drink: "#8b5a3cDrink" sauce-dict: - ffffff ia.tfmc_cooking:milk|ia.tfmc_cooking:milk_plated diff --git a/src/main/resources/conversions.yml b/src/main/resources/conversions.yml index 38ea7de..4e762f5 100644 --- a/src/main/resources/conversions.yml +++ b/src/main/resources/conversions.yml @@ -51,3 +51,5 @@ conversions: - ia.tfmc_cooking:cup_of_milk ingredient(type=cup_of_milk;origin=Cow;tags=freshness.0) - v.milk_bucket ingredient(type=milk_bucket;origin=Cow;tags=freshness.0) - ia.tfmc_cooking:butter ingredient(type=butter;origin=Cow;tags=freshness.0) + # Cocoa beans (vanilla cocoa pods, crops.yml cocoa) roast in the frying pan (types.yml cocoa_beans). They stay plantable. + - v.cocoa_beans ingredient(type=cocoa_beans;origin=Cocoa;tags=freshness.0) diff --git a/src/main/resources/crafting-stations.yml b/src/main/resources/crafting-stations.yml index a4584a8..991e1ac 100644 --- a/src/main/resources/crafting-stations.yml +++ b/src/main/resources/crafting-stations.yml @@ -82,3 +82,25 @@ cutting_board: - c.grain(type=boiled_rice;tags=cooked.3) - c.seafood(type=seafood_fish_filet;tags=cooked.0) output: meal(type=sushi;origin={origin};tags=freshness.0) +# Chocolate mould: right-click it with a bowl of melted chocolate (condiments.yml) to pour it in (you keep the bowl); +# it lies in the mould as one slab, in its own colour per kind ({origin}: milk_chocolate, dark_chocolate). Hit the mould +# with the cutting knife to cut it into 4 bars, which keep its kind and flavourings (Vanilla Milk Chocolate Bar) and +# share its food; take them out with an empty hand. The furniture (InteractibleFurniture) has one slot, input_1, at +# its centre and unscaled, so the slab and the bars are drawn in the mould's coordinates. +chocolate_mould: + furniture: chocolate_mould + single-origin: true + max-slots: 1 + tool: ia.tfmc_cooking:cutting_knife + fill-models: + - ia.tfmc_cooking:chocolate_mould_fill_{origin} + pour-return: v.bowl + recipes: + cut_chocolate: + ratio: 1 + yield: 4 + inherit: true + share-food: true + inputs: + - c.condiment(type=melted_chocolate) + output: snack(type=chocolate_bar) diff --git a/src/main/resources/milling-recipes.yml b/src/main/resources/milling-recipes.yml index 993253c..02bc233 100644 --- a/src/main/resources/milling-recipes.yml +++ b/src/main/resources/milling-recipes.yml @@ -34,3 +34,19 @@ sugar: output-amount: 8 revolutions: 4 duration-ticks: 60 + +# Roasted cocoa beans (types.yml cocoa_beans, roasted in the frying pan) ground into cocoa powder for hot chocolate and +# melted chocolate (condiments.yml). One pan of two beans makes one powder. Only roasted beans that aren't burnt load +# (input); a loaded stone that's broken gives them back as roasted beans. +cocoa_powder: + furniture: milling_stone + input-count: 2 + input: c.ingredient(type=roasted_cocoa_beans;tags=cooked.1) + input-name: roasted cocoa beans + input-display: ia.tfmc_cooking:roasted_cocoa_beans + output-food: cocoa_powder + category: ingredient + origin: Cocoa + output-display: ia.tfmc_cooking:cocoa_powder_pile + revolutions: 4 + duration-ticks: 60 diff --git a/src/main/resources/models.yml b/src/main/resources/models.yml index 86392d3..dfa394a 100644 --- a/src/main/resources/models.yml +++ b/src/main/resources/models.yml @@ -4023,3 +4023,111 @@ caramel: item: ia.tfmc_cooking:caramel display: item: ia.tfmc_cooking:caramel + +# Chocolate (types.yml cocoa_beans to chocolate_bar). Cocoa beans keep the vanilla look (they still plant on jungle +# logs); in the frying pan beans lie flat on the pan floor like chopped corn. +cocoa_beans: + display-data-furniture: + frying_pan: + rotation: + x: 90 + scale: + x: 0.7 + y: 0.7 + z: 0.7 + position: + y: -0.26 + plain: + weight: 1 + tags: [] + gui: + item: v.cocoa_beans + display: + item: v.cocoa_beans + +roasted_cocoa_beans: + display-data-furniture: + frying_pan: + rotation: + x: 90 + scale: + x: 0.7 + y: 0.7 + z: 0.7 + position: + y: -0.26 + cooked: + weight: 1 + gui: + item: ia.tfmc_cooking:roasted_cocoa_beans + display: + item: ia.tfmc_cooking:roasted_cocoa_beans + burnt: + weight: 2 + tags: + - burnt + gui: + item: ia.tfmc_cooking:roasted_cocoa_beans_burnt + display: + item: ia.tfmc_cooking:roasted_cocoa_beans_burnt + +cocoa_powder: + plain: + weight: 1 + tags: [] + gui: + item: ia.tfmc_cooking:cocoa_powder + display: + item: ia.tfmc_cooking:cocoa_powder_pile + +# A cup of hot chocolate (a potion, so it's drunk; types.yml returns gives the cup back). +hot_chocolate: + plain: + weight: 1 + tags: [] + gui: + item: ia.tfmc_cooking:hot_chocolate + display: + item: ia.tfmc_cooking:hot_chocolate + +# A bowl of melted chocolate. Poured into a chocolate mould it shows as the mould's fill instead +# (crafting-stations.yml fill-models), and the bars cut from it lie in the mould as one set slab cut in four. +melted_milk_chocolate: + plain: + weight: 1 + tags: [] + gui: + item: ia.tfmc_cooking:cooking_chocolate + display: + item: ia.tfmc_cooking:cooking_chocolate + +melted_dark_chocolate: + plain: + weight: 1 + tags: [] + gui: + item: ia.tfmc_cooking:melted_dark_chocolate + display: + item: ia.tfmc_cooking:melted_dark_chocolate + +milk_chocolate_bar: + plain: + weight: 1 + tags: [] + gui: + item: ia.tfmc_cooking:milk_chocolate_bar + display: + item: ia.tfmc_cooking:milk_chocolate_bar + furniture: + - chocolate_mould ia.tfmc_cooking:chocolate_mould_bars_milk_chocolate + +dark_chocolate_bar: + plain: + weight: 1 + tags: [] + gui: + item: ia.tfmc_cooking:dark_chocolate_bar + display: + item: ia.tfmc_cooking:dark_chocolate_bar + furniture: + - chocolate_mould ia.tfmc_cooking:chocolate_mould_bars_dark_chocolate diff --git a/src/main/resources/naming.yml b/src/main/resources/naming.yml index c79a437..4526eb2 100644 --- a/src/main/resources/naming.yml +++ b/src/main/resources/naming.yml @@ -3,6 +3,10 @@ prefix-tracks: - sweet - butter_salted - butter_spiced + # Flavourings (tags.yml flavour_*), before the popcorn toppings: Cinnamon Vanilla Hot Chocolate, Vanilla Caramel Popcorn. + - flavour_cinnamon + - flavour_nutmeg + - flavour_vanilla # Popcorn machine toppings, in this order: Buttered Sugared Salted Caramel Popcorn. - topping_butter - topping_sugar diff --git a/src/main/resources/popcorn-machines.yml b/src/main/resources/popcorn-machines.yml index b99bfa6..c324556 100644 --- a/src/main/resources/popcorn-machines.yml +++ b/src/main/resources/popcorn-machines.yml @@ -51,6 +51,15 @@ popcorn_machine: item: c.salt track: topping_salt name: Salt + # Flavourings (tags.yml flavour_*), named before the other toppings: Cinnamon Sugared Popcorn. + cinnamon: + item: c.spice(origin=Cinnamon) + track: flavour_cinnamon + name: Cinnamon + vanilla: + item: c.spice(origin=Vanilla) + track: flavour_vanilla + name: Vanilla models: kettle: ia.tfmc_cooking:popcorn_machine_kettle kettle-loaded: ia.tfmc_cooking:popcorn_machine_kettle_loaded diff --git a/src/main/resources/tags.yml b/src/main/resources/tags.yml index eea880f..3cea524 100644 --- a/src/main/resources/tags.yml +++ b/src/main/resources/tags.yml @@ -353,3 +353,25 @@ popcorn_look: look_caramel: name: "" value: 1 + +# Flavourings: vanilla, cinnamon and nutmeg boiled into hot chocolate or melted chocolate (condiments.yml extras), and +# vanilla or cinnamon put in a popcorn machine (popcorn-machines.yml toppings). Each names the food (naming.yml +# prefix-tracks): Cinnamon Hot Chocolate, Vanilla Milk Chocolate Bar, Cinnamon Caramel Popcorn. +flavour_vanilla: + flavour_vanilla: + name: "#f5e6c8Vanilla" + value: 0 + food-mult: 1.03 + nutrition-mult: 1.05 +flavour_cinnamon: + flavour_cinnamon: + name: "#c8814aCinnamon" + value: 0 + food-mult: 1.03 + nutrition-mult: 1.05 +flavour_nutmeg: + flavour_nutmeg: + name: "#a0704bNutmeg" + value: 0 + food-mult: 1.03 + nutrition-mult: 1.05 diff --git a/src/main/resources/types.yml b/src/main/resources/types.yml index e242da7..39a65e2 100644 --- a/src/main/resources/types.yml +++ b/src/main/resources/types.yml @@ -818,3 +818,100 @@ caramel: nutrition: 2 age: freshness: 60 + +###Chocolate: cocoa beans (picked up or harvested, conversions.yml) roast in the frying pan, are ground on the milling +# stone into cocoa powder (milling-recipes.yml), and boil in the saucepan into hot chocolate or melted chocolate +# (condiments.yml). Melted chocolate poured into a chocolate mould is cut into bars there (crafting-stations.yml). +# Vanilla, cinnamon and nutmeg boiled in with them flavour and name them (tags.yml flavour_*). +cocoa_beans: + name: "#8b5a3cCocoa Beans" + model: cocoa_beans + food: 2 + nutrition: 2 + # Raw beans are roasted first. Its only cooking option has an output, so the beans aren't raw until they're in the pan. + edible: false + cooking-options: + frying_pan: + tag: 1 + time: 10 + burn: 25 + output: ingredient(type=roasted_cocoa_beans) + age: + warmth: 450 + freshness: 28 + +roasted_cocoa_beans: + name: "#5c3a21Roasted Cocoa Beans" + model: roasted_cocoa_beans + food: 3 + nutrition: 3 + age: + warmth: 450 + freshness: 28 + +cocoa_powder: + name: "#7b4a2dCocoa Powder" + model: cocoa_powder + food: 2 + nutrition: 2 + edible: false + age: + warmth: 450 + freshness: 20 + tag-labels: + freshness: + rotten: "#8B7355Musty" + +# Drunk from its cup, which comes back (returns): Hot like soup, it cools to Warm and then cold. +hot_chocolate: + name: "#8b5a3c{prefixes}Hot Chocolate" + model: hot_chocolate + returns: ia.tfmc_cooking:empty_cup + food: 14 + nutrition: 6 + age: + warmth: 450 + freshness: 2 + tag-labels: + freshness: + stale: "#c3db81Skinned" + rotten: "#8B7355Spoiled" + +# Taken out of the saucepan in a bowl. Its origin is its kind (Milk Chocolate, Dark Chocolate), and each kind has its +# own name, which gets the flavourings' prefixes (Vanilla Milk Chocolate Bar). The bars it's cut into share its food +# (crafting-stations.yml share-food). +melted_chocolate: + name: "#6b4226{prefixes}Chocolate (Melted)" + model: melted_milk_chocolate + overrides: + MILK CHOCOLATE: + name: "#7b4a2d{prefixes}Milk Chocolate (Melted)" + model: melted_milk_chocolate + DARK CHOCOLATE: + name: "#4a2c1a{prefixes}Dark Chocolate (Melted)" + model: melted_dark_chocolate + food: 24 + nutrition: 6 + age: + warmth: 450 + freshness: 8 + +chocolate_bar: + name: "#6b4226{prefixes}Chocolate Bar" + model: milk_chocolate_bar + overrides: + MILK CHOCOLATE: + name: "#7b4a2d{prefixes}Milk Chocolate Bar" + model: milk_chocolate_bar + DARK CHOCOLATE: + name: "#4a2c1a{prefixes}Dark Chocolate Bar" + model: dark_chocolate_bar + food: 6 + nutrition: 6 + age: + warmth: 450 + freshness: 14 + tag-labels: + freshness: + stale: "#c3db81Bloomed" + rotten: "#8B7355Mouldy" diff --git a/src/test/java/net/tfminecraft/cooking/condiment/CondimentCoverageTest.java b/src/test/java/net/tfminecraft/cooking/condiment/CondimentCoverageTest.java index 723356d..5c0e8c6 100644 --- a/src/test/java/net/tfminecraft/cooking/condiment/CondimentCoverageTest.java +++ b/src/test/java/net/tfminecraft/cooking/condiment/CondimentCoverageTest.java @@ -123,6 +123,74 @@ void configReadsVinegarSapAndBottlesAndFallsBackToDefaults() throws Exception { assertTrue(CondimentConfig.bottles().isEmpty()); } + @Test + void extrasGoInOnceEachAndTagTheOutputWhileAContainerTakesItOut() throws Exception { + YamlConfiguration config = new YamlConfiguration(); + config.loadFromString(""" + liquid: c.ingredient(type=cup_of_milk) + ingredients: [c.ingredient(type=cocoa_powder), c.sweetener] + extras: + vanilla: {path: c.spice(origin=Vanilla), track: sweet} + cinnamon: {path: c.spice(origin=Cinnamon), track: no_such_track} + pathless: {track: sweet} + flat: 3 + container: test.cup + output: drink(type=hot_chocolate) + """); + BottleRecipe cocoa = new BottleRecipe("cocoa", config); + FoodItem milk = food("cup_of_milk", "ingredient", "Cow"); + FoodItem powder = food("cocoa_powder", "ingredient", "Cocoa"); + FoodItem sugar = food("sweetener_1", "sweetener", "Sugar"); + FoodItem vanilla = food("spice_1", "spice", "Vanilla"); + FoodItem cinnamon = food("spice_1", "spice", "Cinnamon"); + FoodItem nutmeg = food("spice_1", "spice", "Nutmeg"); + + assertTrue(cocoa.takes(vanilla, List.of(powder))); + assertFalse(cocoa.takes(vanilla, List.of(powder, vanilla)), "each extra goes in once"); + assertTrue(cocoa.takes(cinnamon, List.of(vanilla))); + assertFalse(cocoa.takes(nutmeg, List.of())); + assertFalse(cocoa.takes(powder, List.of(nutmeg)), "a pan holding what the recipe doesn't take fits nothing"); + assertTrue(cocoa.matches(milk, false, List.of(vanilla, powder, sugar, cinnamon))); + assertTrue(cocoa.matches(milk, false, List.of(powder, sugar))); + assertFalse(cocoa.matches(milk, false, List.of(powder, vanilla, vanilla, sugar))); + assertFalse(cocoa.matches(milk, false, List.of(powder, vanilla))); + + List tracks = new java.util.ArrayList<>(net.tfminecraft.cooking.loader.TrackLoader.oList); + try (MockedStatic tlibs = mockStatic(net.tfminecraft.tlibs.TLibs.class)) { + net.tfminecraft.cooking.loader.TrackLoader.oList = new java.util.ArrayList<>(); + new net.tfminecraft.cooking.loader.TrackLoader().load(new java.io.File("src/main/resources/tags.yml")); + FoodItem output = food("hot_chocolate", "drink", "Cocoa"); + cocoa.applyExtras(output, List.of(powder, vanilla, sugar, cinnamon)); + assertEquals(List.of("sweet"), output.getTagTracks().stream().map(t -> t.getId()).toList()); + + net.tfminecraft.tlibs.objects.api.ItemAPI api = mock(net.tfminecraft.tlibs.objects.api.ItemAPI.class, RETURNS_DEEP_STUBS); + tlibs.when(net.tfminecraft.tlibs.TLibs::getItemAPI).thenReturn(api); + ItemStack cup = new ItemStack(Material.BOWL); + when(api.getChecker().checkItemWithPath(cup, "test.cup")).thenReturn(true); + assertEquals("an empty cup", cocoa.getContainerName()); + assertTrue(cocoa.takesContainer(cup)); + assertTrue(cocoa.isContainer(cup)); + assertFalse(cocoa.takesContainer(new ItemStack(Material.GLASS_BOTTLE))); + assertFalse(cocoa.takesContainer(null)); + + BottleRecipe bottled = new BottleRecipe("plain", new MemoryConfiguration()); + assertEquals("an empty glass bottle", bottled.getContainerName()); + assertTrue(bottled.takesContainer(new ItemStack(Material.GLASS_BOTTLE))); + assertFalse(bottled.takesContainer(cup)); + assertFalse(bottled.isContainer(new ItemStack(Material.GLASS_BOTTLE))); + MemoryConfiguration bowl = new MemoryConfiguration(); + bowl.set("container", "v.bowl"); + bowl.set("container-name", "a bowl"); + assertEquals("a bowl", new BottleRecipe("melted", bowl).getContainerName()); + + load(CONFIG.replace(" broken: 3", " cocoa:\n container: test.cup\n broken: 3")); + assertTrue(CondimentConfig.isBottlingContainer(cup)); + assertFalse(CondimentConfig.isBottlingContainer(new ItemStack(Material.GLASS_BOTTLE))); + } finally { + net.tfminecraft.cooking.loader.TrackLoader.oList = tracks; + } + } + @Test void aRecipeTakesEachOfItsIngredientsOnceAndMatchesOnlyItsExactPan() throws Exception { YamlConfiguration config = new YamlConfiguration(); diff --git a/src/test/java/net/tfminecraft/cooking/cooking/SauceReferenceContainerTest.java b/src/test/java/net/tfminecraft/cooking/cooking/SauceReferenceContainerTest.java new file mode 100644 index 0000000..0eb84d1 --- /dev/null +++ b/src/test/java/net/tfminecraft/cooking/cooking/SauceReferenceContainerTest.java @@ -0,0 +1,101 @@ +package net.tfminecraft.cooking.cooking; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +import java.nio.file.Files; +import java.nio.file.Path; + +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import net.tfminecraft.tlibs.TLibs; +import net.tfminecraft.cooking.condiment.CondimentConfig; +import net.tfminecraft.cooking.enums.Method; + +/** + * Hot chocolate: the saucepan takes a flavouring extra besides the recipe's ingredients, tags the output with its + * track, and only the recipe's container (an empty cup, here a bowl) takes it out. + */ +class SauceReferenceContainerTest { + // The test environment parses no food paths, so recipes here match by category only. + static final String CONFIG = """ + saucepan: + liquids: [c.vinegar] + bottles: + cocoa: + liquid: c.vinegar + ingredients: [c.paste] + extras: + flavour: {path: c.cream, track: sweet} + container: test.cup + container-name: an empty cup + boil-seconds: 1 + output: drink(type=hot_chocolate) + """; + + CookingReferencesTest.Environment env; + SauceReference sauce; + @TempDir Path directory; + + @BeforeEach void setUp() throws Exception { + env = new CookingReferencesTest.Environment(); + Path file = directory.resolve("condiments.yml"); + Files.writeString(file, CONFIG); + new CondimentConfig().load(file.toFile()); + sauce = new SauceReference(env.furniture, Method.SAUCEPAN); + when(TLibs.getItemAPI().getChecker().checkItemWithPath(argThat(item -> item != null && item.getType() == Material.BOWL), + eq("test.cup"))).thenReturn(true); + } + + @AfterEach void tearDown() throws Exception { + new CondimentConfig().load(directory.resolve("missing.yml").toFile()); + env.close(); + } + + void hold(ItemStack item) { + env.player.getInventory().setItemInMainHand(item); + sauce.interact(env.interaction()); + } + + ItemStack food(String category, String origin) { + return env.stack(env.food(category, category, origin), Material.EXPERIENCE_BOTTLE, 1); + } + + ItemStack hand() { + return env.player.getInventory().getItemInMainHand(); + } + + @Test + void aFlavouredDrinkGoesOnlyIntoItsCup() { + hold(new ItemStack(Material.BOWL)); + verify(env.player).sendMessage("§7The saucepan is empty."); + + hold(food("vinegar", "Wine")); + hold(food("paste", "Cocoa")); + // The flavouring goes in once, only because the recipe has it as an extra. + hold(food("cream", "Vanilla")); + hold(food("cream", "Vanilla")); + assertEquals(2, sauce.getSlots().size()); + + env.heated = true; + sauce.tick(); + hold(new ItemStack(Material.GLASS_BOTTLE)); + verify(env.player).sendMessage("§7Take this out with an empty cup."); + assertFalse(sauce.isEmpty()); + + // A food that happens to be a bowl isn't the cup. + hold(env.stack(env.food("bowl_food", "bowl_food", "Bowl"), Material.BOWL, 1)); + assertFalse(sauce.isEmpty()); + + hold(new ItemStack(Material.BOWL)); + assertEquals(Material.PAPER, hand().getType()); + assertNotNull(env.lastBuilt.getTagTracks().stream().filter(track -> track.getId().equals("sweet")).findFirst().orElse(null)); + assertTrue(sauce.isEmpty()); + } +} diff --git a/src/test/java/net/tfminecraft/cooking/milling/MillingStoneCoverageTest.java b/src/test/java/net/tfminecraft/cooking/milling/MillingStoneCoverageTest.java index 30ec261..4c4ab3b 100644 --- a/src/test/java/net/tfminecraft/cooking/milling/MillingStoneCoverageTest.java +++ b/src/test/java/net/tfminecraft/cooking/milling/MillingStoneCoverageTest.java @@ -408,6 +408,48 @@ void animationStopsOnDisplayRemovalAndMissingTopDisplaysCompleteSynchronously() assertEquals(3, callbacks.get()); } + @Test + void aRecipeLoadedByAFoodPathRefundsThatFood() { + java.util.function.BiFunction refund = (food, matcher) -> + new MillingRecipe("r", "milling_stone", 2, food, matcher, null, "cocoa_powder", 1, 8).getRefundPath(); + assertEquals("ingredient(type=roasted_cocoa_beans;tags=cooked.1)", + refund.apply(null, " C.ingredient(type=roasted_cocoa_beans;tags=cooked.1)")); + assertEquals("ingredient(type=roasted_cocoa_beans)", refund.apply(" ", "c.ingredient(type=roasted_cocoa_beans)")); + assertNull(refund.apply("roasted_cocoa_beans", "c.ingredient(type=roasted_cocoa_beans)")); + assertNull(refund.apply(null, null)); + assertNull(refund.apply(null, "c.ingredient")); + assertNull(refund.apply(null, "ia.tfmc_cooking:roasted_cocoa_beans")); + + // Two roasted beans load the cocoa recipe; breaking the loaded stone gives them back as roasted beans. + MillingRecipe cocoa = new MillingRecipe("cocoa_powder", "milling_stone", 2, null, "c.ingredient(type=roasted_cocoa_beans)", + null, "cocoa_powder", 1, 8, "Cocoa", "ingredient", "roasted cocoa beans", null, null, null, 1); + MillingRecipeRegistry.load(Map.of("cocoa_powder", cocoa)); + env.templates.put("roasted_cocoa_beans", env.food("roasted_cocoa_beans", "Cocoa", 3)); + when(env.api.getChecker().checkItemWithPath(any(), eq("c.ingredient(type=roasted_cocoa_beans)"))).thenAnswer(inv -> { + ItemStack stack = inv.getArgument(0); + return stack != null && stack.getType() == Material.COCOA_BEANS; + }); + ItemStack beans = env.hold(env.stack(env.food("roasted_cocoa_beans", "Cocoa", 4), Material.COCOA_BEANS, 3)); + handler.onInteract(station.interact()); + assertEquals(1, beans.getAmount()); + env.hold(null); + handler.onBreak(new FurnitureBreakEvent(station.furniture, env.player)); + FoodItem back = env.resolve(env.dropped.get(env.dropped.size() - 1)); + assertEquals("roasted_cocoa_beans", back.getId()); + assertEquals("ingredient", back.getCategory()); + assertEquals("Cocoa", back.getOrigin()); + assertEquals(2, env.dropped.get(env.dropped.size() - 1).getAmount()); + + // A refund food that no longer exists keeps the stone and its beans. + env.hold(env.stack(env.food("roasted_cocoa_beans", "Cocoa", 4), Material.COCOA_BEANS, 2)); + handler.onInteract(station.interact()); env.hold(null); + assertEquals(MillingStoneStage.LOADED, MillingStoneState.getStage(station.furniture)); + env.templates.remove("roasted_cocoa_beans"); + FurnitureBreakEvent event = new FurnitureBreakEvent(station.furniture, env.player); + handler.onBreak(event); + assertTrue(event.isCancelled()); + } + // ---------- a second recipe on the same stone: sugar cane into sugar ---------- MillingRecipe sugar(String refund) { MillingRecipe flour = new MillingRecipe("flour", "milling_stone", 8, "wheat", "food:grain", "v.wheat", "flour", 1, 8); @@ -544,10 +586,16 @@ void recipeKeysDefaultAndASavedRecipeThatIsGoneFallsBackToTheFirst(@TempDir Path void theShippedRecipesGrindWheatIntoFlourAndSugarCaneIntoSugar() { new MillingRecipeLoader().load(new java.io.File("src/main/resources/milling-recipes.yml")); List recipes = MillingRecipeRegistry.getAllForFurniture("milling_stone"); - assertEquals(List.of("flour", "sugar"), recipes.stream().map(MillingRecipe::getId).toList()); + assertEquals(List.of("flour", "sugar", "cocoa_powder"), recipes.stream().map(MillingRecipe::getId).toList()); MillingRecipe sugar = recipes.get(1); assertEquals("v.sugar_cane", sugar.getVanillaFallback()); assertEquals("sweetener_1", sugar.getOutputFood()); assertEquals("Sugar", sugar.getOrigin()); assertEquals("sweetener", sugar.getCategory()); assertEquals(8, sugar.getInputCount()); assertEquals(8, sugar.getOutputAmount()); + // Two roasted (not burnt) cocoa beans, one pan's worth, grind into one cocoa powder; a broken stone gives them back. + MillingRecipe cocoa = recipes.get(2); + assertEquals("c.ingredient(type=roasted_cocoa_beans;tags=cooked.1)", cocoa.getInputMatcher()); + assertEquals("ingredient(type=roasted_cocoa_beans;tags=cooked.1)", cocoa.getRefundPath()); + assertEquals("cocoa_powder", cocoa.getOutputFood()); assertEquals("ingredient", cocoa.getCategory()); + assertEquals("Cocoa", cocoa.getOrigin()); assertEquals(2, cocoa.getInputCount()); assertEquals(1, cocoa.getOutputAmount()); } } diff --git a/src/test/java/net/tfminecraft/cooking/nutrition/NutritionListenersCoverageTest.java b/src/test/java/net/tfminecraft/cooking/nutrition/NutritionListenersCoverageTest.java index dea9e45..122a075 100644 --- a/src/test/java/net/tfminecraft/cooking/nutrition/NutritionListenersCoverageTest.java +++ b/src/test/java/net/tfminecraft/cooking/nutrition/NutritionListenersCoverageTest.java @@ -325,6 +325,38 @@ class NutritionListenersCoverageTest { server.getScheduler().performOneTick(); assertEquals(Material.GLASS_BOTTLE,player.getInventory().getItemInMainHand().getType()); } + @Test void aDrinkServedInACupGivesTheCupBackWhereVanillaLeavesTheBottle() { + MockBukkit.createMockPlugin("RPCharacters"); DrinkConsumeListener listener=new DrinkConsumeListener(); + listener.onServedDrink(mock(PlayerItemConsumeEvent.class)); + listener.onServedDrink(consume(new ItemStack(Material.APPLE),EquipmentSlot.HAND)); + // A cup of milk is DrinkConsumeListener.onDrink's; food with no returns keeps vanilla's bottle. + listener.onServedDrink(consume(stack("cup_of_milk",true,"drink",Material.POTION),EquipmentSlot.HAND)); + listener.onServedDrink(consume(stack("stock",true,"stock",Material.POTION),EquipmentSlot.HAND)); + ItemStack blank=served("blank_drink"," "); + listener.onServedDrink(consume(blank,EquipmentSlot.HAND)); + server.getScheduler().performOneTick(); + assertNull(player.getInventory().getItem(0)); + + ItemStack cocoa=served("hot_chocolate","cup.empty"); + player.getInventory().setHeldItemSlot(2); listener.onServedDrink(consume(cocoa,EquipmentSlot.HAND)); + player.getInventory().setItem(2,new ItemStack(Material.GLASS_BOTTLE)); player.getInventory().setHeldItemSlot(5); + server.getScheduler().performOneTick(); assertEquals(Material.BOWL,player.getInventory().getItem(2).getType()); + listener.onServedDrink(consume(cocoa,EquipmentSlot.OFF_HAND)); + player.getInventory().setItemInOffHand(new ItemStack(Material.GLASS_BOTTLE)); + server.getScheduler().performOneTick(); assertEquals(Material.BOWL,player.getInventory().getItemInOffHand().getType()); + + // A cup that can't be built leaves the bottle; so does a drink with no character to drink it. + ItemStack lost=served("lost_drink","cup.missing"); + when(api.getCreator().getItemFromPath("cup.missing")).thenReturn(null); + listener.onServedDrink(consume(lost,EquipmentSlot.OFF_HAND)); + player.getInventory().setItemInOffHand(new ItemStack(Material.GLASS_BOTTLE)); + server.getScheduler().performOneTick(); assertEquals(Material.GLASS_BOTTLE,player.getInventory().getItemInOffHand().getType()); + characters.set(player,null); + listener.onServedDrink(consume(cocoa,EquipmentSlot.OFF_HAND)); + player.getInventory().setItemInOffHand(new ItemStack(Material.GLASS_BOTTLE)); + server.getScheduler().performOneTick(); assertEquals(Material.GLASS_BOTTLE,player.getInventory().getItemInOffHand().getType()); + } + @Test void staleStartCannotInitializeAReplacementGenerationOfTheSameCharacter() { MockBukkit.createMockPlugin("RPCharacters"); NutritionLifecycleListener listener = new NutritionLifecycleListener(); @@ -772,6 +804,12 @@ private ItemStack stack(String id,boolean edible,String category,Material materi meta.getPersistentDataContainer().set(Keys.FOOD_ID,PersistentDataType.STRING,id); stack.setItemMeta(meta); return stack; } + private ItemStack served(String id,String returns) { + ItemStack stack=stack(id,true,"drink",Material.POTION); + YamlConfiguration config=new YamlConfiguration(); config.set("food",10); config.set("returns",returns); + FoodItem food=new FoodItem(id,config); food.setCategory("drink"); FoodLoader.oList.removeIf(f->f.getId().equals(id)); FoodLoader.oList.add(food); + return stack; + } private PlayerItemConsumeEvent consume(ItemStack stack,EquipmentSlot hand) { return new PlayerItemConsumeEvent(player,stack,hand); } diff --git a/src/test/java/net/tfminecraft/cooking/popcorn/PopcornMachineCoverageTest.java b/src/test/java/net/tfminecraft/cooking/popcorn/PopcornMachineCoverageTest.java index 6845617..7ef28e6 100644 --- a/src/test/java/net/tfminecraft/cooking/popcorn/PopcornMachineCoverageTest.java +++ b/src/test/java/net/tfminecraft/cooking/popcorn/PopcornMachineCoverageTest.java @@ -311,7 +311,7 @@ void theShippedMachineTakesSixteenCornAndTwoToppings() { assertEquals(16, machine.getMaxInput()); assertEquals(4, machine.getYield()); assertEquals(2, machine.getMaxToppings()); - assertEquals(List.of("caramel", "sugar", "butter", "salt"), machine.getToppings().stream().map(Topping::id).toList()); + assertEquals(List.of("caramel", "sugar", "butter", "salt", "cinnamon", "vanilla"), machine.getToppings().stream().map(Topping::id).toList()); assertEquals(160, machine.getPopTicks()); assertEquals("ia.tfmc_cooking:popcorn_machine_kettle", machine.kettleFor(false)); assertEquals("ia.tfmc_cooking:popcorn_machine_kettle_loaded", machine.kettleFor(true)); @@ -332,7 +332,10 @@ void theShippedMachineTakesSixteenCornAndTwoToppings() { assertEquals("butter", machine.toppingFor(FoodItem.fromItem(piece("butter", "dairy", "Cow", 3, 1))).id()); assertEquals("butter", machine.toppingFor(FoodItem.fromItem(piece("butter", "ingredient", "Cow", 3, 1))).id()); assertNull(machine.toppingFor(FoodItem.fromItem(corn(3, 1)))); - assertEquals("caramel, sugar, butter or salt", PopcornMachineHandler.toppingNames(machine)); + assertEquals("caramel, sugar, butter, salt, cinnamon or vanilla", PopcornMachineHandler.toppingNames(machine)); + // The shipped flavourings name popcorn by their tags.yml flavour tracks (Cinnamon Sugared Popcorn). + assertEquals("cinnamon", machine.toppingFor(FoodItem.fromItem(piece("sweetener_1", "spice", "Cinnamon", 3, 1))).id()); + assertNull(machine.toppingFor(FoodItem.fromItem(piece("sweetener_1", "spice", "Nutmeg", 3, 1)))); Machine m = new Machine(); assertSame(machine, PopcornMachineConfig.machineFor(m.furniture)); @@ -418,7 +421,7 @@ void cornAndToppingsGoIn() { assertEquals("§cIt already has 2 toppings.", player.nextMessage()); m.click(new ItemStack(Material.STONE)); - assertEquals("§cOnly corn and caramel, sugar, butter or salt go in.", player.nextMessage()); + assertEquals("§cOnly corn and caramel, sugar, butter, salt, cinnamon or vanilla go in.", player.nextMessage()); ItemStack rotten = corn(5, 1); FoodItem food = FoodItem.fromItem(rotten);