Ender Chutes are real

- Fixed chutes directly between two inventories transferring items instantly
- Fixed jittering visuals of the clientside chute item near containers
- Rail blocks can now be picked up with a wrench
This commit is contained in:
simibubi 2021-07-03 15:37:07 +02:00
parent 7264d838a0
commit 8a598a699b
2 changed files with 52 additions and 17 deletions

View file

@ -3,7 +3,11 @@ package com.simibubi.create.content.contraptions.wrench;
import javax.annotation.Nonnull;
import com.simibubi.create.AllItems;
import com.simibubi.create.AllSoundEvents;
import com.simibubi.create.Create;
import net.minecraft.block.AbstractRailBlock;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.minecart.AbstractMinecartEntity;
@ -13,6 +17,9 @@ import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUseContext;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.DamageSource;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.server.ServerWorld;
import net.minecraftforge.event.entity.player.AttackEntityEvent;
public class WrenchItem extends Item {
@ -30,15 +37,40 @@ public class WrenchItem extends Item {
BlockState state = context.getWorld()
.getBlockState(context.getPos());
if (!(state.getBlock() instanceof IWrenchable))
return super.onItemUse(context);
IWrenchable actor = (IWrenchable) state.getBlock();
Block block = state.getBlock();
if (!(block instanceof IWrenchable)) {
if (canWrenchPickup(state))
return onItemUseOnOther(context);
return super.onItemUse(context);
}
IWrenchable actor = (IWrenchable) block;
if (player.isSneaking())
return actor.onSneakWrenched(state, context);
return actor.onWrenched(state, context);
}
private boolean canWrenchPickup(BlockState state) {
return state.getBlock() instanceof AbstractRailBlock;
}
private ActionResultType onItemUseOnOther(ItemUseContext context) {
PlayerEntity player = context.getPlayer();
World world = context.getWorld();
BlockPos pos = context.getPos();
BlockState state = world.getBlockState(pos);
if (!(world instanceof ServerWorld))
return ActionResultType.SUCCESS;
if (player != null && !player.isCreative())
Block.getDrops(state, (ServerWorld) world, pos, world.getTileEntity(pos), player, context.getItem())
.forEach(itemStack -> player.inventory.placeItemBackInInventory(world, itemStack));
state.spawnAdditionalDrops((ServerWorld) world, pos, ItemStack.EMPTY);
world.destroyBlock(pos, false);
AllSoundEvents.WRENCH_REMOVE.playOnServer(world, pos, 1, Create.RANDOM.nextFloat() * .5f + .5f);
return ActionResultType.SUCCESS;
}
public static void wrenchInstaKillsMinecarts(AttackEntityEvent event) {
Entity target = event.getTarget();
if (!(target instanceof AbstractMinecartEntity))
@ -52,5 +84,5 @@ public class WrenchItem extends Item {
AbstractMinecartEntity minecart = (AbstractMinecartEntity) target;
minecart.attackEntityFrom(DamageSource.causePlayerDamage(player), 100);
}
}

View file

@ -159,18 +159,16 @@ public class ChuteTileEntity extends SmartTileEntity implements IHaveGoggleInfor
nextOffset = .5f;
else if (nextOffset < 0) {
handleDownwardOutput(world.isRemote && !isVirtual());
return;
nextOffset = itemPosition.value;
}
}
}
if (itemMotion > 0) {
} else if (itemMotion > 0) {
if (nextOffset > .5f) {
if (!handleUpwardOutput(true))
nextOffset = .5f;
else if (nextOffset > 1) {
handleUpwardOutput(world.isRemote && !isVirtual());
return;
nextOffset = itemPosition.value;
}
}
}
@ -317,7 +315,7 @@ public class ChuteTileEntity extends SmartTileEntity implements IHaveGoggleInfor
float zOff = Create.RANDOM.nextFloat() * .5f + .25f;
Vector3d v = origin.add(xOff, verticalStart, zOff);
Vector3d d = origin.add(xOff, verticalEnd, zOff)
.subtract(v);
.subtract(v);
if (Create.RANDOM.nextFloat() < 2 * motion)
world.addOptionalParticle(airParticleData, v.x, v.y, v.z, d.x, d.y, d.z);
}
@ -325,25 +323,26 @@ public class ChuteTileEntity extends SmartTileEntity implements IHaveGoggleInfor
private void handleInputFromAbove() {
if (!capAbove.isPresent())
capAbove = grabCapability(Direction.UP);
handleInput(capAbove.orElse(null));
handleInput(capAbove.orElse(null), 1);
}
private void handleInputFromBelow() {
if (!capBelow.isPresent())
capBelow = grabCapability(Direction.DOWN);
handleInput(capBelow.orElse(null));
handleInput(capBelow.orElse(null), 0);
}
private void handleInput(IItemHandler inv) {
private void handleInput(IItemHandler inv, float startLocation) {
if (inv == null)
return;
Predicate<ItemStack> canAccept = this::canAcceptItem;
int count = getExtractionAmount();
ExtractionCountMode mode = getExtractionMode();
if (mode == ExtractionCountMode.UPTO || !ItemHelper.extract(inv, canAccept, mode, count, true)
.isEmpty())
item = ItemHelper.extract(inv, canAccept, mode, count, false);
.isEmpty()) {
ItemStack extracted = ItemHelper.extract(inv, canAccept, mode, count, false);
setItem(extracted, startLocation);
}
}
private boolean handleDownwardOutput(boolean simulate) {
@ -356,6 +355,8 @@ public class ChuteTileEntity extends SmartTileEntity implements IHaveGoggleInfor
if (!capBelow.isPresent())
capBelow = grabCapability(Direction.DOWN);
if (capBelow.isPresent()) {
if (world.isRemote && !isVirtual())
return false;
ItemStack remainder = ItemHandlerHelper.insertItemStacked(capBelow.orElse(null), item, simulate);
ItemStack held = getItem();
if (!simulate)
@ -408,6 +409,8 @@ public class ChuteTileEntity extends SmartTileEntity implements IHaveGoggleInfor
if (!capAbove.isPresent())
capAbove = grabCapability(Direction.UP);
if (capAbove.isPresent()) {
if (world.isRemote && !isVirtual() && !ChuteBlock.isChute(stateAbove))
return false;
int countBefore = item.getCount();
ItemStack remainder = ItemHandlerHelper.insertItemStacked(capAbove.orElse(null), item, simulate);
if (!simulate)