From 5d04509ecab3ba8a9ebaaad1291e16fc2870b396 Mon Sep 17 00:00:00 2001 From: stfwi Date: Tue, 29 Oct 2019 18:08:50 +0100 Subject: [PATCH] 1.14: Small Tree Cutter and Block Placer/Planter ported. Factory Hopper recipe added. --- 1.12/gradle.properties | 2 +- 1.12/readme.md | 2 + .../blocks/BlockDecorPlacer.java | 5 - .../blocks/BlockDecorTreeCutter.java | 4 +- 1.14/gradle.properties | 2 +- 1.14/meta/update.json | 3 +- 1.14/readme.md | 4 + .../java/wile/engineersdecor/ModContent.java | 33 +- .../blocks/BlockDecorPlacer.java | 747 ++++++++++++++++++ .../blocks/BlockDecorTreeCutter.java | 194 +++++ .../wile/engineersdecor/detail/ModConfig.java | 6 + .../engineersdecor/detail/TreeCutting.java | 176 +++++ 1.14/src/main/resources/META-INF/mods.toml | 2 +- .../blockstates/factory_placer.json | 9 + .../blockstates/small_tree_cutter.json | 8 + .../block/device/factory_placer_model.json | 170 ++++ .../block/device/small_tree_cutter_model.json | 222 ++++++ .../small_tree_cutter_model_active.json | 221 ++++++ .../models/item/factory_placer.json | 1 + .../models/item/small_tree_cutter.json | 1 + .../block/device/factory_placer_bottom.png | Bin 0 -> 478 bytes .../block/device/factory_placer_side.png | Bin 0 -> 652 bytes .../block/device/factory_placer_top.png | Bin 0 -> 527 bytes .../block/device/tree_cutter_blade.png | Bin 0 -> 637 bytes .../block/device/tree_cutter_blade.png.mcmeta | 1 + .../block/device/tree_cutter_blade_off.png | Bin 0 -> 395 bytes .../block/device/tree_cutter_bottom.png | Bin 0 -> 527 bytes .../block/device/tree_cutter_side.png | Bin 0 -> 368 bytes .../textures/block/device/tree_cutter_top.png | Bin 0 -> 499 bytes .../textures/gui/factory_placer_gui.png | Bin 0 -> 15570 bytes .../loot_tables/blocks/small_tree_cutter.json | 26 + .../factory_hopper_recipe_standalone.json | 24 + .../factory_placer_recipe_standalone.json | 24 + .../small_tree_cutter_recipe_standalone.json | 33 + meta/update.json | 3 +- readme.md | 5 + 36 files changed, 1915 insertions(+), 13 deletions(-) create mode 100644 1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorPlacer.java create mode 100644 1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorTreeCutter.java create mode 100644 1.14/src/main/java/wile/engineersdecor/detail/TreeCutting.java create mode 100644 1.14/src/main/resources/assets/engineersdecor/blockstates/factory_placer.json create mode 100644 1.14/src/main/resources/assets/engineersdecor/blockstates/small_tree_cutter.json create mode 100644 1.14/src/main/resources/assets/engineersdecor/models/block/device/factory_placer_model.json create mode 100644 1.14/src/main/resources/assets/engineersdecor/models/block/device/small_tree_cutter_model.json create mode 100644 1.14/src/main/resources/assets/engineersdecor/models/block/device/small_tree_cutter_model_active.json create mode 100644 1.14/src/main/resources/assets/engineersdecor/models/item/factory_placer.json create mode 100644 1.14/src/main/resources/assets/engineersdecor/models/item/small_tree_cutter.json create mode 100644 1.14/src/main/resources/assets/engineersdecor/textures/block/device/factory_placer_bottom.png create mode 100644 1.14/src/main/resources/assets/engineersdecor/textures/block/device/factory_placer_side.png create mode 100644 1.14/src/main/resources/assets/engineersdecor/textures/block/device/factory_placer_top.png create mode 100644 1.14/src/main/resources/assets/engineersdecor/textures/block/device/tree_cutter_blade.png create mode 100644 1.14/src/main/resources/assets/engineersdecor/textures/block/device/tree_cutter_blade.png.mcmeta create mode 100644 1.14/src/main/resources/assets/engineersdecor/textures/block/device/tree_cutter_blade_off.png create mode 100644 1.14/src/main/resources/assets/engineersdecor/textures/block/device/tree_cutter_bottom.png create mode 100644 1.14/src/main/resources/assets/engineersdecor/textures/block/device/tree_cutter_side.png create mode 100644 1.14/src/main/resources/assets/engineersdecor/textures/block/device/tree_cutter_top.png create mode 100644 1.14/src/main/resources/assets/engineersdecor/textures/gui/factory_placer_gui.png create mode 100644 1.14/src/main/resources/data/engineersdecor/loot_tables/blocks/small_tree_cutter.json create mode 100644 1.14/src/main/resources/data/engineersdecor/recipes/alternative/factory_hopper_recipe_standalone.json create mode 100644 1.14/src/main/resources/data/engineersdecor/recipes/alternative/factory_placer_recipe_standalone.json create mode 100644 1.14/src/main/resources/data/engineersdecor/recipes/alternative/small_tree_cutter_recipe_standalone.json diff --git a/1.12/gradle.properties b/1.12/gradle.properties index 567581f..3b06231 100644 --- a/1.12/gradle.properties +++ b/1.12/gradle.properties @@ -4,4 +4,4 @@ org.gradle.jvmargs=-Xmx8G version_minecraft=1.12.2 version_forge=14.23.5.2768 version_jei=4.10.0.198 -version_engineersdecor=1.0.15-b1 +version_engineersdecor=1.0.15-b2 diff --git a/1.12/readme.md b/1.12/readme.md index 43fded1..35ba7d3 100644 --- a/1.12/readme.md +++ b/1.12/readme.md @@ -10,6 +10,8 @@ Mod sources for Minecraft version 1.12.2. ---- ## Version history + ~ v1.0.15-b2 [A] + - v1.0.15-b1 [A] Added Floor Edge Light. [A] Added Factory Block Placer and Planter. diff --git a/1.12/src/main/java/wile/engineersdecor/blocks/BlockDecorPlacer.java b/1.12/src/main/java/wile/engineersdecor/blocks/BlockDecorPlacer.java index 70e0234..e2b9c51 100644 --- a/1.12/src/main/java/wile/engineersdecor/blocks/BlockDecorPlacer.java +++ b/1.12/src/main/java/wile/engineersdecor/blocks/BlockDecorPlacer.java @@ -8,15 +8,10 @@ */ package wile.engineersdecor.blocks; - - - import wile.engineersdecor.ModEngineersDecor; import wile.engineersdecor.detail.Networking; import net.minecraft.init.Blocks; import net.minecraft.init.SoundEvents; - - import net.minecraft.world.IBlockAccess; import net.minecraft.block.Block; import net.minecraft.block.SoundType; diff --git a/1.12/src/main/java/wile/engineersdecor/blocks/BlockDecorTreeCutter.java b/1.12/src/main/java/wile/engineersdecor/blocks/BlockDecorTreeCutter.java index e996028..dd0e2eb 100644 --- a/1.12/src/main/java/wile/engineersdecor/blocks/BlockDecorTreeCutter.java +++ b/1.12/src/main/java/wile/engineersdecor/blocks/BlockDecorTreeCutter.java @@ -1,10 +1,10 @@ /* - * @file BlockFurnace.java + * @file BlockDecorTreeCutter.java * @author Stefan Wilhelm (wile) * @copyright (C) 2019 Stefan Wilhelm * @license MIT (see https://opensource.org/licenses/MIT) * - * ED Lab furnace. + * Small Tree Cutter */ package wile.engineersdecor.blocks; diff --git a/1.14/gradle.properties b/1.14/gradle.properties index 2901257..5bbdffb 100644 --- a/1.14/gradle.properties +++ b/1.14/gradle.properties @@ -5,4 +5,4 @@ version_minecraft=1.14.4 version_forge_minecraft=1.14.4-28.1.68 version_fml_mappings=20190719-1.14.3 version_jei=1.14.4:6.0.0.10 -version_engineersdecor=1.0.15-b1 +version_engineersdecor=1.0.15-b2 diff --git a/1.14/meta/update.json b/1.14/meta/update.json index 3d45423..3e5d602 100644 --- a/1.14/meta/update.json +++ b/1.14/meta/update.json @@ -1,6 +1,7 @@ { "homepage": "https://www.curseforge.com/minecraft/mc-mods/engineers-decor/", "1.14.4": { + "1.0.15-b2": "[!] Forge version requirement set to 1.14.4-28.1.68 or higher.\n[A] Added Factory Block Placer and Planter.\n[A] Added Small Tree Cutter.", "1.0.15-b1": "[A] Added Floor Edge Light.\n[U] Updated to Forge1.14.4-28.1.68/20190719-1.14.3.", "1.0.14-b1": "[U] Updated to Forge 1.14.4-28.1.40/20190719-1.14.3.\n[A] Factory Hopper added (configurable hopper and item collector).\n[M] Switched to integrated loot table generation.\n[M] Lang file zh_cn updated (scikirbypoke, PR#53).", "1.0.13-b2": "[A] Added Steel Mesh Fence.\n[A] Added Broad Window Sill.", @@ -28,6 +29,6 @@ }, "promos": { "1.14.4-recommended": "", - "1.14.4-latest": "1.0.15-b1" + "1.14.4-latest": "1.0.15-b2" } } \ No newline at end of file diff --git a/1.14/readme.md b/1.14/readme.md index 4dc4ce9..037ccc9 100644 --- a/1.14/readme.md +++ b/1.14/readme.md @@ -11,6 +11,10 @@ Mod sources for Minecraft version 1.14.4. ## Version history + - v1.0.15-b2 [!] Forge version requirement set to 1.14.4-28.1.68 or higher. + [A] Added Factory Block Placer and Planter. + [A] Added Small Tree Cutter. + - v1.0.15-b1 [A] Added Floor Edge Light. [U] Updated to Forge1.14.4-28.1.68/20190719-1.14.3. diff --git a/1.14/src/main/java/wile/engineersdecor/ModContent.java b/1.14/src/main/java/wile/engineersdecor/ModContent.java index e088255..4518bb3 100644 --- a/1.14/src/main/java/wile/engineersdecor/ModContent.java +++ b/1.14/src/main/java/wile/engineersdecor/ModContent.java @@ -368,6 +368,12 @@ public class ModContent ModAuxiliaries.getPixeledAABB(0,0,0, 16,16,15) )).setRegistryName(new ResourceLocation(ModEngineersDecor.MODID, "factory_dropper")); + public static final BlockDecorPlacer FACTORY_PLACER = (BlockDecorPlacer)(new BlockDecorPlacer( + BlockDecor.CFG_LOOK_PLACEMENT|BlockDecor.CFG_FLIP_PLACEMENT_SHIFTCLICK|BlockDecor.CFG_REDSTONE_CONTROLLED, + Block.Properties.create(Material.WOOD, MaterialColor.WOOD).hardnessAndResistance(2f, 15f).sound(SoundType.METAL), + ModAuxiliaries.getPixeledAABB(2,2,2, 14,14,14) + )).setRegistryName(new ResourceLocation(ModEngineersDecor.MODID, "factory_placer")); + public static final BlockDecorHopper FACTORY_HOPPER = (BlockDecorHopper)(new BlockDecorHopper( BlockDecor.CFG_CUTOUT|BlockDecor.CFG_FACING_PLACEMENT|BlockDecor.CFG_OPPOSITE_PLACEMENT|BlockDecor.CFG_REDSTONE_CONTROLLED, Block.Properties.create(Material.IRON, MaterialColor.IRON).hardnessAndResistance(2f, 15f).sound(SoundType.METAL), @@ -392,6 +398,12 @@ public class ModContent ModAuxiliaries.getPixeledAABB(0,0,0, 16,11.5,16) )).setRegistryName(new ResourceLocation(ModEngineersDecor.MODID, "small_solar_panel")); + public static final BlockDecorTreeCutter SMALL_TREE_CUTTER = (BlockDecorTreeCutter)(new BlockDecorTreeCutter( + BlockDecor.CFG_CUTOUT|BlockDecor.CFG_HORIZIONTAL|BlockDecor.CFG_LOOK_PLACEMENT|BlockDecor.CFG_FLIP_PLACEMENT_SHIFTCLICK, + Block.Properties.create(Material.IRON, MaterialColor.IRON).hardnessAndResistance(2f, 15f).sound(SoundType.METAL), + ModAuxiliaries.getPixeledAABB(0,0,0, 16,8,16) + )).setRegistryName(new ResourceLocation(ModEngineersDecor.MODID, "small_tree_cutter")); + public static final BlockDecorPipeValve STRAIGHT_CHECK_VALVE = (BlockDecorPipeValve)(new BlockDecorPipeValve( BlockDecor.CFG_FACING_PLACEMENT|BlockDecor.CFG_OPPOSITE_PLACEMENT|BlockDecor.CFG_FLIP_PLACEMENT_SHIFTCLICK|BlockDecor.CFG_CUTOUT, Block.Properties.create(Material.IRON, MaterialColor.IRON).hardnessAndResistance(2f, 15f).sound(SoundType.METAL), @@ -471,10 +483,12 @@ public class ModContent TREATED_WOOD_CRAFTING_TABLE, SMALL_LAB_FURNACE, FACTORY_DROPPER, + FACTORY_PLACER, FACTORY_HOPPER, SMALL_ELECTRICAL_FURNACE, SMALL_WASTE_INCINERATOR, SMALL_MINERAL_SMELTER, + SMALL_TREE_CUTTER, SMALL_SOLAR_PANEL, CLINKER_BRICK_BLOCK, CLINKER_BRICK_SLAB, @@ -567,6 +581,11 @@ public class ModContent .build(null) .setRegistryName(ModEngineersDecor.MODID, "te_factory_dropper"); + public static final TileEntityType TET_FACTORY_PLACER = TileEntityType.Builder + .create(BlockDecorPlacer.BTileEntity::new, FACTORY_PLACER) + .build(null) + .setRegistryName(ModEngineersDecor.MODID, "te_factory_placer"); + public static final TileEntityType TET_FACTORY_HOPPER = TileEntityType.Builder .create(BlockDecorHopper.BTileEntity::new, FACTORY_HOPPER) .build(null) @@ -597,18 +616,25 @@ public class ModContent .build(null) .setRegistryName(ModEngineersDecor.MODID, "te_small_solar_panel"); + public static final TileEntityType TET_SMALL_TREE_CUTTER = TileEntityType.Builder + .create(BlockDecorTreeCutter.BTileEntity::new, SMALL_TREE_CUTTER) + .build(null) + .setRegistryName(ModEngineersDecor.MODID, "te_small_tree_cutter"); + private static final TileEntityType tile_entity_types[] = { TET_TREATED_WOOD_CRAFTING_TABLE, TET_SMALL_LAB_FURNACE, TET_FACTORY_DROPPER, + TET_FACTORY_PLACER, TET_FACTORY_HOPPER, TET_SMALL_ELECTRICAL_FURNACE, TET_WASTE_INCINERATOR, TET_STRAIGHT_PIPE_VALVE, TET_PASSIVE_FLUID_ACCUMULATOR, TET_MINERAL_SMELTER, - TET_SMALL_SOLAR_PANEL + TET_SMALL_SOLAR_PANEL, + TET_SMALL_TREE_CUTTER }; //-------------------------------------------------------------------------------------------------------------------- @@ -634,6 +660,7 @@ public class ModContent public static final ContainerType CT_TREATED_WOOD_CRAFTING_TABLE; public static final ContainerType CT_FACTORY_DROPPER; + public static final ContainerType CT_FACTORY_PLACER; public static final ContainerType CT_FACTORY_HOPPER; public static final ContainerType CT_SMALL_LAB_FURNACE; public static final ContainerType CT_SMALL_ELECTRICAL_FURNACE; @@ -644,6 +671,8 @@ public class ModContent CT_TREATED_WOOD_CRAFTING_TABLE.setRegistryName(ModEngineersDecor.MODID,"ct_treated_wood_crafting_table"); CT_FACTORY_DROPPER = (new ContainerType(BlockDecorDropper.BContainer::new)); CT_FACTORY_DROPPER.setRegistryName(ModEngineersDecor.MODID,"ct_factory_dropper"); + CT_FACTORY_PLACER = (new ContainerType(BlockDecorPlacer.BContainer::new)); + CT_FACTORY_PLACER.setRegistryName(ModEngineersDecor.MODID,"ct_factory_placer"); CT_FACTORY_HOPPER = (new ContainerType(BlockDecorHopper.BContainer::new)); CT_FACTORY_HOPPER.setRegistryName(ModEngineersDecor.MODID,"ct_factory_hopper"); CT_SMALL_LAB_FURNACE = (new ContainerType(BlockDecorFurnace.BContainer::new)); @@ -658,6 +687,7 @@ public class ModContent private static final ContainerType container_types[] = { CT_TREATED_WOOD_CRAFTING_TABLE, CT_FACTORY_DROPPER, + CT_FACTORY_PLACER, CT_FACTORY_HOPPER, CT_SMALL_LAB_FURNACE, CT_SMALL_ELECTRICAL_FURNACE, @@ -740,6 +770,7 @@ public class ModContent { ScreenManager.registerFactory(CT_TREATED_WOOD_CRAFTING_TABLE, BlockDecorCraftingTable.BGui::new); ScreenManager.registerFactory(CT_FACTORY_DROPPER, BlockDecorDropper.BGui::new); + ScreenManager.registerFactory(CT_FACTORY_PLACER, BlockDecorPlacer.BGui::new); ScreenManager.registerFactory(CT_FACTORY_HOPPER, BlockDecorHopper.BGui::new); ScreenManager.registerFactory(CT_SMALL_LAB_FURNACE, BlockDecorFurnace.BGui::new); ScreenManager.registerFactory(CT_SMALL_ELECTRICAL_FURNACE, BlockDecorFurnaceElectrical.BGui::new); diff --git a/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorPlacer.java b/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorPlacer.java new file mode 100644 index 0000000..0261a66 --- /dev/null +++ b/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorPlacer.java @@ -0,0 +1,747 @@ +/* + * @file BlockDecorPlacer.java + * @author Stefan Wilhelm (wile) + * @copyright (C) 2019 Stefan Wilhelm + * @license MIT (see https://opensource.org/licenses/MIT) + * + * Block placer and planter, factory automation suitable. + */ +package wile.engineersdecor.blocks; + +import wile.engineersdecor.ModContent; +import wile.engineersdecor.ModEngineersDecor; +import wile.engineersdecor.detail.Networking; +import net.minecraft.block.*; +import net.minecraft.state.StateContainer; +import net.minecraft.world.IBlockReader; +import net.minecraft.world.World; +import net.minecraft.world.server.ServerWorld; +import net.minecraft.tileentity.ITickableTileEntity; +import net.minecraft.tileentity.TileEntityType; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.entity.item.ItemEntity; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.item.*; +import net.minecraft.inventory.*; +import net.minecraft.inventory.container.INamedContainerProvider; +import net.minecraft.inventory.container.Container; +import net.minecraft.inventory.container.Slot; +import net.minecraft.client.gui.screen.inventory.ContainerScreen; +import net.minecraft.util.*; +import net.minecraft.util.math.*; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.StringTextComponent; +import net.minecraft.util.math.shapes.ISelectionContext; +import net.minecraft.util.math.shapes.VoxelShape; +import net.minecraft.util.math.shapes.VoxelShapes; +import net.minecraft.util.SoundEvents; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.common.IPlantable; +import net.minecraftforge.common.util.FakePlayer; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.items.wrapper.SidedInvWrapper; +import net.minecraftforge.items.CapabilityItemHandler; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.fml.network.NetworkHooks; +import com.mojang.blaze3d.platform.GlStateManager; +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.List; + + +public class BlockDecorPlacer extends BlockDecorDirected +{ + public BlockDecorPlacer(long config, Block.Properties builder, final AxisAlignedBB unrotatedAABB) + { super(config, builder, unrotatedAABB); } + + @Override + @OnlyIn(Dist.CLIENT) + public BlockRenderLayer getRenderLayer() + { return BlockRenderLayer.SOLID; } + + @Override + public VoxelShape getCollisionShape(BlockState state, IBlockReader world, BlockPos pos, ISelectionContext selectionContext) + { return VoxelShapes.fullCube(); } + + @Override + protected void fillStateContainer(StateContainer.Builder builder) + { super.fillStateContainer(builder); } + + @Override + @Nullable + public BlockState getStateForPlacement(BlockItemUseContext context) + { return super.getStateForPlacement(context); } + + @Override + @SuppressWarnings("deprecation") + public boolean hasComparatorInputOverride(BlockState state) + { return true; } + + @Override + @SuppressWarnings("deprecation") + public int getComparatorInputOverride(BlockState blockState, World world, BlockPos pos) + { return Container.calcRedstone(world.getTileEntity(pos)); } + + @Override + public boolean hasTileEntity(BlockState state) + { return true; } + + @Override + @Nullable + public TileEntity createTileEntity(BlockState state, IBlockReader world) + { return new BTileEntity(); } + + @Override + public void onBlockPlacedBy(World world, BlockPos pos, BlockState state, LivingEntity placer, ItemStack stack) + { + if(world.isRemote) return; + if((!stack.hasTag()) || (!stack.getTag().contains("tedata"))) return; + CompoundNBT te_nbt = stack.getTag().getCompound("tedata"); + if(te_nbt.isEmpty()) return; + final TileEntity te = world.getTileEntity(pos); + if(!(te instanceof BTileEntity)) return; + ((BTileEntity)te).readnbt(te_nbt, false); + ((BTileEntity)te).reset_rtstate(); + ((BTileEntity)te).markDirty(); + } + + @Override + public boolean hasDynamicDropList() + { return true; } + + @Override + public List dropList(BlockState state, World world, BlockPos pos, boolean explosion) + { + final List stacks = new ArrayList(); + if(world.isRemote) return stacks; + final TileEntity te = world.getTileEntity(pos); + if(!(te instanceof BTileEntity)) return stacks; + if(!explosion) { + ItemStack stack = new ItemStack(this, 1); + CompoundNBT te_nbt = ((BTileEntity) te).clear_getnbt(); + if(!te_nbt.isEmpty()) { + CompoundNBT nbt = new CompoundNBT(); + nbt.put("tedata", te_nbt); + stack.setTag(nbt); + } + stacks.add(stack); + } else { + for(ItemStack stack: ((BTileEntity)te).stacks_) { + if(!stack.isEmpty()) stacks.add(stack); + } + ((BTileEntity)te).reset_rtstate(); + } + return stacks; + } + + @Override + @SuppressWarnings("deprecation") + public boolean onBlockActivated(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockRayTraceResult rayTraceResult) + { + if(world.isRemote) return true; + final TileEntity te = world.getTileEntity(pos); + if(!(te instanceof BTileEntity)) return true; + if((!(player instanceof ServerPlayerEntity) && (!(player instanceof FakePlayer)))) return true; + NetworkHooks.openGui((ServerPlayerEntity)player,(INamedContainerProvider)te); + return true; + } + + @Override + @SuppressWarnings("deprecation") + public void neighborChanged(BlockState state, World world, BlockPos pos, Block block, BlockPos fromPos, boolean unused) + { + if(!(world instanceof World) || (((World) world).isRemote)) return; + TileEntity te = world.getTileEntity(pos); + if(!(te instanceof BTileEntity)) return; + ((BTileEntity)te).block_updated(); + } + + @Override + @SuppressWarnings("deprecation") + public boolean canProvidePower(BlockState state) + { return true; } + + @Override + @SuppressWarnings("deprecation") + public int getWeakPower(BlockState blockState, IBlockReader blockAccess, BlockPos pos, Direction side) + { return 0; } + + @Override + @SuppressWarnings("deprecation") + public int getStrongPower(BlockState blockState, IBlockReader blockAccess, BlockPos pos, Direction side) + { return 0; } + + //-------------------------------------------------------------------------------------------------------------------- + // Tile entity + //-------------------------------------------------------------------------------------------------------------------- + + public static class BTileEntity extends TileEntity implements ITickableTileEntity, INameable, IInventory, INamedContainerProvider, ISidedInventory + { + public static final int TICK_INTERVAL = 40; + public static final int NUM_OF_SLOTS = 18; + public static final int NUM_OF_FIELDS = 3; + /// + public static final int LOGIC_INVERTED = 0x01; + public static final int LOGIC_CONTINUOUS = 0x02; + /// + private boolean block_power_signal_ = false; + private boolean block_power_updated_ = false; + private int logic_ = LOGIC_INVERTED|LOGIC_CONTINUOUS; + private int current_slot_index_ = 0; + private int tick_timer_ = 0; + protected NonNullList stacks_; + + public static void on_config(int cooldown_ticks) + { + // ModEngineersDecor.logger.info("Config factory placer:"); + } + + public BTileEntity() + { this(ModContent.TET_FACTORY_PLACER); } + + public BTileEntity(TileEntityType te_type) + { + super(te_type); + stacks_ = NonNullList.withSize(NUM_OF_SLOTS, ItemStack.EMPTY); + reset_rtstate(); + } + + public CompoundNBT clear_getnbt() + { + CompoundNBT nbt = new CompoundNBT(); + writenbt(nbt, false); + for(int i=0; iwithSize(NUM_OF_SLOTS, ItemStack.EMPTY); + ItemStackHelper.loadAllItems(nbt, stacks_); + while(stacks_.size() < NUM_OF_SLOTS) stacks_.add(ItemStack.EMPTY); + block_power_signal_ = nbt.getBoolean("powered"); + current_slot_index_ = nbt.getInt("act_slot_index"); + logic_ = nbt.getInt("logic"); + } + + protected void writenbt(CompoundNBT nbt, boolean update_packet) + { + ItemStackHelper.saveAllItems(nbt, stacks_); + nbt.putBoolean("powered", block_power_signal_); + nbt.putInt("act_slot_index", current_slot_index_); + nbt.putInt("logic", logic_); + } + + public void block_updated() + { + boolean powered = world.isBlockPowered(pos); + if(block_power_signal_ != powered) block_power_updated_ = true; + block_power_signal_ = powered; + if(block_power_updated_) { + tick_timer_ = 1; + } else if(tick_timer_ > 4) { + tick_timer_ = 4; + } + } + + public boolean is_input_slot(int index) + { return (index >= 0) && (index < NUM_OF_SLOTS); } + + // TileEntity ------------------------------------------------------------------------------ + + @Override + public void read(CompoundNBT nbt) + { super.read(nbt); readnbt(nbt, false); } + + @Override + public CompoundNBT write(CompoundNBT nbt) + { super.write(nbt); writenbt(nbt, false); return nbt; } + + // INamable ---------------------------------------------------------------------------------------------- + + @Override + public ITextComponent getName() + { final Block block=getBlockState().getBlock(); return new StringTextComponent((block!=null) ? block.getTranslationKey() : "Factory placer"); } + + @Override + public boolean hasCustomName() + { return false; } + + @Override + public ITextComponent getCustomName() + { return getName(); } + + // INamedContainerProvider ------------------------------------------------------------------------------ + + @Override + public ITextComponent getDisplayName() + { return INameable.super.getDisplayName(); } + + @Override + public Container createMenu(int id, PlayerInventory inventory, PlayerEntity player ) + { return new BContainer(id, inventory, this, IWorldPosCallable.of(world, pos), fields); } + + // IInventory ------------------------------------------------------------------------------------------- + + @Override + public int getSizeInventory() + { return stacks_.size(); } + + @Override + public boolean isEmpty() + { for(ItemStack stack: stacks_) { if(!stack.isEmpty()) return false; } return true; } + + @Override + public ItemStack getStackInSlot(int index) + { return (index < getSizeInventory()) ? stacks_.get(index) : ItemStack.EMPTY; } + + @Override + public ItemStack decrStackSize(int index, int count) + { return ItemStackHelper.getAndSplit(stacks_, index, count); } + + @Override + public ItemStack removeStackFromSlot(int index) + { return ItemStackHelper.getAndRemove(stacks_, index); } + + @Override + public void setInventorySlotContents(int index, ItemStack stack) + { + if((index<0) || (index >= NUM_OF_SLOTS)) return; + stacks_.set(index, stack); + if(stack.getCount() > getInventoryStackLimit()) stack.setCount(getInventoryStackLimit()); + if(tick_timer_ > 8) tick_timer_ = 8; + markDirty(); + } + + @Override + public int getInventoryStackLimit() + { return 64; } + + @Override + public void markDirty() + { super.markDirty(); } + + @Override + public boolean isUsableByPlayer(PlayerEntity player) + { return getPos().distanceSq(player.getPosition()) < 36; } + + @Override + public void openInventory(PlayerEntity player) + {} + + @Override + public void closeInventory(PlayerEntity player) + { markDirty(); } + + @Override + public boolean isItemValidForSlot(int index, ItemStack stack) + { return (index>=0) && (index[] item_handlers = SidedInvWrapper.create(this, Direction.UP); + private static final int[] SIDED_INV_SLOTS; + static { + SIDED_INV_SLOTS = new int[NUM_OF_SLOTS]; + for(int i=0; i LazyOptional getCapability(net.minecraftforge.common.capabilities.Capability capability, @Nullable Direction facing) + { + if(!this.removed && (facing != null)) { + if(capability==CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) return item_handlers[0].cast(); + } + return super.getCapability(capability, facing); + } + + // ITickable and aux methods ---------------------------------------------------------------------------- + + private static int next_slot(int i) + { return (i= NUM_OF_SLOTS) current_slot_index_ = 0; + current_stack = stacks_.get(current_slot_index_); + if(!current_stack.isEmpty()) break; + current_slot_index_ = next_slot(current_slot_index_); + } + if(current_stack.isEmpty()) { current_slot_index_ = 0; return false; } + boolean no_space = false; + final Item item = current_stack.getItem(); + Block block = (item instanceof IPlantable) ? (((IPlantable)item).getPlant(world, pos).getBlock()) : Block.getBlockFromItem(item); + if(block == Blocks.AIR) { + if(item != null) { + return spit_out(facing); // Item not accepted + } else { + // try next slot + } + } else if(block instanceof IPlantable) { + if(world.isAirBlock(placement_pos)) { + // plant here, block below has to be valid soil. + BlockState soilstate = world.getBlockState(placement_pos.down()); + if(!soilstate.getBlock().canSustainPlant(soilstate, world, pos, Direction.UP, (IPlantable)block)) { + block = Blocks.AIR; + } + } else { + // adjacent block is the soil, plant above if the soil is valid. + BlockState soilstate = world.getBlockState(placement_pos); + if(soilstate.getBlock() == block) { + // The plant is already planted from the case above. + block = Blocks.AIR; + no_space = true; + } else if(!world.isAirBlock(placement_pos.up())) { + // If this is the soil an air block is needed above, if that is blocked we can't plant. + block = Blocks.AIR; + no_space = true; + } else if(!soilstate.getBlock().canSustainPlant(soilstate, world, pos, Direction.UP, (IPlantable)block)) { + // Would be space above, but it's not the right soil for the plant. + block = Blocks.AIR; + } else { + // Ok, plant above. + placement_pos = placement_pos.up(); + } + } + } else if(!world.getBlockState(placement_pos).getMaterial().isReplaceable()) { + block = Blocks.AIR; + no_space = true; + } + // System.out.println("PLACE " + current_stack + " --> " + block + " at " + placement_pos.subtract(pos) + "( item=" + item + ")"); + if(block != Blocks.AIR) { + try { + BlockItemUseContext use_context = null; + { + final FakePlayer placer = net.minecraftforge.common.util.FakePlayerFactory.getMinecraft((ServerWorld)world); + if(placer != null) { + ItemStack placement_stack = current_stack.copy(); + placement_stack.setCount(1); + ItemStack held = placer.getHeldItem(Hand.MAIN_HAND); + placer.setHeldItem(Hand.MAIN_HAND, placement_stack); + use_context = new BlockItemUseContext(new ItemUseContext(placer, Hand.MAIN_HAND, new BlockRayTraceResult(new Vec3d(0.5,0,0.5), Direction.DOWN, placement_pos, false))); + placer.setHeldItem(Hand.MAIN_HAND, held); + } + } + final BlockState placement_state = (use_context==null) ? (block.getDefaultState()) : (block.getStateForPlacement(use_context)); + if(placement_state == null) { + return spit_out(facing); + } else if(item instanceof BlockItem) { + if(((BlockItem)item).tryPlace(use_context) == ActionResultType.SUCCESS) { + SoundType stype = block.getSoundType(placement_state, world, pos, null); + if(stype != null) world.playSound(null, placement_pos, stype.getPlaceSound(), SoundCategory.BLOCKS, stype.getVolume()*0.6f, stype.getPitch()); + } else { + return spit_out(facing); + } + } else { + if(world.setBlockState(placement_pos, placement_state, 1|2|8)) { + SoundType stype = block.getSoundType(placement_state, world, pos, null); + if(stype != null) world.playSound(null, placement_pos, stype.getPlaceSound(), SoundCategory.BLOCKS, stype.getVolume()*0.6f, stype.getPitch()); + } + } + current_stack.shrink(1); + stacks_.set(current_slot_index_, current_stack); + return true; + } catch(Throwable e) { + // The block really needs a player or other issues happened during placement. + // A hard crash should not be fired here, instead spit out the item to indicated that this + // block is not compatible. + System.out.println("Exception while trying to place " + e); + world.removeBlock(placement_pos, false); + return spit_out(facing); + } + } + if((!no_space) && (!current_stack.isEmpty())) { + // There is space, but the current plant cannot be planted there, so try next. + for(int i=0; i 0) return; + tick_timer_ = TICK_INTERVAL; + // Cycle init + boolean dirty = block_power_updated_; + boolean rssignal = ((logic_ & LOGIC_INVERTED)!=0)==(!block_power_signal_); + boolean trigger = (rssignal && ((block_power_updated_) || ((logic_ & LOGIC_CONTINUOUS)!=0))); + final BlockState state = world.getBlockState(pos); + if(state == null) { block_power_signal_= false; return; } + final Direction placer_facing = state.get(FACING); + // Trigger edge detection for next cycle + { + boolean tr = world.isBlockPowered(pos); + block_power_updated_ = (block_power_signal_ != tr); + block_power_signal_ = tr; + if(block_power_updated_) dirty = true; + } + // Placing + if(trigger && try_place(placer_facing)) dirty = true; + if(dirty) markDirty(); + if(trigger && (tick_timer_ > TICK_INTERVAL)) tick_timer_ = TICK_INTERVAL; + } + } + + //-------------------------------------------------------------------------------------------------------------------- + // container + //-------------------------------------------------------------------------------------------------------------------- + + public static class BContainer extends Container implements Networking.INetworkSynchronisableContainer + { + private static final int PLAYER_INV_START_SLOTNO = BTileEntity.NUM_OF_SLOTS; + private final PlayerEntity player_; + private final IInventory inventory_; + private final IWorldPosCallable wpc_; + private final IIntArray fields_; + + public final int field(int index) { return fields_.get(index); } + + public BContainer(int cid, PlayerInventory player_inventory) + { this(cid, player_inventory, new Inventory(BTileEntity.NUM_OF_SLOTS), IWorldPosCallable.DUMMY, new IntArray(BTileEntity.NUM_OF_FIELDS)); } + + private BContainer(int cid, PlayerInventory player_inventory, IInventory block_inventory, IWorldPosCallable wpc, IIntArray fields) + { + super(ModContent.CT_FACTORY_PLACER, cid); + fields_ = fields; + wpc_ = wpc; + player_ = player_inventory.player; + inventory_ = block_inventory; + int i=-1; + // device slots (stacks 0 to 17) + for(int y=0; y<3; ++y) { + for(int x=0; x<6; ++x) { + int xpos = 11+x*18, ypos = 9+y*17; + addSlot(new Slot(inventory_, ++i, xpos, ypos)); + } + } + // player slots + for(int x=0; x<9; ++x) { + addSlot(new Slot(player_inventory, x, 8+x*18, 129)); // player slots: 0..8 + } + for(int y=0; y<3; ++y) { + for(int x=0; x<9; ++x) { + addSlot(new Slot(player_inventory, x+y*9+9, 8+x*18, 71+y*18)); // player slots: 9..35 + } + } + this.trackIntArray(fields_); // === Add reference holders + } + + @Override + public boolean canInteractWith(PlayerEntity player) + { return inventory_.isUsableByPlayer(player); } + + @Override + public ItemStack transferStackInSlot(PlayerEntity player, int index) + { + Slot slot = getSlot(index); + if((slot==null) || (!slot.getHasStack())) return ItemStack.EMPTY; + ItemStack slot_stack = slot.getStack(); + ItemStack transferred = slot_stack.copy(); + if((index>=0) && (index= PLAYER_INV_START_SLOTNO) && (index <= PLAYER_INV_START_SLOTNO+36)) { + // Player slot + if(!mergeItemStack(slot_stack, 0, BTileEntity.NUM_OF_SLOTS, false)) return ItemStack.EMPTY; + } else { + // invalid slot + return ItemStack.EMPTY; + } + if(slot_stack.isEmpty()) { + slot.putStack(ItemStack.EMPTY); + } else { + slot.onSlotChanged(); + } + if(slot_stack.getCount() == transferred.getCount()) return ItemStack.EMPTY; + slot.onTake(player, slot_stack); + return transferred; + } + + // INetworkSynchronisableContainer --------------------------------------------------------- + + @OnlyIn(Dist.CLIENT) + public void onGuiAction(CompoundNBT nbt) + { Networking.PacketContainerSyncClientToServer.sendToServer(windowId, nbt); } + + @OnlyIn(Dist.CLIENT) + public void onGuiAction(String key, int value) + { + CompoundNBT nbt = new CompoundNBT(); + nbt.putInt(key, value); + Networking.PacketContainerSyncClientToServer.sendToServer(windowId, nbt); + } + + @Override + public void onServerPacketReceived(int windowId, CompoundNBT nbt) + {} + + @Override + public void onClientPacketReceived(int windowId, PlayerEntity player, CompoundNBT nbt) + { + if(!(inventory_ instanceof BTileEntity)) return; + BTileEntity te = (BTileEntity)inventory_; + if(nbt.contains("logic")) te.logic_ = nbt.getInt("logic"); + if(nbt.contains("manual_trigger") && (nbt.getInt("manual_trigger")!=0)) { te.block_power_signal_=true; te.block_power_updated_=true; te.tick_timer_=1; } + te.markDirty(); + } + } + + //-------------------------------------------------------------------------------------------------------------------- + // GUI + //-------------------------------------------------------------------------------------------------------------------- + + @OnlyIn(Dist.CLIENT) + public static class BGui extends ContainerScreen + { + protected final PlayerEntity player_; + + public BGui(BContainer container, PlayerInventory player_inventory, ITextComponent title) + { super(container, player_inventory, title); this.player_ = player_inventory.player; } + + @Override + public void init() + { super.init(); } + + @Override + public void render(int mouseX, int mouseY, float partialTicks) + { + renderBackground(); + super.render(mouseX, mouseY, partialTicks); + renderHoveredToolTip(mouseX, mouseY); + } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int mouseButton) + { + BContainer container = (BContainer)getContainer(); + int mx = (int)(mouseX - getGuiLeft() + .5), my = (int)(mouseY - getGuiTop() + .5); + if((!isPointInRegion(126, 1, 49, 60, mouseX, mouseY))) { + return super.mouseClicked(mouseX, mouseY, mouseButton); + } else if(isPointInRegion(133, 49, 9, 9, mouseX, mouseY)) { + container.onGuiAction("manual_trigger", 1); + } else if(isPointInRegion(145, 49, 9, 9, mouseX, mouseY)) { + container.onGuiAction("logic", container.field(0) ^ BTileEntity.LOGIC_INVERTED); + } else if(isPointInRegion(159, 49, 7, 9, mouseX, mouseY)) { + container.onGuiAction("logic", container.field(0) ^ BTileEntity.LOGIC_CONTINUOUS); + } + return true; + } + + @Override + protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) + { + GlStateManager.color4f(1f, 1f, 1f, 1f); + this.minecraft.getTextureManager().bindTexture(new ResourceLocation(ModEngineersDecor.MODID, "textures/gui/factory_placer_gui.png")); + final int x0=getGuiLeft(), y0=getGuiTop(), w=getXSize(), h=getYSize(); + blit(x0, y0, 0, 0, w, h); + BContainer container = (BContainer)getContainer(); + // active slot + { + int slot_index = container.field(2); + if((slot_index < 0) || (slot_index >= BTileEntity.NUM_OF_SLOTS)) slot_index = 0; + int x = (x0+10+((slot_index % 6) * 18)); + int y = (y0+8+((slot_index / 6) * 17)); + blit(x, y, 200, 8, 18, 18); + } + // redstone input + { + if(container.field(1) != 0) { + blit(x0+133, y0+49, 217, 49, 9, 9); + } + } + // trigger logic + { + int inverter_offset = ((container.field(0) & BTileEntity.LOGIC_INVERTED) != 0) ? 11 : 0; + blit(x0+145, y0+49, 177+inverter_offset, 49, 9, 9); + int pulse_mode_offset = ((container.field(0) & BTileEntity.LOGIC_CONTINUOUS ) != 0) ? 9 : 0; + blit(x0+159, y0+49, 199+pulse_mode_offset, 49, 9, 9); + } + } + } + +} diff --git a/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorTreeCutter.java b/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorTreeCutter.java new file mode 100644 index 0000000..3e453f3 --- /dev/null +++ b/1.14/src/main/java/wile/engineersdecor/blocks/BlockDecorTreeCutter.java @@ -0,0 +1,194 @@ +/* + * @file BlockDecorTreeCutter.java + * @author Stefan Wilhelm (wile) + * @copyright (C) 2019 Stefan Wilhelm + * @license MIT (see https://opensource.org/licenses/MIT) + * + * Small Tree Cutter + */ +package wile.engineersdecor.blocks; + +import net.minecraft.item.BlockItemUseContext; +import wile.engineersdecor.ModContent; +import wile.engineersdecor.ModEngineersDecor; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.particles.ParticleTypes; +import net.minecraft.state.BooleanProperty; +import net.minecraft.state.StateContainer; +import net.minecraft.tileentity.ITickableTileEntity; +import net.minecraft.tileentity.TileEntityType; +import net.minecraft.world.IBlockReader; +import net.minecraft.world.World; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.*; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.energy.CapabilityEnergy; +import net.minecraftforge.energy.IEnergyStorage; +import wile.engineersdecor.detail.TreeCutting; + +import javax.annotation.Nullable; +import java.util.Random; + + +public class BlockDecorTreeCutter extends BlockDecorDirectedHorizontal +{ + public static final BooleanProperty ACTIVE = BooleanProperty.create("active"); + + public BlockDecorTreeCutter(long config, Block.Properties builder, final AxisAlignedBB unrotatedAABB) + { super(config, builder, unrotatedAABB); } + + @Override + protected void fillStateContainer(StateContainer.Builder builder) + { super.fillStateContainer(builder); builder.add(ACTIVE); } + + @Override + @Nullable + public BlockState getStateForPlacement(BlockItemUseContext context) + { return super.getStateForPlacement(context).with(ACTIVE, false); } + + @Override + public boolean hasTileEntity(BlockState state) + { return true; } + + @Override + @Nullable + public TileEntity createTileEntity(BlockState state, IBlockReader world) + { return new BTileEntity(); } + + @OnlyIn(Dist.CLIENT) + public void animateTick(BlockState state, World world, BlockPos pos, Random rnd) + { + if((state.getBlock()!=this) || (!state.get(ACTIVE))) return; + final double rv = rnd.nextDouble(); + if(rv > 0.8) return; + final double x=0.5+pos.getX(), y=0.5+pos.getY(), z=0.5+pos.getZ(); + final double xc=0.52, xr=rnd.nextDouble()*0.4-0.2, yr=(y-0.3+rnd.nextDouble()*0.2); + switch(state.get(HORIZONTAL_FACING)) { + case WEST: world.addParticle(ParticleTypes.SMOKE, x-xc, yr, z+xr, 0.0, 0.0, 0.0); break; + case EAST: world.addParticle(ParticleTypes.SMOKE, x+xc, yr, z+xr, 0.0, 0.0, 0.0); break; + case NORTH: world.addParticle(ParticleTypes.SMOKE, x+xr, yr, z-xc, 0.0, 0.0, 0.0); break; + default: world.addParticle(ParticleTypes.SMOKE, x+xr, yr, z+xc, 0.0, 0.0, 0.0); break; + } + } + + //-------------------------------------------------------------------------------------------------------------------- + // Tile entity + //-------------------------------------------------------------------------------------------------------------------- + + public static class BTileEntity extends TileEntity implements ITickableTileEntity, IEnergyStorage + { + public static final int IDLE_TICK_INTERVAL = 40; + public static final int TICK_INTERVAL = 5; + public static final int BOOST_FACTOR = 6; + public static final int DEFAULT_BOOST_ENERGY = 64; + public static final int DEFAULT_CUTTING_TIME_NEEDED = 20 * 60; // 60 secs, so that people don't come to the bright idea to carry one with them. + private static int boost_energy_consumption = DEFAULT_BOOST_ENERGY; + private static int cutting_time_needed = DEFAULT_CUTTING_TIME_NEEDED; + + private int tick_timer_; + private int proc_time_elapsed_; // small, not saved in nbt. + private int boost_energy_; // small, not saved in nbt. + + public static void on_config(int boost_energy_per_tick) + { + boost_energy_consumption = TICK_INTERVAL * MathHelper.clamp(boost_energy_per_tick, 16, 512); + ModEngineersDecor.logger().info("Config tree cutter: Boost energy consumption:" + boost_energy_consumption + "rf/t"); + } + + public BTileEntity() + { super(ModContent.TET_SMALL_TREE_CUTTER); } + + public BTileEntity(TileEntityType te_type) + { super(te_type); } + + // IEnergyStorage ---------------------------------------------------------------------------- + + protected LazyOptional energy_handler_ = LazyOptional.of(() -> (IEnergyStorage)this); + + @Override + public boolean canExtract() + { return false; } + + @Override + public boolean canReceive() + { return true; } + + @Override + public int getMaxEnergyStored() + { return boost_energy_consumption; } + + @Override + public int getEnergyStored() + { return boost_energy_; } + + @Override + public int extractEnergy(int maxExtract, boolean simulate) + { return 0; } + + @Override + public int receiveEnergy(int maxReceive, boolean simulate) + { // only speedup support, no buffering, not in nbt -> no markdirty + if((boost_energy_ >= boost_energy_consumption) || (maxReceive < boost_energy_consumption)) return 0; + if(!simulate) boost_energy_ = boost_energy_consumption; + return boost_energy_consumption; + } + + // Capability export ---------------------------------------------------------------------------- + + @Override + public LazyOptional getCapability(net.minecraftforge.common.capabilities.Capability capability, @Nullable Direction facing) + { + if(!this.removed && (facing != null)) { + if(capability== CapabilityEnergy.ENERGY) { + return energy_handler_.cast(); + } + } + return super.getCapability(capability, facing); + } + + // ITickable ------------------------------------------------------------------------------------ + + @Override + public void tick() + { + if(--tick_timer_ > 0) return; + if(world.isRemote) { + if(!world.getBlockState(pos).get(ACTIVE)) { + tick_timer_ = TICK_INTERVAL; + } else { + tick_timer_ = 1; + world.playSound(pos.getX(), pos.getY(), pos.getZ(), SoundEvents.BLOCK_WOOD_HIT, SoundCategory.BLOCKS, 0.1f, 1.0f, false); + } + } else { + tick_timer_ = TICK_INTERVAL; + final BlockState device_state = world.getBlockState(pos); + final BlockPos tree_pos = pos.offset(device_state.get(HORIZONTAL_FACING)); + final BlockState tree_state = world.getBlockState(tree_pos); + if(!TreeCutting.canChop(tree_state) || (world.isBlockPowered(pos))) { + if(device_state.get(ACTIVE)) world.setBlockState(pos, device_state.with(ACTIVE, false), 1|2); + proc_time_elapsed_ = 0; + tick_timer_ = IDLE_TICK_INTERVAL; + return; + } + proc_time_elapsed_ += TICK_INTERVAL; + if(boost_energy_ >= boost_energy_consumption) { boost_energy_ = 0; proc_time_elapsed_ += TICK_INTERVAL*BOOST_FACTOR; } + boolean active = true; + if(proc_time_elapsed_ >= cutting_time_needed) { + proc_time_elapsed_ = 0; + TreeCutting.chopTree(world, tree_state, tree_pos, 512, false); + world.playSound(null, pos.getX(), pos.getY(), pos.getZ(), SoundEvents.BLOCK_WOOD_BREAK, SoundCategory.BLOCKS, 1.0f, 1.0f); + active = false; + } + if(device_state.get(ACTIVE) != active) { + world.setBlockState(pos, device_state.with(ACTIVE, active), 1|2); + } + } + } + } +} diff --git a/1.14/src/main/java/wile/engineersdecor/detail/ModConfig.java b/1.14/src/main/java/wile/engineersdecor/detail/ModConfig.java index 9da05b9..765df19 100644 --- a/1.14/src/main/java/wile/engineersdecor/detail/ModConfig.java +++ b/1.14/src/main/java/wile/engineersdecor/detail/ModConfig.java @@ -109,6 +109,7 @@ public class ModConfig public final ForgeConfigSpec.BooleanValue without_waste_incinerator; public final ForgeConfigSpec.BooleanValue without_sign_plates; public final ForgeConfigSpec.BooleanValue without_factory_dropper; + public final ForgeConfigSpec.BooleanValue without_factory_placer; public final ForgeConfigSpec.BooleanValue without_slabs; public final ForgeConfigSpec.BooleanValue without_halfslabs; public final ForgeConfigSpec.BooleanValue without_direct_slab_pickup; @@ -247,6 +248,10 @@ public class ModConfig .translation(ModEngineersDecor.MODID + ".config.without_factory_dropper") .comment("Disable the factory dropper.") .define("without_factory_dropper", false); + without_factory_placer = builder + .translation(ModEngineersDecor.MODID + ".config.without_factory_placer") + .comment("Disable the factory placer.") + .define("without_factory_placer", false); without_slabs = builder .translation(ModEngineersDecor.MODID + ".config.without_slabs") .comment("Disable horizontal half-block slab.") @@ -419,6 +424,7 @@ public class ModConfig if(block instanceof BlockDecorPassiveFluidAccumulator) return COMMON.without_passive_fluid_accumulator.get(); if(block instanceof BlockDecorWasteIncinerator) return COMMON.without_waste_incinerator.get(); if(block instanceof BlockDecorDropper) return COMMON.without_factory_dropper.get(); + if(block instanceof BlockDecorPlacer) return COMMON.without_factory_placer.get(); if(block instanceof BlockDecorHalfSlab) return COMMON.without_halfslabs.get(); if(block instanceof BlockDecorLadder) return COMMON.without_ladders.get(); if(block instanceof BlockDecorWindow) return COMMON.without_windows.get(); diff --git a/1.14/src/main/java/wile/engineersdecor/detail/TreeCutting.java b/1.14/src/main/java/wile/engineersdecor/detail/TreeCutting.java new file mode 100644 index 0000000..13c5c0b --- /dev/null +++ b/1.14/src/main/java/wile/engineersdecor/detail/TreeCutting.java @@ -0,0 +1,176 @@ +/* + * @file TreeCutting.java + * @author Stefan Wilhelm (wile) + * @copyright (C) 2019 Stefan Wilhelm + * @license MIT (see https://opensource.org/licenses/MIT) + * + * Simple tree cutting algorithm. + */ +package wile.engineersdecor.detail; + +import net.minecraft.block.*; +import net.minecraft.util.ResourceLocation; +import wile.engineersdecor.ModEngineersDecor; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3i; +import net.minecraft.world.World; +import com.google.common.collect.ImmutableList; +import java.util.*; + + +public class TreeCutting +{ + private static org.apache.logging.log4j.Logger LOGGER = ModEngineersDecor.logger(); + + public static boolean canChop(BlockState state) + { return isLog(state); } + + // ------------------------------------------------------------------------------------------------------------------- + + private static final List hoffsets = ImmutableList.of( + new Vec3i( 1,0, 0), new Vec3i( 1,0, 1), new Vec3i( 0,0, 1), + new Vec3i(-1,0, 1), new Vec3i(-1,0, 0), new Vec3i(-1,0,-1), + new Vec3i( 0,0,-1), new Vec3i( 1,0,-1) + ); + + private static boolean isLog(BlockState state) + { return (state.getBlock() instanceof LogBlock) || (state.getBlock().getTags().contains(new ResourceLocation("minecraft","logs"))); } + + private static boolean isSameLog(BlockState a, BlockState b) + { return (a.getBlock()==b.getBlock()); } + + private static boolean isLeaves(BlockState state) + { + if(state.getBlock() instanceof LeavesBlock) return true; + if(state.getBlock().getTags().contains(new ResourceLocation("minecraft","leaves"))) return true; + return false; + } + + private static List findBlocksAround(final World world, final BlockPos centerPos, final BlockState leaf_type_state, final Set checked, int recursion_left) + { + ArrayList to_decay = new ArrayList(); + for(int y=-1; y<=1; ++y) { + final BlockPos layer = centerPos.add(0,y,0); + for(Vec3i v:hoffsets) { + BlockPos pos = layer.add(v); + if((!checked.contains(pos)) && (world.getBlockState(pos).getBlock()==leaf_type_state.getBlock())) { + checked.add(pos); + to_decay.add(pos); + if(recursion_left > 0) { + to_decay.addAll(findBlocksAround(world, pos, leaf_type_state, checked, recursion_left-1)); + } + } + } + } + return to_decay; + } + + private static void breakBlock(World world, BlockPos pos) + { + Block.spawnDrops(world.getBlockState(pos), world, pos); + if(world.setBlockState(pos, world.getFluidState(pos).getBlockState(), 1|2|8)) {} //state.getBlock().onPlayerDestroy(world, pos, state); + } + + public static int chopTree(World world, BlockState broken_state, BlockPos startPos, int max_blocks_to_break, boolean without_target_block) + { + if(world.isRemote || !isLog(broken_state)) return 0; + final long ymin = startPos.getY(); + final long max_leaf_distance = 6; + Set checked = new HashSet(); + ArrayList to_break = new ArrayList(); + ArrayList to_decay = new ArrayList(); + checked.add(startPos); + // Initial simple layer-up search of same logs. This forms the base corpus, and only leaves and + // leaf-enclosed logs attached to this corpus may be broken/decayed. + { + LinkedList queue = new LinkedList(); + LinkedList upqueue = new LinkedList(); + queue.add(startPos); + int cutlevel = 0; + int steps_left = 64; + while(!queue.isEmpty() && (--steps_left >= 0)) { + final BlockPos pos = queue.removeFirst(); + // Vertical search + final BlockPos uppos = pos.up(); + final BlockState upstate = world.getBlockState(uppos); + if(!checked.contains(uppos)) { + checked.add(uppos); + if(isSameLog(upstate, broken_state)) { + // Up is log + upqueue.add(uppos); + to_break.add(uppos); + steps_left = 64; + } else { + boolean isleaf = isLeaves(upstate); + if(isleaf || world.isAirBlock(uppos) || (upstate.getBlock() instanceof VineBlock)) { + if(isleaf) to_decay.add(uppos); + // Up is air, check adjacent for diagonal up (e.g. Accacia) + for(Vec3i v:hoffsets) { + final BlockPos p = uppos.add(v); + if(checked.contains(p)) continue; + checked.add(p); + final BlockState st = world.getBlockState(p); + final Block bl = st.getBlock(); + if(isSameLog(st, broken_state)) { + queue.add(p); + to_break.add(p); + } else if(isLeaves(st)) { + to_decay.add(p); + } + } + } + } + } + // Lateral search + for(Vec3i v:hoffsets) { + final BlockPos p = pos.add(v); + if(checked.contains(p)) continue; + checked.add(p); + if(p.distanceSq(new BlockPos(startPos.getX(), p.getY(), startPos.getZ())) > (3+cutlevel*cutlevel)) continue; + final BlockState st = world.getBlockState(p); + final Block bl = st.getBlock(); + if(isSameLog(st, broken_state)) { + queue.add(p); + to_break.add(p); + } else if(isLeaves(st)) { + to_decay.add(p); + } + } + if(queue.isEmpty() && (!upqueue.isEmpty())) { + queue = upqueue; + upqueue = new LinkedList(); + ++cutlevel; + } + } + } + { + // Determine lose logs between the leafs + for(BlockPos pos:to_decay) { + int dist = 1; + to_break.addAll(findBlocksAround(world, pos, broken_state, checked, dist)); + } + } + if(!to_decay.isEmpty()) { + final BlockState leaf_type_state = world.getBlockState(to_decay.get(0)); + final ArrayList leafs = to_decay; + to_decay = new ArrayList(); + for(BlockPos pos:leafs) { + int dist = 2; + to_decay.add(pos); + to_decay.addAll(findBlocksAround(world, pos, leaf_type_state, checked, dist)); + } + } + if(without_target_block) { + checked.remove(startPos); + } else { + to_break.add(startPos); + } + for(BlockPos pos:to_break) breakBlock(world, pos); + for(BlockPos pos:to_decay) breakBlock(world, pos); + { + // And now the bill. + return MathHelper.clamp(((to_break.size()*6/5)+(to_decay.size()/10)-1), 1, 65535); + } + } +} diff --git a/1.14/src/main/resources/META-INF/mods.toml b/1.14/src/main/resources/META-INF/mods.toml index 748ef9e..b011df3 100644 --- a/1.14/src/main/resources/META-INF/mods.toml +++ b/1.14/src/main/resources/META-INF/mods.toml @@ -18,7 +18,7 @@ logoFile="logo.png" [[dependencies.engineersdecor]] modId="forge" mandatory=true - versionRange="[28.0.81,)" + versionRange="[28.1.68,)" ordering="NONE" side="BOTH" diff --git a/1.14/src/main/resources/assets/engineersdecor/blockstates/factory_placer.json b/1.14/src/main/resources/assets/engineersdecor/blockstates/factory_placer.json new file mode 100644 index 0000000..abc2ed5 --- /dev/null +++ b/1.14/src/main/resources/assets/engineersdecor/blockstates/factory_placer.json @@ -0,0 +1,9 @@ +{ + "forge_marker": 1, + "defaults": { + "model": "engineersdecor:block/device/factory_placer_model" + }, + "variants": { + "facing": { "north":{"y":0}, "south":{"y":180}, "west":{"y":270}, "east":{"y":90}, "up": {"x":-90}, "down": {"x":90} } + } +} diff --git a/1.14/src/main/resources/assets/engineersdecor/blockstates/small_tree_cutter.json b/1.14/src/main/resources/assets/engineersdecor/blockstates/small_tree_cutter.json new file mode 100644 index 0000000..dc5a4d9 --- /dev/null +++ b/1.14/src/main/resources/assets/engineersdecor/blockstates/small_tree_cutter.json @@ -0,0 +1,8 @@ +{ + "forge_marker": 1, + "defaults": { "model": "engineersdecor:block/device/small_tree_cutter_model" }, + "variants": { + "facing": { "north": {"y":0}, "south": {"y":180}, "west": {"y":-90}, "east": {"y":90} }, + "active": { "true":{ "model": "engineersdecor:block/device/small_tree_cutter_model_active" }, "false":{}} + } +} diff --git a/1.14/src/main/resources/assets/engineersdecor/models/block/device/factory_placer_model.json b/1.14/src/main/resources/assets/engineersdecor/models/block/device/factory_placer_model.json new file mode 100644 index 0000000..a46a6ce --- /dev/null +++ b/1.14/src/main/resources/assets/engineersdecor/models/block/device/factory_placer_model.json @@ -0,0 +1,170 @@ +{ + "parent": "block/cube", + "textures": { + "top": "engineersdecor:block/device/factory_placer_top", + "bottom": "engineersdecor:block/device/factory_placer_bottom", + "side": "engineersdecor:block/device/factory_placer_side", + "particle": "engineersdecor:block/device/factory_placer_side" + }, + "elements": [ + { + "from": [0, 0, 3], + "to": [16, 16, 16], + "faces": { + "north": {"uv": [0, 0, 16, 16], "texture": "#bottom"}, + "east": {"uv": [3, 0, 16, 16], "rotation": 180, "texture": "#side"}, + "south": {"uv": [0, 0, 16, 16], "texture": "#top"}, + "west": {"uv": [3, 0, 16, 16], "texture": "#side"}, + "up": {"uv": [3, 0, 16, 16], "rotation": 90, "texture": "#side"}, + "down": {"uv": [3, 0, 16, 16], "rotation": 270, "texture": "#side"} + } + }, + { + "from": [15, 0, 0], + "to": [16, 16, 1], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 7]}, + "faces": { + "north": {"uv": [0, 0, 1, 16], "texture": "#bottom"}, + "east": {"uv": [15, 0, 16, 16], "texture": "#side"}, + "south": {"uv": [14, 0, 16, 16], "texture": "#top"}, + "west": {"uv": [0, 0, 1, 16], "texture": "#side"}, + "up": {"uv": [14, 0, 15, 1], "rotation": 90, "texture": "#side"}, + "down": {"uv": [14, 15, 16, 16], "texture": "#side"} + } + }, + { + "from": [15, 0, 2], + "to": [16, 16, 3], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 11]}, + "faces": { + "north": {"uv": [0, 0, 1, 16], "texture": "#bottom"}, + "east": {"uv": [2, 0, 3, 16], "rotation": 180, "texture": "#side"}, + "south": {"uv": [15, 0, 16, 16], "texture": "#top"}, + "west": {"uv": [2, 0, 4, 16], "texture": "#side"}, + "up": {"uv": [15, 2, 16, 4], "rotation": 90, "texture": "#side"}, + "down": {"uv": [15, 12, 16, 14], "rotation": 270, "texture": "#side"} + } + }, + { + "from": [0, 0, 0], + "to": [1, 16, 1], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 7]}, + "faces": { + "north": {"uv": [15, 0, 16, 16], "texture": "#bottom"}, + "east": {"uv": [15, 0, 16, 16], "texture": "#side"}, + "south": {"uv": [0, 0, 2, 16], "texture": "#top"}, + "west": {"uv": [0, 0, 1, 16], "texture": "#side"}, + "up": {"uv": [0, 0, 1, 1], "rotation": 90, "texture": "#side"}, + "down": {"uv": [0, 15, 2, 16], "texture": "#side"} + } + }, + { + "from": [0, 0, 2], + "to": [1, 16, 3], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 11]}, + "faces": { + "north": {"uv": [15, 0, 16, 16], "texture": "#bottom"}, + "east": {"uv": [2, 0, 3, 16], "texture": "#side"}, + "south": {"uv": [0, 0, 1, 16], "texture": "#top"}, + "west": {"uv": [2, 0, 3, 16], "texture": "#side"}, + "up": {"uv": [0, 2, 1, 3], "rotation": 90, "texture": "#side"}, + "down": {"uv": [0, 13, 1, 14], "rotation": 270, "texture": "#side"} + } + }, + { + "from": [0, 15, 1], + "to": [1, 16, 2], + "faces": { + "north": {"uv": [15, 0, 16, 1], "texture": "#bottom"}, + "east": {"uv": [14, 0, 15, 1], "texture": "#side"}, + "south": {"uv": [0, 0, 1, 1], "texture": "#top"}, + "west": {"uv": [1, 0, 2, 1], "texture": "#side"}, + "up": {"uv": [1, 0, 2, 1], "rotation": 90, "texture": "#side"}, + "down": {"uv": [0, 14, 1, 15], "rotation": 270, "texture": "#side"} + } + }, + { + "from": [15, 15, 1], + "to": [16, 16, 2], + "rotation": {"angle": 0, "axis": "y", "origin": [23, 8, 8]}, + "faces": { + "north": {"uv": [0, 0, 1, 1], "texture": "#bottom"}, + "east": {"uv": [14, 0, 15, 1], "texture": "#side"}, + "south": {"uv": [15, 0, 16, 1], "texture": "#top"}, + "west": {"uv": [1, 0, 2, 1], "texture": "#side"}, + "up": {"uv": [15, 1, 16, 2], "rotation": 90, "texture": "#side"}, + "down": {"uv": [15, 14, 16, 15], "rotation": 270, "texture": "#side"} + } + }, + { + "from": [15, 0, 1], + "to": [16, 1, 2], + "rotation": {"angle": 0, "axis": "y", "origin": [23, -7, 8]}, + "faces": { + "north": {"uv": [0, 15, 1, 16], "texture": "#bottom"}, + "east": {"uv": [14, 15, 15, 16], "texture": "#side"}, + "south": {"uv": [15, 15, 16, 16], "texture": "#top"}, + "west": {"uv": [1, 15, 2, 16], "texture": "#side"}, + "up": {"uv": [15, 1, 16, 2], "rotation": 90, "texture": "#side"}, + "down": {"uv": [15, 14, 16, 15], "rotation": 270, "texture": "#side"} + } + }, + { + "from": [0, 0, 1], + "to": [1, 1, 2], + "rotation": {"angle": 0, "axis": "y", "origin": [8, -7, 8]}, + "faces": { + "north": {"uv": [15, 15, 16, 16], "texture": "#bottom"}, + "east": {"uv": [14, 15, 15, 16], "texture": "#side"}, + "south": {"uv": [0, 15, 1, 16], "texture": "#top"}, + "west": {"uv": [1, 15, 2, 16], "texture": "#side"}, + "up": {"uv": [0, 1, 1, 2], "rotation": 90, "texture": "#side"}, + "down": {"uv": [0, 14, 1, 15], "texture": "#side"} + } + }, + { + "from": [1, 15, 2], + "to": [15, 16, 3], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 11]}, + "faces": { + "north": {"uv": [1, 0, 15, 1], "texture": "#bottom"}, + "east": {"uv": [12, 0, 14, 1], "texture": "#side"}, + "south": {"uv": [1, 0, 15, 1], "texture": "#top"}, + "west": {"uv": [2, 0, 4, 1], "texture": "#side"}, + "up": {"uv": [2, 1, 3, 15], "rotation": 90, "texture": "#side"}, + "down": {"uv": [2, 1, 3, 15], "rotation": 270, "texture": "#side"} + } + }, + { + "from": [1, 0, 2], + "to": [15, 1, 3], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 11]}, + "faces": { + "north": {"uv": [1, 15, 15, 16], "texture": "#bottom"}, + "east": {"uv": [12, 15, 14, 16], "texture": "#side"}, + "south": {"uv": [1, 15, 15, 16], "texture": "#top"}, + "west": {"uv": [2, 15, 4, 16], "texture": "#side"}, + "up": {"uv": [2, 1, 3, 15], "rotation": 180, "texture": "#side"}, + "down": {"uv": [2, 1, 3, 15], "rotation": 270, "texture": "#side"} + } + } + ], + "display": { + "thirdperson_righthand": { + "rotation": [85, 3, -10], + "translation": [1.75, -0.75, -2.25], + "scale": [0.35, 0.35, 0.35] + }, + "ground": { + "translation": [0, -0.75, 0], + "scale": [0.2, 0.2, 0.2] + }, + "gui": { + "rotation": [30, 225, 0], + "scale": [0.625, 0.625, 0.625] + }, + "fixed": { + "scale": [0.5, 0.5, 0.5] + } + } +} \ No newline at end of file diff --git a/1.14/src/main/resources/assets/engineersdecor/models/block/device/small_tree_cutter_model.json b/1.14/src/main/resources/assets/engineersdecor/models/block/device/small_tree_cutter_model.json new file mode 100644 index 0000000..7912ca7 --- /dev/null +++ b/1.14/src/main/resources/assets/engineersdecor/models/block/device/small_tree_cutter_model.json @@ -0,0 +1,222 @@ +{ + "parent": "block/cube", + "textures": { + "2": "engineersdecor:block/device/tree_cutter_side", + "3": "engineersdecor:block/device/tree_cutter_top", + "particle": "engineersdecor:block/device/tree_cutter_side", + "b": "engineersdecor:block/device/tree_cutter_blade_off", + "top": "engineersdecor:block/device/tree_cutter_bottom" + }, + "elements": [ + { + "from": [0, 0, 0], + "to": [16, 3, 16], + "faces": { + "north": {"uv": [0, 13, 16, 16], "texture": "#2"}, + "east": {"uv": [0, 13, 16, 16], "texture": "#2"}, + "south": {"uv": [0, 13, 16, 16], "texture": "#2"}, + "west": {"uv": [0, 13, 16, 16], "texture": "#2"}, + "up": {"uv": [0, 0, 16, 16], "texture": "#3"}, + "down": {"uv": [0, 0, 16, 16], "texture": "#top"} + } + }, + { + "from": [0, 3, 0], + "to": [3, 8, 16], + "faces": { + "north": {"uv": [13, 0, 16, 5], "texture": "#2"}, + "east": {"uv": [0, 3, 16, 8], "texture": "#2"}, + "south": {"uv": [0, 8, 3, 13], "texture": "#2"}, + "west": {"uv": [0, 8, 16, 13], "texture": "#2"}, + "up": {"uv": [0, 0, 3, 16], "texture": "#3"}, + "down": {"uv": [0, 0, 3, 16], "texture": "#top"} + } + }, + { + "from": [3, 3, 13], + "to": [16, 8, 16], + "faces": { + "north": {"uv": [0, 3, 13, 8], "texture": "#2"}, + "east": {"uv": [0, 8, 3, 13], "texture": "#2"}, + "south": {"uv": [3, 8, 16, 13], "texture": "#2"}, + "west": {"uv": [13, 8, 16, 13], "texture": "#b"}, + "up": {"uv": [3, 13, 16, 16], "texture": "#3"}, + "down": {"uv": [3, 0, 16, 3], "texture": "#top"} + } + }, + { + "from": [15, 3, 0], + "to": [16, 6, 13], + "faces": { + "north": {"uv": [0, 10, 1, 13], "texture": "#2"}, + "east": {"uv": [3, 10, 16, 13], "texture": "#2"}, + "south": {"uv": [15, 10, 16, 13], "texture": "#b"}, + "west": {"uv": [0, 0, 13, 3], "texture": "#2"}, + "up": {"uv": [15, 0, 16, 13], "texture": "#3"}, + "down": {"uv": [15, 3, 16, 16], "texture": "#top"} + } + }, + { + "from": [3, 7, 0], + "to": [5, 8, 13], + "rotation": {"angle": 0, "axis": "y", "origin": [10, 13, 5]}, + "faces": { + "north": {"uv": [11, 8, 13, 9], "texture": "#2"}, + "east": {"uv": [3, 8, 16, 9], "texture": "#2"}, + "south": {"uv": [3, 8, 5, 9], "texture": "#b"}, + "west": {"uv": [0, 8, 13, 9], "texture": "#b"}, + "up": {"uv": [3, 0, 5, 13], "texture": "#3"}, + "down": {"uv": [3, 3, 5, 16], "texture": "#b"} + } + }, + { + "from": [5, 6, 12], + "to": [16, 8, 13], + "rotation": {"angle": 0, "axis": "y", "origin": [11, 13, 5]}, + "faces": { + "north": {"uv": [0, 0, 11, 2], "texture": "#2"}, + "east": {"uv": [3, 8, 4, 10], "texture": "#2"}, + "south": {"uv": [5, 8, 16, 10], "texture": "#b"}, + "west": {"uv": [12, 8, 13, 10], "texture": "#b"}, + "up": {"uv": [5, 12, 16, 13], "texture": "#3"}, + "down": {"uv": [5, 3, 16, 4], "texture": "#top"} + } + }, + { + "from": [5, 4.5, 4], + "to": [13, 5, 12], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 7.5, 8]}, + "faces": { + "north": {"uv": [3, 11, 11, 11.5], "texture": "#b"}, + "east": {"uv": [4, 11, 12, 11.5], "texture": "#b"}, + "south": {"uv": [5, 11, 13, 11.5], "texture": "#b"}, + "west": {"uv": [4, 11, 12, 11.5], "texture": "#b"}, + "up": {"uv": [5, 4, 13, 12], "texture": "#b"}, + "down": {"uv": [5, 4, 13, 12], "texture": "#b"} + } + }, + { + "from": [8, 5, 7], + "to": [10, 5.5, 9], + "faces": { + "north": {"uv": [6, 10.5, 8, 11], "texture": "#2"}, + "east": {"uv": [7, 10.5, 9, 11], "texture": "#b"}, + "south": {"uv": [8, 10.5, 10, 11], "texture": "#b"}, + "west": {"uv": [7, 10.5, 9, 11], "texture": "#b"}, + "up": {"uv": [8, 7, 10, 9], "texture": "#b"}, + "down": {"uv": [8, 7, 10, 9], "texture": "#b"} + } + }, + { + "from": [8, 4, 7], + "to": [10, 4.5, 9], + "faces": { + "north": {"uv": [6, 11.5, 8, 12], "texture": "#b"}, + "east": {"uv": [7, 11.5, 9, 12], "texture": "#b"}, + "south": {"uv": [8, 11.5, 10, 12], "texture": "#b"}, + "west": {"uv": [7, 11.5, 9, 12], "texture": "#b"}, + "up": {"uv": [8, 7, 10, 9], "texture": "#b"}, + "down": {"uv": [8, 7, 10, 9], "texture": "#b"} + } + }, + { + "from": [3, 3.5, 7], + "to": [10, 4, 9], + "faces": { + "north": {"uv": [8, 6, 15, 6.5], "texture": "#2"}, + "east": {"uv": [7, 12, 9, 12.5], "texture": "#2"}, + "south": {"uv": [3, 12, 10, 12.5], "texture": "#2"}, + "west": {"uv": [7, 12, 9, 12.5], "texture": "#2"}, + "up": {"uv": [3, 7, 10, 9], "texture": "#2"}, + "down": {"uv": [3, 7, 10, 9], "texture": "#2"} + } + }, + { + "from": [3, 5.5, 7], + "to": [10, 6, 9], + "faces": { + "north": {"uv": [6, 10, 13, 10.5], "texture": "#2"}, + "east": {"uv": [7, 10, 9, 10.5], "texture": "#2"}, + "south": {"uv": [3, 10, 10, 10.5], "texture": "#2"}, + "west": {"uv": [7, 10, 9, 10.5], "texture": "#2"}, + "up": {"uv": [9, 0, 16, 2], "texture": "#2"}, + "down": {"uv": [3, 7, 10, 9], "texture": "#2"} + } + }, + { + "from": [6, 4.5, 3], + "to": [12, 5, 4], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 7.5, 8]}, + "faces": { + "north": {"uv": [4, 11, 10, 11.5], "texture": "#b"}, + "east": {"uv": [12, 11, 13, 11.5], "texture": "#b"}, + "south": {"uv": [6, 11, 12, 11.5], "texture": "#b"}, + "west": {"uv": [3, 11, 4, 11.5], "texture": "#b"}, + "up": {"uv": [6, 3, 12, 4], "texture": "#b"}, + "down": {"uv": [6, 12, 12, 13], "texture": "#b"} + } + }, + { + "from": [4, 4.5, 5], + "to": [5, 5, 11], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 7.5, 8]}, + "faces": { + "north": {"uv": [11, 11, 12, 11.5], "texture": "#b"}, + "east": {"uv": [5, 11, 11, 11.5], "texture": "#b"}, + "south": {"uv": [4, 11, 5, 11.5], "texture": "#b"}, + "west": {"uv": [5, 11, 11, 11.5], "texture": "#b"}, + "up": {"uv": [4, 5, 5, 11], "texture": "#b"}, + "down": {"uv": [4, 5, 5, 11], "texture": "#b"} + } + }, + { + "from": [13, 4.5, 5], + "to": [14, 5, 11], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 7.5, 8]}, + "faces": { + "north": {"uv": [2, 11, 3, 11.5], "texture": "#b"}, + "east": {"uv": [5, 11, 11, 11.5], "texture": "#b"}, + "south": {"uv": [13, 11, 14, 11.5], "texture": "#b"}, + "west": {"uv": [5, 11, 11, 11.5], "texture": "#b"}, + "up": {"uv": [13, 5, 14, 11], "texture": "#b"}, + "down": {"uv": [13, 5, 14, 11], "texture": "#b"} + } + }, + { + "from": [6, 4.5, 12], + "to": [12, 5, 13], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 7.5, 8]}, + "faces": { + "north": {"uv": [4, 11, 10, 11.5], "texture": "#b"}, + "east": {"uv": [3, 11, 4, 11.5], "texture": "#b"}, + "south": {"uv": [6, 11, 12, 11.5], "texture": "#b"}, + "west": {"uv": [12, 11, 13, 11.5], "texture": "#b"}, + "up": {"uv": [6, 12, 12, 13], "texture": "#b"}, + "down": {"uv": [6, 3, 12, 4], "texture": "#b"} + } + } + ], + "display": { + "thirdperson_righthand": { + "rotation": [85, 3, -10], + "translation": [0.75, 0.25, 0.5], + "scale": [0.35, 0.35, 0.35] + }, + "firstperson_righthand": { + "rotation": [18, 22, 0], + "translation": [1.25, 0, 0], + "scale": [0.4, 0.4, 0.4] + }, + "ground": { + "translation": [0, -1.25, 0], + "scale": [0.2, 0.2, 0.2] + }, + "gui": { + "rotation": [30, 225, 0], + "scale": [0.625, 0.625, 0.625] + }, + "fixed": { + "scale": [0.5, 0.5, 0.5] + } + } +} \ No newline at end of file diff --git a/1.14/src/main/resources/assets/engineersdecor/models/block/device/small_tree_cutter_model_active.json b/1.14/src/main/resources/assets/engineersdecor/models/block/device/small_tree_cutter_model_active.json new file mode 100644 index 0000000..6583da4 --- /dev/null +++ b/1.14/src/main/resources/assets/engineersdecor/models/block/device/small_tree_cutter_model_active.json @@ -0,0 +1,221 @@ +{ + "parent": "block/cube", + "textures": { + "2": "engineersdecor:block/device/tree_cutter_side", + "3": "engineersdecor:block/device/tree_cutter_top", + "particle": "engineersdecor:block/device/tree_cutter_side", + "b": "engineersdecor:block/device/tree_cutter_blade", + "top": "engineersdecor:block/device/tree_cutter_bottom" + }, + "elements": [ + { + "from": [0, 0, 0], + "to": [16, 3, 16], + "faces": { + "north": {"uv": [0, 13, 16, 16], "texture": "#2"}, + "east": {"uv": [0, 13, 16, 16], "texture": "#2"}, + "south": {"uv": [0, 13, 16, 16], "texture": "#2"}, + "west": {"uv": [0, 13, 16, 16], "texture": "#2"}, + "up": {"uv": [0, 0, 16, 16], "texture": "#3"}, + "down": {"uv": [0, 0, 16, 16], "texture": "#top"} + } + }, + { + "from": [0, 3, 0], + "to": [3, 8, 16], + "faces": { + "north": {"uv": [13, 0, 16, 5], "texture": "#2"}, + "east": {"uv": [0, 3, 16, 8], "texture": "#2"}, + "south": {"uv": [0, 8, 3, 13], "texture": "#2"}, + "west": {"uv": [0, 8, 16, 13], "texture": "#2"}, + "up": {"uv": [0, 0, 3, 16], "texture": "#3"}, + "down": {"uv": [0, 0, 3, 16], "texture": "#top"} + } + }, + { + "from": [3, 3, 13], + "to": [16, 8, 16], + "faces": { + "north": {"uv": [0, 3, 13, 8], "texture": "#2"}, + "east": {"uv": [0, 8, 3, 13], "texture": "#2"}, + "south": {"uv": [3, 8, 16, 13], "texture": "#2"}, + "west": {"uv": [13, 8, 16, 13], "texture": "#b"}, + "up": {"uv": [3, 13, 16, 16], "texture": "#3"}, + "down": {"uv": [3, 0, 16, 3], "texture": "#top"} + } + }, + { + "from": [15, 3, 0], + "to": [16, 6, 13], + "faces": { + "north": {"uv": [0, 10, 1, 13], "texture": "#2"}, + "east": {"uv": [3, 10, 16, 13], "texture": "#2"}, + "south": {"uv": [15, 10, 16, 13], "texture": "#b"}, + "west": {"uv": [0, 0, 13, 3], "texture": "#2"}, + "up": {"uv": [15, 0, 16, 13], "texture": "#3"}, + "down": {"uv": [15, 3, 16, 16], "texture": "#top"} + } + }, + { + "from": [3, 7, 0], + "to": [5, 8, 13], + "rotation": {"angle": 0, "axis": "y", "origin": [10, 13, 5]}, + "faces": { + "north": {"uv": [11, 8, 13, 9], "texture": "#2"}, + "east": {"uv": [3, 8, 16, 9], "texture": "#2"}, + "south": {"uv": [3, 8, 5, 9], "texture": "#b"}, + "west": {"uv": [0, 8, 13, 9], "texture": "#b"}, + "up": {"uv": [3, 0, 5, 13], "texture": "#3"}, + "down": {"uv": [3, 3, 5, 16], "texture": "#b"} + } + }, + { + "from": [5, 6, 12], + "to": [16, 8, 13], + "rotation": {"angle": 0, "axis": "y", "origin": [11, 13, 5]}, + "faces": { + "north": {"uv": [0, 0, 11, 2], "texture": "#2"}, + "east": {"uv": [3, 8, 4, 10], "texture": "#2"}, + "south": {"uv": [5, 8, 16, 10], "texture": "#b"}, + "west": {"uv": [12, 8, 13, 10], "texture": "#b"}, + "up": {"uv": [5, 12, 16, 13], "texture": "#3"}, + "down": {"uv": [5, 3, 16, 4], "texture": "#top"} + } + }, + { + "from": [5, 4.5, -3], + "to": [13, 5, 5], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 7.5, 1]}, + "faces": { + "north": {"uv": [5, 13, 13, 13.5], "texture": "#b"}, + "east": {"uv": [11, 11, 16, 11.5], "texture": "#b"}, + "south": {"uv": [5, 11, 13, 11.5], "texture": "#b"}, + "west": {"uv": [0, 11, 5, 11.5], "texture": "#b"}, + "up": {"uv": [5, 4, 13, 12], "texture": "#b"}, + "down": {"uv": [5, 4, 13, 12], "texture": "#b"} + } + }, + { + "from": [8, 5, 0], + "to": [10, 5.5, 2], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 1]}, + "faces": { + "north": {"uv": [6, 10.5, 8, 11], "texture": "#2"}, + "east": {"uv": [14, 10.5, 16, 11], "texture": "#b"}, + "south": {"uv": [8, 10.5, 10, 11], "texture": "#b"}, + "west": {"uv": [0, 10.5, 2, 11], "texture": "#b"}, + "up": {"uv": [8, 0, 10, 2], "texture": "#b"}, + "down": {"uv": [8, 14, 10, 16], "texture": "#b"} + } + }, + { + "from": [8, 4, 0], + "to": [10, 4.5, 2], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 1]}, + "faces": { + "north": {"uv": [6, 11.5, 8, 12], "texture": "#b"}, + "east": {"uv": [14, 11.5, 16, 12], "texture": "#b"}, + "south": {"uv": [8, 11.5, 10, 12], "texture": "#b"}, + "west": {"uv": [0, 11.5, 2, 12], "texture": "#b"}, + "up": {"uv": [8, 0, 10, 2], "texture": "#b"}, + "down": {"uv": [8, 14, 10, 16], "texture": "#b"} + } + }, + { + "from": [3, 3.5, 0], + "to": [10, 4, 2], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 1]}, + "faces": { + "north": {"uv": [8, 6, 15, 6.5], "texture": "#2"}, + "east": {"uv": [7, 12, 9, 12.5], "texture": "#2"}, + "south": {"uv": [3, 12, 10, 12.5], "texture": "#2"}, + "west": {"uv": [7, 12, 9, 12.5], "texture": "#2"}, + "up": {"uv": [3, 7, 10, 9], "texture": "#2"}, + "down": {"uv": [3, 7, 10, 9], "texture": "#2"} + } + }, + { + "from": [3, 5.5, 0], + "to": [10, 6, 2], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 1]}, + "faces": { + "north": {"uv": [6, 10, 13, 10.5], "texture": "#2"}, + "east": {"uv": [7, 10, 9, 10.5], "texture": "#2"}, + "south": {"uv": [3, 10, 10, 10.5], "texture": "#2"}, + "west": {"uv": [7, 10, 9, 10.5], "texture": "#2"}, + "up": {"uv": [9, 0, 16, 2], "texture": "#2"}, + "down": {"uv": [3, 7, 10, 9], "texture": "#2"} + } + }, + { + "from": [6, 4.5, -4], + "to": [12, 5, -3], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 7.5, 1]}, + "faces": { + "north": {"uv": [7, 12, 13, 12.5], "texture": "#b"}, + "east": {"uv": [16, 11, 16, 11.5], "texture": "#b"}, + "south": {"uv": [6, 11, 12, 11.5], "texture": "#b"}, + "west": {"uv": [0, 11, 0, 11.5], "texture": "#b"}, + "up": {"uv": [6, 12, 12, 13], "texture": "#b"}, + "down": {"uv": [6, 3, 12, 4], "texture": "#b"} + } + }, + { + "from": [4, 4.5, -2], + "to": [5, 5, 4], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 7.5, 1]}, + "faces": { + "north": {"uv": [11, 12, 12, 12.5], "texture": "#b"}, + "east": {"uv": [12, 11, 16, 11.5], "texture": "#b"}, + "south": {"uv": [4, 11, 5, 11.5], "texture": "#b"}, + "west": {"uv": [0, 11, 4, 11.5], "texture": "#b"}, + "up": {"uv": [4, 4, 5, 12], "texture": "#b"}, + "down": {"uv": [4, 5, 5, 11], "texture": "#b"} + } + }, + { + "from": [13, 4.5, -2], + "to": [14, 5, 4], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 7.5, 1]}, + "faces": { + "north": {"uv": [2, 11, 3, 11.5], "texture": "#b"}, + "east": {"uv": [6, 12, 10, 12.5], "texture": "#b"}, + "south": {"uv": [13, 11, 14, 11.5], "texture": "#b"}, + "west": {"uv": [0, 11, 4, 11.5], "texture": "#b"}, + "up": {"uv": [13, 5, 14, 11], "texture": "#b"}, + "down": {"uv": [13, 5, 14, 11], "texture": "#b"} + } + }, + { + "from": [6, 4.5, 5], + "to": [12, 5, 6], + "rotation": {"angle": 0, "axis": "y", "origin": [8, 7.5, 1]}, + "faces": { + "north": {"uv": [4, 11, 10, 11.5], "texture": "#b"}, + "east": {"uv": [10, 11, 11, 11.5], "texture": "#b"}, + "south": {"uv": [6, 11, 12, 11.5], "texture": "#b"}, + "west": {"uv": [5, 11, 6, 11.5], "texture": "#b"}, + "up": {"uv": [6, 12, 12, 13], "texture": "#b"}, + "down": {"uv": [6, 10, 12, 11], "texture": "#b"} + } + } + ], + "display": { + "thirdperson_righthand": { + "rotation": [85, 3, -10], + "translation": [1.75, -0.75, -2.25], + "scale": [0.35, 0.35, 0.35] + }, + "ground": { + "translation": [0, -0.75, 0], + "scale": [0.2, 0.2, 0.2] + }, + "gui": { + "rotation": [30, 225, 0], + "scale": [0.625, 0.625, 0.625] + }, + "fixed": { + "scale": [0.5, 0.5, 0.5] + } + } +} \ No newline at end of file diff --git a/1.14/src/main/resources/assets/engineersdecor/models/item/factory_placer.json b/1.14/src/main/resources/assets/engineersdecor/models/item/factory_placer.json new file mode 100644 index 0000000..127f322 --- /dev/null +++ b/1.14/src/main/resources/assets/engineersdecor/models/item/factory_placer.json @@ -0,0 +1 @@ +{ "parent": "engineersdecor:block/device/factory_placer_model" } \ No newline at end of file diff --git a/1.14/src/main/resources/assets/engineersdecor/models/item/small_tree_cutter.json b/1.14/src/main/resources/assets/engineersdecor/models/item/small_tree_cutter.json new file mode 100644 index 0000000..e7897ef --- /dev/null +++ b/1.14/src/main/resources/assets/engineersdecor/models/item/small_tree_cutter.json @@ -0,0 +1 @@ +{ "parent": "engineersdecor:block/device/small_tree_cutter_model" } \ No newline at end of file diff --git a/1.14/src/main/resources/assets/engineersdecor/textures/block/device/factory_placer_bottom.png b/1.14/src/main/resources/assets/engineersdecor/textures/block/device/factory_placer_bottom.png new file mode 100644 index 0000000000000000000000000000000000000000..40de3fc528332002da999bad45c622c482ff690e GIT binary patch literal 478 zcmV<40U`d0P)$k^0x| zRF%4gSw?r*1!Osu`qvf$=6!U`q%RT@5Mv+TYq?&pJ;sQtVrI0~0O-Bbdj~*7c)ecZ ztg46zwN@g)Hz#`%2y zA~+llq?A~eg_IKWJhLnd%d(7^)9FMAfoNtNk4JufeyFt$R3DsLE5NYQb@H+P2j!YN U)}m`PQUCw|07*qoM6N<$g4e;)s{jB1 literal 0 HcmV?d00001 diff --git a/1.14/src/main/resources/assets/engineersdecor/textures/block/device/factory_placer_side.png b/1.14/src/main/resources/assets/engineersdecor/textures/block/device/factory_placer_side.png new file mode 100644 index 0000000000000000000000000000000000000000..bbd474e3f5ccedefdc56a99d30d4e42f12dcf9bb GIT binary patch literal 652 zcmV;70(1R|P); zWOk>k%E4#`yOXB7sHVPiPRq^BO>H(C+#NGRMA&RLR23pZL||q_1XYEql9>RgD%x6O z97j|Y5n;F6addQqnPFzQJMPXf47Ao5hJoE~$9B5~z*}pG2qHpNaesf$^Yb%TS6BS? z+fOVjt8f)Qefx#GyE~qqo*2gwUq)R0c}lLb*lbLH>fe?cfdef}O*#ex5cGM|fP0w_^MWRY1E1;~mF z;7jwO!NNPmeE+eLbBUtpAJ}Gwt11zJs?u6xnkG~Px7n4AD^A#>Y%#COw6WBx**;EHdYss^a_oo~j}u=)L3a6mx(84u=l^#mfR)w945=fYurj zF~2N|YN7}mcX}4`!T-+34!%gYPb*Vn5%nTeTkI2;fW-rnALe0=2M;sT$hiHC=WHC?L8`T051G_l|B mQB`{HsOtKiMTBu20r(eT1vqCr<9b*C0000lDhCh3JO9V&> z5FwNj@)oJnq)y8_<`wb`*C0W;4GmQkZfC}Jie)!fCv;-Jc3NHG9z{mB9l*FzHxqjPHPQY z*hB;s;ltSpEu4)OAm31uo=KQ8^*F#WcRy&bYfg2?%UmS-)*zB30hz@!Lqst4!V`A2 zk(pEvRB}e~z~|3U^slJB_d|pt@c!)G{}D2odaPo)JGSouPmUsZ%-&c=Z2JkouOkS9 zm3``2#6^(q!N(&AziU4*nVA`?IwwVsBB;QEy^e7h21JC~oz@*yVd{>)VMQjULgakz zy|4RWr4+8Nu6TZa=JVI@xI3!4zLJ^$*!k}6j&U4$eSJlH?>sy_@bvTquqxbpCo^fS zty5YWFT0SLvkxvVE;v0s<>lptVHnmmuC)>oY&IKIm1&wVo4t2)bHg-E`~eTnlD;QT Rtvmn#002ovPDHLkV1oRy=vV*% literal 0 HcmV?d00001 diff --git a/1.14/src/main/resources/assets/engineersdecor/textures/block/device/tree_cutter_blade.png b/1.14/src/main/resources/assets/engineersdecor/textures/block/device/tree_cutter_blade.png new file mode 100644 index 0000000000000000000000000000000000000000..49298dae329b882d2f52515250247bb3adca92e3 GIT binary patch literal 637 zcmV-@0)qXCP)QdKmvjd zN%^~Ilh?`nzd=eA@`FtP7kk;+UWB-*sH;d(rKltM#@=&0XXl)e>+9>t2g>ll`ga7y zdQFlf__Czm?Q-y*BuP%rxj%u^G^O9~)9G~hdU=VpmSi|YL|ErJh%|TLs|pdJ-EI>? zpe#$g_W*Pa;B$ z5$`>6Y`x#>H4_YnLt>0L=djk|oFm3a2!Rj+s!En+%>@q&Y_+O^0M=TpwY8L2aH9{5wd{5~vek-Y zFd)k^Mi&?4S%!7)eNKFSe#Sb-wkT+II&3zZ6YwVw(|mecTNX|T27>|JZWmR>T3f#lA=CjYc00PqM4m{vT`X$f zt14AhQI;jDN{kT^VfrRaCj`^U1OQdVdtU?fs6WQY>fxc8AkVTo_pg66#?--5Rnpou;^VOta!YsvHc6Nc$0 XtF{vPj;^UQ00000NkvXXu0mjfn*t}f literal 0 HcmV?d00001 diff --git a/1.14/src/main/resources/assets/engineersdecor/textures/block/device/tree_cutter_blade.png.mcmeta b/1.14/src/main/resources/assets/engineersdecor/textures/block/device/tree_cutter_blade.png.mcmeta new file mode 100644 index 0000000..77f273a --- /dev/null +++ b/1.14/src/main/resources/assets/engineersdecor/textures/block/device/tree_cutter_blade.png.mcmeta @@ -0,0 +1 @@ +{ "animation":{ "frames": [0,1], "frametime":2, "interpolate":false }} \ No newline at end of file diff --git a/1.14/src/main/resources/assets/engineersdecor/textures/block/device/tree_cutter_blade_off.png b/1.14/src/main/resources/assets/engineersdecor/textures/block/device/tree_cutter_blade_off.png new file mode 100644 index 0000000000000000000000000000000000000000..01e965d4349473d9f187a31f6aa664cf44f4126b GIT binary patch literal 395 zcmV;60d)R}P)eu znp2EaRdsRCepb&ZIyS+7B4*g@=jM1;|3L`sRS>xeM|kWym) z@Iccv!+_hnJG}Qe=P)yJ&YVss%nVf}=S;g=4FjH+OLERQ_jV*Am>Drfl!n|dylH(y~oT*DUnhl=S&D;7_i&#G5hS6d|6oE_W<0_=fkhiOsD7EB7&;ooI^x# z&e3%ptCtt#J>rFf5CWlX&q4rIMODvHKE#7PaH<>*2SVFYjmLx#Xl66kA)wy>tclz0 p7WJO}@yJzCu-ok}#Q)lDhCh3JO9V&> z5FwNj@)oJnq)y8_<`wb`*C0W;4GmQkZfC}Jie)!fCv;-Jc3NHG9z{mB9l*FzHxqjPHPQY z*hB;s;ltSpEu4)OAm31uo=KQ8^*F#WcRy&bYfg2?%UmS-)*zB30hz@!Lqst4!V`A2 zk(pEvRB}e~z~|3U^slJB_d|pt@c!)G{}D2odaPo)JGSouPmUsZ%-&c=Z2JkouOkS9 zm3``2#6^(q!N(&AziU4*nVA`?IwwVsBB;QEy^e7h21JC~oz@*yVd{>)VMQjULgakz zy|4RWr4+8Nu6TZa=JVI@xI3!4zLJ^$*!k}6j&U4$eSJlH?>sy_@bvTquqxbpCo^fS zty5YWFT0SLvkxvVE;v0s<>lptVHnmmuC)>oY&IKIm1&wVo4t2)bHg-E`~eTnlD;QT Rtvmn#002ovPDHLkV1oRy=vV*% literal 0 HcmV?d00001 diff --git a/1.14/src/main/resources/assets/engineersdecor/textures/block/device/tree_cutter_side.png b/1.14/src/main/resources/assets/engineersdecor/textures/block/device/tree_cutter_side.png new file mode 100644 index 0000000000000000000000000000000000000000..ece524934674c24b31eb6b624dca407f32020ffd GIT binary patch literal 368 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj11EYYai(`nz>9dmzi#^;|qS85%9ENHxVt6Mg2 zLy(tv%rsU8W93OxgCeFqRb^06I~e>tFIsbK4Uh1T(q-h0{=b+r91o=?-i(R0|pp_ Mr>mdKI;Vst0IM&SeEQRzFS%SUSxNyQGs#R!DXi-XK&_R` zBq9(IN-0DHnF)Z6rt|sCvMkK=%<|_q9v}j#ibs$MR+QO;$fSP%iJ4)UiHJ~Z<$As1 z?x+Y~r%$ZmR4u^vx8^~Zvh+ZAB_<+71h?Cbfzm~oSEsq-WkVB%)`KJg!QD3m5!pV> zhzJ0dgt@I`Cd~ttq^Q#Rc3)I5RYU|ElZG+9cZ$H5>GQ`3nJj%X^gtLjylBZw1dqg2 zA6rmWGLu^CvA*{g2q!DlTAAk=E2SKAG81>Fd+_ZA!o77)rxW-4eH&nAM_3{PE6Uq# zW~}%l1?##}O4$%1;z*c?{Fj1JHu%j9cgNj{Oy1uAqAGYabT?WBA|ZBVM-qp80C(r~ z;}^BoV=I|?m}_SA-f6ATdw(E|hH0A6eMQd?%*-}FcEy>wnK<}I^B6etp?l)SovIQM p^xhv)9_~Mf>bXSZI78`B@eiZ;WjasX;35D3002ovPDHLkV1f>G*^B@H literal 0 HcmV?d00001 diff --git a/1.14/src/main/resources/assets/engineersdecor/textures/gui/factory_placer_gui.png b/1.14/src/main/resources/assets/engineersdecor/textures/gui/factory_placer_gui.png new file mode 100644 index 0000000000000000000000000000000000000000..5e475217bc81440842ff6d0c8757f9321c9d1398 GIT binary patch literal 15570 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 literal 0 HcmV?d00001 diff --git a/1.14/src/main/resources/data/engineersdecor/loot_tables/blocks/small_tree_cutter.json b/1.14/src/main/resources/data/engineersdecor/loot_tables/blocks/small_tree_cutter.json new file mode 100644 index 0000000..9ed6580 --- /dev/null +++ b/1.14/src/main/resources/data/engineersdecor/loot_tables/blocks/small_tree_cutter.json @@ -0,0 +1,26 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "name": "small_tree_cutter_dlt", + "rolls": 1, + "entries": [ + { + "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:copy_name", + "source": "block_entity" + }, + { + "function": "minecraft:copy_nbt", + "source": "block_entity", + "ops": [] + } + ], + "name": "engineersdecor:small_tree_cutter" + } + ] + } + ] +} \ No newline at end of file diff --git a/1.14/src/main/resources/data/engineersdecor/recipes/alternative/factory_hopper_recipe_standalone.json b/1.14/src/main/resources/data/engineersdecor/recipes/alternative/factory_hopper_recipe_standalone.json new file mode 100644 index 0000000..62cecd2 --- /dev/null +++ b/1.14/src/main/resources/data/engineersdecor/recipes/alternative/factory_hopper_recipe_standalone.json @@ -0,0 +1,24 @@ +{ + "conditions": [ + { + "type": "engineersdecor:optional", + "result": "engineersdecor:factory_hopper", + "missing": ["immersiveengineering:material"] + } + ], + "type": "minecraft:crafting_shaped", + "pattern": [ + "WWW", + "WHW", + "WPW" + ], + "key": { + "H": { "item": "minecraft:hopper" }, + "P": { "item": "minecraft:iron_ingot" }, + "W": { "tag": "minecraft:planks" } + }, + "result": { + "item": "engineersdecor:factory_hopper", + "count": 1 + } +} diff --git a/1.14/src/main/resources/data/engineersdecor/recipes/alternative/factory_placer_recipe_standalone.json b/1.14/src/main/resources/data/engineersdecor/recipes/alternative/factory_placer_recipe_standalone.json new file mode 100644 index 0000000..3b934c9 --- /dev/null +++ b/1.14/src/main/resources/data/engineersdecor/recipes/alternative/factory_placer_recipe_standalone.json @@ -0,0 +1,24 @@ +{ + "conditions": [ + { + "type": "engineersdecor:optional", + "result": "engineersdecor:factory_placer", + "missing": ["immersiveengineering:material"] + } + ], + "type": "minecraft:crafting_shaped", + "pattern": [ + "WWW", + "WDP", + "WWW" + ], + "key": { + "D": { "item": "minecraft:dispenser" }, + "P": { "item": "minecraft:iron_ingot" }, + "W": { "tag": "minecraft:planks" } + }, + "result": { + "item": "engineersdecor:factory_placer", + "count": 1 + } +} \ No newline at end of file diff --git a/1.14/src/main/resources/data/engineersdecor/recipes/alternative/small_tree_cutter_recipe_standalone.json b/1.14/src/main/resources/data/engineersdecor/recipes/alternative/small_tree_cutter_recipe_standalone.json new file mode 100644 index 0000000..dc8b907 --- /dev/null +++ b/1.14/src/main/resources/data/engineersdecor/recipes/alternative/small_tree_cutter_recipe_standalone.json @@ -0,0 +1,33 @@ +{ + "conditions": [ + { + "type": "engineersdecor:optional", + "result": "engineersdecor:small_solar_panel", + "missing": ["immersiveengineering:metal_device1"] + } + ], + "type": "minecraft:crafting_shaped", + "pattern": [ + "PPP", + "PAO", + "PRP" + ], + "key": { + "O": { + "item": "minecraft:observer" + }, + "P": { + "item": "minecraft:iron_ingot" + }, + "A": { + "item": "minecraft:iron_axe" + }, + "R": { + "item": "minecraft:redstone_block" + } + }, + "result": { + "item": "engineersdecor:small_tree_cutter", + "count": 1 + } +} diff --git a/meta/update.json b/meta/update.json index a70d1e5..3b0def1 100644 --- a/meta/update.json +++ b/meta/update.json @@ -4,7 +4,7 @@ "1.12.2-recommended": "1.0.14", "1.12.2-latest": "1.0.15-b1", "1.14.4-recommended": "", - "1.14.4-latest": "1.0.15-b1" + "1.14.4-latest": "1.0.15-b2" }, "1.12.2": { "1.0.15-b1": "[A] Added Floor Edge Light.\n[A] Added Factory Block Placer and Planter.", @@ -69,6 +69,7 @@ "1.0.0-b1": "[A] Initial structure.\n[A] Added clinker bricks and clinker brick stairs.\n[A] Added slag bricks and slag brick stairs.\n[A] Added metal rung ladder.\n[A] Added staggered metal steps ladder.\n[A] Added treated wood ladder.\n[A] Added treated wood pole.\n[A] Added treated wood table." }, "1.14.4": { + "1.0.15-b2": "[!] Forge version requirement set to 1.14.4-28.1.68 or higher.\n[A] Added Factory Block Placer and Planter.\n[A] Added Small Tree Cutter.", "1.0.15-b1": "[A] Added Floor Edge Light.\n[U] Updated to Forge1.14.4-28.1.68/20190719-1.14.3.", "1.0.14-b1": "[U] Updated to Forge 1.14.4-28.1.40/20190719-1.14.3.\n[A] Factory Hopper added (configurable hopper and item collector).\n[M] Switched to integrated loot table generation.\n[M] Lang file zh_cn updated (scikirbypoke, PR#53).", "1.0.13-b2": "[A] Added Steel Mesh Fence.\n[A] Added Broad Window Sill.", diff --git a/readme.md b/readme.md index 072c1bd..3b99982 100644 --- a/readme.md +++ b/readme.md @@ -67,6 +67,11 @@ looking manufacturing contraptions. Current feature set: allowed to be picked up and on the ground. This prevents that the hopper snatches blocks that you break when building before you can pick them up yourself. +- *Factory Block Placer*: Places blocks or plants crops/saplings in front of it. + Supports spike planting, means it can plant e.g. from underneath the soil block. + Automatically spits out items that it cannot plant or place. Can be redstone + controlled similar to the Factory Hopper (invertible, pulse/continuous mode). + - *Small Waste Incinerator*: Buffered and delayed item disposal device. 16 fifo slots are filled when new items are pushed in from any side. A GUI allows to take out accidentally trashed items or put in items to get rid of. When the fifo