Merge pull request #1620 from LordGrimmauld/DynamicTreesCompat
Dynamic trees compat
This commit is contained in:
commit
95f4656d40
7 changed files with 156 additions and 3 deletions
|
@ -115,6 +115,10 @@ repositories {
|
||||||
includeGroup "curse.maven"
|
includeGroup "curse.maven"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
maven {
|
||||||
|
//location of the maven for dynamic trees
|
||||||
|
url "http://harleyoconnor.com/maven"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
configurations {
|
configurations {
|
||||||
|
@ -140,6 +144,8 @@ dependencies {
|
||||||
runtimeOnly fg.deobf("mezz.jei:jei-1.16.5:${jei_version}")
|
runtimeOnly fg.deobf("mezz.jei:jei-1.16.5:${jei_version}")
|
||||||
|
|
||||||
// implementation fg.deobf("curse.maven:druidcraft-340991:3101903")
|
// implementation fg.deobf("curse.maven:druidcraft-340991:3101903")
|
||||||
|
implementation fg.deobf("com.ferreusveritas.dynamictrees:DynamicTrees-1.16.5:0.10.0-Beta12.1")
|
||||||
|
|
||||||
|
|
||||||
// i'll leave this here commented for easier testing
|
// i'll leave this here commented for easier testing
|
||||||
//runtimeOnly fg.deobf("vazkii.arl:AutoRegLib:1.4-35.69")
|
//runtimeOnly fg.deobf("vazkii.arl:AutoRegLib:1.4-35.69")
|
||||||
|
|
38
src/main/java/com/simibubi/create/compat/Mods.java
Normal file
38
src/main/java/com/simibubi/create/compat/Mods.java
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
package com.simibubi.create.compat;
|
||||||
|
|
||||||
|
import net.minecraftforge.fml.ModList;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For compatibility with and without another mod present, we have to define load conditions of the specific code
|
||||||
|
*/
|
||||||
|
public enum Mods {
|
||||||
|
DYNAMICTREES;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return a boolean of whether the mod is loaded or not based on mod id
|
||||||
|
*/
|
||||||
|
public boolean isLoaded() {
|
||||||
|
return ModList.get().isLoaded(asId());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the mod id
|
||||||
|
*/
|
||||||
|
public String asId() {
|
||||||
|
return name().toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple hook to run code if a mod is installed
|
||||||
|
* @param toRun will be run only if the mod is loaded
|
||||||
|
* @return Optional.empty() if the mod is not loaded, otherwise an Optional of the return value of the given supplier
|
||||||
|
*/
|
||||||
|
public <T> Optional<T> runIfInstalled(Supplier<Supplier<T>> toRun) {
|
||||||
|
if (isLoaded())
|
||||||
|
return Optional.of(toRun.get().get());
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
package com.simibubi.create.compat.dynamictrees;
|
||||||
|
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.ferreusveritas.dynamictrees.api.TreeHelper;
|
||||||
|
import com.ferreusveritas.dynamictrees.blocks.branches.BranchBlock;
|
||||||
|
import com.ferreusveritas.dynamictrees.blocks.branches.TrunkShellBlock;
|
||||||
|
import com.ferreusveritas.dynamictrees.util.BranchDestructionData;
|
||||||
|
import com.simibubi.create.foundation.utility.AbstractBlockBreakQueue;
|
||||||
|
|
||||||
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.util.Direction;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
public class DynamicTree extends AbstractBlockBreakQueue {
|
||||||
|
private BlockPos startCutPos;
|
||||||
|
|
||||||
|
public DynamicTree(BlockPos startCutPos) {
|
||||||
|
this.startCutPos = startCutPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroyBlocks(World world, ItemStack toDamage, @Nullable PlayerEntity playerEntity, BiConsumer<BlockPos, ItemStack> drop) {
|
||||||
|
BranchBlock start = TreeHelper.getBranch(world.getBlockState(startCutPos));
|
||||||
|
if (start == null) //if start is null, it was not a branch
|
||||||
|
start = setBranchToShellMuse(world, world.getBlockState(startCutPos)); //we check for a trunk shell instead
|
||||||
|
|
||||||
|
if (start == null) //if it is null again, it was neither a branch nor a trunk shell and thus we return
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Play and render block break sound and particles
|
||||||
|
world.playEvent(null, 2001, startCutPos, Block.getStateId(world.getBlockState(startCutPos)));
|
||||||
|
// Actually breaks the tree
|
||||||
|
|
||||||
|
BranchDestructionData data = start.destroyBranchFromNode(world, startCutPos, Direction.DOWN, false, playerEntity);
|
||||||
|
|
||||||
|
// Feed all the tree drops to drop bi-consumer
|
||||||
|
data.leavesDrops.forEach(stackPos -> drop.accept(stackPos.pos.add(startCutPos), stackPos.stack));
|
||||||
|
start.getLogDrops(world, startCutPos, data.species, data.woodVolume).forEach(stack -> drop.accept(startCutPos, stack));
|
||||||
|
}
|
||||||
|
|
||||||
|
private BranchBlock setBranchToShellMuse(World world, BlockState state){
|
||||||
|
Block block = state.getBlock();
|
||||||
|
if (block instanceof TrunkShellBlock){
|
||||||
|
TrunkShellBlock.ShellMuse muse = ((TrunkShellBlock)block).getMuse(world, startCutPos);
|
||||||
|
if (muse != null){
|
||||||
|
startCutPos = muse.pos; //the cut pos is moved to the center of the trunk
|
||||||
|
return TreeHelper.getBranch(muse.state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isDynamicBranch(Block block) {
|
||||||
|
return TreeHelper.isBranch(block) || block instanceof TrunkShellBlock;
|
||||||
|
}
|
||||||
|
}
|
|
@ -166,10 +166,10 @@ public class BlockBreakingMovementBehaviour extends MovementBehaviour {
|
||||||
float breakSpeed = MathHelper.clamp(Math.abs(context.getAnimationSpeed()) / 500f, 1 / 128f, 16f);
|
float breakSpeed = MathHelper.clamp(Math.abs(context.getAnimationSpeed()) / 500f, 1 / 128f, 16f);
|
||||||
destroyProgress += MathHelper.clamp((int) (breakSpeed / blockHardness), 1, 10 - destroyProgress);
|
destroyProgress += MathHelper.clamp((int) (breakSpeed / blockHardness), 1, 10 - destroyProgress);
|
||||||
world.playSound(null, breakingPos, stateToBreak.getSoundType().getHitSound(), SoundCategory.NEUTRAL, .25f, 1);
|
world.playSound(null, breakingPos, stateToBreak.getSoundType().getHitSound(), SoundCategory.NEUTRAL, .25f, 1);
|
||||||
|
|
||||||
if (destroyProgress >= 10) {
|
if (destroyProgress >= 10) {
|
||||||
world.sendBlockBreakProgress(id, breakingPos, -1);
|
world.sendBlockBreakProgress(id, breakingPos, -1);
|
||||||
|
|
||||||
// break falling blocks from top to bottom
|
// break falling blocks from top to bottom
|
||||||
BlockPos ogPos = breakingPos;
|
BlockPos ogPos = breakingPos;
|
||||||
BlockState stateAbove = world.getBlockState(breakingPos.up());
|
BlockState stateAbove = world.getBlockState(breakingPos.up());
|
||||||
|
@ -178,8 +178,9 @@ public class BlockBreakingMovementBehaviour extends MovementBehaviour {
|
||||||
stateAbove = world.getBlockState(breakingPos.up());
|
stateAbove = world.getBlockState(breakingPos.up());
|
||||||
}
|
}
|
||||||
stateToBreak = world.getBlockState(breakingPos);
|
stateToBreak = world.getBlockState(breakingPos);
|
||||||
|
|
||||||
context.stall = false;
|
context.stall = false;
|
||||||
|
if (shouldDestroyStartBlock(stateToBreak))
|
||||||
BlockHelper.destroyBlock(context.world, breakingPos, 1f, stack -> this.dropItem(context, stack));
|
BlockHelper.destroyBlock(context.world, breakingPos, 1f, stack -> this.dropItem(context, stack));
|
||||||
onBlockBroken(context, ogPos, stateToBreak);
|
onBlockBroken(context, ogPos, stateToBreak);
|
||||||
ticksUntilNextProgress = -1;
|
ticksUntilNextProgress = -1;
|
||||||
|
@ -195,6 +196,10 @@ public class BlockBreakingMovementBehaviour extends MovementBehaviour {
|
||||||
data.putInt("Progress", destroyProgress);
|
data.putInt("Progress", destroyProgress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected boolean shouldDestroyStartBlock(BlockState stateToBreak) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean canBreak(World world, BlockPos breakingPos, BlockState state) {
|
public boolean canBreak(World world, BlockPos breakingPos, BlockState state) {
|
||||||
float blockHardness = state.getBlockHardness(world, breakingPos);
|
float blockHardness = state.getBlockHardness(world, breakingPos);
|
||||||
return BlockBreakingKineticTileEntity.isBreakable(state, blockHardness);
|
return BlockBreakingKineticTileEntity.isBreakable(state, blockHardness);
|
||||||
|
|
|
@ -4,6 +4,7 @@ import com.simibubi.create.content.contraptions.components.saw.SawBlock;
|
||||||
import com.simibubi.create.content.contraptions.components.saw.SawRenderer;
|
import com.simibubi.create.content.contraptions.components.saw.SawRenderer;
|
||||||
import com.simibubi.create.content.contraptions.components.saw.SawTileEntity;
|
import com.simibubi.create.content.contraptions.components.saw.SawTileEntity;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext;
|
||||||
|
import com.simibubi.create.foundation.utility.AbstractBlockBreakQueue;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices;
|
import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices;
|
||||||
import com.simibubi.create.foundation.utility.TreeCutter;
|
import com.simibubi.create.foundation.utility.TreeCutter;
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
@ -23,6 +24,8 @@ import net.minecraftforge.api.distmarker.Dist;
|
||||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
import net.minecraftforge.items.ItemHandlerHelper;
|
import net.minecraftforge.items.ItemHandlerHelper;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
public class SawMovementBehaviour extends BlockBreakingMovementBehaviour {
|
public class SawMovementBehaviour extends BlockBreakingMovementBehaviour {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -58,6 +61,13 @@ public class SawMovementBehaviour extends BlockBreakingMovementBehaviour {
|
||||||
protected void onBlockBroken(MovementContext context, BlockPos pos, BlockState brokenState) {
|
protected void onBlockBroken(MovementContext context, BlockPos pos, BlockState brokenState) {
|
||||||
if (brokenState.isIn(BlockTags.LEAVES))
|
if (brokenState.isIn(BlockTags.LEAVES))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
Optional<AbstractBlockBreakQueue> dynamicTree = TreeCutter.findDynamicTree(brokenState.getBlock(), pos);
|
||||||
|
if (dynamicTree.isPresent()) {
|
||||||
|
dynamicTree.get().destroyBlocks(context.world, null, (stack, dropPos) -> dropItemFromCutTree(context, stack, dropPos));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
TreeCutter.findTree(context.world, pos).destroyBlocks(context.world, null, (stack, dropPos) -> dropItemFromCutTree(context, stack, dropPos));
|
TreeCutter.findTree(context.world, pos).destroyBlocks(context.world, null, (stack, dropPos) -> dropItemFromCutTree(context, stack, dropPos));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,6 +91,11 @@ public class SawMovementBehaviour extends BlockBreakingMovementBehaviour {
|
||||||
SawRenderer.renderInContraption(context, renderWorld, matrices, buffer);
|
SawRenderer.renderInContraption(context, renderWorld, matrices, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean shouldDestroyStartBlock(BlockState stateToBreak) {
|
||||||
|
return !TreeCutter.canDynamicTreeCutFrom(stateToBreak.getBlock());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected DamageSource getDamageSource() {
|
protected DamageSource getDamageSource() {
|
||||||
return SawBlock.damageSourceSaw;
|
return SawBlock.damageSourceSaw;
|
||||||
|
|
|
@ -22,6 +22,7 @@ import com.simibubi.create.foundation.item.ItemHelper;
|
||||||
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||||
import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour;
|
import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour;
|
||||||
import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour;
|
import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour;
|
||||||
|
import com.simibubi.create.foundation.utility.AbstractBlockBreakQueue;
|
||||||
import com.simibubi.create.foundation.utility.TreeCutter;
|
import com.simibubi.create.foundation.utility.TreeCutter;
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
import com.simibubi.create.foundation.utility.recipe.RecipeConditions;
|
import com.simibubi.create.foundation.utility.recipe.RecipeConditions;
|
||||||
|
@ -435,6 +436,12 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBlockBroken(BlockState stateToBreak) {
|
public void onBlockBroken(BlockState stateToBreak) {
|
||||||
|
Optional<AbstractBlockBreakQueue> dynamicTree = TreeCutter.findDynamicTree(stateToBreak.getBlock(), breakingPos);
|
||||||
|
if (dynamicTree.isPresent()) {
|
||||||
|
dynamicTree.get().destroyBlocks(world, null, this::dropItemFromCutTree);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
super.onBlockBroken(stateToBreak);
|
super.onBlockBroken(stateToBreak);
|
||||||
TreeCutter.findTree(world, breakingPos)
|
TreeCutter.findTree(world, breakingPos)
|
||||||
.destroyBlocks(world, null, this::dropItemFromCutTree);
|
.destroyBlocks(world, null, this::dropItemFromCutTree);
|
||||||
|
@ -474,6 +481,8 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity {
|
||||||
return true;
|
return true;
|
||||||
if (block instanceof ChorusPlantBlock)
|
if (block instanceof ChorusPlantBlock)
|
||||||
return true;
|
return true;
|
||||||
|
if (TreeCutter.canDynamicTreeCutFrom(block))
|
||||||
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
@ -14,6 +15,10 @@ import javax.annotation.Nullable;
|
||||||
|
|
||||||
import com.simibubi.create.AllTags;
|
import com.simibubi.create.AllTags;
|
||||||
|
|
||||||
|
import com.simibubi.create.compat.Mods;
|
||||||
|
|
||||||
|
import com.simibubi.create.compat.dynamictrees.DynamicTree;
|
||||||
|
|
||||||
import net.minecraft.block.BambooBlock;
|
import net.minecraft.block.BambooBlock;
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
|
@ -36,6 +41,18 @@ import net.minecraft.world.World;
|
||||||
public class TreeCutter {
|
public class TreeCutter {
|
||||||
public static final Tree NO_TREE = new Tree(Collections.emptyList(), Collections.emptyList());
|
public static final Tree NO_TREE = new Tree(Collections.emptyList(), Collections.emptyList());
|
||||||
|
|
||||||
|
public static boolean canDynamicTreeCutFrom(Block startBlock) {
|
||||||
|
return Mods.DYNAMICTREES.runIfInstalled(() -> () -> DynamicTree.isDynamicBranch(startBlock)).orElse(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
public static Optional<AbstractBlockBreakQueue> findDynamicTree(Block startBlock, BlockPos pos) {
|
||||||
|
if (canDynamicTreeCutFrom(startBlock)) {
|
||||||
|
return Mods.DYNAMICTREES.runIfInstalled(() -> () -> new DynamicTree(pos));
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds a tree at the given pos. Block at the position should be air
|
* Finds a tree at the given pos. Block at the position should be air
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in a new issue