From 172725150a980108b2c304e4b065a760179eb20a Mon Sep 17 00:00:00 2001 From: EERussianguy Date: Mon, 27 Mar 2023 15:27:05 -0400 Subject: [PATCH] ash trays. finally fix nutritive basin renderer. half fruit leaf drop rate. other fixes and testing --- resources/assets.py | 13 +- resources/constants.py | 8 +- resources/data.py | 4 +- resources/generate_book.py | 8 +- resources/recipes.py | 1 + .../firmalife/client/FLClientEvents.java | 12 +- .../NutritiveBasinBlockEntityRenderer.java | 41 ----- .../blockentities/AshTrayBlockEntity.java | 56 +++++++ .../common/blockentities/FLBlockEntities.java | 2 +- .../NutritiveBasinBlockEntity.java | 16 -- .../blockentities/OvenBottomBlockEntity.java | 26 +++- .../blockentities/OvenTopBlockEntity.java | 2 +- .../blockentities/SprinklerBlockEntity.java | 38 ++++- .../firmalife/common/blocks/AshtrayBlock.java | 91 +++++++++++ .../firmalife/common/blocks/FLBlocks.java | 7 +- .../greenhouse/NutritiveBasinBlock.java | 3 +- .../blocks/greenhouse/SprinklerBlock.java | 26 +--- .../common/misc/AddItemModifier.java | 12 +- .../common/misc/FLDamageSources.java | 1 + .../assets/firmalife/blockstates/ashtray.json | 38 +++++ .../blockstates/nutritive_basin.json | 5 +- .../assets/firmalife/lang/en_us.json | 8 +- .../firmalife/models/block/ashtray_0.json | 8 + .../firmalife/models/block/ashtray_1.json | 8 + .../firmalife/models/block/ashtray_10.json | 8 + .../firmalife/models/block/ashtray_2.json | 8 + .../firmalife/models/block/ashtray_3.json | 8 + .../firmalife/models/block/ashtray_4.json | 8 + .../firmalife/models/block/ashtray_5.json | 8 + .../firmalife/models/block/ashtray_6.json | 8 + .../firmalife/models/block/ashtray_7.json | 8 + .../firmalife/models/block/ashtray_8.json | 8 + .../firmalife/models/block/ashtray_9.json | 8 + .../models/block/nutritive_basin_water.json | 142 ++++++++++++++++++ .../firmalife/models/block/oven_hopper.json | 2 +- .../assets/firmalife/models/item/ashtray.json | 4 + .../textures/block/ashtray_side_0.png | Bin 0 -> 6642 bytes .../textures/block/ashtray_side_1.png | Bin 0 -> 6902 bytes .../textures/block/ashtray_side_10.png | Bin 0 -> 6748 bytes .../textures/block/ashtray_side_2.png | Bin 0 -> 6935 bytes .../textures/block/ashtray_side_3.png | Bin 0 -> 6893 bytes .../textures/block/ashtray_side_4.png | Bin 0 -> 7139 bytes .../textures/block/ashtray_side_5.png | Bin 0 -> 7117 bytes .../textures/block/ashtray_side_6.png | Bin 0 -> 7121 bytes .../textures/block/ashtray_side_7.png | Bin 0 -> 7089 bytes .../textures/block/ashtray_side_8.png | Bin 0 -> 7058 bytes .../textures/block/ashtray_side_9.png | Bin 0 -> 6786 bytes .../firmalife/textures/block/ashtray_top.png | Bin 0 -> 6597 bytes .../firmalife/textures/block/water_face.png | Bin 0 -> 11082 bytes .../textures/block/water_face.png.mcmeta | 3 + .../advancements/crafting/ashtray.json | 33 ++++ .../firmalife/plantable/papyrus.json | 2 +- .../firmalife/loot_modifiers/fruit_leaf.json | 3 +- .../firmalife/loot_tables/blocks/ashtray.json | 21 +++ .../en_us/entries/firmalife/ovens.json | 5 + .../firmalife/recipes/crafting/ashtray.json | 22 +++ .../tags/blocks/mineable/pickaxe.json | 1 + 57 files changed, 625 insertions(+), 119 deletions(-) delete mode 100644 src/main/java/com/eerussianguy/firmalife/client/render/NutritiveBasinBlockEntityRenderer.java create mode 100644 src/main/java/com/eerussianguy/firmalife/common/blockentities/AshTrayBlockEntity.java delete mode 100644 src/main/java/com/eerussianguy/firmalife/common/blockentities/NutritiveBasinBlockEntity.java create mode 100644 src/main/java/com/eerussianguy/firmalife/common/blocks/AshtrayBlock.java create mode 100644 src/main/resources/assets/firmalife/blockstates/ashtray.json create mode 100644 src/main/resources/assets/firmalife/models/block/ashtray_0.json create mode 100644 src/main/resources/assets/firmalife/models/block/ashtray_1.json create mode 100644 src/main/resources/assets/firmalife/models/block/ashtray_10.json create mode 100644 src/main/resources/assets/firmalife/models/block/ashtray_2.json create mode 100644 src/main/resources/assets/firmalife/models/block/ashtray_3.json create mode 100644 src/main/resources/assets/firmalife/models/block/ashtray_4.json create mode 100644 src/main/resources/assets/firmalife/models/block/ashtray_5.json create mode 100644 src/main/resources/assets/firmalife/models/block/ashtray_6.json create mode 100644 src/main/resources/assets/firmalife/models/block/ashtray_7.json create mode 100644 src/main/resources/assets/firmalife/models/block/ashtray_8.json create mode 100644 src/main/resources/assets/firmalife/models/block/ashtray_9.json create mode 100644 src/main/resources/assets/firmalife/models/block/nutritive_basin_water.json create mode 100644 src/main/resources/assets/firmalife/models/item/ashtray.json create mode 100644 src/main/resources/assets/firmalife/textures/block/ashtray_side_0.png create mode 100644 src/main/resources/assets/firmalife/textures/block/ashtray_side_1.png create mode 100644 src/main/resources/assets/firmalife/textures/block/ashtray_side_10.png create mode 100644 src/main/resources/assets/firmalife/textures/block/ashtray_side_2.png create mode 100644 src/main/resources/assets/firmalife/textures/block/ashtray_side_3.png create mode 100644 src/main/resources/assets/firmalife/textures/block/ashtray_side_4.png create mode 100644 src/main/resources/assets/firmalife/textures/block/ashtray_side_5.png create mode 100644 src/main/resources/assets/firmalife/textures/block/ashtray_side_6.png create mode 100644 src/main/resources/assets/firmalife/textures/block/ashtray_side_7.png create mode 100644 src/main/resources/assets/firmalife/textures/block/ashtray_side_8.png create mode 100644 src/main/resources/assets/firmalife/textures/block/ashtray_side_9.png create mode 100644 src/main/resources/assets/firmalife/textures/block/ashtray_top.png create mode 100644 src/main/resources/assets/firmalife/textures/block/water_face.png create mode 100644 src/main/resources/assets/firmalife/textures/block/water_face.png.mcmeta create mode 100644 src/main/resources/data/firmalife/advancements/crafting/ashtray.json create mode 100644 src/main/resources/data/firmalife/loot_tables/blocks/ashtray.json create mode 100644 src/main/resources/data/firmalife/recipes/crafting/ashtray.json diff --git a/resources/assets.py b/resources/assets.py index d028078e..f628453c 100644 --- a/resources/assets.py +++ b/resources/assets.py @@ -33,7 +33,13 @@ def generate(rm: ResourceManager): rm.item_model('%soven_hopper' % pref, parent='firmalife:block/%soven_hopper' % pref, no_textures=True) rm.block_model('cured_oven_hopper', parent='minecraft:block/orientable', textures={'top': 'firmalife:block/oven_hopper_top', 'side': 'minecraft:block/bricks', 'front': 'firmalife:block/oven_hopper_front'}) - rm.block_model('oven_hopper', parent='minecraft:block/orientable', textures={'top': 'firmalife:block/clay_oven_hopper_top', 'side': 'minecraft:block/bricks', 'front': 'firmalife:block/clay_oven_hopper_front'}) + rm.block_model('oven_hopper', parent='minecraft:block/orientable', textures={'top': 'firmalife:block/clay_oven_hopper_top', 'side': 'firmalife:block/unfired_bricks', 'front': 'firmalife:block/clay_oven_hopper_front'}) + + block = rm.blockstate('ashtray', variants=dict(('stage=%s' % i, {'model': 'firmalife:block/ashtray_%s' % i}) for i in range(0, 11))) + block.with_lang(lang('ashtray')).with_tag('minecraft:mineable/pickaxe').with_block_loot('firmalife:ashtray') + for i in range(0, 11): + rm.block_model('ashtray_%s' % i, parent='minecraft:block/cube_column', textures={'side': 'firmalife:block/ashtray_side_%s' % i, 'end': 'firmalife:block/ashtray_top'}) + rm.item_model('ashtray', parent='firmalife:block/ashtray_0', no_textures=True) rm.blockstate('drying_mat', model='firmalife:block/drying_mat').with_item_model().with_tag('tfc:mineable_with_sharp_tool').with_lang(lang('drying mat')).with_block_loot('firmalife:drying_mat') rm.blockstate('solar_drier', model='firmalife:block/solar_drier').with_item_model().with_tag('minecraft:mineable/axe').with_lang(lang('solar drier')).with_block_loot('firmalife:solar_drier') @@ -122,7 +128,10 @@ def generate(rm: ResourceManager): block = rm.block('firmalife:sealed_door').with_tag('minecraft:doors').with_lang(lang('sealed door')).with_tag('minecraft:mineable/pickaxe') door_loot(block, 'firmalife:sealed_door') - rm.blockstate('nutritive_basin', model='firmalife:block/nutritive_basin').with_block_loot('firmalife:nutritive_basin').with_lang(lang('nutritive basin')).with_tag('minecraft:mineable/axe').with_item_model() + rm.blockstate('nutritive_basin', variants={ + 'watered=false': {'model': 'firmalife:block/nutritive_basin'}, + 'watered=true': {'model': 'firmalife:block/nutritive_basin_water'}, + }).with_block_loot('firmalife:nutritive_basin').with_lang(lang('nutritive basin')).with_tag('minecraft:mineable/axe').with_item_model() for cheese in CHEESE_WHEELS: for age in ('fresh', 'aged', 'vintage'): diff --git a/resources/constants.py b/resources/constants.py index 503b882f..99b8e7fa 100644 --- a/resources/constants.py +++ b/resources/constants.py @@ -22,7 +22,7 @@ class Wood(NamedTuple): 'treated_wood': 'minecraft:mineable/axe' } COLORS = ('white', 'orange', 'magenta', 'light_blue', 'yellow', 'lime', 'pink', 'gray', 'light_gray', 'cyan', 'purple', 'blue', 'brown', 'green', 'red', 'black') -BLOCK_ENTITIES = ('oven_bottom', 'oven_top', 'drying_mat', 'beehive', 'solar_drier', 'mixing_bowl', 'iron_composter', 'string', 'berry_bush', 'large_planter', 'bonsai_planter', 'trellis_planter', 'hanging_planter', 'quad_planter', 'climate_station', 'hydroponic_planter', 'vat', 'oven_hopper') +BLOCK_ENTITIES = ('oven_bottom', 'oven_top', 'drying_mat', 'beehive', 'solar_drier', 'mixing_bowl', 'iron_composter', 'string', 'berry_bush', 'large_planter', 'bonsai_planter', 'trellis_planter', 'hanging_planter', 'quad_planter', 'climate_station', 'hydroponic_planter', 'vat', 'oven_hopper', 'ashtray') EXTRA_FLUIDS = ('yeast_starter', 'coconut_milk', 'yak_milk', 'goat_milk', 'curdled_yak_milk', 'curdled_goat_milk', 'pina_colada', 'cream', 'chocolate') JARS: Sequence[Tuple[str, int, str, str]] = ( ('honey', 1, 'minecraft:block/honey_block_side', 'firmalife:raw_honey'), @@ -254,8 +254,10 @@ def preset_vein(ore: str, vein_type: str, rocks: List[str], spoiler_ore: Optiona 'death.attack.firmalife.oven': '%1$s died by sticking their hand in a hot oven.', 'death.attack.firmalife.oven.player': '%1$s climbed into an oven to escape %2$s.', - 'death.attack.firmalife.swarm': '%1$s was stung to death by bees.', - 'death.attack.firmalife.swarm.player': '%1$s was stung to death by bees while trying to escape %2$s.', + 'death.attack.firmalife.swarm': '%1$s was stung to death by a swarm of bees!', + 'death.attack.firmalife.swarm.player': '%1$s was stung to death by a swarm of bees while trying to escape %2$s.', + 'death.attack.firmalife.ash': '%1$s lit wood ash on fire and was exploded.', + 'death.attack.firmalife.ash.player': '%1$s lit wood ash on fire and was exploded while trying to escape %2$s.', 'subtitles.item.firmalife.hollow_shell.blow': 'Shell whistles', 'item.firmalife.hollow_shell.filled': '%s Hollow Shell', diff --git a/resources/data.py b/resources/data.py index cd22fa76..2f94a7ed 100644 --- a/resources/data.py +++ b/resources/data.py @@ -135,8 +135,8 @@ def generate(rm: ResourceManager): simple_plantable(rm, 'green_bean', 'nitrogen', 4, planter='large', firmalife=True) simple_plantable(rm, 'tomato', 'potassium', 4, planter='large', firmalife=True) simple_plantable(rm, 'sugarcane', 'potassium', 4, planter='large', firmalife=True) - simple_plantable(rm, 'papyrus', 'potassium', 5, planter='large', firmalife=True) plantable(rm, 'jute', 'tfc:seeds/jute', 'tfc:jute', 'potassium', ['firmalife:block/crop/jute_%s' % i for i in range(0, 5)], 4, 'large') + plantable(rm, 'papyrus', 'tfc:seeds/papyrus', 'tfc:papyrus', 'potassium', ['firmalife:block/crop/papyrus_%s' % i for i in range(0, 6)], 5, 'large') bonsai_plantable(rm, 'cherry', 'nitrogen') bonsai_plantable(rm, 'green_apple', 'nitrogen') @@ -232,7 +232,7 @@ def generate(rm: ResourceManager): global_loot_modifiers(rm, 'firmalife:fruit_leaf', 'firmalife:rennet', 'firmalife:rennet_three') global_loot_modifier(rm, 'rennet', 'firmalife:add_item', {'item': utils.item_stack('2 firmalife:rennet')}, match_entity_tag('firmalife:drops_rennet')) global_loot_modifier(rm, 'rennet_three', 'firmalife:add_item', {'item': utils.item_stack('3 firmalife:rennet')}, match_entity_tag('firmalife:drops_three_rennet')) - global_loot_modifier(rm, 'fruit_leaf', 'firmalife:add_item', {'item': utils.item_stack('firmalife:fruit_leaf')}, match_block_ingredient('firmalife:drops_fruit_leaf')) + global_loot_modifier(rm, 'fruit_leaf', 'firmalife:add_item', {'item': utils.item_stack('firmalife:fruit_leaf'), 'chance': 0.5}, match_block_ingredient('firmalife:drops_fruit_leaf')) def greenhouse(rm: ResourceManager, name: str, block_ingredient: str, tier: int): diff --git a/resources/generate_book.py b/resources/generate_book.py index 1870603b..89c66b27 100644 --- a/resources/generate_book.py +++ b/resources/generate_book.py @@ -180,9 +180,9 @@ def make_book(rm: ResourceManager, i18n: I18n, local_instance: bool = False): ('WT0TW', 'WWCWW'), ('WBBBW', 'WWCWW'), ), { - '0': 'firmalife:%soven_top[facing=south]' % pref, - 'T': 'firmalife:%soven_top[facing=south]' % pref, - 'B': 'firmalife:%soven_bottom[facing=south]' % pref, + '0': 'firmalife:%soven_top[facing=north]' % pref, + 'T': 'firmalife:%soven_top[facing=north]' % pref, + 'B': 'firmalife:%soven_bottom[facing=north]' % pref, 'W': 'minecraft:bricks', 'C': 'firmalife:%soven_chimney' % pref, }) for pref in ('cured_', '')]), @@ -190,6 +190,8 @@ def make_book(rm: ResourceManager, i18n: I18n, local_instance: bool = False): text('The Top Oven contains the items that are being cooked. It will draw heat from the Bottom Oven and slowly release it over time. This means that even if your fuel runs out, your Top Oven can continue to work for a little while. Adding items to it is as simple as pressing $(item)$(k:key.use)$(). Remember to use a $(thing)Peel$() to remove the items after.'), text('Curing Oven blocks is easy, but requires patience. Simply start running your Bottom Oven as you would normally, and then wait. If an oven block is above 600 degrees for about 80 seconds, it will cure itself and any oven blocks around it. The curing effect will pass all the way up chimneys nearby.'), crafting('firmalife:crafting/oven_hopper', text_contents='The $(thing)Oven Hopper$() will input logs into any Bottom Oven that it is facing. It holds 16 logs (4 stacks of 4, like a log pile), and its inventory is fed by dropping items in the top. It can also be fed via automation from other mods.'), + crafting('firmalife:crafting/ashtray', text_contents='The $(thing)Ashtray$() collects $(thing)Wood Ash$() when placed below a $(thing)Bottom Oven Block$(). There is a 0.5 chance it gains ash when fuel is consumed. Ash is extracted with $(item)$(k:key.use)$() and inserted via attacking it.'), + empty_last_page() )), entry('bread', 'Bread', 'tfc:food/rye_bread', pages=( text('To make $(thing)Bread$(), one first must get $(thing)Yeast$(). To get your first yeast, seal $(l:firmalife:firmalife/drying)Dried Fruit$() in a Barrel of $(thing)Water$(). After three days, $(thing)Yeast Starter$() will form.$(br)From now on, your yeast can be fed by sealing Yeast Starter in a Barrel with $(thing)Flour$(). This causes it to multiply. 1 flour per 100mB of Yeast produces 600mB of Yeast. That\'s a good deal!'), diff --git a/resources/recipes.py b/resources/recipes.py index 3d4fd88c..5d0f33d7 100644 --- a/resources/recipes.py +++ b/resources/recipes.py @@ -90,6 +90,7 @@ def generate(rm: ResourceManager): rm.crafting_shapeless('crafting/toast_with_butter', ('firmalife:food/toast', 'firmalife:food/butter'), 'firmalife:food/toast_with_butter').with_advancement('firmalife:food/toast') damage_shapeless(rm, 'crafting/bacon', (not_rotten(has_trait('tfc:food/pork', trait='firmalife:smoked')), '#tfc:knives', 'tfc:powder/salt'), '4 firmalife:food/bacon').with_advancement('tfc:food/cooked_pork') rm.crafting_shapeless('crafting/tomato_sauce_mix', (not_rotten('tfc:food/tomato'), utils.ingredient('tfc:powder/salt'), not_rotten('tfc:food/garlic')), 'firmalife:food/tomato_sauce_mix').with_advancement('tfc:food/tomato') + rm.crafting_shaped('crafting/ashtray', ['ZZZ', 'XYX'], {'Z': 'tfc:powder/salt', 'X': 'firmalife:sealed_bricks', 'Y': '#forge:sheets/wrought_iron'}, 'firmalife:ashtray').with_advancement('#forge:sheets/wrought_iron') for i in range(1, 9): advanced_shapeless(rm, 'crafting/masa_%s' % i, ( diff --git a/src/main/java/com/eerussianguy/firmalife/client/FLClientEvents.java b/src/main/java/com/eerussianguy/firmalife/client/FLClientEvents.java index 57648bf2..03429eed 100644 --- a/src/main/java/com/eerussianguy/firmalife/client/FLClientEvents.java +++ b/src/main/java/com/eerussianguy/firmalife/client/FLClientEvents.java @@ -36,7 +36,6 @@ import net.dries007.tfc.client.TFCColors; import net.dries007.tfc.client.particle.GlintParticleProvider; import net.dries007.tfc.client.screen.KnappingScreen; -import net.dries007.tfc.common.blocks.TFCBlocks; import net.dries007.tfc.common.capabilities.food.FoodCapability; import net.dries007.tfc.common.items.TFCItems; @@ -68,10 +67,11 @@ public static void clientSetup(FMLClientSetupEvent event) FLBlocks.CURED_OVEN_CHIMNEY, FLBlocks.QUAD_PLANTER, FLBlocks.LARGE_PLANTER, FLBlocks.HANGING_PLANTER, FLBlocks.BONSAI_PLANTER, FLBlocks.IRON_COMPOSTER, FLBlocks.COMPOST_JAR, FLBlocks.HONEY_JAR, FLBlocks.ROTTEN_COMPOST_JAR, FLBlocks.GUANO_JAR, FLBlocks.CHEDDAR_WHEEL, FLBlocks.RAJYA_METOK_WHEEL, FLBlocks.CHEVRE_WHEEL, FLBlocks.SHOSHA_WHEEL, FLBlocks.FETA_WHEEL, FLBlocks.GOUDA_WHEEL, FLBlocks.SMALL_CHROMITE, - FLBlocks.MIXING_BOWL, FLBlocks.BUTTERFLY_GRASS, FLBlocks.SPRINKLER, FLBlocks.DRIBBLER, FLBlocks.VAT, FLBlocks.HYDROPONIC_PLANTER, FLBlocks.NUTRITIVE_BASIN + FLBlocks.MIXING_BOWL, FLBlocks.BUTTERFLY_GRASS, FLBlocks.SPRINKLER, FLBlocks.DRIBBLER, FLBlocks.VAT, FLBlocks.HYDROPONIC_PLANTER ).forEach(reg -> ItemBlockRenderTypes.setRenderLayer(reg.get(), cutout)); ItemBlockRenderTypes.setRenderLayer(FLBlocks.SOLAR_DRIER.get(), translucent); + ItemBlockRenderTypes.setRenderLayer(FLBlocks.NUTRITIVE_BASIN.get(), translucent); FLBlocks.CHROMITE_ORES.values().forEach(map -> map.values().forEach(reg -> ItemBlockRenderTypes.setRenderLayer(reg.get(), cutout))); FLBlocks.FRUIT_PRESERVES.values().forEach(reg -> ItemBlockRenderTypes.setRenderLayer(reg.get(), translucent)); @@ -149,7 +149,6 @@ public static void registerEntityRenderers(EntityRenderersEvent.RegisterRenderer event.registerBlockEntityRenderer(FLBlockEntities.MIXING_BOWL.get(), ctx -> new MixingBowlBlockEntityRenderer()); event.registerBlockEntityRenderer(FLBlockEntities.HANGER.get(), ctx -> new HangerBlockEntityRenderer()); event.registerBlockEntityRenderer(FLBlockEntities.FOOD_SHELF.get(), ctx -> new FoodShelfBlockEntityRenderer()); - event.registerBlockEntityRenderer(FLBlockEntities.NUTRITIVE_BASIN.get(), ctx -> new NutritiveBasinBlockEntityRenderer()); event.registerEntityRenderer(FLEntities.SEED_BALL.get(), ThrownItemRenderer::new); } @@ -170,6 +169,13 @@ public static void onTextureStitch(TextureStitchEvent.Pre event) event.addSprite(FLHelpers.identifier("block/crop/" + name + "_" + i)); } } + for (String name : new String[] {"papyrus"}) + { + for (int i = 0; i < 6; i++) + { + event.addSprite(FLHelpers.identifier("block/crop/" + name + "_" + i)); + } + } for (String name : new String[] {"squash", "banana"}) { for (int i = 0; i < 5; i++) diff --git a/src/main/java/com/eerussianguy/firmalife/client/render/NutritiveBasinBlockEntityRenderer.java b/src/main/java/com/eerussianguy/firmalife/client/render/NutritiveBasinBlockEntityRenderer.java deleted file mode 100644 index 858f6abd..00000000 --- a/src/main/java/com/eerussianguy/firmalife/client/render/NutritiveBasinBlockEntityRenderer.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.eerussianguy.firmalife.client.render; - -import com.eerussianguy.firmalife.common.blockentities.NutritiveBasinBlockEntity; -import com.eerussianguy.firmalife.common.blocks.greenhouse.NutritiveBasinBlock; -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.Fluids; -import net.minecraftforge.client.model.data.EmptyModelData; - -import net.dries007.tfc.client.RenderHelpers; - -import static net.dries007.tfc.client.RenderHelpers.*; - -public class NutritiveBasinBlockEntityRenderer implements BlockEntityRenderer -{ - @Override - public void render(NutritiveBasinBlockEntity basin, float partialTicks, PoseStack poseStack, MultiBufferSource buffers, int combinedLight, int combinedOverlay) - { - final BlockState state = basin.getBlockState(); - if (state.getValue(NutritiveBasinBlock.WATERED) && basin.getLevel() != null) - { - poseStack.pushPose(); - poseStack.scale(0.9f, 0.95f, 0.9f); - Minecraft.getInstance().getBlockRenderer().renderSingleBlock(Blocks.WATER.defaultBlockState(), poseStack, buffers, combinedLight, combinedOverlay, EmptyModelData.INSTANCE); - poseStack.popPose(); - -// final ResourceLocation texture = Fluids.WATER.getAttributes().getStillTexture(); -// final TextureAtlasSprite sprite = Minecraft.getInstance().getTextureAtlas(BLOCKS_ATLAS).apply(texture); -// final VertexConsumer builder = buffers.getBuffer(RenderType.entityTranslucentCull(BLOCKS_ATLAS)); -// RenderHelpers.renderTexturedCuboid(poseStack, builder, sprite, combinedLight, combinedOverlay, 2f / 16, 2f / 16, 2f / 16, 14f / 16, 1, 14f / 16); - } - } -} diff --git a/src/main/java/com/eerussianguy/firmalife/common/blockentities/AshTrayBlockEntity.java b/src/main/java/com/eerussianguy/firmalife/common/blockentities/AshTrayBlockEntity.java new file mode 100644 index 00000000..ca431c1a --- /dev/null +++ b/src/main/java/com/eerussianguy/firmalife/common/blockentities/AshTrayBlockEntity.java @@ -0,0 +1,56 @@ +package com.eerussianguy.firmalife.common.blockentities; + +import com.eerussianguy.firmalife.common.FLHelpers; +import com.eerussianguy.firmalife.common.blocks.AshtrayBlock; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.util.Mth; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.items.ItemStackHandler; + +import net.dries007.tfc.common.blockentities.InventoryBlockEntity; +import net.dries007.tfc.common.capabilities.PartialItemHandler; +import net.dries007.tfc.common.items.Powder; +import net.dries007.tfc.common.items.TFCItems; +import net.dries007.tfc.util.Helpers; + +public class AshTrayBlockEntity extends InventoryBlockEntity +{ + public AshTrayBlockEntity(BlockPos pos, BlockState state) + { + super(FLBlockEntities.ASHTRAY.get(), pos, state, defaultInventory(1), FLHelpers.blockEntityName("ashtray")); + + sidedInventory.on(new PartialItemHandler(inventory).extract(0), d -> d != Direction.UP); + } + + @Override + public boolean isItemValid(int slot, ItemStack stack) + { + return Helpers.isItem(stack, TFCItems.POWDERS.get(Powder.WOOD_ASH).get()); + } + + @Override + public int getSlotStackLimit(int slot) + { + return 16; + } + + @Override + public void setAndUpdateSlots(int slot) + { + super.setAndUpdateSlots(slot); + updateBlockState(); + } + + public void updateBlockState() + { + assert level != null; + final BlockState current = level.getBlockState(getBlockPos()); + final int stage = Mth.clamp(Mth.ceil(inventory.getStackInSlot(0).getCount() * 10f / 16f), 0, 5); + if (current.hasProperty(AshtrayBlock.STAGE) && current.getValue(AshtrayBlock.STAGE) != stage) + { + level.setBlockAndUpdate(getBlockPos(), current.setValue(AshtrayBlock.STAGE, stage)); + } + } +} diff --git a/src/main/java/com/eerussianguy/firmalife/common/blockentities/FLBlockEntities.java b/src/main/java/com/eerussianguy/firmalife/common/blockentities/FLBlockEntities.java index c571b921..ea612073 100644 --- a/src/main/java/com/eerussianguy/firmalife/common/blockentities/FLBlockEntities.java +++ b/src/main/java/com/eerussianguy/firmalife/common/blockentities/FLBlockEntities.java @@ -41,7 +41,7 @@ public class FLBlockEntities public static final RegistryObject> FOOD_SHELF = register("food_shelf", FoodShelfBlockEntity::new, Stream.of(FLBlocks.FOOD_SHELVES.values()).>flatMap(Helpers::flatten)); public static final RegistryObject> HANGER = register("hanger", HangerBlockEntity::new, Stream.of(FLBlocks.HANGERS.values()).>flatMap(Helpers::flatten)); public static final RegistryObject> VAT = register("vat", VatBlockEntity::new, FLBlocks.VAT); - public static final RegistryObject> NUTRITIVE_BASIN = register("nutritive_basin", NutritiveBasinBlockEntity::new, FLBlocks.NUTRITIVE_BASIN); + public static final RegistryObject> ASHTRAY = register("ashtray", AshTrayBlockEntity::new, FLBlocks.ASHTRAY); public static final RegistryObject> LARGE_PLANTER = register("large_planter", LargePlanterBlockEntity::new, FLBlocks.LARGE_PLANTER); public static final RegistryObject> BONSAI_PLANTER = register("bonsai_planter", BonsaiPlanterBlockEntity::new, FLBlocks.BONSAI_PLANTER); diff --git a/src/main/java/com/eerussianguy/firmalife/common/blockentities/NutritiveBasinBlockEntity.java b/src/main/java/com/eerussianguy/firmalife/common/blockentities/NutritiveBasinBlockEntity.java deleted file mode 100644 index cdace74b..00000000 --- a/src/main/java/com/eerussianguy/firmalife/common/blockentities/NutritiveBasinBlockEntity.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.eerussianguy.firmalife.common.blockentities; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; - -import net.dries007.tfc.common.blockentities.TFCBlockEntity; - -public class NutritiveBasinBlockEntity extends TFCBlockEntity -{ - public NutritiveBasinBlockEntity(BlockPos pos, BlockState state) - { - super(FLBlockEntities.NUTRITIVE_BASIN.get(), pos, state); - } - -} diff --git a/src/main/java/com/eerussianguy/firmalife/common/blockentities/OvenBottomBlockEntity.java b/src/main/java/com/eerussianguy/firmalife/common/blockentities/OvenBottomBlockEntity.java index ac86d054..ccfc3ac0 100644 --- a/src/main/java/com/eerussianguy/firmalife/common/blockentities/OvenBottomBlockEntity.java +++ b/src/main/java/com/eerussianguy/firmalife/common/blockentities/OvenBottomBlockEntity.java @@ -3,6 +3,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.NonNullList; import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvents; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; @@ -16,7 +17,10 @@ import com.eerussianguy.firmalife.common.blocks.ICure; import com.eerussianguy.firmalife.common.blocks.OvenBottomBlock; import net.dries007.tfc.common.blockentities.TickableInventoryBlockEntity; +import net.dries007.tfc.common.capabilities.Capabilities; import net.dries007.tfc.common.capabilities.heat.HeatCapability; +import net.dries007.tfc.common.items.Powder; +import net.dries007.tfc.common.items.TFCItems; import net.dries007.tfc.util.Fuel; import net.dries007.tfc.util.Helpers; import net.dries007.tfc.util.calendar.Calendars; @@ -30,10 +34,7 @@ public class OvenBottomBlockEntity extends TickableInventoryBlockEntity { @@ -242,11 +243,28 @@ private boolean consumeFuel() burnTicks += fuel.getDuration(); burnTemperature = fuel.getTemperature(); } + onFuelConsumed(); markForSync(); } return burnTicks > 0; } + public void onFuelConsumed() + { + assert level != null; + if (level.getRandom().nextFloat() < 0.5f && level.getBlockEntity(getBlockPos().below()) instanceof AshTrayBlockEntity tray) + { + tray.getCapability(Capabilities.ITEM).ifPresent(inv -> { + final ItemStack leftover = inv.insertItem(0, new ItemStack(TFCItems.POWDERS.get(Powder.WOOD_ASH).get()), false); + if (leftover.isEmpty()) + { + Helpers.playSound(level, getBlockPos(), SoundEvents.SAND_PLACE); + tray.updateBlockState(); + } + }); + } + } + public boolean light(BlockState state) { assert level != null; diff --git a/src/main/java/com/eerussianguy/firmalife/common/blockentities/OvenTopBlockEntity.java b/src/main/java/com/eerussianguy/firmalife/common/blockentities/OvenTopBlockEntity.java index d578962f..a1e0f281 100644 --- a/src/main/java/com/eerussianguy/firmalife/common/blockentities/OvenTopBlockEntity.java +++ b/src/main/java/com/eerussianguy/firmalife/common/blockentities/OvenTopBlockEntity.java @@ -40,7 +40,7 @@ public class OvenTopBlockEntity extends TickableInventoryBlockEntity { diff --git a/src/main/java/com/eerussianguy/firmalife/common/blockentities/SprinklerBlockEntity.java b/src/main/java/com/eerussianguy/firmalife/common/blockentities/SprinklerBlockEntity.java index 268c423d..0ffff396 100644 --- a/src/main/java/com/eerussianguy/firmalife/common/blockentities/SprinklerBlockEntity.java +++ b/src/main/java/com/eerussianguy/firmalife/common/blockentities/SprinklerBlockEntity.java @@ -1,5 +1,6 @@ package com.eerussianguy.firmalife.common.blockentities; +import com.eerussianguy.firmalife.common.blocks.greenhouse.SprinklerBlock; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; @@ -24,16 +25,39 @@ public class SprinklerBlockEntity extends TFCBlockEntity implements FluidTankCal { public static void serverTick(Level level, BlockPos pos, BlockState state, SprinklerBlockEntity sprinkler) { - if (level.getGameTime() % 20 == 0 && sprinkler.valid && sprinkler.tank.getFluidInTank(0).getAmount() < TANK_CAPACITY) + if (level.getGameTime() % 20 == 0 && sprinkler.valid) { - final BlockEntity above = level.getBlockEntity(pos.above()); - if (above != null) + if (sprinkler.tank.getFluidInTank(0).getAmount() < TANK_CAPACITY) { - above.getCapability(Capabilities.FLUID, Direction.DOWN).ifPresent(aboveCap -> { - final int amount = TANK_CAPACITY - sprinkler.tank.getFluidInTank(0).getAmount(); - if (amount > 0) + final BlockEntity above = level.getBlockEntity(pos.above()); + if (above != null) + { + above.getCapability(Capabilities.FLUID, Direction.DOWN).ifPresent(aboveCap -> { + final int amount = TANK_CAPACITY - sprinkler.tank.getFluidInTank(0).getAmount(); + if (amount > 0) + { + sprinkler.tank.fill(aboveCap.drain(amount, IFluidHandler.FluidAction.EXECUTE), IFluidHandler.FluidAction.EXECUTE); + } + }); + } + } + + if (level.getGameTime() % 40 == 0 && state.getBlock() instanceof SprinklerBlock block) + { + sprinkler.getCapability(Capabilities.FLUID, Direction.UP).ifPresent(cap -> { + for (BlockPos testPos : block.getPathMaker().apply(pos)) { - sprinkler.tank.fill(aboveCap.drain(amount, IFluidHandler.FluidAction.EXECUTE), IFluidHandler.FluidAction.EXECUTE); + final ClimateReceiver receiver = ClimateReceiver.get(level, testPos); + if (receiver != null) + { + if (cap.getFluidInTank(0).getAmount() > 10) + { + if (receiver.addWater(0.1f)) + { + cap.drain(10, IFluidHandler.FluidAction.EXECUTE); + } + } + } } }); } diff --git a/src/main/java/com/eerussianguy/firmalife/common/blocks/AshtrayBlock.java b/src/main/java/com/eerussianguy/firmalife/common/blocks/AshtrayBlock.java new file mode 100644 index 00000000..64806392 --- /dev/null +++ b/src/main/java/com/eerussianguy/firmalife/common/blocks/AshtrayBlock.java @@ -0,0 +1,91 @@ +package com.eerussianguy.firmalife.common.blocks; + +import java.util.Random; +import com.eerussianguy.firmalife.common.FLHelpers; +import com.eerussianguy.firmalife.common.blockentities.FLBlockEntities; +import com.eerussianguy.firmalife.common.misc.FLDamageSources; +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Explosion; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.IntegerProperty; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraftforge.items.ItemHandlerHelper; + +import net.dries007.tfc.common.blockentities.AbstractFirepitBlockEntity; +import net.dries007.tfc.common.blocks.ExtendedProperties; +import net.dries007.tfc.common.blocks.TFCBlockStateProperties; +import net.dries007.tfc.common.blocks.devices.DeviceBlock; +import net.dries007.tfc.common.items.Powder; +import net.dries007.tfc.common.items.TFCItems; +import net.dries007.tfc.util.Helpers; + +public class AshtrayBlock extends DeviceBlock +{ + public static final IntegerProperty STAGE = TFCBlockStateProperties.STAGE_10; + + public AshtrayBlock(ExtendedProperties properties) + { + super(properties, InventoryRemoveBehavior.DROP); + registerDefaultState(getStateDefinition().any().setValue(STAGE, 0)); + } + + @Override + @SuppressWarnings("deprecation") + public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult result) + { + return FLHelpers.consumeInventory(level, pos, FLBlockEntities.ASHTRAY, (ashtray, inv) -> { + final ItemStack stack = inv.extractItem(0, player.isShiftKeyDown() ? Integer.MAX_VALUE : 1, false); + if (!stack.isEmpty()) + { + ItemHandlerHelper.giveItemToPlayer(player, stack); + ashtray.updateBlockState(); + Helpers.playSound(level, pos, SoundEvents.SAND_PLACE); + return InteractionResult.sidedSuccess(level.isClientSide); + } + return InteractionResult.PASS; + }); + } + + @Override + @SuppressWarnings("deprecation") + public void randomTick(BlockState state, ServerLevel level, BlockPos pos, Random rand) + { + if (level.getBlockEntity(pos.below()) instanceof AbstractFirepitBlockEntity firepit && firepit.getTemperature() > 0 && state.getValue(STAGE) > 0) + { + level.explode(null, FLDamageSources.ASH, null, pos.getX(), pos.getY(), pos.getZ(), 10f, true, Explosion.BlockInteraction.BREAK); + } + } + + @Override + @SuppressWarnings("deprecation") + public void attack(BlockState state, Level level, BlockPos pos, Player player) + { + final ItemStack held = player.getMainHandItem(); + if (Helpers.isItem(held, TFCItems.POWDERS.get(Powder.WOOD_ASH).get())) + { + FLHelpers.readInventory(level, pos, FLBlockEntities.ASHTRAY, (ashtray, inv) -> { + var res = FLHelpers.insertOne(level, held, 0, inv, player); + if (res.consumesAction()) + { + Helpers.playSound(level, pos, SoundEvents.SAND_PLACE); + } + ashtray.updateBlockState(); + }); + } + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder builder) + { + super.createBlockStateDefinition(builder.add(STAGE)); + } +} diff --git a/src/main/java/com/eerussianguy/firmalife/common/blocks/FLBlocks.java b/src/main/java/com/eerussianguy/firmalife/common/blocks/FLBlocks.java index cab0de55..6320d01f 100644 --- a/src/main/java/com/eerussianguy/firmalife/common/blocks/FLBlocks.java +++ b/src/main/java/com/eerussianguy/firmalife/common/blocks/FLBlocks.java @@ -65,6 +65,7 @@ public class FLBlocks public static final RegistryObject OVEN_CHIMNEY = register("oven_chimney", () -> new OvenChimneyBlock(Properties.of(Material.STONE).strength(4.0f).sound(SoundType.STONE).noOcclusion(), FLBlocks.CURED_OVEN_CHIMNEY), DECORATIONS); public static final RegistryObject OVEN_HOPPER = register("oven_hopper", () -> new OvenHopperBlock(ExtendedProperties.of(Material.STONE).strength(4.0f).sound(SoundType.STONE).blockEntity(FLBlockEntities.OVEN_HOPPER), FLBlocks.CURED_OVEN_HOPPER), DECORATIONS); + public static final RegistryObject ASHTRAY = register("ashtray", () -> new AshtrayBlock(ExtendedProperties.of(Material.METAL).sound(SoundType.METAL).strength(2f).randomTicks().blockEntity(FLBlockEntities.ASHTRAY)), DECORATIONS); public static final RegistryObject DRYING_MAT = register("drying_mat", () -> new DryingMatBlock(ExtendedProperties.of(Material.DECORATION).strength(0.6f).sound(SoundType.AZALEA_LEAVES).flammable(60, 30).blockEntity(FLBlockEntities.DRYING_MAT).serverTicks(DryingMatBlockEntity::serverTick)), DECORATIONS); public static final RegistryObject SOLAR_DRIER = register("solar_drier", () -> new SolarDrierBlock(ExtendedProperties.of(Material.WOOD).strength(3.0f).sound(SoundType.WOOD).noOcclusion().flammable(60, 30).blockEntity(FLBlockEntities.SOLAR_DRIER).serverTicks(DryingMatBlockEntity::serverTick)), DECORATIONS); public static final RegistryObject BEEHIVE = register("beehive", () -> new FLBeehiveBlock(ExtendedProperties.of(Material.WOOD).strength(0.6f).sound(SoundType.WOOD).flammable(60, 30).randomTicks().blockEntity(FLBlockEntities.BEEHIVE).serverTicks(FLBeehiveBlockEntity::serverTick)), DECORATIONS); @@ -101,9 +102,9 @@ public class FLBlocks public static final RegistryObject EMBEDDED_PIPE = register("embedded_pipe", () -> new Block(Properties.of(Material.METAL).sound(SoundType.COPPER).strength(2f)), DECORATIONS); public static final RegistryObject TREATED_WOOD = register("treated_wood", () -> new ExtendedBlock(ExtendedProperties.of(Material.WOOD).sound(SoundType.WOOL).strength(2f).flammableLikePlanks()), DECORATIONS); public static final RegistryObject SQUIRTING_MOISTURE_TRANSDUCER = register("squirting_moisture_transducer", () -> new SquirtingMoistureTransducerBlock(ExtendedProperties.of(Material.METAL).strength(8f).sound(SoundType.LANTERN).blockEntity(FLBlockEntities.SQUIRTING_MOISTURE_TRANSDUCER).serverTicks(SquirtingMoistureTransducerBlockEntity::serverTick)), DECORATIONS); - public static final RegistryObject SPRINKLER = register("sprinkler", () -> SprinklerBlock.createSprinkler(ExtendedProperties.of(Material.METAL).requiresCorrectToolForDrops().strength(4.0f).sound(SoundType.METAL).blockEntity(FLBlockEntities.SPRINKLER).serverTicks(SprinklerBlockEntity::serverTick).randomTicks().noOcclusion()), DECORATIONS); - public static final RegistryObject DRIBBLER = register("dribbler", () -> SprinklerBlock.createDribbler(ExtendedProperties.of(Material.METAL).requiresCorrectToolForDrops().strength(4.0f).sound(SoundType.METAL).blockEntity(FLBlockEntities.SPRINKLER).serverTicks(SprinklerBlockEntity::serverTick).randomTicks().noOcclusion()), DECORATIONS); - public static final RegistryObject NUTRITIVE_BASIN = register("nutritive_basin", () -> new NutritiveBasinBlock(ExtendedProperties.of(Material.WOOD).strength(4f).sound(SoundType.WOOD).blockEntity(FLBlockEntities.NUTRITIVE_BASIN)), DECORATIONS); + public static final RegistryObject SPRINKLER = register("sprinkler", () -> SprinklerBlock.createSprinkler(ExtendedProperties.of(Material.METAL).requiresCorrectToolForDrops().strength(4.0f).sound(SoundType.METAL).blockEntity(FLBlockEntities.SPRINKLER).serverTicks(SprinklerBlockEntity::serverTick).noOcclusion()), DECORATIONS); + public static final RegistryObject DRIBBLER = register("dribbler", () -> SprinklerBlock.createDribbler(ExtendedProperties.of(Material.METAL).requiresCorrectToolForDrops().strength(4.0f).sound(SoundType.METAL).blockEntity(FLBlockEntities.SPRINKLER).serverTicks(SprinklerBlockEntity::serverTick).noOcclusion()), DECORATIONS); + public static final RegistryObject NUTRITIVE_BASIN = register("nutritive_basin", () -> new NutritiveBasinBlock(ExtendedProperties.of(Material.WOOD).strength(4f).sound(SoundType.WOOD)), DECORATIONS); public static final RegistryObject BUTTERFLY_GRASS = register("plant/butterfly_grass", () -> MutatingPlantBlock.create(FLPlant.BUTTERFLY_GRASS, FLPlant.BUTTERFLY_GRASS.nonSolidFire(), FLTags.Blocks.BUTTERFLY_GRASS_MUTANTS), FLORA); public static final RegistryObject POTTED_BUTTERFLY_GRASS = register("plant/potted/butterfly_grass", () -> new FlowerPotBlock(() -> (FlowerPotBlock) Blocks.FLOWER_POT, BUTTERFLY_GRASS, Properties.of(Material.DECORATION).instabreak().noOcclusion())); diff --git a/src/main/java/com/eerussianguy/firmalife/common/blocks/greenhouse/NutritiveBasinBlock.java b/src/main/java/com/eerussianguy/firmalife/common/blocks/greenhouse/NutritiveBasinBlock.java index 6df18b79..549fb8f6 100644 --- a/src/main/java/com/eerussianguy/firmalife/common/blocks/greenhouse/NutritiveBasinBlock.java +++ b/src/main/java/com/eerussianguy/firmalife/common/blocks/greenhouse/NutritiveBasinBlock.java @@ -24,12 +24,13 @@ import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.IFluidHandler; +import net.dries007.tfc.common.blocks.EntityBlockExtension; import net.dries007.tfc.common.blocks.ExtendedBlock; import net.dries007.tfc.common.blocks.ExtendedProperties; import net.dries007.tfc.common.capabilities.Capabilities; import net.dries007.tfc.util.Helpers; -public class NutritiveBasinBlock extends ExtendedBlock +public class NutritiveBasinBlock extends ExtendedBlock implements EntityBlockExtension { public static final VoxelShape SHAPE = Shapes.join( Shapes.block(), diff --git a/src/main/java/com/eerussianguy/firmalife/common/blocks/greenhouse/SprinklerBlock.java b/src/main/java/com/eerussianguy/firmalife/common/blocks/greenhouse/SprinklerBlock.java index 9864c73c..c84556ff 100644 --- a/src/main/java/com/eerussianguy/firmalife/common/blocks/greenhouse/SprinklerBlock.java +++ b/src/main/java/com/eerussianguy/firmalife/common/blocks/greenhouse/SprinklerBlock.java @@ -59,7 +59,7 @@ public SprinklerBlock(ExtendedProperties properties, Function> getPathMaker() { - if (level.getBlockEntity(origin) instanceof SprinklerBlockEntity sprinkler && sprinkler.isValid()) - { - sprinkler.getCapability(Capabilities.FLUID, Direction.UP).ifPresent(cap -> { - for (BlockPos pos : pathMaker.apply(origin)) - { - final ClimateReceiver receiver = ClimateReceiver.get(level, pos); - if (receiver != null) - { - if (cap.getFluidInTank(0).getAmount() > 10) - { - if (receiver.addWater(0.1f)) - { - cap.drain(10, IFluidHandler.FluidAction.EXECUTE); - } - } - } - } - }); - } + return pathMaker; } @Override diff --git a/src/main/java/com/eerussianguy/firmalife/common/misc/AddItemModifier.java b/src/main/java/com/eerussianguy/firmalife/common/misc/AddItemModifier.java index aa63e98c..f9256fb8 100644 --- a/src/main/java/com/eerussianguy/firmalife/common/misc/AddItemModifier.java +++ b/src/main/java/com/eerussianguy/firmalife/common/misc/AddItemModifier.java @@ -18,18 +18,23 @@ public class AddItemModifier extends LootModifier { private final ItemStack item; + private final float chance; - protected AddItemModifier(LootItemCondition[] conditions, ItemStack item) + protected AddItemModifier(LootItemCondition[] conditions, ItemStack item, float chance) { super(conditions); this.item = FoodCapability.setStackNonDecaying(item); + this.chance = chance; } @NotNull @Override protected List doApply(List loot, LootContext context) { - loot.add(item.copy()); + if (context.getRandom().nextFloat() < chance) + { + loot.add(item.copy()); + } return loot; } @@ -38,7 +43,7 @@ public static class Serializer extends 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 aqsHZlE%FOI_ghf>VRRQS=W@r;wf_R=7Y|eb literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/firmalife/textures/block/ashtray_side_1.png b/src/main/resources/assets/firmalife/textures/block/ashtray_side_1.png new file mode 100644 index 0000000000000000000000000000000000000000..ae307906e0361445ce4d423a41224301acbc2875 GIT binary patch literal 6902 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/firmalife/textures/block/ashtray_side_10.png b/src/main/resources/assets/firmalife/textures/block/ashtray_side_10.png new file mode 100644 index 0000000000000000000000000000000000000000..f2db84b61e4c6a5883cf9eee407035c911558413 GIT binary patch literal 6748 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/firmalife/textures/block/ashtray_side_3.png b/src/main/resources/assets/firmalife/textures/block/ashtray_side_3.png new file mode 100644 index 0000000000000000000000000000000000000000..0e22bec914bf5efac2cd1fd7f9d42111b862ec83 GIT binary patch literal 6893 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/firmalife/textures/block/ashtray_side_4.png b/src/main/resources/assets/firmalife/textures/block/ashtray_side_4.png new file mode 100644 index 0000000000000000000000000000000000000000..fa9c38a2e781e8dfb9e12cdc55ecc171c21ede9c GIT binary patch literal 7139 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 Fe*nZ3t=<3t literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/firmalife/textures/block/ashtray_side_5.png b/src/main/resources/assets/firmalife/textures/block/ashtray_side_5.png new file mode 100644 index 0000000000000000000000000000000000000000..09f5260c0d1588f4f81eb8e50743e5ed2b6837db GIT binary patch literal 7117 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/firmalife/textures/block/ashtray_side_6.png b/src/main/resources/assets/firmalife/textures/block/ashtray_side_6.png new file mode 100644 index 0000000000000000000000000000000000000000..f1bf94cca8bede2b3e2bc6c08c6fc9df1d3736e7 GIT binary patch literal 7121 zcmeHLdpK0<8XuyIkf=y#jNL`;HTT<^+!;}n5JItL%^EWn_M6GQDq===PUYA7Vr)=igM2|PT_2KORJ?iZ9j0%$B5g$ge{20z zzrnVNd9$2K95r+CjslYI-iap-+66m%%{K<=9i?9`0k-sz-p_)%tz1^cm14S zOi##*yFG2*nK_cjSMHt_Xa?2i>UKxyrq34F%(1>Z=Scnhd7E+xJ%sGd`+COeS?}q* z*1vl1o8q1Z@vAhh`NG%NqJl0Q0te1^88*b67Oadg!S~i346DsP{wkpkG3q%p#zfut z(jM``^&NoCfhG>&UZO53@a&ak`7Vr8q-pcqZmfoFs_GMwdbZ8>Gn;7@S9*5~wNv*m zQWL6oYw+H7*x3sWA8D}1AKkFWCGeLN-mQSRM;~fC%GcEB-IcFZKX+!FX=6uCFC#)l zrzFy-Q`}u1a4h){#@1MvOe8jk6rI`b723;8RXG`$$H@}d=HSPQCv)d-H&s#nC2ek0 z(K=A4a@*v7E^+Jk$pjmlpZs%XEtot>jElU>)Z@QE9)mw*s$)GZbj?+>H4htU%y=~C z%w~hydCxp=hg?7CT&&+!7TvYJtC}!w0-oP(y1~G`W?62MVT>jzGlR1vORaiY+EUZ% z?e14~GAqG0*`E!VuTy>|J$XAZrzMjwxc9}MjZ z&lWVCzRp<;JQ#nFSBj>*4jGcDwWtexY&JB4ZM^!|=p?+3_{lzA=opd!mPzW`MVH z2J~unX}9RN-(Nit@B6Z)z=t#@XYai z{01{fKDX(8bG)J#thf~Gtvhgb+QdoV^)^Gw+#}D5R*Z{Tr5gW+Dd=;`FTdKpX3L7# z8M&FK3T_$gc4*GVuC7U%_JdI4l1DlebVTz>E&oR{t=BGAN1xTvG&={FpLuO}QS7qY zB4Nz=b1xUX!i6j^3rIC%YF;3@a>aDbhN2vieS2X))i8 zcEEMYlS=nzE6#DF=4}Kj%E^mm4e{-H^L1ldw zUfSzLEu=MrN0939h5W!LZL9puaUC6mt3Fot2{lDEiDIDD#OGaSm@D7);KB8nU??z1e5fY1X+ zTnIn!xbptVok!j~{`O(gj#XMQCJpt6r#GHXdL@S+`^0)q{pGPmj9rA8U~l#y-DL9$ zD{P5l&zPn&)SeS>MGbV(_D|>!j*QCLl z5`TO7zJV9u+|rVr=Adou# z^PV=dHt9b1o)t?Sd*RTNogo7+152wYril?H7X8QYTZV*^%zQ8NJr=7Dbpl!X_xh(4 z_AJKU#NUsg+u!=(e#>Cwc5>d@A(j04N3m^Y_+4=-*=29Ly*Ad &ks1@`uC&i3{n zn>5;*vtm*#oi5lIRR?(F_vkC?)=GZm8-4qx2(B$Zp;SXErq;hgY4j)DSu;E zyF{=x%c{1iya_b4*QNBzgH5%ry$YW+GoTA+Q8#dJU*6&?yEMDETr75BeE%r?QK9SN zr)5ixIBaKAt2rjLj)aTb{L@#)w)u;FT6dY6?a4CJo}838ZKq$xRIMHIROaD>hL0ys zPoH|#FYC5@BJI~J0S5JgI`gBqj2twRHk+wTCeOQLGhrI;WbpnBr<<{j7anx=>$Rs| zIi=#59JM{iPBPdU*InvIu_paGTRqQaASoy?1Gz*?!$ZtYF!lau8tP? zB<)SG$HbW`EzK3x;T~yy@pZ=8UC!y6S5gM4iEB;d)_I~@)pMt9p8nMA2hTh($tJVJ zw?su-dtHhuaxAK>H1E{uxNFpR11fC>lE!JqLyZ`WE+{}xO&?bm7Ay+GLtGID!OO$M z=&6dqSXj%&5FCQYupA^vAhg7Fm7d381zbyX6OImnK`zeP zO2b0VLJ7hU8HAOGg$kuCxg}1?%R-+O(*zt=36X_Z;(T1)u=XMef~DfAcp|`-3nIuk zD-EoLgv(>OJ2;L|pd(8hUnUc?2!zPUNPHv(FOmciNFWFjh-3np44?==8YPrLazH3G zQ&0?ZI3QA3A`r_2A|Y1632{W>GD{o|UB`})qpL7mj!up!P>hxIQW=-vj1H)%Jt%-c zCK8zdkqnSQ!f1JP)z$Trv`{+YMbw`JIV2{K@I*pb*cTE~89U;$zTcIQdZL#Xf;%D= zg-c+B9f1gCW}}sgL&K$`b%sk3#gua2pgo%|B3iN0s z7yg73hf6}07%ogeLXj|ZBT|%^^aWlf;C&9z7xpMt{$(Smx=;LHpg;Ocxfi8hSq>sN zT%pw2!4jv~FN-UJ1zeW$kw+oY$rP9la1kOGpu#*J0P%QSfJvv5I4~EX!Z33bm9tPP zgM=`mphC&<0+ff&ByzZP2nKjO8VR6+ObWn(Kp0>^WDX2cm?Q=WjiOj85ulX-g^u2p zf{Ke$QD`v4fglKgxCjTJk~uVh36o&}gdiS=M1dGw<}j5a4lG+YXGRL!q9VoMM9<_#LFF_!gNa86Hg<9ei+*k#r zvZ$~YBjv(!5y479B^coVK$sO%>Qkf*m`9B!-PdJO=gmpq?MUtpd`aO``<3X4^? z0Tu)gyI%@LAY5e#P(KbY!F)&r3w|e&DP$6r!vN_3M4_Rzz$8-9G5{$6 zLg&)BAP=I$RLYm^QV~xU2}uy!AT$TiIHSd-j5BubNdB3BiI3zXisT}aDFBfIkQtsN z5{trM(TKR=XpcnyuQ89xp)u(&4Fnh*5CW)Nm;rzcrlJ=!88i+^=5k5!m)reQ%ww{s z{}=OUJQ@|^(un{S;(-7afye;FATt0ChfCy9m}D}UPW|)Eqmuql=JA*ai9v%wMa&og zl|iEeObU$wFd+&Zr1D5ih&0~}^> z5x|I0D*B_XkA@7pWz;PR-ShAqdiz2zbA(T~xsev8=<Q?`Nxb%wX^=HRp479rr&X|qa`<(px0OsJ^?;kei>1&u*%x3M;?#)aY zuV&|Vs1AR_4jZ9%Zxe|SaBipS*~Uz-;w^XiI%-x;%e3Qf$X$jC^q&{|11j?S#F`Fv z@Q$rhoaTdThfE&y?UI`;GTn!{!d2O~yX@ z{w+zg>a45+-+8mr_?b(F3NE*@LmsSWqzlfJImPe1J+|WKW7>`W31<)I8()S9xyRdy?hoq z)mL^$tNLIgy)aEj`^f79HE%noV+v1qJz(?BYE-1@bVNl>A}@33`)yjhBtNy$H81&j z$vw@imufAs0UrkJQcBl-mrv2iJgTZQ*6-o9fN}{hvw128e^?r|Qa|CXyOnOSKT;M& rEUtk2Tff^s$8>IbGGg|D5<5oa^t~nCxwS)R24I}oOB{~c1t$Ch-AbfU literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/firmalife/textures/block/ashtray_side_7.png b/src/main/resources/assets/firmalife/textures/block/ashtray_side_7.png new file mode 100644 index 0000000000000000000000000000000000000000..f446d887d06bbeae64b5e79b7207d524bb8e0f68 GIT binary patch literal 7089 zcmeHLd0dR^9-k!IsFNg7O@kwcx7kdh|& z9O%<8HDsPjs4JN7>AOBoF&a>dJOf8>e$*0wxb~#bqitZvU^*Br6)0jy9f2wW)ean;ko+FL<8uT1D!+*>6# z*d452q4AvU_dGt|6Eg;&(hqIxI7n%9)cBDh)OF83eKh%)=4OLQ$HrKn9=uuWkj_qg zcqDfDc}sJ@;AbqSfPI>mGLEKeU0~FQ_Wv4TZKr*v+w3=Iido@`NpI0{lXsmSy!?~C z1fGkl7?(q@i<&hAWJ=g^Sw`e0Q{(rIk@WX0elQTcY_ zt~0IYb2@H+IM+N=)OvKu>Jzh;TwC$8dDZws6Q`cd+_wjMV|Dj|D%%WCYA-ksf-hq!(`pXStJC4=A$aIfRX&8+xTt<@7oRR3?A4tAegly6zsBwefNnBeK&aL;mEr%i-BMqe-C{sU>X zh+#0cEPrvn%awX+>#02ne16Sqn^S)7IvrqkM`nQcBe#q*_cE_e$?THn9l31w{Q3ch zyE(RtvZu^12zrwq&(`%@7p*;CRvX(6%^u(1>&UOmxPOAOE4l4Dqt)o_FMV^ai8mdX ztThfNJ?r^;Pi46yy0))EbJ1JPYgeV+@!Fh)dlvwg-o>O+W>!71HeV9GKEzbrf0_J3 zok&yaah`nrrFwVENz!Wa3uF9A#UT(Cqu*R#r{CGp)n1EBI#yV{BP~v`FWPitlE5!u zTlMp-Ray=8`RQZBpK3ME~!{{=mr8EtcL{hiBxb#}vQG(j>iUh}h%n<8$HX zS!PpM{&|Uuit?ZPw9(&{Y|CgXw7t6g+U%;y?5A0Zt^U(v7YDY^esSM&?v2a>`j%AU zZ0gf!&xkQLn9@Qo*5O;_UO%_%%ImekCDGcPl|5_pvw`r&GIG3`)!iRd&X zbW_vB-CFa4&9kxwmSI_!?HG}gf^Ffx5AKkn<6iBbl9kTr9-S7o&vet>-Dlj&iaxH+ zb*&yWb={u#a&e)^Uvc#Qz&NW9A80@69e9C4sm1f1oIIIMPM_v7GL3Vh(`?+T?5AD| z^v=Uf)R>#V7+tW?$l1j-Z?nr$&qnPdjBNjY3liVW%YUjy!}<;8NsGr$3JNgw*Kp`j zzj)^ov(CkRAkZuLhsWnv**$1k-CUs_=bKo-Yck%uGBYjN<(rIxj>8@q$rfNom>n;A+QY1 zfrI!$8%%fESqz%bwZZt1SvZ#12@dAFMM+@qsD*4ODg>f)F?P1v)^Y|yAb@2cS}q6` zN*Qt+jEa|md{-`GF=!P;7Gi^0%JM`zi6k(ZWJR*V0WNZWI00j;jkcC>c?>US*I^3e z$p#ZFlZhEvY(zwaRRqyWBniUe>2x|4N5B#Y0D=IdkwO_L2ZYjTN{S&4XIKhJ_+lAf zBt$DYL5?U)W`n^X`{-eEWEXOgBa6cdl+P-9sf>$dA`c|Q9|V9U;BYhmM*s+P>_~ZJ zm&N)lEtC#N5s4>O4vMjOD;!oJ_)0=5a|!>V?{_7nY~;Rz^@63MFbM>^gu_DFw2?~1 zp<&XII>V%}a!F-(D3^ytj8bVHDKn4B^875L3}X;qAXZ5z(Ib&u=rc|nCJ9wxxDXZ& zg$0NqQiK`*6<)^YeM!(){wR0;#Slc@Xa29ypW>ymMHN?uvj_@PDrGv`V3hVUxFU$p zWvIULh&T#?2vGnojN<|%h{pp!9*+yqC=@&g;=&{dqK%+p3Z*ho2*FA!gxrdc@Zh-w z0*;J>0TPc!0Z2qH4WRL8cz}lo@mxBMj4a?sP8Y+?N&4P*BDbNd!oH@r7Jbg!Ic6 zn=gR9WuP)_cnXzHCsGI$90Bo?Fyx<#aS1GuB4w^*#pA391eG`!Vz?rlAX0980T={h z#lj%fhB7e>#2qBGpt3sfj#hDK5-Ull4eS~Uh3AT$(yDHslORVhH? zIJ5-?gTf#fnYY8u_Gz8}JB3Un;7J@RodSSFGSUk)90_RyIuU>=Tr!u=11S)R_%*v! z#FIsU64)UKsR1O}w-~bZH zqXQ%uBmf|lKm|A)E{;c}5eNhd>CbnMg#SOeN5pf81TK{Zz&suqAkis2fQF;v05XqC z<8p{R9ucXcue#!Y&mMt6rjBsW8mm11KeeK@@_=Nq7$ck2T6usnn93>X9VQls@?pu> zP5f!7{Tti}`QZWjpTtMPhNPWD;z;C(36^<82>($1?*NAw7VsfhC>8yY=_4USVHt5t zLTnydLvCNlWe)rKHa9%NlvDmM{24BSzfc20{awj7#rJ!-zK83ZBJfS%@747^T;CLd zZvua>u0JhY+F#xW!9wJpk_hB&Pcx?nM&1;S;mn`sjLJr3q5^tX+2$cDT4J|lQWQ#O zg7Tw=+L2?7ERK~iSuSH0>QnUTmT1P2cI18FO{TL0n^u#z^@jA8z2Ox*`@Pd+1x$<7 zl*SjArp=reR8Aih?4J5@oL;|=_|^XU-0&akeP`XgX<%YdG7xM%hiPAzB;o}Q}lb;fGy}#~81kfpUF}uQ*&2cSCYw^h0LNe$RqB982TxAv4xL+=$l9?z8nh zku%22a#T<5+pU}A8ut3N1!lLI{RjC`8g`rIuh*>8$D+hJL^R4iVSJC_6}sR1&PqGu z(6{IbB^J%LO>ksG*s^QW9c8yp%v$hfCo}HZ-j0pFDX;#9%U0_*-ye{Ak^0-JCF>W} zeVkmrET-ga5~IoH-o%_fN7-PbPAy?dNCQiw%>A9Iq`z-;Y;)7wZcf?S(dR0*v9ETT z8@6R9{ThPmJh**#(~=1{Uj5Qpc3;OT%7$!z$7DmL!4n-5SC_G9ZDNlC8%RIaRX92} zsEr-n5YMe-J8>Ge7#EM_8TIRmTG%q|jMr7s83`Xt1LvX}arex(g(2xiF+&pr1rF^6Ub;}lV?mV`D@Y(fWT z9i(+gZKst|iY=iO`=rCBEv19>-ZNBspMCdv`+Rnvzw-GEb6?l@_x+uJ*X7>o>Fzv5 z&r}bAKuqDdFumZvhN{n`3Gi?8=kEaoLMJiWXSKo$h(t&L>?$?A9)f=|&*sz1CYa3-W{o?Ll z28>&6Uf;C{vBr0!*avMK*6ZRKmLa+>*U`W8o>toQkvnT`b)SFp4jN96+r)_XGZ-uh zx{9SZv3oCXIjC{Kj-9h9?ev~)7aSe;q?%A}A6u${+$+6?SygPge4H zE5?{h(x{(tH57aC!c5cXUQb^u`}GUU_=#05#L|&B#zO`=0lo%NsJT;DRi(rj{+!z4 z9}mu$v@i5RhJM1(yLx)%1pSK%v{R>xo=?x%yejMk6`vH6v^gV6!~q}-1Fqb0^XcF;OIC`o%(?4-qK(^1Yz zeO9e3bEj0?LMv{1Zq+it!8PY-6M02M$NhBBUFWWMSjN5YF%COdd;PX<@iS(4`wdT! zyUog5NzV+9DZEZy_n%_MyYZYvp=pDDut_&z0^3#5y zK;;pz=d(_o7|=)N|0F-4wWhhm`v&d0k+5ab8P^AWJ`YnjI&>!gR&b{Ka@QQm#anmo zZKKFbyoW5az4L0#u|qp+49eQS6@5=$hi%&qOk6p~tT8Kpuak`2c3XC~sVdQ~&(E?j zrFCtLLDdOd0d|R~V*AoTD0ucG(bmWR^0#6Po=Rh|)7PF`R86iuHa+3NVef$~*SNHz z(Bd_3vJ(%HEU(XCLRH4c|YMdO)j+GEi5MVu`LS|E1>f=zp>=P zp<{jx504)^`R!?3T>WiwXZFMXrr!;?cQzKfeY3jeewX1U!+j>tZ-!X?8u~=~1o_11 zXhU#er-J!1+9Sm+CG8;Qq{PnX`T_Kfp)RqtP0@EiiC@;ipEDLiheeAetB?2YJZ{=> zxD>xd#?hOIX;J>7-Kad0p0UxKXV_EdTh_U}yTVy}L2X4Bv)k*;7W|bd%RA?geJPnO zXN)cS9)Fv-YvU{TBWU+I>rR|LpJT4~da~!c)!Q2`wyv1ufwuTzV1H|Fy}wmNOvT!~ z?n|{DGmz1(+YEyHiZ5u;qVN3SW2ehEg4y@x9c+yI=2>E1 zbmGg|M~$^85g4yGg6fE*$Hg=YjQKs0U;frIKJ%A6r)cAn%0<@i8oAMtKHc-o%P#Q? zS+y62-OGX-FQ;@6vsdmt6uZpyj@eFMc00iS}=Zn#o^tPEmnCd-pO?AxT|mMYD~z&f^BH*S`%jy*20IW3vt z@c2FIiQCbd@>}^v>DN1zmbsy;R=F^aY(HLDm<7$t6wM84{2|7*G}luxyfkqMW43eu zyJbbq9+T(Cjx=@UT;epBUIQNya($Bvb{}XWA33?U`j3(HyU{o924Y>y2XgL^_4ZyE zK4%qwcgNKJ(s&KP`?2$+L!CnigvMr}lanXM$?3y1hG%eYT!yX78GEyHf!_O3Gjx_E z)3uA;XEIrH_kYi-^1P*2PS5s#V?h+Uc=?;@+(=9^Pgyx}R&c;ve;tRXT4&qOaavif z!+~BQM!l!k+uiPt>1xp0w03K;pwlFOT~zrEzOTYf-?HYqYrcTocFO=&nrd;_W z+`v3=0L5s2+qJiFMN^Lc)2(NZx>1(i3%^&)U2(tO!;Ht`SS+`kN9s>JyWM|Rz=mFb z>FS;wi}`uE^QRi6Y@V6rmpx<3PGu&w?2zeilV|Um(c+ie?zNfpq$$wklCasj;<_1A zKP7p-h7o@8O?%y$sAKDjvR$riXghOf;FWP-W>d8WJ1y#meU7r>p7^JAegr$*lSMj( z_HR=}@%maD1M5TBHM%=boeTHgF_h3eH-CV$ zOTQ^&n7BE1p3<&Ra#6FP#{Paurypp3(7=9o?b=$6sZ%#*XhM}y^>u~SHSt%7Z{BM3 zn#kH_&VAp8Kun_v;p1^N*NqNJL^c3l!h>v-A}M@)A`lEar4#@|AqA2L1q;QtsDZjh z6jI2yMfsArSgzCw3K62(0cS|7YkA@lxBOjw_uh0mD^FIZRuW%3eBO0t)$b^;ZD_OU4sG zGMW!z`Dh|25TF5pfRCn<$v7U!hln6Z9Y@6x%N2kagj7^8xs4F!;gbY-kO+ZjA_dMY z5lf|_0Rn}D##4wSB80;W@B-2}3J;kO?gSugyj3bHK1@X*fdCHx05rgdcxWP?M?zCU zJcyB0rvEr~cc)VJi57OB%Cjgh5Py_@+7^yf|y`f4B z9d-u}EuiWSm|49Jdqa1UL4ZOc^N~oxY*8w1q>57AR7l2HyU^VvpjuE3hWM(E8|yho zAQ+>5WMKXZ{BKO&A(BY(|BvSr^dpOdOc5!Og?h+5cENYy7Z)pAK)96SF6RJanM5@OC9RNqeF9#wZzB&bP97ngn5I`IZ z!Si;k**>fb|D=!!cpQ;Op^@S8CBeNw#S-B*pb^jznNQ-=1OOQ%5-`4(0me>LZCtvfJgh= zixW>Lk?ADdhvH;lRLB2^R%ECSNG_K?zF8Tn1C-8DO-b)?sWeOo$v$u54@2$$z>Sk1 z8=(J5d^~Ja+DRgff{&OGg-4|LFV+7EaFoGK2ts1H3t9+hW{yvgx~fQb!@PK-xN*Yt#D={vJqK`fWh_4_roi?QkOMy1Y)wW>Z5_!oofOw zPE>HXtcmxv<`_~5N0}=*@cY0z4%5Mh+Pr_qY4I(4!!35F48!t;(o;Q$L`O<|if0AJ zR75{6HfZ;5ztO)hPEXu$?A}fGk!dXL}pEPwhn*SgZzjUBJ6y=(Y2fLJ-_Hpm6k9Hyu&C7X}{yIJ9%?W$Cw5nP}2)p6*g9nnGH=jr`^AYEJ zjYQ28f=snv-PK1ltX=dYm$rSsW;(m_Mq&36y#0cO<;P1hmoAWL8TxxDpTEr0^wEo_ zK8!fLY;J+o*_)+^9*;%(HZ8ufSq3W*KSnNft)76s?vqfk%0j>L)zcB3icaU`8^wJK zD>|WurDGDi!uO;Tz1@-wadhbPu;sw?P^nwRp^rT(b959`-3 zCr#v1+GO2<%)4e+-y4aN%3iW@Yifep2J@QsjFh!d4nMz{Bx;K4J-%6xQ?7UfC5p=X zEG)02X;{S$4_hDJ^Btm#!znKriM8fX>*}@hg}XZ%MAf>92`T$(Hk|GV%AauPb`a60 zfX6v==mFwvtLgB&3m$2rm~PEeOV$^heB>x=^l{=*404LJ2-^>&RyMdPEEir*id&id aKDDv1xSdqv+t&wY7Qtb;Gb0pXH4BoPn@Q-CnZEQmKZH{n7ik^lh(1<^_Y1ucj} zEs9jJA}S~jh@v>_L$Qcj3xa}*RYWPGb$B-c6<_=HeXiAhf0?yzl5@^)|Mqb9-sh~F z6X@?X+Q`fZ0D#dPZ}(vA*F^mojKaRBKYs@SfSw{PBtjVsrQl?8sQ?urIAy8~!67PC z00636mEqyVcNxa7@7oL*=$=rSkLo*ixMAAT+#vCRqrz_Sf?{_HE_7UJ%Wu6^KfG=D z+9nR!J=UJJqmOje-9Jv(X&&mx+0++3uU}Hv|0CtZ1JgR>t+C{C`krjuyWc&3@*424)|wM%u*GiLc*Ag0$`*WLWY)5}+;wjk6{T&HNA-KW)0vQ1 z9lP}|t>j5v`@p*N=}TyCuU)IZEqhtsUN8`lGVn{(=v@aA($?p(y?>F%A0lj=3KzVBF2-&anH1#-)1W!8XN$f+}AZuW7p$ z8ApsYWtjSo;V&9+Uj+lshFRLV9mWRdqW0`vo4-njk$F_IyN}wvzw2iHWvkd8n?yv)A zten6!T3eQH|7tQX&&Czax|iKzI6nBo=2@FW)fb(=Hdo9k4IrJK7{0`CSL50_;T7k` zw}i&B^Jy{4OrQ0Kf9fZ#H)OEBB>= zr-FNH4SF6nCSO`Md8&42y(QqLIP0fRUK#rJ9{2~#=FJf+iw-WIUtu{)_p*m*s>QF8 zdkbar&%7qwR$1;~Dd%Nw?zxhld0Tk9tu$=$0h_3wTy{!NO$z~UWQ1pBj5)s{@b^uY z$t(8_;@eqsH$JF5P-`;LA#H-^W7>VMgZ(Hn614%E z;qo@=oZoJ)yA@pB-(do^m{ni1usFT2OfR1ud&SO|^yG;7To^H^&C|BI7HoCT)3PjU z587GPb-Jrrg4Ra0h|%==Eclh`n3zs#xw^l09yQ&|{PBbpsf#a-b}cnHU2@iKYsAmd z9k+81=?fQMbg%6Ih-i(RV|_5ErGJJ$K%OD;_3e6?;n_2HjDL7;;+u%8XDxb~BX*zZ z8GJLxA+b6e@1WnR>d;db zn-}!BHeZgsyh6UaD%F%+6l`C;_loU)Mj76u{r9@B{98xaSt-4qTfA%c-n86k+;$ne zsN2*f_T;vGW7g$y*V{^*nre48X}vK&H!r8GCv*GUjPAy&%NAh;K0-=zZgHZhhn6D<~i&oO|N%itw)6 z2SUWFO4x-(H>6v0FR|_wMf6@M>`fAPi?WfT8l_^-v$mbSOAb{pk1aB>$~=aKF}0!9 z-5aL8oM{&SC1mvoA*Agjd`Pg za)a*7MI2c@0BB{SY<3`r&3@m0v8KB@z0k?~l#BW4*!ku7qA|%PN#_E;vs?8I!^d`F zgBxmF)3Zqaa1s^u4vse0Yt33dJvUT;k}$?1TF>>VPGiey&Q%Ye*RjEIVK3P~*CjYsO{c+zLu6tSGsWs?}AC2M5z8bw#$_e`~Je z)4*RAFmsFW2sBP=(jbcjVV+Q}3@mrQKva^`>$&!_Thx zNW>Ff7(JwOO6RI=@!t~eMTaq@iD5q`U9Y!V3hgbeY-6~q<;eh6;7NA@=`(S47qt&x}wbsu)ab=zTl(m*GQKQrNrx~8@ z-|CN&X1=A>)($xPPhV!2bYO{&xw-b;Sr-<*P^HACNZ)NiU%b!>UoGEkFqUy10LDe3 z*l`%a^<%+Ou|33>@(_EKScV;!0N^-JC4=AuM2X`eLR8{}?>%}Pk3;!R_;4DR$d$2? zIMh2$j?7Q<4}sGXU?v|w&)LXP#li^0h!Vo7#3G4;rEkN@g{7Keh{GLGz;aZkM5Pj(niJwllax+)JhqM-CdXD`4;3~! ztUx{1&?}UD0tXvVF@G=sflMSaKq46=GYKQ*u~jbjgS13397Qai1QjGBknD*BvG@}S zh0-JWqrN|tP=sK&5<)PdkS57t#3LDzC@n`Sm5GuRBXuSz5cQPCZV_KVz>Lyp9x3C+ z;Rb$?QHN28ie(xJHF_kH4}ZYPlH?){h7S`E5hBJ6QDDrZPw+}q@Nt7a@khP#2SYG* zANW5(zmJ#37EN4P?ov2Ot(4>Lgjd_k;!9za&(i!AP>6Ig1*U_1gvbY}us{Gp0s$Xn z(CH)|%txp&%ost%ktmdq1V+?U7`Z))@jxW1z=6+Wf@A?C0I3v&0zyn00+JyTkIYAS zbO#D`1Vw-x#VP?3jkHQl#mA^9G#KJR5ClS)97rYeXdnY7!ypra1UwQ2a^N!{4V8Ky zSgwH_Cp_7n_;Dss1Sthlxfm-iRKl00C_XNQpkidc5>khaM0a2^DI^CXkw|hNQ^_Ae zVTfFTrMa4wM6@Rlt?*%%C&me3>4u6SAwrNzgc=d`#;`DVu+T#4>cE&a^O!d*wj62%S&kGX)SGrcyp-S4aiQ6iAM^3b7o(_8BWK%|7F-hx5%A+ypFpUX1@R$%t<--mj(}AJx#S8}; zk4fh9N${uU{w?k?Sk(U)_hf|(?@#=e^ zP?76b>Zcn?7E-6RWXI)cPdpH19TW5j+FEl%mbjLiV)gvp<4Ynd#S*#MGn($5%AaS2 zztVTvSLfY(S?@$mSme1bE!D&1$^DMSm&|}~!t4?i3Q#BiE9dO7E<3KBA%cKoYx&Q; zTBY3zU8gliUAzIy1ghEOP>S}TTOjQo*b#{10WV$_J^n7nu%u~8b<~ghj@RnBRHqs) z6H7gXKkxBs-&eK!k!e9__rn+8U-6xp)wvfXoj4@@X4}N4SvV&HQ)diwv*y-g{#b#b zF!Fk$`AVH}S9h%FTidz8de`jm>eLnO(}5mBkQu+Ob$`cp-OAE`8T%(Z@eK?Zz=5hG ziRcd{X-PFnrqV5=^4ZtlRcRG487$+<3uK_zE%4mMr5X0dhtrqnmTr4g*iIfD-P%>( zz&5fL$y9y$TkcD14l&4Ot nCjXgfld>)ZM=orf{#bufZfmw-5%(0faRA4|-+hnUqO5-dM12*c literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/firmalife/textures/block/ashtray_top.png b/src/main/resources/assets/firmalife/textures/block/ashtray_top.png new file mode 100644 index 0000000000000000000000000000000000000000..860b71356b7f9f40e7b925a5fb3d19e72366f98b GIT binary patch literal 6597 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/firmalife/textures/block/water_face.png b/src/main/resources/assets/firmalife/textures/block/water_face.png new file mode 100644 index 0000000000000000000000000000000000000000..69f156590319b7173ad131e0e3de3a6e4d25fd82 GIT binary patch literal 11082 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 ap>FA-wpy0&fS+eUAY*+Cy<#1g@c#mWyk}?t literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/firmalife/textures/block/water_face.png.mcmeta b/src/main/resources/assets/firmalife/textures/block/water_face.png.mcmeta new file mode 100644 index 00000000..4f0718ac --- /dev/null +++ b/src/main/resources/assets/firmalife/textures/block/water_face.png.mcmeta @@ -0,0 +1,3 @@ +{ + "animation": {} +} \ No newline at end of file diff --git a/src/main/resources/data/firmalife/advancements/crafting/ashtray.json b/src/main/resources/data/firmalife/advancements/crafting/ashtray.json new file mode 100644 index 00000000..f6d75154 --- /dev/null +++ b/src/main/resources/data/firmalife/advancements/crafting/ashtray.json @@ -0,0 +1,33 @@ +{ + "__comment__": "This file was automatically created by mcresources", + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "tag": "forge:sheets/wrought_iron" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "firmalife:crafting/ashtray" + } + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "firmalife:crafting/ashtray" + ] + } +} \ No newline at end of file diff --git a/src/main/resources/data/firmalife/firmalife/plantable/papyrus.json b/src/main/resources/data/firmalife/firmalife/plantable/papyrus.json index 862c4289..ef3cc613 100644 --- a/src/main/resources/data/firmalife/firmalife/plantable/papyrus.json +++ b/src/main/resources/data/firmalife/firmalife/plantable/papyrus.json @@ -8,7 +8,7 @@ "item": "tfc:seeds/papyrus" }, "crop": { - "item": "tfc:food/papyrus" + "item": "tfc:papyrus" }, "nutrient": "potassium", "stages": 5, diff --git a/src/main/resources/data/firmalife/loot_modifiers/fruit_leaf.json b/src/main/resources/data/firmalife/loot_modifiers/fruit_leaf.json index fff78f04..727b0f7b 100644 --- a/src/main/resources/data/firmalife/loot_modifiers/fruit_leaf.json +++ b/src/main/resources/data/firmalife/loot_modifiers/fruit_leaf.json @@ -11,5 +11,6 @@ ], "item": { "item": "firmalife:fruit_leaf" - } + }, + "chance": 0.5 } \ No newline at end of file diff --git a/src/main/resources/data/firmalife/loot_tables/blocks/ashtray.json b/src/main/resources/data/firmalife/loot_tables/blocks/ashtray.json new file mode 100644 index 00000000..7e228e12 --- /dev/null +++ b/src/main/resources/data/firmalife/loot_tables/blocks/ashtray.json @@ -0,0 +1,21 @@ +{ + "__comment__": "This file was automatically created by mcresources", + "type": "minecraft:block", + "pools": [ + { + "name": "loot_pool", + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "name": "firmalife:ashtray" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/data/firmalife/patchouli_books/field_guide/en_us/entries/firmalife/ovens.json b/src/main/resources/data/firmalife/patchouli_books/field_guide/en_us/entries/firmalife/ovens.json index 18b852f2..3ad43537 100644 --- a/src/main/resources/data/firmalife/patchouli_books/field_guide/en_us/entries/firmalife/ovens.json +++ b/src/main/resources/data/firmalife/patchouli_books/field_guide/en_us/entries/firmalife/ovens.json @@ -113,6 +113,11 @@ "type": "patchouli:crafting", "recipe": "firmalife:crafting/oven_hopper", "text": "The $(thing)Oven Hopper$() will input logs into any Bottom Oven that it is facing. It holds 16 logs (4 stacks of 4, like a log pile), and its inventory is fed by dropping items in the top. It can also be fed via automation from other mods." + }, + { + "type": "patchouli:crafting", + "recipe": "firmalife:crafting/ashtray", + "text": "The $(thing)Ashtray$() collects $(thing)Wood Ash$() when placed below a $(thing)Bottom Oven Block$(). There is a 0.5 chance it gains ash when fuel is consumed. Ash is extracted with $(item)$(k:key.use)$() and inserted via attacking it." } ], "read_by_default": true, diff --git a/src/main/resources/data/firmalife/recipes/crafting/ashtray.json b/src/main/resources/data/firmalife/recipes/crafting/ashtray.json new file mode 100644 index 00000000..a9c02628 --- /dev/null +++ b/src/main/resources/data/firmalife/recipes/crafting/ashtray.json @@ -0,0 +1,22 @@ +{ + "__comment__": "This file was automatically created by mcresources", + "type": "minecraft:crafting_shaped", + "pattern": [ + "ZZZ", + "XYX" + ], + "key": { + "Z": { + "item": "tfc:powder/salt" + }, + "X": { + "item": "firmalife:sealed_bricks" + }, + "Y": { + "tag": "forge:sheets/wrought_iron" + } + }, + "result": { + "item": "firmalife:ashtray" + } +} \ No newline at end of file diff --git a/src/main/resources/data/minecraft/tags/blocks/mineable/pickaxe.json b/src/main/resources/data/minecraft/tags/blocks/mineable/pickaxe.json index 8ec8da80..76852e26 100644 --- a/src/main/resources/data/minecraft/tags/blocks/mineable/pickaxe.json +++ b/src/main/resources/data/minecraft/tags/blocks/mineable/pickaxe.json @@ -2,6 +2,7 @@ "__comment__": "This file was automatically created by mcresources", "replace": false, "values": [ + "firmalife:ashtray", "firmalife:rusted_iron_greenhouse_roof_top", "firmalife:rusted_iron_greenhouse_roof", "firmalife:rusted_iron_greenhouse_wall",