From fca3b7490958c74116a051bbd613c5738472bf38 Mon Sep 17 00:00:00 2001 From: simibubi <31564874+simibubi@users.noreply.github.com> Date: Fri, 13 Dec 2019 18:15:11 +0100 Subject: [PATCH] Flicker awareness & Tree cutting - Kinetic blocks break when their speed updates to frequently - Fixed Stress gauge not resetting when source was removed - Fixed Kinetic networks doubling their stress when saving and loading the world - Fixed Generators not updating network stress when their speed changed - Fixed Processing saw crashing when used - Fixed tree cutting algorithm looping indefinitely - Fixed sourceless kinetic blocks in rainbow debug - Horizontal saws cut trees in front of them - Deforester now works in creative mode --- build.gradle | 4 +- .../foundation/utility/BlockHelper.java | 30 ++++ .../create/foundation/utility/Debug.java | 2 + .../create/foundation/utility/TreeCutter.java | 5 + .../utility/recipe/RecipeConditions.java | 2 +- .../utility/recipe/RecipeFinder.java | 11 +- .../modules/contraptions/KineticNetwork.java | 4 +- .../contraptions/RotationPropagator.java | 16 +- .../base/GeneratingKineticTileEntity.java | 8 +- .../contraptions/base/KineticTileEntity.java | 17 +- .../base/KineticTileEntityRenderer.java | 2 + .../BlockBreakingKineticTileEntity.java | 150 ++++++++++++++++++ .../components/actors/DrillTileEntity.java | 124 +-------------- .../bearing/MechanicalBearingTileEntity.java | 6 +- .../piston/MechanicalPistonTileEntity.java | 4 +- .../crusher/CrushingWheelTileEntity.java | 6 +- .../components/fan/EncasedFanBlock.java | 16 +- .../components/fan/EncasedFanTileEntity.java | 4 +- .../mixer/MechanicalMixerTileEntity.java | 4 +- .../contraptions/components/saw/SawBlock.java | 6 +- .../components/saw/SawTileEntity.java | 68 ++++++-- .../relays/gauge/GaugeTileEntity.java | 6 - .../relays/gauge/SpeedGaugeTileEntity.java | 4 +- .../relays/gauge/StressGaugeTileEntity.java | 11 +- .../deforester/DeforesterItem.java | 53 +++++-- .../create/textures/block/bearing_side.png | Bin 487 -> 558 bytes 26 files changed, 358 insertions(+), 205 deletions(-) create mode 100644 src/main/java/com/simibubi/create/modules/contraptions/components/actors/BlockBreakingKineticTileEntity.java diff --git a/build.gradle b/build.gradle index 104fc1a73..74f612743 100644 --- a/build.gradle +++ b/build.gradle @@ -20,7 +20,7 @@ archivesBaseName = 'create' sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.8' minecraft { - mappings channel: 'snapshot', version: '20191107-1.14.3' + mappings channel: 'snapshot', version: '20191130-1.14.3' runs { client { @@ -71,7 +71,7 @@ repositories { } dependencies { - minecraft 'net.minecraftforge:forge:1.14.4-28.1.85' + minecraft 'net.minecraftforge:forge:1.14.4-28.1.106' // compile against the JEI API but do not include it at runtime compileOnly fg.deobf("mezz.jei:jei-1.14.4:6.0.0.10:api") diff --git a/src/main/java/com/simibubi/create/foundation/utility/BlockHelper.java b/src/main/java/com/simibubi/create/foundation/utility/BlockHelper.java index 891504fa7..1197aa3cf 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/BlockHelper.java +++ b/src/main/java/com/simibubi/create/foundation/utility/BlockHelper.java @@ -1,11 +1,20 @@ package com.simibubi.create.foundation.utility; +import java.util.function.Consumer; + +import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.fluid.IFluidState; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.state.properties.SlabType; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.GameRules; +import net.minecraft.world.World; +import net.minecraft.world.server.ServerWorld; public class BlockHelper { @@ -61,4 +70,25 @@ public class BlockHelper { return itemStack; } + public static void destroyBlock(World world, BlockPos pos, float effectChance) { + destroyBlock(world, pos, effectChance, stack -> Block.spawnAsEntity(world, pos, stack)); + } + + public static void destroyBlock(World world, BlockPos pos, float effectChance, + Consumer droppedItemCallback) { + IFluidState ifluidstate = world.getFluidState(pos); + BlockState state = world.getBlockState(pos); + if (world.rand.nextFloat() < effectChance) + world.playEvent(2001, pos, Block.getStateId(state)); + TileEntity tileentity = state.hasTileEntity() ? world.getTileEntity(pos) : null; + + if (world.getGameRules().getBoolean(GameRules.DO_TILE_DROPS) && !world.restoringBlockSnapshots) { + for (ItemStack itemStack : Block.getDrops(state, (ServerWorld) world, pos, tileentity)) + droppedItemCallback.accept(itemStack); + state.spawnAdditionalDrops(world, pos, ItemStack.EMPTY); + } + + world.setBlockState(pos, ifluidstate.getBlockState()); + } + } diff --git a/src/main/java/com/simibubi/create/foundation/utility/Debug.java b/src/main/java/com/simibubi/create/foundation/utility/Debug.java index 5b99afbe8..d1843ba95 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/Debug.java +++ b/src/main/java/com/simibubi/create/foundation/utility/Debug.java @@ -43,5 +43,7 @@ public class Debug { } return text + TextFormatting.GRAY + " ..."; } + + public static void markTemporary() {}; } diff --git a/src/main/java/com/simibubi/create/foundation/utility/TreeCutter.java b/src/main/java/com/simibubi/create/foundation/utility/TreeCutter.java index 84c5b77ce..a07b5e590 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/TreeCutter.java +++ b/src/main/java/com/simibubi/create/foundation/utility/TreeCutter.java @@ -49,6 +49,8 @@ public class TreeCutter { // Find all logs while (!frontier.isEmpty()) { BlockPos currentPos = frontier.remove(0); + if (visited.contains(currentPos)) + continue; visited.add(currentPos); if (!isLog(reader.getBlockState(currentPos))) @@ -63,6 +65,9 @@ public class TreeCutter { frontier.addAll(logs); while (!frontier.isEmpty()) { BlockPos currentPos = frontier.remove(0); + if (!logs.contains(currentPos)) + if (visited.contains(currentPos)) + continue; visited.add(currentPos); BlockState blockState = reader.getBlockState(currentPos); diff --git a/src/main/java/com/simibubi/create/foundation/utility/recipe/RecipeConditions.java b/src/main/java/com/simibubi/create/foundation/utility/recipe/RecipeConditions.java index 0fafa6b6b..4bf1364fb 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/recipe/RecipeConditions.java +++ b/src/main/java/com/simibubi/create/foundation/utility/recipe/RecipeConditions.java @@ -1,6 +1,6 @@ package com.simibubi.create.foundation.utility.recipe; -import java.util.function.Predicate; +import com.google.common.base.Predicate; import net.minecraft.item.ItemStack; import net.minecraft.item.crafting.IRecipe; diff --git a/src/main/java/com/simibubi/create/foundation/utility/recipe/RecipeFinder.java b/src/main/java/com/simibubi/create/foundation/utility/recipe/RecipeFinder.java index 1c369d74d..6f4804bae 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/recipe/RecipeFinder.java +++ b/src/main/java/com/simibubi/create/foundation/utility/recipe/RecipeFinder.java @@ -50,14 +50,9 @@ public class RecipeFinder { public > RecipeStream assumeType(IRecipeType type) { return (RecipeStream) this; } - - public RecipeStream filter(Predicate condition) { - stream.filter(condition); - return this; - } - - public List asList() { - return stream.collect(Collectors.toList()); + + public List filter(Predicate condition) { + return stream.filter(condition).collect(Collectors.toList()); } } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/KineticNetwork.java b/src/main/java/com/simibubi/create/modules/contraptions/KineticNetwork.java index b034fc27a..0e2a39c8d 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/KineticNetwork.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/KineticNetwork.java @@ -38,11 +38,11 @@ public class KineticNetwork { return; if (te.isSource()) { float capacity = te.getAddedStressCapacity(); - unloadedStressCapacity -= capacity; + unloadedStressCapacity -= capacity * getStressMultiplierForSpeed(te.getGeneratedSpeed()); sources.put(te, capacity); } float stressApplied = te.getStressApplied(); - unloadedStress -= stressApplied; + unloadedStress -= stressApplied * getStressMultiplierForSpeed(te.speed); members.put(te, stressApplied); } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/RotationPropagator.java b/src/main/java/com/simibubi/create/modules/contraptions/RotationPropagator.java index 453f3881a..f756e1910 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/RotationPropagator.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/RotationPropagator.java @@ -176,14 +176,14 @@ public class RotationPropagator { continue; if (neighbourTE.hasSource() && neighbourTE.getSource().equals(addedTE.getPos())) { addedTE.setSpeed(neighbourTE.speed * speedModifier); - addedTE.onSpeedChanged(); + addedTE.onSpeedChanged(0); addedTE.sendData(); continue; } addedTE.setSpeed(neighbourTE.speed * speedModifier); addedTE.setSource(neighbourTE.getPos()); - addedTE.onSpeedChanged(); + addedTE.onSpeedChanged(0); addedTE.sendData(); propagateNewSource(addedTE); return; @@ -209,7 +209,8 @@ public class RotationPropagator { && (newSpeed != 0 && neighbourTE.speed != 0); boolean tooFast = Math.abs(newSpeed) > parameters.maxRotationSpeed.get(); - if (tooFast) { + boolean speedChangedTooOften = updateTE.speedChangeCounter > 25; + if (tooFast || speedChangedTooOften) { world.destroyBlock(pos, true); return; } @@ -224,8 +225,9 @@ public class RotationPropagator { if (Math.abs(oppositeSpeed) > Math.abs(updateTE.speed)) { // Neighbour faster, overpower the incoming tree updateTE.setSource(neighbourTE.getPos()); + float prevSpeed = updateTE.getSpeed(); updateTE.setSpeed(neighbourTE.speed * getRotationSpeedModifier(neighbourTE, updateTE)); - updateTE.onSpeedChanged(); + updateTE.onSpeedChanged(prevSpeed); updateTE.sendData(); propagateNewSource(updateTE); @@ -241,8 +243,9 @@ public class RotationPropagator { } neighbourTE.setSource(updateTE.getPos()); + float prevSpeed = neighbourTE.getSpeed(); neighbourTE.setSpeed(updateTE.speed * getRotationSpeedModifier(updateTE, neighbourTE)); - neighbourTE.onSpeedChanged(); + neighbourTE.onSpeedChanged(prevSpeed); neighbourTE.sendData(); propagateNewSource(neighbourTE); } @@ -253,9 +256,10 @@ public class RotationPropagator { if (neighbourTE.speed == newSpeed) continue; + float prevSpeed = neighbourTE.getSpeed(); neighbourTE.setSpeed(newSpeed); neighbourTE.setSource(updateTE.getPos()); - neighbourTE.onSpeedChanged(); + neighbourTE.onSpeedChanged(prevSpeed); neighbourTE.sendData(); propagateNewSource(neighbourTE); diff --git a/src/main/java/com/simibubi/create/modules/contraptions/base/GeneratingKineticTileEntity.java b/src/main/java/com/simibubi/create/modules/contraptions/base/GeneratingKineticTileEntity.java index ffc3b77fe..199a3060a 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/base/GeneratingKineticTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/base/GeneratingKineticTileEntity.java @@ -24,6 +24,7 @@ public abstract class GeneratingKineticTileEntity extends KineticTileEntity { public void updateGeneratedRotation() { float speed = getGeneratedSpeed(); + float prevSpeed = this.speed; if (this.speed != speed) { @@ -71,10 +72,13 @@ public abstract class GeneratingKineticTileEntity extends KineticTileEntity { } } - if (hasNetwork() && speed != 0) + if (hasNetwork() && speed != 0) { + getNetwork().updateCapacityFor(this, getAddedStressCapacity()); getNetwork().updateStressCapacity(); + getNetwork().updateStress(); + } - onSpeedChanged(); + onSpeedChanged(prevSpeed); sendData(); } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/base/KineticTileEntity.java b/src/main/java/com/simibubi/create/modules/contraptions/base/KineticTileEntity.java index edd1bb7ed..fa6a49e1e 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/base/KineticTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/base/KineticTileEntity.java @@ -64,8 +64,9 @@ public abstract class KineticTileEntity extends SyncedTileEntity implements ITic this.currentStress = currentStress; boolean overStressed = maxStress < currentStress; if (overStressed != this.overStressed) { + float prevSpeed = getSpeed(); this.overStressed = overStressed; - onSpeedChanged(); + onSpeedChanged(prevSpeed); sendData(); } } @@ -95,8 +96,12 @@ public abstract class KineticTileEntity extends SyncedTileEntity implements ITic return true; } - public void onSpeedChanged() { - speedChangeCounter += 5; + public void onSpeedChanged(float previousSpeed) { + boolean fromOrToZero = (previousSpeed == 0) != (getSpeed() == 0); + boolean directionSwap = !fromOrToZero && Math.signum(previousSpeed) != Math.signum(getSpeed()); + if (fromOrToZero || directionSwap) { + speedChangeCounter += 5; + } } @Override @@ -217,8 +222,9 @@ public abstract class KineticTileEntity extends SyncedTileEntity implements ITic this.source = Optional.empty(); newNetworkID = null; updateNetwork = true; + float prevSpeed = getSpeed(); setSpeed(0); - onSpeedChanged(); + onSpeedChanged(prevSpeed); } public KineticNetwork getNetwork() { @@ -263,9 +269,6 @@ public abstract class KineticTileEntity extends SyncedTileEntity implements ITic public void tick() { if (world.isRemote) return; - - if (speedChangeCounter > 25) - world.destroyBlock(pos, true); if (speedChangeCounter > 0) speedChangeCounter--; diff --git a/src/main/java/com/simibubi/create/modules/contraptions/base/KineticTileEntityRenderer.java b/src/main/java/com/simibubi/create/modules/contraptions/base/KineticTileEntityRenderer.java index b6ee79367..dd7d77f17 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/base/KineticTileEntityRenderer.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/base/KineticTileEntityRenderer.java @@ -59,6 +59,8 @@ public class KineticTileEntityRenderer extends TileEntityRendererFast typeIn) { + super(typeIn); + } + + @Override + public void onSpeedChanged(float prevSpeed) { + super.onSpeedChanged(prevSpeed); + if (destroyProgress == -1) + destroyNextTick(); + } + + public void destroyNextTick() { + ticksUntilNextProgress = 1; + } + + protected abstract BlockPos getBreakingPos(); + + protected boolean shouldRun() { + return true; + } + + @Override + public CompoundNBT write(CompoundNBT compound) { + compound.putInt("Progress", destroyProgress); + compound.putInt("NextTick", ticksUntilNextProgress); + if (breakingPos != null) + compound.put("Breaking", NBTUtil.writeBlockPos(breakingPos)); + return super.write(compound); + } + + @Override + public void read(CompoundNBT compound) { + destroyProgress = compound.getInt("Progress"); + ticksUntilNextProgress = compound.getInt("NextTick"); + if (compound.contains("Breaking")) + breakingPos = NBTUtil.readBlockPos(compound.getCompound("Breaking")); + super.read(compound); + } + + @Override + public void remove() { + if (!world.isRemote && destroyProgress != 0) + world.sendBlockBreakProgress(breakerId, breakingPos, -1); + super.remove(); + } + + @Override + public void tick() { + super.tick(); + + if (world.isRemote) + return; + if (!shouldRun()) + return; + if (getSpeed() == 0) + return; + if (breakingPos == null) + breakingPos = getBreakingPos(); + if (ticksUntilNextProgress < 0) + return; + if (ticksUntilNextProgress-- > 0) + return; + + BlockState stateToBreak = world.getBlockState(breakingPos); + float blockHardness = stateToBreak.getBlockHardness(world, breakingPos); + + if (!canBreak(stateToBreak, blockHardness)) { + if (destroyProgress != 0) { + destroyProgress = 0; + world.sendBlockBreakProgress(breakerId, breakingPos, -1); + } + return; + } + + float breakSpeed = getBreakSpeed(); + destroyProgress += MathHelper.clamp((int) (breakSpeed / blockHardness), 1, 10 - destroyProgress); + + if (destroyProgress >= 10) { + onBlockBroken(stateToBreak); + destroyProgress = 0; + ticksUntilNextProgress = -1; + world.sendBlockBreakProgress(breakerId, breakingPos, -1); + return; + } + + ticksUntilNextProgress = (int) (blockHardness / breakSpeed); + world.sendBlockBreakProgress(breakerId, breakingPos, (int) destroyProgress); + } + + public boolean canBreak(BlockState stateToBreak, float blockHardness) { + return !(stateToBreak.getMaterial().isLiquid() || stateToBreak.getBlock() instanceof AirBlock + || blockHardness == -1); + } + + public void onBlockBroken(BlockState stateToBreak) { + IFluidState ifluidstate = world.getFluidState(breakingPos); + world.playEvent(2001, breakingPos, Block.getStateId(stateToBreak)); + TileEntity tileentity = stateToBreak.hasTileEntity() ? world.getTileEntity(breakingPos) : null; + Vec3d vec = VecHelper.offsetRandomly(VecHelper.getCenterOf(breakingPos), world.rand, .125f); + + Block.getDrops(stateToBreak, (ServerWorld) world, breakingPos, tileentity).forEach((stack) -> { + if (!stack.isEmpty() && world.getGameRules().getBoolean(GameRules.DO_TILE_DROPS) + && !world.restoringBlockSnapshots) { + ItemEntity itementity = new ItemEntity(world, vec.x, vec.y, vec.z, stack); + itementity.setDefaultPickupDelay(); + itementity.setMotion(Vec3d.ZERO); + world.addEntity(itementity); + } + }); + + stateToBreak.spawnAdditionalDrops(world, breakingPos, ItemStack.EMPTY); + world.setBlockState(breakingPos, ifluidstate.getBlockState(), 3); + } + + protected float getBreakSpeed() { + return Math.abs(speed / 100f); + } + +} diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/actors/DrillTileEntity.java b/src/main/java/com/simibubi/create/modules/contraptions/components/actors/DrillTileEntity.java index c827ba418..f2c31c166 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/components/actors/DrillTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/actors/DrillTileEntity.java @@ -1,139 +1,21 @@ package com.simibubi.create.modules.contraptions.components.actors; -import java.util.concurrent.atomic.AtomicInteger; - import com.simibubi.create.AllTileEntities; -import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.modules.contraptions.base.KineticTileEntity; -import net.minecraft.block.AirBlock; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.entity.Entity; -import net.minecraft.entity.item.ItemEntity; -import net.minecraft.fluid.IFluidState; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompoundNBT; -import net.minecraft.state.properties.BlockStateProperties; -import net.minecraft.tileentity.TileEntity; import net.minecraft.util.DamageSource; -import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.MathHelper; -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.GameRules; -import net.minecraft.world.server.ServerWorld; -public class DrillTileEntity extends KineticTileEntity { - - private static final AtomicInteger NEXT_DRILL_ID = new AtomicInteger(); +public class DrillTileEntity extends BlockBreakingKineticTileEntity { public static DamageSource damageSourceDrill = new DamageSource("create.drill").setDamageBypassesArmor(); - private int ticksUntilNextProgress; - private int destroyProgress; - private int drillId = -NEXT_DRILL_ID.incrementAndGet(); public DrillTileEntity() { super(AllTileEntities.DRILL.type); } @Override - public void onSpeedChanged() { - super.onSpeedChanged(); - if (destroyProgress == -1) - destroyNextTick(); - } - - public void destroyNextTick() { - ticksUntilNextProgress = 1; - } - - @Override - public CompoundNBT write(CompoundNBT compound) { - compound.putInt("Progress", destroyProgress); - compound.putInt("NextTick", ticksUntilNextProgress); - return super.write(compound); - } - - @Override - public void read(CompoundNBT compound) { - destroyProgress = compound.getInt("Progress"); - ticksUntilNextProgress = compound.getInt("NextTick"); - super.read(compound); - } - - @Override - public void remove() { - if (!world.isRemote && destroyProgress != 0) { - BlockPos posToBreak = pos.offset(getBlockState().get(BlockStateProperties.FACING)); - world.sendBlockBreakProgress(drillId, posToBreak, -1); - } - super.remove(); - } - - @Override - public void tick() { - super.tick(); - - if (world.isRemote) - return; - if (getSpeed() == 0) - return; - - BlockPos posToBreak = pos.offset(getBlockState().get(BlockStateProperties.FACING)); - - if (ticksUntilNextProgress < 0) { - for (Entity entity : world.getEntitiesWithinAABBExcludingEntity(null, new AxisAlignedBB(posToBreak))) - if (!(entity instanceof ItemEntity)) - entity.attackEntityFrom(damageSourceDrill, MathHelper.clamp(Math.abs(speed / 512f) + 1, 0, 20)); - return; - } - if (ticksUntilNextProgress-- > 0) - return; - - BlockState stateToBreak = world.getBlockState(posToBreak); - float blockHardness = stateToBreak.getBlockHardness(world, posToBreak); - - if (stateToBreak.getMaterial().isLiquid() || stateToBreak.getBlock() instanceof AirBlock - || blockHardness == -1) { - if (destroyProgress != 0) { - destroyProgress = 0; - world.sendBlockBreakProgress(drillId, posToBreak, -1); - } - return; - } - - float breakSpeed = Math.abs(speed / 100f); - destroyProgress += MathHelper.clamp((int) (breakSpeed / blockHardness), 1, 10 - destroyProgress); - - if (destroyProgress >= 10) { - - IFluidState ifluidstate = world.getFluidState(pos); - world.playEvent(2001, posToBreak, Block.getStateId(stateToBreak)); - TileEntity tileentity = stateToBreak.hasTileEntity() ? world.getTileEntity(posToBreak) : null; - Vec3d vec = VecHelper.offsetRandomly(VecHelper.getCenterOf(posToBreak), world.rand, .125f); - - Block.getDrops(stateToBreak, (ServerWorld) world, posToBreak, tileentity).forEach((stack) -> { - if (!stack.isEmpty() && world.getGameRules().getBoolean(GameRules.DO_TILE_DROPS) - && !world.restoringBlockSnapshots) { - ItemEntity itementity = new ItemEntity(world, vec.x, vec.y, vec.z, stack); - itementity.setDefaultPickupDelay(); - itementity.setMotion(Vec3d.ZERO); - world.addEntity(itementity); - } - }); - - stateToBreak.spawnAdditionalDrops(world, posToBreak, ItemStack.EMPTY); - world.setBlockState(posToBreak, ifluidstate.getBlockState(), 3); - - destroyProgress = 0; - ticksUntilNextProgress = -1; - world.sendBlockBreakProgress(drillId, posToBreak, -1); - return; - } - - ticksUntilNextProgress = (int) (blockHardness / breakSpeed); - world.sendBlockBreakProgress(drillId, posToBreak, (int) destroyProgress); + protected BlockPos getBreakingPos() { + return getPos().offset(getBlockState().get(DrillBlock.FACING)); } } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/bearing/MechanicalBearingTileEntity.java b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/bearing/MechanicalBearingTileEntity.java index d4cc4dc14..f70725796 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/bearing/MechanicalBearingTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/bearing/MechanicalBearingTileEntity.java @@ -45,7 +45,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp if (!isWindmill && running) { updateGeneratedRotation(); if (getSpeed() == 0) - disassembleConstruct(); + assembleNextTick = true; } sendData(); @@ -89,8 +89,8 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp } @Override - public void onSpeedChanged() { - super.onSpeedChanged(); + public void onSpeedChanged(float prevSpeed) { + super.onSpeedChanged(prevSpeed); assembleNextTick = true; } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/piston/MechanicalPistonTileEntity.java b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/piston/MechanicalPistonTileEntity.java index 273e87e35..a7f7c7777 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/piston/MechanicalPistonTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/contraptions/piston/MechanicalPistonTileEntity.java @@ -30,8 +30,8 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ICo } @Override - public void onSpeedChanged() { - super.onSpeedChanged(); + public void onSpeedChanged(float prevSpeed) { + super.onSpeedChanged(prevSpeed); assembleNextTick = true; } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/crusher/CrushingWheelTileEntity.java b/src/main/java/com/simibubi/create/modules/contraptions/components/crusher/CrushingWheelTileEntity.java index 7419e45e3..bebec9635 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/components/crusher/CrushingWheelTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/crusher/CrushingWheelTileEntity.java @@ -13,13 +13,13 @@ public class CrushingWheelTileEntity extends KineticTileEntity { } @Override - public void onSpeedChanged() { - super.onSpeedChanged(); + public void onSpeedChanged(float prevSpeed) { + super.onSpeedChanged(prevSpeed); for (Direction d : Direction.values()) ((CrushingWheelBlock) getBlockState().getBlock()).updateControllers(getBlockState(), getWorld(), getPos(), d); } - + @Override public AxisAlignedBB getRenderBoundingBox() { return new AxisAlignedBB(pos).grow(1); diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/fan/EncasedFanBlock.java b/src/main/java/com/simibubi/create/modules/contraptions/components/fan/EncasedFanBlock.java index 7d70bace2..c55fdcb9c 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/components/fan/EncasedFanBlock.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/fan/EncasedFanBlock.java @@ -29,18 +29,13 @@ public class EncasedFanBlock extends DirectionalKineticBlock implements IWithTil @Override public void onBlockAdded(BlockState state, World worldIn, BlockPos pos, BlockState oldState, boolean isMoving) { - notifyFanTile(worldIn, pos); + blockUpdate(state, worldIn, pos); } @Override public void neighborChanged(BlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos, boolean isMoving) { - notifyFanTile(worldIn, pos); - - if (worldIn.isRemote || getRotationAxis(state).isHorizontal()) - return; - - withTileEntityDo(worldIn, pos, EncasedFanTileEntity::updateGenerator); + blockUpdate(state, worldIn, pos); } @Override @@ -52,6 +47,13 @@ public class EncasedFanBlock extends DirectionalKineticBlock implements IWithTil context.isPlacerSneaking() ? preferredFacing : preferredFacing.getOpposite()); } + protected void blockUpdate(BlockState state, World worldIn, BlockPos pos) { + notifyFanTile(worldIn, pos); + if (worldIn.isRemote || state.get(FACING) != Direction.DOWN) + return; + withTileEntityDo(worldIn, pos, EncasedFanTileEntity::updateGenerator); + } + protected void notifyFanTile(IWorld world, BlockPos pos) { withTileEntityDo(world, pos, EncasedFanTileEntity::blockInFrontChanged); } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/fan/EncasedFanTileEntity.java b/src/main/java/com/simibubi/create/modules/contraptions/components/fan/EncasedFanTileEntity.java index 10bc63a47..c97fdb3ce 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/components/fan/EncasedFanTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/fan/EncasedFanTileEntity.java @@ -84,8 +84,8 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity { } @Override - public void onSpeedChanged() { - super.onSpeedChanged(); + public void onSpeedChanged(float prevSpeed) { + super.onSpeedChanged(prevSpeed); updateAirFlow = true; } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/mixer/MechanicalMixerTileEntity.java b/src/main/java/com/simibubi/create/modules/contraptions/components/mixer/MechanicalMixerTileEntity.java index 76abf4619..3142b852a 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/components/mixer/MechanicalMixerTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/mixer/MechanicalMixerTileEntity.java @@ -60,8 +60,8 @@ public class MechanicalMixerTileEntity extends KineticTileEntity { } @Override - public void onSpeedChanged() { - super.onSpeedChanged(); + public void onSpeedChanged(float prevSpeed) { + super.onSpeedChanged(prevSpeed); checkBasin = true; } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/saw/SawBlock.java b/src/main/java/com/simibubi/create/modules/contraptions/components/saw/SawBlock.java index 3f41608be..d8bbaa93f 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/components/saw/SawBlock.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/saw/SawBlock.java @@ -148,8 +148,8 @@ public class SawBlock extends DirectionalAxisKineticBlock @Override public Vec3d getFilterPosition(BlockState state) { - Vec3d x = new Vec3d(8f / 16f, 12.5f / 16f + 1f/256f, 12.25f / 16f); - Vec3d z = new Vec3d(12.25f / 16f, 12.5f / 16f + 1f/256f, 8f / 16f); + Vec3d x = new Vec3d(8f / 16f, 12.5f / 16f + 1f / 256f, 12.25f / 16f); + Vec3d z = new Vec3d(12.25f / 16f, 12.5f / 16f + 1f / 256f, 8f / 16f); return state.get(AXIS_ALONG_FIRST_COORDINATE) ? z : x; } @@ -157,7 +157,7 @@ public class SawBlock extends DirectionalAxisKineticBlock public float getFilterAngle(BlockState state) { return 0; } - + @Override public boolean isFilterVisible(BlockState state) { return state.get(FACING) == Direction.UP; diff --git a/src/main/java/com/simibubi/create/modules/contraptions/components/saw/SawTileEntity.java b/src/main/java/com/simibubi/create/modules/contraptions/components/saw/SawTileEntity.java index 33159657b..416014972 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/components/saw/SawTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/components/saw/SawTileEntity.java @@ -6,17 +6,24 @@ import java.util.LinkedList; import java.util.List; import java.util.Random; +import com.google.common.base.Predicates; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllRecipes; import com.simibubi.create.AllTileEntities; +import com.simibubi.create.foundation.utility.BlockHelper; +import com.simibubi.create.foundation.utility.TreeCutter; +import com.simibubi.create.foundation.utility.TreeCutter.Tree; import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.recipe.RecipeConditions; import com.simibubi.create.foundation.utility.recipe.RecipeFinder; -import com.simibubi.create.modules.contraptions.base.KineticTileEntity; +import com.simibubi.create.foundation.utility.recipe.RecipeFinder.StartedSearch; +import com.simibubi.create.foundation.utility.recipe.RecipeFinder.StartedSearch.RecipeStream; +import com.simibubi.create.modules.contraptions.components.actors.BlockBreakingKineticTileEntity; import com.simibubi.create.modules.contraptions.processing.ProcessingInventory; import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity; import com.simibubi.create.modules.logistics.block.IHaveFilter; +import net.minecraft.block.BlockState; import net.minecraft.entity.item.ItemEntity; import net.minecraft.item.BlockItem; import net.minecraft.item.ItemStack; @@ -28,6 +35,7 @@ import net.minecraft.particles.BlockParticleData; import net.minecraft.particles.IParticleData; import net.minecraft.particles.ItemParticleData; import net.minecraft.particles.ParticleTypes; +import net.minecraft.tags.BlockTags; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Direction; import net.minecraft.util.Direction.Axis; @@ -39,7 +47,7 @@ import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; -public class SawTileEntity extends KineticTileEntity implements IHaveFilter { +public class SawTileEntity extends BlockBreakingKineticTileEntity implements IHaveFilter { private static final Object cuttingRecipesKey = new Object(); public ProcessingInventory inventory; @@ -62,8 +70,8 @@ public class SawTileEntity extends KineticTileEntity implements IHaveFilter { } @Override - public void onSpeedChanged() { - super.onSpeedChanged(); + public void onSpeedChanged(float prevSpeed) { + super.onSpeedChanged(prevSpeed); boolean shouldRun = Math.abs(getSpeed()) > 1 / 64f; boolean running = getBlockState().get(RUNNING); if (shouldRun != running) @@ -88,7 +96,10 @@ public class SawTileEntity extends KineticTileEntity implements IHaveFilter { @Override public void tick() { + if (shouldRun() && ticksUntilNextProgress < 0) + destroyNextTick(); super.tick(); + if (!canProcess()) return; if (getSpeed() == 0) @@ -229,7 +240,7 @@ public class SawTileEntity extends KineticTileEntity implements IHaveFilter { float offset = inventory.recipeDuration != 0 ? (float) (inventory.remainingTime) / inventory.recipeDuration : 0; offset -= .5f; world.addParticle(particleData, pos.getX() + -vec.x * offset, pos.getY() + .45f, pos.getZ() + -vec.z * offset, - vec.x * speed, r.nextFloat() * speed, vec.z * speed); + -vec.x * speed, r.nextFloat() * speed, -vec.z * speed); } public Vec3d getItemMovementVec() { @@ -272,11 +283,11 @@ public class SawTileEntity extends KineticTileEntity implements IHaveFilter { } private List> getRecipes() { - return RecipeFinder - .get(cuttingRecipesKey, world, - RecipeConditions.isOfType(IRecipeType.STONECUTTING, AllRecipes.Types.CUTTING)) - .search().filter(RecipeConditions.outputMatchesFilter(filter)) - .filter(RecipeConditions.firstIngredientMatches(inventory.getStackInSlot(0))).asList(); + StartedSearch startedSearch = RecipeFinder.get(cuttingRecipesKey, world, + RecipeConditions.isOfType(IRecipeType.STONECUTTING, AllRecipes.Types.CUTTING)); + RecipeStream> search = startedSearch.search(); + return search.filter(Predicates.and(RecipeConditions.outputMatchesFilter(filter), + RecipeConditions.firstIngredientMatches(inventory.getStackInSlot(0)))); } public void insertItem(ItemEntity entity) { @@ -345,4 +356,41 @@ public class SawTileEntity extends KineticTileEntity implements IHaveFilter { return filter; } + // Block Breaker + + @Override + protected boolean shouldRun() { + return getBlockState().get(SawBlock.FACING).getAxis().isHorizontal(); + } + + @Override + protected BlockPos getBreakingPos() { + return getPos().offset(getBlockState().get(SawBlock.FACING)); + } + + @Override + public void onBlockBroken(BlockState stateToBreak) { + super.onBlockBroken(stateToBreak); + Tree tree = TreeCutter.cutTree(world, breakingPos); + if (tree != null) { + for (BlockPos log : tree.logs) + BlockHelper.destroyBlock(world, log, 1 / 2f, stack -> dropItemFromCutTree(log, stack)); + for (BlockPos leaf : tree.leaves) + BlockHelper.destroyBlock(world, leaf, 1 / 8f, stack -> dropItemFromCutTree(leaf, stack)); + } + } + + public void dropItemFromCutTree(BlockPos pos, ItemStack stack) { + float distance = (float) Math.sqrt(pos.distanceSq(breakingPos)); + Vec3d dropPos = VecHelper.getCenterOf(pos); + ItemEntity entity = new ItemEntity(world, dropPos.x, dropPos.y, dropPos.z, stack); + entity.setMotion(new Vec3d(breakingPos.subtract(this.pos)).scale(distance / 20f)); + world.addEntity(entity); + } + + @Override + public boolean canBreak(BlockState stateToBreak, float blockHardness) { + return super.canBreak(stateToBreak, blockHardness) && stateToBreak.isIn(BlockTags.LOGS); + } + } diff --git a/src/main/java/com/simibubi/create/modules/contraptions/relays/gauge/GaugeTileEntity.java b/src/main/java/com/simibubi/create/modules/contraptions/relays/gauge/GaugeTileEntity.java index 571c31a8b..2bfb65ac1 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/relays/gauge/GaugeTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/relays/gauge/GaugeTileEntity.java @@ -30,12 +30,6 @@ public class GaugeTileEntity extends KineticTileEntity { super.read(compound); } - @Override - public void removeSource() { - super.removeSource(); - dialTarget = 0; - } - @Override public void tick() { super.tick(); diff --git a/src/main/java/com/simibubi/create/modules/contraptions/relays/gauge/SpeedGaugeTileEntity.java b/src/main/java/com/simibubi/create/modules/contraptions/relays/gauge/SpeedGaugeTileEntity.java index 96e2241ca..a2dc93a4f 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/relays/gauge/SpeedGaugeTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/relays/gauge/SpeedGaugeTileEntity.java @@ -14,8 +14,8 @@ public class SpeedGaugeTileEntity extends GaugeTileEntity { } @Override - public void onSpeedChanged() { - super.onSpeedChanged(); + public void onSpeedChanged(float prevSpeed) { + super.onSpeedChanged(prevSpeed); float speed = Math.abs(getSpeed()); float medium = CreateConfig.parameters.mediumSpeed.get().floatValue(); float fast = CreateConfig.parameters.fastSpeed.get().floatValue(); diff --git a/src/main/java/com/simibubi/create/modules/contraptions/relays/gauge/StressGaugeTileEntity.java b/src/main/java/com/simibubi/create/modules/contraptions/relays/gauge/StressGaugeTileEntity.java index 82678d9b7..414b0a9b1 100644 --- a/src/main/java/com/simibubi/create/modules/contraptions/relays/gauge/StressGaugeTileEntity.java +++ b/src/main/java/com/simibubi/create/modules/contraptions/relays/gauge/StressGaugeTileEntity.java @@ -28,8 +28,17 @@ public class StressGaugeTileEntity extends GaugeTileEntity { else color = 0xFF0000; } - + sendData(); } + @Override + public void onSpeedChanged(float prevSpeed) { + super.onSpeedChanged(prevSpeed); + if (getSpeed() == 0) + dialTarget = 0; + else + sync(maxStress, currentStress); + } + } diff --git a/src/main/java/com/simibubi/create/modules/curiosities/deforester/DeforesterItem.java b/src/main/java/com/simibubi/create/modules/curiosities/deforester/DeforesterItem.java index 417440782..1b2dc5bf1 100644 --- a/src/main/java/com/simibubi/create/modules/curiosities/deforester/DeforesterItem.java +++ b/src/main/java/com/simibubi/create/modules/curiosities/deforester/DeforesterItem.java @@ -1,40 +1,63 @@ package com.simibubi.create.modules.curiosities.deforester; +import com.simibubi.create.AllItems; +import com.simibubi.create.foundation.utility.BlockHelper; import com.simibubi.create.foundation.utility.TreeCutter; import com.simibubi.create.foundation.utility.TreeCutter.Tree; import com.simibubi.create.modules.curiosities.tools.AllToolTiers; +import net.minecraft.block.Block; import net.minecraft.block.BlockState; -import net.minecraft.entity.LivingEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.AxeItem; import net.minecraft.item.ItemStack; import net.minecraft.tags.BlockTags; import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IWorld; import net.minecraft.world.World; +import net.minecraftforge.event.world.BlockEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus; +@EventBusSubscriber(bus = Bus.FORGE) public class DeforesterItem extends AxeItem { public DeforesterItem(Properties builder) { super(AllToolTiers.RADIANT, 10.0F, -3.1F, builder); } - @Override - public boolean onBlockDestroyed(ItemStack stack, World worldIn, BlockState state, BlockPos pos, - LivingEntity entityLiving) { + // Moved away from Item#onBlockDestroyed as it does not get called in Creative + public static void destroyTree(ItemStack stack, IWorld worldIn, BlockState state, BlockPos pos, + PlayerEntity player) { + if (!state.isIn(BlockTags.LOGS) || player.isSneaking()) + return; + Tree tree = TreeCutter.cutTree(worldIn, pos); + if (tree == null) + return; + boolean dropBlock = !player.isCreative(); + World world = worldIn.getWorld(); + if (world == null) + return; - if (state.isIn(BlockTags.LOGS) && !entityLiving.isSneaking()) { - Tree tree = TreeCutter.cutTree(worldIn, pos); - if (tree == null) - return super.onBlockDestroyed(stack, worldIn, state, pos, entityLiving); - boolean dropBlock = !(entityLiving instanceof PlayerEntity) || !((PlayerEntity) entityLiving).isCreative(); - for (BlockPos log : tree.logs) - worldIn.destroyBlock(log, dropBlock); - for (BlockPos leaf : tree.leaves) - worldIn.destroyBlock(leaf, dropBlock); - } + for (BlockPos log : tree.logs) + BlockHelper.destroyBlock(world, log, 1 / 2f, item -> { + if (dropBlock) + Block.spawnAsEntity(world, log, item); + }); + for (BlockPos leaf : tree.leaves) + BlockHelper.destroyBlock(world, leaf, 1 / 8f, item -> { + if (dropBlock) + Block.spawnAsEntity(world, leaf, item); + }); + } - return super.onBlockDestroyed(stack, worldIn, state, pos, entityLiving); + @SubscribeEvent + public static void onBlockDestroyed(BlockEvent.BreakEvent event) { + ItemStack heldItemMainhand = event.getPlayer().getHeldItemMainhand(); + if (!AllItems.DEFORESTER.typeOf(heldItemMainhand)) + return; + destroyTree(heldItemMainhand, event.getWorld(), event.getState(), event.getPos(), event.getPlayer()); } } diff --git a/src/main/resources/assets/create/textures/block/bearing_side.png b/src/main/resources/assets/create/textures/block/bearing_side.png index a627b3a15dafd19fb58c2ea25eb21e615f666e00..b34ac3d87fe3bca85426a72ff249faeb51ade295 100644 GIT binary patch delta 495 zcmVkZo8z@zU1eK!pgQsu^@i@ja=1i_@QI4*!&fK~0F&_*D zjIp99%Cb~SK?7QA7;W3;oP!X^f%p6UPN!4Z7;_wl$aFd-0)GoQbdn@eN*>2C0?6;3 z6A`iiRY0%Ts|^3})(NPy5cuKIVMYH3k`WO?fY;gttamq3IkjyI*GlO;mtoMv60F(8 z$tV$itHHI^Xq^B2VVr>9r^o1Ix%uJx=>^T8~HVa|5cHUR{csqw^wfrAWh#((dgAs3f7$nl11~ycL&B zkA~-r^M_O?lf0I>QWr{-@qUyptZv`l-SUI)2isda7>JTJqc(JrRnH926?O`ZhpT=K l`Vp{Z==undr9LvoUIAQK>}C*;mmL5A002ovPDHLkV1fx1?4SSu delta 424 zcmV;Z0ayO61m^>gNq@rt01m?e$8V@)0004eNklsG*>?opuVI;Wh*6&Gh8l_nq6}ylVMx~1Af*(LEZ`tf z6q$rhr?UuH%AeYlX@w7N1||J1C`N=Pv1k&G4v*tRxvm3uQOvR|S@#=yK6f~WC7MLC z9#r|vsa78z?@bWo>FyRNga-@+8!3ZU-WEgcUtR$#_?(&qUbMGP_Ui3zKMZ_AujT?t zMSv#-MluPn!+#gl&NQEX=c&rVRwgCQOQ)(o^Nge+ENjQs#8!qMs_ S$%Z)q00005>~