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
This commit is contained in:
parent
785d77a59d
commit
fca3b74909
26 changed files with 358 additions and 205 deletions
|
@ -20,7 +20,7 @@ archivesBaseName = 'create'
|
||||||
sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.8'
|
sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.8'
|
||||||
|
|
||||||
minecraft {
|
minecraft {
|
||||||
mappings channel: 'snapshot', version: '20191107-1.14.3'
|
mappings channel: 'snapshot', version: '20191130-1.14.3'
|
||||||
|
|
||||||
runs {
|
runs {
|
||||||
client {
|
client {
|
||||||
|
@ -71,7 +71,7 @@ repositories {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
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
|
// 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")
|
compileOnly fg.deobf("mezz.jei:jei-1.14.4:6.0.0.10:api")
|
||||||
|
|
|
@ -1,11 +1,20 @@
|
||||||
package com.simibubi.create.foundation.utility;
|
package com.simibubi.create.foundation.utility;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.fluid.IFluidState;
|
||||||
import net.minecraft.item.Item;
|
import net.minecraft.item.Item;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.state.properties.BlockStateProperties;
|
import net.minecraft.state.properties.BlockStateProperties;
|
||||||
import net.minecraft.state.properties.SlabType;
|
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 {
|
public class BlockHelper {
|
||||||
|
|
||||||
|
@ -61,4 +70,25 @@ public class BlockHelper {
|
||||||
return itemStack;
|
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<ItemStack> 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());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,4 +44,6 @@ public class Debug {
|
||||||
return text + TextFormatting.GRAY + " ...";
|
return text + TextFormatting.GRAY + " ...";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void markTemporary() {};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,8 @@ public class TreeCutter {
|
||||||
// Find all logs
|
// Find all logs
|
||||||
while (!frontier.isEmpty()) {
|
while (!frontier.isEmpty()) {
|
||||||
BlockPos currentPos = frontier.remove(0);
|
BlockPos currentPos = frontier.remove(0);
|
||||||
|
if (visited.contains(currentPos))
|
||||||
|
continue;
|
||||||
visited.add(currentPos);
|
visited.add(currentPos);
|
||||||
|
|
||||||
if (!isLog(reader.getBlockState(currentPos)))
|
if (!isLog(reader.getBlockState(currentPos)))
|
||||||
|
@ -63,6 +65,9 @@ public class TreeCutter {
|
||||||
frontier.addAll(logs);
|
frontier.addAll(logs);
|
||||||
while (!frontier.isEmpty()) {
|
while (!frontier.isEmpty()) {
|
||||||
BlockPos currentPos = frontier.remove(0);
|
BlockPos currentPos = frontier.remove(0);
|
||||||
|
if (!logs.contains(currentPos))
|
||||||
|
if (visited.contains(currentPos))
|
||||||
|
continue;
|
||||||
visited.add(currentPos);
|
visited.add(currentPos);
|
||||||
|
|
||||||
BlockState blockState = reader.getBlockState(currentPos);
|
BlockState blockState = reader.getBlockState(currentPos);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package com.simibubi.create.foundation.utility.recipe;
|
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.ItemStack;
|
||||||
import net.minecraft.item.crafting.IRecipe;
|
import net.minecraft.item.crafting.IRecipe;
|
||||||
|
|
|
@ -51,13 +51,8 @@ public class RecipeFinder {
|
||||||
return (RecipeStream<X>) this;
|
return (RecipeStream<X>) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RecipeStream<R> filter(Predicate<R> condition) {
|
public List<R> filter(Predicate<R> condition) {
|
||||||
stream.filter(condition);
|
return stream.filter(condition).collect(Collectors.toList());
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<R> asList() {
|
|
||||||
return stream.collect(Collectors.toList());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,11 +38,11 @@ public class KineticNetwork {
|
||||||
return;
|
return;
|
||||||
if (te.isSource()) {
|
if (te.isSource()) {
|
||||||
float capacity = te.getAddedStressCapacity();
|
float capacity = te.getAddedStressCapacity();
|
||||||
unloadedStressCapacity -= capacity;
|
unloadedStressCapacity -= capacity * getStressMultiplierForSpeed(te.getGeneratedSpeed());
|
||||||
sources.put(te, capacity);
|
sources.put(te, capacity);
|
||||||
}
|
}
|
||||||
float stressApplied = te.getStressApplied();
|
float stressApplied = te.getStressApplied();
|
||||||
unloadedStress -= stressApplied;
|
unloadedStress -= stressApplied * getStressMultiplierForSpeed(te.speed);
|
||||||
members.put(te, stressApplied);
|
members.put(te, stressApplied);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -176,14 +176,14 @@ public class RotationPropagator {
|
||||||
continue;
|
continue;
|
||||||
if (neighbourTE.hasSource() && neighbourTE.getSource().equals(addedTE.getPos())) {
|
if (neighbourTE.hasSource() && neighbourTE.getSource().equals(addedTE.getPos())) {
|
||||||
addedTE.setSpeed(neighbourTE.speed * speedModifier);
|
addedTE.setSpeed(neighbourTE.speed * speedModifier);
|
||||||
addedTE.onSpeedChanged();
|
addedTE.onSpeedChanged(0);
|
||||||
addedTE.sendData();
|
addedTE.sendData();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
addedTE.setSpeed(neighbourTE.speed * speedModifier);
|
addedTE.setSpeed(neighbourTE.speed * speedModifier);
|
||||||
addedTE.setSource(neighbourTE.getPos());
|
addedTE.setSource(neighbourTE.getPos());
|
||||||
addedTE.onSpeedChanged();
|
addedTE.onSpeedChanged(0);
|
||||||
addedTE.sendData();
|
addedTE.sendData();
|
||||||
propagateNewSource(addedTE);
|
propagateNewSource(addedTE);
|
||||||
return;
|
return;
|
||||||
|
@ -209,7 +209,8 @@ public class RotationPropagator {
|
||||||
&& (newSpeed != 0 && neighbourTE.speed != 0);
|
&& (newSpeed != 0 && neighbourTE.speed != 0);
|
||||||
|
|
||||||
boolean tooFast = Math.abs(newSpeed) > parameters.maxRotationSpeed.get();
|
boolean tooFast = Math.abs(newSpeed) > parameters.maxRotationSpeed.get();
|
||||||
if (tooFast) {
|
boolean speedChangedTooOften = updateTE.speedChangeCounter > 25;
|
||||||
|
if (tooFast || speedChangedTooOften) {
|
||||||
world.destroyBlock(pos, true);
|
world.destroyBlock(pos, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -224,8 +225,9 @@ public class RotationPropagator {
|
||||||
if (Math.abs(oppositeSpeed) > Math.abs(updateTE.speed)) {
|
if (Math.abs(oppositeSpeed) > Math.abs(updateTE.speed)) {
|
||||||
// Neighbour faster, overpower the incoming tree
|
// Neighbour faster, overpower the incoming tree
|
||||||
updateTE.setSource(neighbourTE.getPos());
|
updateTE.setSource(neighbourTE.getPos());
|
||||||
|
float prevSpeed = updateTE.getSpeed();
|
||||||
updateTE.setSpeed(neighbourTE.speed * getRotationSpeedModifier(neighbourTE, updateTE));
|
updateTE.setSpeed(neighbourTE.speed * getRotationSpeedModifier(neighbourTE, updateTE));
|
||||||
updateTE.onSpeedChanged();
|
updateTE.onSpeedChanged(prevSpeed);
|
||||||
updateTE.sendData();
|
updateTE.sendData();
|
||||||
|
|
||||||
propagateNewSource(updateTE);
|
propagateNewSource(updateTE);
|
||||||
|
@ -241,8 +243,9 @@ public class RotationPropagator {
|
||||||
}
|
}
|
||||||
|
|
||||||
neighbourTE.setSource(updateTE.getPos());
|
neighbourTE.setSource(updateTE.getPos());
|
||||||
|
float prevSpeed = neighbourTE.getSpeed();
|
||||||
neighbourTE.setSpeed(updateTE.speed * getRotationSpeedModifier(updateTE, neighbourTE));
|
neighbourTE.setSpeed(updateTE.speed * getRotationSpeedModifier(updateTE, neighbourTE));
|
||||||
neighbourTE.onSpeedChanged();
|
neighbourTE.onSpeedChanged(prevSpeed);
|
||||||
neighbourTE.sendData();
|
neighbourTE.sendData();
|
||||||
propagateNewSource(neighbourTE);
|
propagateNewSource(neighbourTE);
|
||||||
}
|
}
|
||||||
|
@ -253,9 +256,10 @@ public class RotationPropagator {
|
||||||
if (neighbourTE.speed == newSpeed)
|
if (neighbourTE.speed == newSpeed)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
float prevSpeed = neighbourTE.getSpeed();
|
||||||
neighbourTE.setSpeed(newSpeed);
|
neighbourTE.setSpeed(newSpeed);
|
||||||
neighbourTE.setSource(updateTE.getPos());
|
neighbourTE.setSource(updateTE.getPos());
|
||||||
neighbourTE.onSpeedChanged();
|
neighbourTE.onSpeedChanged(prevSpeed);
|
||||||
neighbourTE.sendData();
|
neighbourTE.sendData();
|
||||||
propagateNewSource(neighbourTE);
|
propagateNewSource(neighbourTE);
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ public abstract class GeneratingKineticTileEntity extends KineticTileEntity {
|
||||||
|
|
||||||
public void updateGeneratedRotation() {
|
public void updateGeneratedRotation() {
|
||||||
float speed = getGeneratedSpeed();
|
float speed = getGeneratedSpeed();
|
||||||
|
float prevSpeed = this.speed;
|
||||||
|
|
||||||
if (this.speed != 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().updateStressCapacity();
|
||||||
|
getNetwork().updateStress();
|
||||||
|
}
|
||||||
|
|
||||||
onSpeedChanged();
|
onSpeedChanged(prevSpeed);
|
||||||
sendData();
|
sendData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,8 +64,9 @@ public abstract class KineticTileEntity extends SyncedTileEntity implements ITic
|
||||||
this.currentStress = currentStress;
|
this.currentStress = currentStress;
|
||||||
boolean overStressed = maxStress < currentStress;
|
boolean overStressed = maxStress < currentStress;
|
||||||
if (overStressed != this.overStressed) {
|
if (overStressed != this.overStressed) {
|
||||||
|
float prevSpeed = getSpeed();
|
||||||
this.overStressed = overStressed;
|
this.overStressed = overStressed;
|
||||||
onSpeedChanged();
|
onSpeedChanged(prevSpeed);
|
||||||
sendData();
|
sendData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,9 +96,13 @@ public abstract class KineticTileEntity extends SyncedTileEntity implements ITic
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onSpeedChanged() {
|
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;
|
speedChangeCounter += 5;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void remove() {
|
public void remove() {
|
||||||
|
@ -217,8 +222,9 @@ public abstract class KineticTileEntity extends SyncedTileEntity implements ITic
|
||||||
this.source = Optional.empty();
|
this.source = Optional.empty();
|
||||||
newNetworkID = null;
|
newNetworkID = null;
|
||||||
updateNetwork = true;
|
updateNetwork = true;
|
||||||
|
float prevSpeed = getSpeed();
|
||||||
setSpeed(0);
|
setSpeed(0);
|
||||||
onSpeedChanged();
|
onSpeedChanged(prevSpeed);
|
||||||
}
|
}
|
||||||
|
|
||||||
public KineticNetwork getNetwork() {
|
public KineticNetwork getNetwork() {
|
||||||
|
@ -263,9 +269,6 @@ public abstract class KineticTileEntity extends SyncedTileEntity implements ITic
|
||||||
public void tick() {
|
public void tick() {
|
||||||
if (world.isRemote)
|
if (world.isRemote)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (speedChangeCounter > 25)
|
|
||||||
world.destroyBlock(pos, true);
|
|
||||||
if (speedChangeCounter > 0)
|
if (speedChangeCounter > 0)
|
||||||
speedChangeCounter--;
|
speedChangeCounter--;
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,8 @@ public class KineticTileEntityRenderer extends TileEntityRendererFast<KineticTil
|
||||||
rainbowMode = true;
|
rainbowMode = true;
|
||||||
if (te.hasNetwork())
|
if (te.hasNetwork())
|
||||||
buffer.color(LogisticalActorTileEntity.colorFromUUID(te.getNetworkID()));
|
buffer.color(LogisticalActorTileEntity.colorFromUUID(te.getNetworkID()));
|
||||||
|
else
|
||||||
|
buffer.color(0xFFFFFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
|
|
|
@ -0,0 +1,150 @@
|
||||||
|
package com.simibubi.create.modules.contraptions.components.actors;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
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.item.ItemEntity;
|
||||||
|
import net.minecraft.fluid.IFluidState;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
|
import net.minecraft.nbt.NBTUtil;
|
||||||
|
import net.minecraft.tileentity.TileEntity;
|
||||||
|
import net.minecraft.tileentity.TileEntityType;
|
||||||
|
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 abstract class BlockBreakingKineticTileEntity extends KineticTileEntity {
|
||||||
|
|
||||||
|
private static final AtomicInteger NEXT_BREAKER_ID = new AtomicInteger();
|
||||||
|
protected int ticksUntilNextProgress;
|
||||||
|
protected int destroyProgress;
|
||||||
|
protected int breakerId = -NEXT_BREAKER_ID.incrementAndGet();
|
||||||
|
protected BlockPos breakingPos;
|
||||||
|
|
||||||
|
public BlockBreakingKineticTileEntity(TileEntityType<?> 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,139 +1,21 @@
|
||||||
package com.simibubi.create.modules.contraptions.components.actors;
|
package com.simibubi.create.modules.contraptions.components.actors;
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
|
|
||||||
import com.simibubi.create.AllTileEntities;
|
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.DamageSource;
|
||||||
import net.minecraft.util.math.AxisAlignedBB;
|
|
||||||
import net.minecraft.util.math.BlockPos;
|
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 {
|
public class DrillTileEntity extends BlockBreakingKineticTileEntity {
|
||||||
|
|
||||||
private static final AtomicInteger NEXT_DRILL_ID = new AtomicInteger();
|
|
||||||
|
|
||||||
public static DamageSource damageSourceDrill = new DamageSource("create.drill").setDamageBypassesArmor();
|
public static DamageSource damageSourceDrill = new DamageSource("create.drill").setDamageBypassesArmor();
|
||||||
private int ticksUntilNextProgress;
|
|
||||||
private int destroyProgress;
|
|
||||||
private int drillId = -NEXT_DRILL_ID.incrementAndGet();
|
|
||||||
|
|
||||||
public DrillTileEntity() {
|
public DrillTileEntity() {
|
||||||
super(AllTileEntities.DRILL.type);
|
super(AllTileEntities.DRILL.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSpeedChanged() {
|
protected BlockPos getBreakingPos() {
|
||||||
super.onSpeedChanged();
|
return getPos().offset(getBlockState().get(DrillBlock.FACING));
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
|
||||||
if (!isWindmill && running) {
|
if (!isWindmill && running) {
|
||||||
updateGeneratedRotation();
|
updateGeneratedRotation();
|
||||||
if (getSpeed() == 0)
|
if (getSpeed() == 0)
|
||||||
disassembleConstruct();
|
assembleNextTick = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
sendData();
|
sendData();
|
||||||
|
@ -89,8 +89,8 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSpeedChanged() {
|
public void onSpeedChanged(float prevSpeed) {
|
||||||
super.onSpeedChanged();
|
super.onSpeedChanged(prevSpeed);
|
||||||
assembleNextTick = true;
|
assembleNextTick = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,8 +30,8 @@ public class MechanicalPistonTileEntity extends KineticTileEntity implements ICo
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSpeedChanged() {
|
public void onSpeedChanged(float prevSpeed) {
|
||||||
super.onSpeedChanged();
|
super.onSpeedChanged(prevSpeed);
|
||||||
assembleNextTick = true;
|
assembleNextTick = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,8 +13,8 @@ public class CrushingWheelTileEntity extends KineticTileEntity {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSpeedChanged() {
|
public void onSpeedChanged(float prevSpeed) {
|
||||||
super.onSpeedChanged();
|
super.onSpeedChanged(prevSpeed);
|
||||||
for (Direction d : Direction.values())
|
for (Direction d : Direction.values())
|
||||||
((CrushingWheelBlock) getBlockState().getBlock()).updateControllers(getBlockState(), getWorld(), getPos(),
|
((CrushingWheelBlock) getBlockState().getBlock()).updateControllers(getBlockState(), getWorld(), getPos(),
|
||||||
d);
|
d);
|
||||||
|
|
|
@ -29,18 +29,13 @@ public class EncasedFanBlock extends DirectionalKineticBlock implements IWithTil
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBlockAdded(BlockState state, World worldIn, BlockPos pos, BlockState oldState, boolean isMoving) {
|
public void onBlockAdded(BlockState state, World worldIn, BlockPos pos, BlockState oldState, boolean isMoving) {
|
||||||
notifyFanTile(worldIn, pos);
|
blockUpdate(state, worldIn, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void neighborChanged(BlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos,
|
public void neighborChanged(BlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos,
|
||||||
boolean isMoving) {
|
boolean isMoving) {
|
||||||
notifyFanTile(worldIn, pos);
|
blockUpdate(state, worldIn, pos);
|
||||||
|
|
||||||
if (worldIn.isRemote || getRotationAxis(state).isHorizontal())
|
|
||||||
return;
|
|
||||||
|
|
||||||
withTileEntityDo(worldIn, pos, EncasedFanTileEntity::updateGenerator);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -52,6 +47,13 @@ public class EncasedFanBlock extends DirectionalKineticBlock implements IWithTil
|
||||||
context.isPlacerSneaking() ? preferredFacing : preferredFacing.getOpposite());
|
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) {
|
protected void notifyFanTile(IWorld world, BlockPos pos) {
|
||||||
withTileEntityDo(world, pos, EncasedFanTileEntity::blockInFrontChanged);
|
withTileEntityDo(world, pos, EncasedFanTileEntity::blockInFrontChanged);
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,8 +84,8 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSpeedChanged() {
|
public void onSpeedChanged(float prevSpeed) {
|
||||||
super.onSpeedChanged();
|
super.onSpeedChanged(prevSpeed);
|
||||||
updateAirFlow = true;
|
updateAirFlow = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,8 +60,8 @@ public class MechanicalMixerTileEntity extends KineticTileEntity {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSpeedChanged() {
|
public void onSpeedChanged(float prevSpeed) {
|
||||||
super.onSpeedChanged();
|
super.onSpeedChanged(prevSpeed);
|
||||||
checkBasin = true;
|
checkBasin = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,17 +6,24 @@ import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicates;
|
||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.AllBlocks;
|
||||||
import com.simibubi.create.AllRecipes;
|
import com.simibubi.create.AllRecipes;
|
||||||
import com.simibubi.create.AllTileEntities;
|
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.VecHelper;
|
||||||
import com.simibubi.create.foundation.utility.recipe.RecipeConditions;
|
import com.simibubi.create.foundation.utility.recipe.RecipeConditions;
|
||||||
import com.simibubi.create.foundation.utility.recipe.RecipeFinder;
|
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.processing.ProcessingInventory;
|
||||||
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
|
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
|
||||||
import com.simibubi.create.modules.logistics.block.IHaveFilter;
|
import com.simibubi.create.modules.logistics.block.IHaveFilter;
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.entity.item.ItemEntity;
|
import net.minecraft.entity.item.ItemEntity;
|
||||||
import net.minecraft.item.BlockItem;
|
import net.minecraft.item.BlockItem;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
|
@ -28,6 +35,7 @@ import net.minecraft.particles.BlockParticleData;
|
||||||
import net.minecraft.particles.IParticleData;
|
import net.minecraft.particles.IParticleData;
|
||||||
import net.minecraft.particles.ItemParticleData;
|
import net.minecraft.particles.ItemParticleData;
|
||||||
import net.minecraft.particles.ParticleTypes;
|
import net.minecraft.particles.ParticleTypes;
|
||||||
|
import net.minecraft.tags.BlockTags;
|
||||||
import net.minecraft.tileentity.TileEntity;
|
import net.minecraft.tileentity.TileEntity;
|
||||||
import net.minecraft.util.Direction;
|
import net.minecraft.util.Direction;
|
||||||
import net.minecraft.util.Direction.Axis;
|
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.CapabilityItemHandler;
|
||||||
import net.minecraftforge.items.IItemHandler;
|
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();
|
private static final Object cuttingRecipesKey = new Object();
|
||||||
public ProcessingInventory inventory;
|
public ProcessingInventory inventory;
|
||||||
|
@ -62,8 +70,8 @@ public class SawTileEntity extends KineticTileEntity implements IHaveFilter {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSpeedChanged() {
|
public void onSpeedChanged(float prevSpeed) {
|
||||||
super.onSpeedChanged();
|
super.onSpeedChanged(prevSpeed);
|
||||||
boolean shouldRun = Math.abs(getSpeed()) > 1 / 64f;
|
boolean shouldRun = Math.abs(getSpeed()) > 1 / 64f;
|
||||||
boolean running = getBlockState().get(RUNNING);
|
boolean running = getBlockState().get(RUNNING);
|
||||||
if (shouldRun != running)
|
if (shouldRun != running)
|
||||||
|
@ -88,7 +96,10 @@ public class SawTileEntity extends KineticTileEntity implements IHaveFilter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick() {
|
public void tick() {
|
||||||
|
if (shouldRun() && ticksUntilNextProgress < 0)
|
||||||
|
destroyNextTick();
|
||||||
super.tick();
|
super.tick();
|
||||||
|
|
||||||
if (!canProcess())
|
if (!canProcess())
|
||||||
return;
|
return;
|
||||||
if (getSpeed() == 0)
|
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;
|
float offset = inventory.recipeDuration != 0 ? (float) (inventory.remainingTime) / inventory.recipeDuration : 0;
|
||||||
offset -= .5f;
|
offset -= .5f;
|
||||||
world.addParticle(particleData, pos.getX() + -vec.x * offset, pos.getY() + .45f, pos.getZ() + -vec.z * offset,
|
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() {
|
public Vec3d getItemMovementVec() {
|
||||||
|
@ -272,11 +283,11 @@ public class SawTileEntity extends KineticTileEntity implements IHaveFilter {
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<? extends IRecipe<?>> getRecipes() {
|
private List<? extends IRecipe<?>> getRecipes() {
|
||||||
return RecipeFinder
|
StartedSearch startedSearch = RecipeFinder.get(cuttingRecipesKey, world,
|
||||||
.get(cuttingRecipesKey, world,
|
RecipeConditions.isOfType(IRecipeType.STONECUTTING, AllRecipes.Types.CUTTING));
|
||||||
RecipeConditions.isOfType(IRecipeType.STONECUTTING, AllRecipes.Types.CUTTING))
|
RecipeStream<IRecipe<?>> search = startedSearch.search();
|
||||||
.search().filter(RecipeConditions.outputMatchesFilter(filter))
|
return search.filter(Predicates.and(RecipeConditions.outputMatchesFilter(filter),
|
||||||
.filter(RecipeConditions.firstIngredientMatches(inventory.getStackInSlot(0))).asList();
|
RecipeConditions.firstIngredientMatches(inventory.getStackInSlot(0))));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void insertItem(ItemEntity entity) {
|
public void insertItem(ItemEntity entity) {
|
||||||
|
@ -345,4 +356,41 @@ public class SawTileEntity extends KineticTileEntity implements IHaveFilter {
|
||||||
return filter;
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,12 +30,6 @@ public class GaugeTileEntity extends KineticTileEntity {
|
||||||
super.read(compound);
|
super.read(compound);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removeSource() {
|
|
||||||
super.removeSource();
|
|
||||||
dialTarget = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick() {
|
public void tick() {
|
||||||
super.tick();
|
super.tick();
|
||||||
|
|
|
@ -14,8 +14,8 @@ public class SpeedGaugeTileEntity extends GaugeTileEntity {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSpeedChanged() {
|
public void onSpeedChanged(float prevSpeed) {
|
||||||
super.onSpeedChanged();
|
super.onSpeedChanged(prevSpeed);
|
||||||
float speed = Math.abs(getSpeed());
|
float speed = Math.abs(getSpeed());
|
||||||
float medium = CreateConfig.parameters.mediumSpeed.get().floatValue();
|
float medium = CreateConfig.parameters.mediumSpeed.get().floatValue();
|
||||||
float fast = CreateConfig.parameters.fastSpeed.get().floatValue();
|
float fast = CreateConfig.parameters.fastSpeed.get().floatValue();
|
||||||
|
|
|
@ -32,4 +32,13 @@ public class StressGaugeTileEntity extends GaugeTileEntity {
|
||||||
sendData();
|
sendData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSpeedChanged(float prevSpeed) {
|
||||||
|
super.onSpeedChanged(prevSpeed);
|
||||||
|
if (getSpeed() == 0)
|
||||||
|
dialTarget = 0;
|
||||||
|
else
|
||||||
|
sync(maxStress, currentStress);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,40 +1,63 @@
|
||||||
package com.simibubi.create.modules.curiosities.deforester;
|
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;
|
||||||
import com.simibubi.create.foundation.utility.TreeCutter.Tree;
|
import com.simibubi.create.foundation.utility.TreeCutter.Tree;
|
||||||
import com.simibubi.create.modules.curiosities.tools.AllToolTiers;
|
import com.simibubi.create.modules.curiosities.tools.AllToolTiers;
|
||||||
|
|
||||||
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.entity.LivingEntity;
|
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.item.AxeItem;
|
import net.minecraft.item.AxeItem;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.tags.BlockTags;
|
import net.minecraft.tags.BlockTags;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.world.IWorld;
|
||||||
import net.minecraft.world.World;
|
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 class DeforesterItem extends AxeItem {
|
||||||
|
|
||||||
public DeforesterItem(Properties builder) {
|
public DeforesterItem(Properties builder) {
|
||||||
super(AllToolTiers.RADIANT, 10.0F, -3.1F, builder);
|
super(AllToolTiers.RADIANT, 10.0F, -3.1F, builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
// Moved away from Item#onBlockDestroyed as it does not get called in Creative
|
||||||
public boolean onBlockDestroyed(ItemStack stack, World worldIn, BlockState state, BlockPos pos,
|
public static void destroyTree(ItemStack stack, IWorld worldIn, BlockState state, BlockPos pos,
|
||||||
LivingEntity entityLiving) {
|
PlayerEntity player) {
|
||||||
|
if (!state.isIn(BlockTags.LOGS) || player.isSneaking())
|
||||||
if (state.isIn(BlockTags.LOGS) && !entityLiving.isSneaking()) {
|
return;
|
||||||
Tree tree = TreeCutter.cutTree(worldIn, pos);
|
Tree tree = TreeCutter.cutTree(worldIn, pos);
|
||||||
if (tree == null)
|
if (tree == null)
|
||||||
return super.onBlockDestroyed(stack, worldIn, state, pos, entityLiving);
|
return;
|
||||||
boolean dropBlock = !(entityLiving instanceof PlayerEntity) || !((PlayerEntity) entityLiving).isCreative();
|
boolean dropBlock = !player.isCreative();
|
||||||
|
World world = worldIn.getWorld();
|
||||||
|
if (world == null)
|
||||||
|
return;
|
||||||
|
|
||||||
for (BlockPos log : tree.logs)
|
for (BlockPos log : tree.logs)
|
||||||
worldIn.destroyBlock(log, dropBlock);
|
BlockHelper.destroyBlock(world, log, 1 / 2f, item -> {
|
||||||
|
if (dropBlock)
|
||||||
|
Block.spawnAsEntity(world, log, item);
|
||||||
|
});
|
||||||
for (BlockPos leaf : tree.leaves)
|
for (BlockPos leaf : tree.leaves)
|
||||||
worldIn.destroyBlock(leaf, dropBlock);
|
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());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 487 B After Width: | Height: | Size: 558 B |
Loading…
Reference in a new issue