Smelty on the Belty returns

- Encased fans now work on the "fake items" moving on the belt
- Chunk no longer redraws when TEs send data. (May break stuff)
- Regular fan particles are less noisy
- Items no longer spazz out when the belt is stopped
- Fixed extractors waiting indefinitely if belt is occupied
This commit is contained in:
simibubi 2019-11-20 22:50:19 +01:00
parent e742149c8d
commit 55818d33fa
19 changed files with 418 additions and 219 deletions

View file

@ -28,9 +28,9 @@ public abstract class SyncedTileEntity extends TileEntity {
}
public void sendData() {
world.notifyBlockUpdate(getPos(), getBlockState(), getBlockState(), 2 | 16);
world.notifyBlockUpdate(getPos(), getBlockState(), getBlockState(), 2 | 4 | 16);
}
public void causeBlockUpdate() {
world.notifyBlockUpdate(getPos(), getBlockState(), getBlockState(), 1);
}

View file

@ -0,0 +1,71 @@
package com.simibubi.create.modules.contraptions.receivers;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.modules.logistics.InWorldProcessing;
import com.simibubi.create.modules.logistics.InWorldProcessing.Type;
import net.minecraft.particles.ParticleTypes;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
public class EncasedFanBeltHandler {
// Fans need to be aware of belt TEs within their range
// all belts are handled equally
// requires ref to controller and index
static List<BeltTileEntity> findBelts(EncasedFanTileEntity fan) {
if (fan.getSpeed() == 0)
return Collections.emptyList();
List<BeltTileEntity> belts = new ArrayList<>();
AxisAlignedBB searchBB = fan.frontBB.shrink(.25).contract(0, 0, 0).expand(0, -.25f, 0);
BlockPos.getAllInBox((int) searchBB.minX, (int) searchBB.minY, (int) searchBB.minZ, (int) searchBB.maxX - 1,
(int) searchBB.maxY - 1, (int) searchBB.maxZ - 1)
.filter(p -> AllBlocks.BELT.typeOf(fan.getWorld().getBlockState(p))).forEach(p -> {
TileEntity te = fan.getWorld().getTileEntity(p);
if (te == null || !(te instanceof BeltTileEntity))
return;
belts.add((BeltTileEntity) te);
});
return belts;
}
static void tickBelts(EncasedFanTileEntity fan, List<BeltTileEntity> belts) {
Type processingType = fan.getProcessingType();
if (processingType == null)
return;
for (BeltTileEntity belt : belts) {
BeltTileEntity controller = belt.getControllerTE();
if (controller == null)
continue;
World world = belt.getWorld();
controller.getInventory().forEachWithin(belt.index + .5f, .5f, (transported) -> {
if (world.rand.nextInt(4) == 0 && world.isRemote) {
Vec3d vec = controller.getInventory().getVectorForOffset(transported.beltPosition);
if (processingType == Type.BLASTING)
world.addParticle(ParticleTypes.LARGE_SMOKE, vec.x, vec.y + .25f, vec.z, 0, 1 / 16f, 0);
if (processingType == Type.SMOKING)
world.addParticle(ParticleTypes.CLOUD, vec.x, vec.y + .25f, vec.z, 0, 1 / 16f, 0);
if (processingType == Type.SPLASHING)
world.addParticle(ParticleTypes.BUBBLE_POP, vec.x + (world.rand.nextFloat() - .5f) * .5f,
vec.y + .25f, vec.z + (world.rand.nextFloat() - .5f) * .5f, 0, 1 / 16f, 0);
}
if (world.isRemote)
return null;
return InWorldProcessing.applyProcessing(transported, belt, processingType);
});
}
}
}

View file

@ -26,7 +26,7 @@ public class EncasedFanParticleHandler {
private void initEffects() {
List<FanEffect> standardFX = new ArrayList<>(2);
standardFX.add(new FanEffect(ParticleTypes.BUBBLE_POP, 1 / 4f, 1 / 4f, 1 / 3f, 1));
standardFX.add(new FanEffect(ParticleTypes.BUBBLE_POP, 1 / 4f, 1 / 4f, 1 / 8f, 1));
standardFX.add(new FanEffect(new RedstoneParticleData(1, 1, 1, 1), 1 / 2f, 1 / 32f, 1/16f, 512f));
effects.put(Blocks.AIR, standardFX);

View file

@ -5,6 +5,7 @@ import static net.minecraft.state.properties.BlockStateProperties.AXIS;
import static net.minecraft.util.Direction.AxisDirection.NEGATIVE;
import static net.minecraft.util.Direction.AxisDirection.POSITIVE;
import java.util.Collections;
import java.util.List;
import com.simibubi.create.AllBlockTags;
@ -14,6 +15,7 @@ import com.simibubi.create.CreateClient;
import com.simibubi.create.CreateConfig;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.base.GeneratingKineticTileEntity;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.modules.logistics.InWorldProcessing;
import com.simibubi.create.modules.logistics.InWorldProcessing.Type;
@ -51,6 +53,7 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity {
protected boolean findFrontBlock;
protected BlockState frontBlock;
protected boolean isGenerator;
protected List<BeltTileEntity> affectedBelts = Collections.emptyList();
public EncasedFanTileEntity() {
super(AllTileEntities.ENCASED_FAN.type);
@ -67,6 +70,7 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity {
super.readClientUpdate(tag);
updateFrontBlock();
updateBBs();
affectedBelts = EncasedFanBeltHandler.findBelts(this);
}
@Override
@ -140,6 +144,7 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity {
backBB = new AxisAlignedBB(0, 0, 0, 0, 0, 0);
}
affectedBelts = EncasedFanBeltHandler.findBelts(this);
sendData();
}
@ -190,6 +195,8 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity {
if (getSpeed() == 0 || isGenerator)
return;
EncasedFanBeltHandler.tickBelts(this, affectedBelts);
List<Entity> frontEntities = world.getEntitiesWithinAABBExcludingEntity(null, frontBB);
for (Entity entity : frontEntities) {
moveEntity(entity, true);
@ -238,7 +245,7 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity {
return;
if (canProcess((ItemEntity) entity))
InWorldProcessing.process((ItemEntity) entity, getProcessingType());
InWorldProcessing.applyProcessing((ItemEntity) entity, getProcessingType());
} else {
if (getProcessingType() == Type.SMOKING) {

View file

@ -13,9 +13,9 @@ import com.simibubi.create.modules.contraptions.base.HorizontalKineticBlock;
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.BeltAttachmentState;
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.IBeltAttachment;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
import com.simibubi.create.modules.contraptions.relays.belt.BeltInventory.TransportedItemStack;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.modules.contraptions.relays.belt.TransportedItemStack;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;

View file

@ -6,8 +6,8 @@ import com.simibubi.create.AllRecipes;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
import com.simibubi.create.modules.contraptions.relays.belt.BeltInventory.TransportedItemStack;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.modules.contraptions.relays.belt.TransportedItemStack;
import com.simibubi.create.modules.logistics.InWorldProcessing;
import net.minecraft.entity.Entity;

View file

@ -6,7 +6,6 @@ import java.util.function.Consumer;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.Create;
import com.simibubi.create.modules.contraptions.relays.belt.BeltInventory.TransportedItemStack;
import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity;

View file

@ -1,6 +1,6 @@
package com.simibubi.create.modules.contraptions.relays.belt;
import java.util.Iterator;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
@ -10,7 +10,6 @@ import com.simibubi.create.foundation.block.IWithTileEntity;
import com.simibubi.create.foundation.block.IWithoutBlockItem;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.modules.contraptions.base.HorizontalKineticBlock;
import com.simibubi.create.modules.contraptions.relays.belt.BeltInventory.TransportedItemStack;
import com.simibubi.create.modules.contraptions.relays.belt.BeltMovementHandler.TransportedEntityInfo;
import net.minecraft.block.Block;
@ -91,7 +90,7 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt
public boolean isFlammable(BlockState state, IBlockReader world, BlockPos pos, Direction face) {
return false;
}
@Override
public void onLanded(IBlockReader worldIn, Entity entityIn) {
super.onLanded(worldIn, entityIn);
@ -187,22 +186,15 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt
BeltTileEntity belt = (BeltTileEntity) te;
if (isHand) {
TileEntity controllerTe = worldIn.getTileEntity(belt.getController());
if (controllerTe == null || !(controllerTe instanceof BeltTileEntity))
BeltTileEntity controllerBelt = belt.getControllerTE();
if (controllerBelt == null)
return false;
if (worldIn.isRemote)
return true;
BeltTileEntity controllerBelt = (BeltTileEntity) controllerTe;
for (Iterator<TransportedItemStack> iterator = controllerBelt.getInventory().items.iterator(); iterator
.hasNext();) {
TransportedItemStack transportedItemStack = iterator.next();
if (Math.abs(belt.index + .5 - transportedItemStack.beltPosition) < .75f) {
player.inventory.placeItemBackInInventory(worldIn, transportedItemStack.stack);
iterator.remove();
controllerBelt.markDirty();
controllerBelt.sendData();
}
}
controllerBelt.getInventory().forEachWithin(belt.index, .75f, (transportedItemStack) -> {
player.inventory.placeItemBackInInventory(worldIn, transportedItemStack.stack);
return Collections.emptyList();
});
}
if (isShaft) {

View file

@ -1,10 +1,11 @@
package com.simibubi.create.modules.contraptions.relays.belt;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.function.Function;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.utility.VecHelper;
@ -122,13 +123,14 @@ public class BeltInventory {
int upcomingSegment = (int) (current.beltPosition + (beltMovementPositive ? .5f : -.5f));
for (int segment = upcomingSegment; beltMovementPositive
? segment + .5f <= current.beltPosition + limitedMovement
: segment + .5f >= current.beltPosition + limitedMovement; segment += beltMovementPositive ? 1 : -1) {
: segment + .5f >= current.beltPosition + limitedMovement; segment += beltMovementPositive ? 1
: -1) {
BeltTileEntity beltSegment = getBeltSegment(segmentBefore);
if (beltSegment == null)
break;
for (BeltAttachmentState attachmentState : beltSegment.attachmentTracker.attachments) {
if (attachmentState.attachment.startProcessingItem(beltSegment, current, attachmentState)) {
current.beltPosition += (segment + .5f) - current.beltPosition;
current.beltPosition = segment + .5f + (beltMovementPositive ? 1 / 64f : -1 / 64f);
current.locked = true;
belt.sendData();
continue Items;
@ -230,63 +232,6 @@ public class BeltInventory {
}
public static class TransportedItemStack implements Comparable<TransportedItemStack> {
public ItemStack stack;
public float beltPosition;
public float sideOffset;
public int angle;
public int insertedAt;
public Direction insertedFrom;
public boolean locked;
public float prevBeltPosition;
public float prevSideOffset;
public TransportedItemStack(ItemStack stack) {
this.stack = stack;
angle = new Random().nextInt(360);
sideOffset = prevSideOffset = getTargetSideOffset();
insertedFrom = Direction.UP;
}
public float getTargetSideOffset() {
return (angle - 180) / (360 * 3f);
}
@Override
public int compareTo(TransportedItemStack o) {
return beltPosition < o.beltPosition ? 1 : beltPosition > o.beltPosition ? -1 : 0;
}
public CompoundNBT serializeNBT() {
CompoundNBT nbt = new CompoundNBT();
nbt.put("Item", stack.serializeNBT());
nbt.putFloat("Pos", beltPosition);
nbt.putFloat("PrevPos", prevBeltPosition);
nbt.putFloat("Offset", sideOffset);
nbt.putFloat("PrevOffset", prevSideOffset);
nbt.putInt("InSegment", insertedAt);
nbt.putInt("Angle", angle);
nbt.putInt("InDirection", insertedFrom.getIndex());
nbt.putBoolean("Locked", locked);
return nbt;
}
public static TransportedItemStack read(CompoundNBT nbt) {
TransportedItemStack stack = new TransportedItemStack(ItemStack.read(nbt.getCompound("Item")));
stack.beltPosition = nbt.getFloat("Pos");
stack.prevBeltPosition = nbt.getFloat("PrevPos");
stack.sideOffset = nbt.getFloat("Offset");
stack.prevSideOffset = nbt.getFloat("PrevOffset");
stack.insertedAt = nbt.getInt("InSegment");
stack.angle = nbt.getInt("Angle");
stack.insertedFrom = Direction.byIndex(nbt.getInt("InDirection"));
stack.locked = nbt.getBoolean("Locked");
return stack;
}
}
public boolean canInsertAt(int segment) {
return canInsertFrom(segment, Direction.UP);
}
@ -328,9 +273,6 @@ public class BeltInventory {
}
items.add(index, newStack);
}
belt.markDirty();
belt.sendData();
}
public TransportedItemStack getStackAtOffset(int offset) {
@ -373,7 +315,7 @@ public class BeltInventory {
belt.getWorld().addEntity(entity);
}
private Vec3d getVectorForOffset(float offset) {
public Vec3d getVectorForOffset(float offset) {
Slope slope = belt.getBlockState().get(BeltBlock.SLOPE);
int verticality = slope == Slope.DOWNWARD ? -1 : slope == Slope.UPWARD ? 1 : 0;
float verticalMovement = verticality;
@ -409,70 +351,30 @@ public class BeltInventory {
return belt.getDirectionAwareBeltMovementSpeed() > 0;
}
public class ItemHandlerSegment implements IItemHandler {
int offset;
public ItemHandlerSegment(int offset) {
this.offset = offset;
}
@Override
public int getSlots() {
return 1;
}
@Override
public ItemStack getStackInSlot(int slot) {
TransportedItemStack stackAtOffset = getStackAtOffset(offset);
if (stackAtOffset == null)
return ItemStack.EMPTY;
return stackAtOffset.stack;
}
@Override
public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) {
if (canInsertAt(offset)) {
if (!simulate) {
TransportedItemStack newStack = new TransportedItemStack(stack);
newStack.insertedAt = offset;
newStack.beltPosition = offset + .5f;
newStack.prevBeltPosition = newStack.beltPosition;
insert(newStack);
}
return ItemStack.EMPTY;
}
return stack;
}
@Override
public ItemStack extractItem(int slot, int amount, boolean simulate) {
TransportedItemStack transported = getStackAtOffset(offset);
if (transported == null)
return ItemStack.EMPTY;
amount = Math.min(amount, transported.stack.getCount());
ItemStack extracted = simulate ? transported.stack.copy().split(amount) : transported.stack.split(amount);
if (!simulate) {
belt.markDirty();
belt.sendData();
}
return extracted;
}
@Override
public int getSlotLimit(int slot) {
return Math.min(getStackInSlot(slot).getMaxStackSize(), 64);
}
@Override
public boolean isItemValid(int slot, ItemStack stack) {
return true;
}
public IItemHandler createHandlerForSegment(int segment) {
return new ItemHandlerBeltSegment(this, segment);
}
public IItemHandler createHandlerForSegment(int segment) {
return new ItemHandlerSegment(segment);
public void forEachWithin(float position, float distance,
Function<TransportedItemStack, List<TransportedItemStack>> callback) {
List<TransportedItemStack> toBeAdded = new ArrayList<>();
boolean dirty = false;
for (Iterator<TransportedItemStack> iterator = items.iterator(); iterator.hasNext();) {
TransportedItemStack transportedItemStack = iterator.next();
if (Math.abs(position - transportedItemStack.beltPosition) < distance) {
List<TransportedItemStack> apply = callback.apply(transportedItemStack);
if (apply == null)
continue;
dirty = true;
toBeAdded.addAll(apply);
iterator.remove();
}
}
toBeAdded.forEach(this::insert);
if (dirty) {
belt.markDirty();
belt.sendData();
}
}
}

View file

@ -20,7 +20,6 @@ import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.Tracker;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Part;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
import com.simibubi.create.modules.contraptions.relays.belt.BeltInventory.TransportedItemStack;
import com.simibubi.create.modules.contraptions.relays.belt.BeltMovementHandler.TransportedEntityInfo;
import net.minecraft.block.BlockState;
@ -183,6 +182,15 @@ public class BeltTileEntity extends KineticTileEntity {
}
}
public BeltTileEntity getControllerTE() {
if (!world.isBlockPresent(controller))
return null;
TileEntity te = world.getTileEntity(controller);
if (te == null || !(te instanceof BeltTileEntity))
return null;
return (BeltTileEntity) te;
}
public void setController(BlockPos controller) {
this.controller = controller;
}
@ -283,13 +291,9 @@ public class BeltTileEntity extends KineticTileEntity {
}
public boolean tryInsertingFromSide(Direction side, TransportedItemStack transportedStack, boolean simulate) {
BlockPos controller = getController();
if (!world.isBlockPresent(controller))
BeltTileEntity nextBeltController = getControllerTE();
if (nextBeltController == null)
return false;
TileEntity te = world.getTileEntity(controller);
if (te == null || !(te instanceof BeltTileEntity))
return false;
BeltTileEntity nextBeltController = (BeltTileEntity) te;
BeltInventory nextInventory = nextBeltController.getInventory();
if (!nextInventory.canInsertFrom(index, side))
@ -314,6 +318,7 @@ public class BeltTileEntity extends KineticTileEntity {
transportedStack.insertedFrom = side;
transportedStack.prevBeltPosition = transportedStack.beltPosition;
nextInventory.insert(transportedStack);
nextBeltController.markDirty();
nextBeltController.sendData();
return true;
}

View file

@ -11,7 +11,6 @@ import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer;
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer.BlockModelSpinner;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
import com.simibubi.create.modules.contraptions.relays.belt.BeltInventory.TransportedItemStack;
import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft;
@ -56,6 +55,11 @@ public class BeltTileEntityRenderer extends TileEntityRenderer<BeltTileEntity> {
float offset = MathHelper.lerp(partialTicks, transported.prevBeltPosition, transported.beltPosition);
float sideOffset = MathHelper.lerp(partialTicks, transported.prevSideOffset, transported.sideOffset);
float verticalMovement = verticality;
if (te.getSpeed() == 0) {
offset = transported.beltPosition;
sideOffset = transported.sideOffset;
}
if (offset < .5)
verticalMovement = 0;

View file

@ -0,0 +1,69 @@
package com.simibubi.create.modules.contraptions.relays.belt;
import net.minecraft.item.ItemStack;
import net.minecraftforge.items.IItemHandler;
public class ItemHandlerBeltSegment implements IItemHandler {
private final BeltInventory beltInventory;
int offset;
public ItemHandlerBeltSegment(BeltInventory beltInventory, int offset) {
this.beltInventory = beltInventory;
this.offset = offset;
}
@Override
public int getSlots() {
return 1;
}
@Override
public ItemStack getStackInSlot(int slot) {
TransportedItemStack stackAtOffset = this.beltInventory.getStackAtOffset(offset);
if (stackAtOffset == null)
return ItemStack.EMPTY;
return stackAtOffset.stack;
}
@Override
public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) {
if (this.beltInventory.canInsertAt(offset)) {
if (!simulate) {
TransportedItemStack newStack = new TransportedItemStack(stack);
newStack.insertedAt = offset;
newStack.beltPosition = offset + .5f;
newStack.prevBeltPosition = newStack.beltPosition;
this.beltInventory.insert(newStack);
}
return ItemStack.EMPTY;
}
return stack;
}
@Override
public ItemStack extractItem(int slot, int amount, boolean simulate) {
TransportedItemStack transported = this.beltInventory.getStackAtOffset(offset);
if (transported == null)
return ItemStack.EMPTY;
amount = Math.min(amount, transported.stack.getCount());
ItemStack extracted = simulate ? transported.stack.copy().split(amount) : transported.stack.split(amount);
if (!simulate) {
this.beltInventory.belt.markDirty();
this.beltInventory.belt.sendData();
}
return extracted;
}
@Override
public int getSlotLimit(int slot) {
return Math.min(getStackInSlot(slot).getMaxStackSize(), 64);
}
@Override
public boolean isItemValid(int slot, ItemStack stack) {
return true;
}
}

View file

@ -0,0 +1,87 @@
package com.simibubi.create.modules.contraptions.relays.belt;
import java.util.Random;
import com.simibubi.create.modules.logistics.InWorldProcessing;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.Direction;
public class TransportedItemStack implements Comparable<TransportedItemStack> {
public ItemStack stack;
public float beltPosition;
public float sideOffset;
public int angle;
public int insertedAt;
public Direction insertedFrom;
public boolean locked;
public float prevBeltPosition;
public float prevSideOffset;
public InWorldProcessing.Type processedBy;
public int processingTime;
public TransportedItemStack(ItemStack stack) {
this.stack = stack;
angle = new Random().nextInt(360);
sideOffset = prevSideOffset = getTargetSideOffset();
insertedFrom = Direction.UP;
}
public float getTargetSideOffset() {
return (angle - 180) / (360 * 3f);
}
@Override
public int compareTo(TransportedItemStack o) {
return beltPosition < o.beltPosition ? 1 : beltPosition > o.beltPosition ? -1 : 0;
}
public TransportedItemStack getSimilar() {
TransportedItemStack copy = new TransportedItemStack(stack.copy());
copy.beltPosition = beltPosition;
copy.insertedAt = insertedAt;
copy.insertedFrom = insertedFrom;
copy.prevBeltPosition = prevBeltPosition;
copy.prevSideOffset = prevSideOffset;
copy.processedBy = processedBy;
copy.processingTime = processingTime;
return copy;
}
public TransportedItemStack copy() {
TransportedItemStack copy = getSimilar();
copy.angle = angle;
return copy;
}
public CompoundNBT serializeNBT() {
CompoundNBT nbt = new CompoundNBT();
nbt.put("Item", stack.serializeNBT());
nbt.putFloat("Pos", beltPosition);
nbt.putFloat("PrevPos", prevBeltPosition);
nbt.putFloat("Offset", sideOffset);
nbt.putFloat("PrevOffset", prevSideOffset);
nbt.putInt("InSegment", insertedAt);
nbt.putInt("Angle", angle);
nbt.putInt("InDirection", insertedFrom.getIndex());
nbt.putBoolean("Locked", locked);
return nbt;
}
public static TransportedItemStack read(CompoundNBT nbt) {
TransportedItemStack stack = new TransportedItemStack(ItemStack.read(nbt.getCompound("Item")));
stack.beltPosition = nbt.getFloat("Pos");
stack.prevBeltPosition = nbt.getFloat("PrevPos");
stack.sideOffset = nbt.getFloat("Offset");
stack.prevSideOffset = nbt.getFloat("PrevOffset");
stack.insertedAt = nbt.getInt("InSegment");
stack.angle = nbt.getInt("Angle");
stack.insertedFrom = Direction.byIndex(nbt.getInt("InDirection"));
stack.locked = nbt.getBoolean("Locked");
return stack;
}
}

View file

@ -20,7 +20,7 @@ public class WindowInABlockTileEntity extends SyncedTileEntity {
private BlockState partialBlock = Blocks.AIR.getDefaultState();
private BlockState windowBlock = Blocks.AIR.getDefaultState();
@OnlyIn(value = Dist.CLIENT)
private IModelData modelData;
@ -64,7 +64,7 @@ public class WindowInABlockTileEntity extends SyncedTileEntity {
windowBlock = getWindowBlock().updatePostPlacement(side, world.getBlockState(offsetPos), world, pos,
offsetPos);
}
sendData();
world.notifyBlockUpdate(getPos(), getBlockState(), getBlockState(), 2 | 16);
markDirty();
}

View file

@ -1,13 +1,17 @@
package com.simibubi.create.modules.logistics;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import com.simibubi.create.AllRecipes;
import com.simibubi.create.CreateConfig;
import com.simibubi.create.foundation.utility.ItemHelper;
import com.simibubi.create.modules.contraptions.base.ProcessingRecipe;
import com.simibubi.create.modules.contraptions.receivers.SplashingRecipe;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.modules.contraptions.relays.belt.TransportedItemStack;
import net.minecraft.entity.item.ItemEntity;
import net.minecraft.item.ItemStack;
@ -40,12 +44,27 @@ public class InWorldProcessing {
}
public static boolean canProcess(ItemEntity entity, Type type) {
World world = entity.world;
if (entity.getPersistentData().contains("CreateData")) {
CompoundNBT compound = entity.getPersistentData().getCompound("CreateData");
if (compound.contains("Processing")) {
CompoundNBT processing = compound.getCompound("Processing");
if (entity.getPersistentData().contains("CreateData")
&& entity.getPersistentData().getCompound("CreateData").contains("Processing"))
return true;
if (Type.valueOf(processing.getString("Type")) != type) {
boolean canProcess = canProcess(entity.getItem(), type, entity.world);
processing.putString("Type", type.name());
if (!canProcess)
processing.putInt("Time", -1);
return canProcess;
} else if (processing.getInt("Time") >= 0)
return true;
else if (processing.getInt("Time") == -1)
return false;
}
}
return canProcess(entity.getItem(), type, entity.world);
}
private static boolean canProcess(ItemStack stack, Type type, World world) {
if (type == Type.BLASTING) {
return true;
}
@ -53,13 +72,13 @@ public class InWorldProcessing {
if (type == Type.SMOKING) {
SmokerTileEntity smoker = new SmokerTileEntity();
smoker.setWorld(world);
smoker.setInventorySlotContents(0, entity.getItem());
smoker.setInventorySlotContents(0, stack);
Optional<SmokingRecipe> recipe = world.getRecipeManager().getRecipe(IRecipeType.SMOKING, smoker, world);
return recipe.isPresent();
}
if (type == Type.SPLASHING) {
splashingInv.setInventorySlotContents(0, entity.getItem());
splashingInv.setInventorySlotContents(0, stack);
Optional<SplashingRecipe> recipe = world.getRecipeManager().getRecipe(AllRecipes.Types.SPLASHING,
splashingInv, world);
return recipe.isPresent();
@ -68,59 +87,90 @@ public class InWorldProcessing {
return false;
}
public static void process(ItemEntity entity, Type type) {
World world = entity.world;
public static void applyProcessing(ItemEntity entity, Type type) {
if (decrementProcessingTime(entity, type) != 0)
return;
List<ItemStack> stacks = process(entity.getItem(), type, entity.world);
if (stacks == null)
return;
if (stacks.isEmpty()) {
entity.remove();
return;
}
entity.setItem(stacks.remove(0));
for (ItemStack additional : stacks) {
ItemEntity entityIn = new ItemEntity(entity.world, entity.posX, entity.posY, entity.posZ, additional);
entityIn.setMotion(entity.getMotion());
entity.world.addEntity(entityIn);
}
}
public static List<TransportedItemStack> applyProcessing(TransportedItemStack transported, BeltTileEntity belt, Type type) {
if (transported.processedBy != type) {
transported.processedBy = type;
transported.processingTime = CreateConfig.parameters.inWorldProcessingTime.get() + 1;
if (!canProcess(transported.stack, type, belt.getWorld()))
transported.processingTime = -1;
return null;
}
if (transported.processingTime == -1)
return null;
if (transported.processingTime-- > 0)
return null;
List<ItemStack> stacks = process(transported.stack, type, belt.getWorld());
List<TransportedItemStack> transportedStacks = new ArrayList<>();
for (ItemStack additional : stacks) {
TransportedItemStack newTransported = transported.getSimilar();
newTransported.stack = additional.copy();
transportedStacks.add(newTransported);
}
return transportedStacks;
}
private static List<ItemStack> process(ItemStack stack, Type type, World world) {
if (type == Type.SPLASHING) {
splashingInv.setInventorySlotContents(0, entity.getItem());
splashingInv.setInventorySlotContents(0, stack);
Optional<SplashingRecipe> recipe = world.getRecipeManager().getRecipe(AllRecipes.Types.SPLASHING,
splashingInv, world);
if (recipe.isPresent())
applyRecipeOn(entity, recipe.get());
return;
return applyRecipeOn(stack, recipe.get());
return null;
}
SmokerTileEntity smoker = new SmokerTileEntity();
smoker.setWorld(world);
smoker.setInventorySlotContents(0, entity.getItem());
smoker.setInventorySlotContents(0, stack);
Optional<SmokingRecipe> smokingRecipe = world.getRecipeManager().getRecipe(IRecipeType.SMOKING, smoker, world);
if (type == Type.BLASTING) {
FurnaceTileEntity furnace = new FurnaceTileEntity();
furnace.setWorld(world);
furnace.setInventorySlotContents(0, entity.getItem());
furnace.setInventorySlotContents(0, stack);
Optional<FurnaceRecipe> smeltingRecipe = world.getRecipeManager().getRecipe(IRecipeType.SMELTING, furnace,
world);
if (!smokingRecipe.isPresent()) {
if (smeltingRecipe.isPresent()) {
applyRecipeOn(entity, smeltingRecipe.get());
return;
}
if (smeltingRecipe.isPresent())
return applyRecipeOn(stack, smeltingRecipe.get());
BlastFurnaceTileEntity blastFurnace = new BlastFurnaceTileEntity();
blastFurnace.setWorld(world);
blastFurnace.setInventorySlotContents(0, entity.getItem());
blastFurnace.setInventorySlotContents(0, stack);
Optional<BlastingRecipe> blastingRecipe = world.getRecipeManager().getRecipe(IRecipeType.BLASTING,
blastFurnace, world);
if (blastingRecipe.isPresent()) {
applyRecipeOn(entity, blastingRecipe.get());
return;
}
if (blastingRecipe.isPresent())
return applyRecipeOn(stack, blastingRecipe.get());
}
entity.remove();
return;
return Collections.emptyList();
}
if (type == Type.SMOKING && smokingRecipe.isPresent()) {
applyRecipeOn(entity, smokingRecipe.get());
return;
}
if (type == Type.SMOKING && smokingRecipe.isPresent())
return applyRecipeOn(stack, smokingRecipe.get());
return null;
}
private static int decrementProcessingTime(ItemEntity entity, Type type) {
@ -143,14 +193,31 @@ public class InWorldProcessing {
processing.putInt("Time", value);
return value;
}
public static void applyRecipeOn(ItemEntity entity, IRecipe<?> recipe) {
List<ItemStack> stacks = applyRecipeOn(entity.getItem(), recipe);
if (stacks == null)
return;
if (stacks.isEmpty()) {
entity.remove();
return;
}
entity.setItem(stacks.remove(0));
for (ItemStack additional : stacks) {
ItemEntity entityIn = new ItemEntity(entity.world, entity.posX, entity.posY, entity.posZ, additional);
entityIn.setMotion(entity.getMotion());
entity.world.addEntity(entityIn);
}
}
private static List<ItemStack> applyRecipeOn(ItemStack stackIn, IRecipe<?> recipe) {
List<ItemStack> stacks;
if (recipe instanceof SplashingRecipe) {
if (recipe instanceof ProcessingRecipe) {
stacks = new ArrayList<>();
for (int i = 0; i < entity.getItem().getCount(); i++) {
for (ItemStack stack : ((SplashingRecipe) recipe).rollResults()) {
for (int i = 0; i < stackIn.getCount(); i++) {
List<ItemStack> rollResults = ((ProcessingRecipe<?>) recipe).rollResults();
for (ItemStack stack : rollResults) {
for (ItemStack previouslyRolled : stacks) {
if (stack.isEmpty())
continue;
@ -170,19 +237,10 @@ public class InWorldProcessing {
}
} else {
ItemStack out = recipe.getRecipeOutput().copy();
stacks = ItemHelper.multipliedOutput(entity.getItem(), out);
stacks = ItemHelper.multipliedOutput(stackIn, out);
}
if (stacks.isEmpty()) {
entity.remove();
return;
}
entity.setItem(stacks.remove(0));
for (ItemStack additional : stacks) {
ItemEntity entityIn = new ItemEntity(entity.world, entity.posX, entity.posY, entity.posZ, additional);
entityIn.setMotion(entity.getMotion());
entity.world.addEntity(entityIn);
}
return stacks;
}
public static boolean isFrozen() {

View file

@ -123,7 +123,22 @@ public interface IExtractor extends ITickableTileEntity, IInventoryManipulator {
}
default boolean hasSpaceForExtracting() {
return getWorld().getEntitiesWithinAABBExcludingEntity(null, new AxisAlignedBB(getPos())).isEmpty();
BlockPos pos = getPos();
World world = getWorld();
if (AllBlocks.BELT.typeOf(world.getBlockState(pos.down()))) {
TileEntity te = world.getTileEntity(pos.down());
if (te != null && te instanceof BeltTileEntity) {
BeltTileEntity belt = (BeltTileEntity) te;
BeltTileEntity controller = belt.getControllerTE();
if (controller != null) {
if (!controller.getInventory().canInsertFrom(belt.index, Direction.UP))
return false;
}
}
}
return world.getEntitiesWithinAABBExcludingEntity(null, new AxisAlignedBB(getPos())).isEmpty();
}
default ItemStack extract(boolean simulate) {
@ -131,7 +146,6 @@ public interface IExtractor extends ITickableTileEntity, IInventoryManipulator {
ItemStack extracting = ItemStack.EMPTY;
ItemStack filterItem = (this instanceof IHaveFilter) ? ((IHaveFilter) this).getFilter() : ItemStack.EMPTY;
World world = getWorld();
BlockPos pos = getPos();
int extractionCount = filterItem.isEmpty() ? CreateConfig.parameters.extractorAmount.get()
: filterItem.getCount();
boolean checkHasEnoughItems = !filterItem.isEmpty();
@ -177,15 +191,6 @@ public interface IExtractor extends ITickableTileEntity, IInventoryManipulator {
break Extraction;
} while (true);
if (AllBlocks.BELT.typeOf(world.getBlockState(pos.down()))) {
TileEntity te = world.getTileEntity(pos.down());
if (te != null && te instanceof BeltTileEntity && !extracting.isEmpty()) {
if (((BeltTileEntity) te).tryInsertingFromSide(Direction.UP, extracting.copy(), simulate))
return extracting;
return ItemStack.EMPTY;
}
}
if (!simulate && hasEnoughItems) {
Vec3d entityPos = VecHelper.getCenterOf(getPos()).add(0, -0.5f, 0);
Entity entityIn = null;

View file

@ -10,8 +10,8 @@ import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.BeltAttachmentState;
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.IBeltAttachment;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock;
import com.simibubi.create.modules.contraptions.relays.belt.BeltInventory.TransportedItemStack;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.modules.contraptions.relays.belt.TransportedItemStack;
import com.simibubi.create.modules.logistics.block.IBlockWithFilter;
import com.simibubi.create.modules.logistics.block.IInventoryManipulator;
@ -25,8 +25,8 @@ import net.minecraft.item.ItemStack;
import net.minecraft.state.StateContainer.Builder;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.Hand;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.Vec3d;

View file

@ -3,7 +3,7 @@ package com.simibubi.create.modules.logistics.block.belts;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.foundation.block.SyncedTileEntity;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.relays.belt.BeltInventory.ItemHandlerSegment;
import com.simibubi.create.modules.contraptions.relays.belt.ItemHandlerBeltSegment;
import com.simibubi.create.modules.logistics.block.IHaveFilter;
import com.simibubi.create.modules.logistics.block.IInventoryManipulator;
@ -113,7 +113,7 @@ public class BeltFunnelTileEntity extends SyncedTileEntity
public ItemStack tryToInsert(ItemStack stack) {
if (!inventory.isPresent())
return stack;
if (waitingForInventorySpace && !(inventory.orElse(null) instanceof ItemHandlerSegment))
if (waitingForInventorySpace && !(inventory.orElse(null) instanceof ItemHandlerBeltSegment))
return stack;
if (!filter.isEmpty() && !ItemStack.areItemsEqual(filter, stack))
return stack;

View file

@ -13,8 +13,8 @@ import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.I
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Part;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
import com.simibubi.create.modules.contraptions.relays.belt.BeltInventory.TransportedItemStack;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.modules.contraptions.relays.belt.TransportedItemStack;
import com.simibubi.create.modules.logistics.block.IBlockWithFilter;
import net.minecraft.block.Block;