misc pipe fixes

This commit is contained in:
Ellpeck 2020-04-14 21:04:41 +02:00
parent 6abfec9c94
commit 44a5d6b4ec
3 changed files with 65 additions and 29 deletions

View file

@ -25,16 +25,11 @@ import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemHandlerHelper; import net.minecraftforge.items.ItemHandlerHelper;
import net.minecraftforge.items.ItemStackHandler; import net.minecraftforge.items.ItemStackHandler;
import org.jgrapht.GraphPath;
import org.jgrapht.alg.interfaces.ShortestPathAlgorithm;
import org.jgrapht.alg.interfaces.ShortestPathAlgorithm.SingleSourcePaths;
import org.jgrapht.traverse.ClosestFirstIterator;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.function.Predicate;
public class PipeTileEntity extends TileEntity implements INamedContainerProvider, ITickableTileEntity { public class PipeTileEntity extends TileEntity implements INamedContainerProvider, ITickableTileEntity {
@ -81,8 +76,18 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide
super.read(compound); super.read(compound);
} }
@Override
public CompoundNBT getUpdateTag() {
// by default, this is just writeInternal, but we
// want to sync the current pipe items on load too
return this.write(new CompoundNBT());
}
@Override @Override
public void tick() { public void tick() {
if (!this.world.isAreaLoaded(this.pos, 1))
return;
for (int i = this.items.size() - 1; i >= 0; i--) for (int i = this.items.size() - 1; i >= 0; i--)
this.items.get(i).updateInPipe(this); this.items.get(i).updateInPipe(this);

View file

@ -37,19 +37,18 @@ public class PipeItem implements INBTSerializable<CompoundNBT> {
public float lastY; public float lastY;
public float lastZ; public float lastZ;
private final List<BlockPos> path; private List<BlockPos> path;
private BlockPos startPipe; private BlockPos startPipe;
private BlockPos startInventory;
private BlockPos destPipe; private BlockPos destPipe;
private BlockPos destInventory; private BlockPos destInventory;
private int pipeTimer; private int pipeTimer;
private int currentTile; private int currentTile;
private boolean dropOnObstruction;
public PipeItem(ItemStack stack, BlockPos startPipe, BlockPos startInventory, BlockPos destPipe, BlockPos destInventory, GraphPath<BlockPos, NetworkEdge> path) { public PipeItem(ItemStack stack, BlockPos startPipe, BlockPos startInventory) {
this.stack = stack; this.stack = stack;
this.startPipe = startPipe; this.startInventory = startInventory;
this.destPipe = destPipe;
this.destInventory = destInventory;
this.path = compilePath(path);
this.x = MathHelper.lerp(0.5F, startInventory.getX(), startPipe.getX()) + 0.5F; this.x = MathHelper.lerp(0.5F, startInventory.getX(), startPipe.getX()) + 0.5F;
this.y = MathHelper.lerp(0.5F, startInventory.getY(), startPipe.getY()) + 0.5F; this.y = MathHelper.lerp(0.5F, startInventory.getY(), startPipe.getY()) + 0.5F;
this.z = MathHelper.lerp(0.5F, startInventory.getZ(), startPipe.getZ()) + 0.5F; this.z = MathHelper.lerp(0.5F, startInventory.getZ(), startPipe.getZ()) + 0.5F;
@ -60,6 +59,15 @@ public class PipeItem implements INBTSerializable<CompoundNBT> {
this.deserializeNBT(nbt); this.deserializeNBT(nbt);
} }
public void setDestination(BlockPos startPipe, BlockPos destPipe, BlockPos destInventory, GraphPath<BlockPos, NetworkEdge> path) {
this.startPipe = startPipe;
this.destPipe = destPipe;
this.destInventory = destInventory;
this.path = compilePath(path);
this.currentTile = 0;
this.pipeTimer = 0;
}
public void updateInPipe(PipeTileEntity currPipe) { public void updateInPipe(PipeTileEntity currPipe) {
this.pipeTimer++; this.pipeTimer++;
BlockPos goalPos; BlockPos goalPos;
@ -73,9 +81,9 @@ public class PipeItem implements INBTSerializable<CompoundNBT> {
// ..or store in our destination container if we reached our destination // ..or store in our destination container if we reached our destination
this.stack = this.store(currPipe); this.stack = this.store(currPipe);
if (!this.stack.isEmpty()) if (!this.stack.isEmpty())
this.onPathObstructed(currPipe); this.onPathObstructed(currPipe, true);
} else { } else {
this.onPathObstructed(currPipe); this.onPathObstructed(currPipe, false);
} }
} }
return; return;
@ -93,7 +101,7 @@ public class PipeItem implements INBTSerializable<CompoundNBT> {
} else { } else {
currPipe.items.remove(this); currPipe.items.remove(this);
if (!currPipe.getWorld().isRemote) if (!currPipe.getWorld().isRemote)
this.onPathObstructed(currPipe); this.onPathObstructed(currPipe, false);
return; return;
} }
} else { } else {
@ -116,8 +124,14 @@ public class PipeItem implements INBTSerializable<CompoundNBT> {
this.z += dist.z * speed; this.z += dist.z * speed;
} }
private void onPathObstructed(PipeTileEntity currPipe) { private void onPathObstructed(PipeTileEntity currPipe, boolean tryReturn) {
// TODO when the path is obstructed, try to turn back home first if (!this.dropOnObstruction && tryReturn) {
PipeNetwork network = PipeNetwork.get(currPipe.getWorld());
if (network.routeItemToLocation(currPipe.getPos(), this.startPipe, this.startInventory, () -> this)) {
this.dropOnObstruction = true;
return;
}
}
this.drop(currPipe.getWorld()); this.drop(currPipe.getWorld());
} }
@ -156,8 +170,10 @@ public class PipeItem implements INBTSerializable<CompoundNBT> {
CompoundNBT nbt = new CompoundNBT(); CompoundNBT nbt = new CompoundNBT();
nbt.put("stack", this.stack.serializeNBT()); nbt.put("stack", this.stack.serializeNBT());
nbt.put("start_pipe", NBTUtil.writeBlockPos(this.startPipe)); nbt.put("start_pipe", NBTUtil.writeBlockPos(this.startPipe));
nbt.put("start_inventory", NBTUtil.writeBlockPos(this.startInventory));
nbt.put("dest_pipe", NBTUtil.writeBlockPos(this.destPipe)); nbt.put("dest_pipe", NBTUtil.writeBlockPos(this.destPipe));
nbt.put("dest_inv", NBTUtil.writeBlockPos(this.destInventory)); nbt.put("dest_inv", NBTUtil.writeBlockPos(this.destInventory));
nbt.putBoolean("drop_on_obstruction", this.dropOnObstruction);
nbt.putInt("timer", this.pipeTimer); nbt.putInt("timer", this.pipeTimer);
nbt.putInt("tile", this.currentTile); nbt.putInt("tile", this.currentTile);
nbt.putFloat("x", this.x); nbt.putFloat("x", this.x);
@ -174,8 +190,10 @@ public class PipeItem implements INBTSerializable<CompoundNBT> {
public void deserializeNBT(CompoundNBT nbt) { public void deserializeNBT(CompoundNBT nbt) {
this.stack = ItemStack.read(nbt.getCompound("stack")); this.stack = ItemStack.read(nbt.getCompound("stack"));
this.startPipe = NBTUtil.readBlockPos(nbt.getCompound("start_pipe")); this.startPipe = NBTUtil.readBlockPos(nbt.getCompound("start_pipe"));
this.startInventory = NBTUtil.readBlockPos(nbt.getCompound("start_inventory"));
this.destPipe = NBTUtil.readBlockPos(nbt.getCompound("dest_pipe")); this.destPipe = NBTUtil.readBlockPos(nbt.getCompound("dest_pipe"));
this.destInventory = NBTUtil.readBlockPos(nbt.getCompound("dest_inv")); this.destInventory = NBTUtil.readBlockPos(nbt.getCompound("dest_inv"));
this.dropOnObstruction = nbt.getBoolean("drop_on_obstruction");
this.pipeTimer = nbt.getInt("timer"); this.pipeTimer = nbt.getInt("timer");
this.currentTile = nbt.getInt("tile"); this.currentTile = nbt.getInt("tile");
this.x = nbt.getFloat("x"); this.x = nbt.getFloat("x");

View file

@ -1,21 +1,17 @@
package de.ellpeck.prettypipes.network; package de.ellpeck.prettypipes.network;
import com.google.common.collect.Sets;
import de.ellpeck.prettypipes.Registry; import de.ellpeck.prettypipes.Registry;
import de.ellpeck.prettypipes.Utility; import de.ellpeck.prettypipes.Utility;
import de.ellpeck.prettypipes.blocks.pipe.PipeBlock; import de.ellpeck.prettypipes.blocks.pipe.PipeBlock;
import de.ellpeck.prettypipes.blocks.pipe.PipeTileEntity; import de.ellpeck.prettypipes.blocks.pipe.PipeTileEntity;
import de.ellpeck.prettypipes.packets.PacketHandler; import de.ellpeck.prettypipes.packets.PacketHandler;
import de.ellpeck.prettypipes.packets.PacketItemEnterPipe; import de.ellpeck.prettypipes.packets.PacketItemEnterPipe;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.ListNBT; import net.minecraft.nbt.ListNBT;
import net.minecraft.nbt.NBTUtil; import net.minecraft.nbt.NBTUtil;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.Tuple;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.Capability;
@ -23,8 +19,6 @@ import net.minecraftforge.common.capabilities.ICapabilitySerializable;
import net.minecraftforge.common.util.Constants; import net.minecraftforge.common.util.Constants;
import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.common.util.LazyOptional;
import org.jgrapht.GraphPath; import org.jgrapht.GraphPath;
import org.jgrapht.alg.interfaces.ShortestPathAlgorithm;
import org.jgrapht.alg.interfaces.ShortestPathAlgorithm.SingleSourcePaths;
import org.jgrapht.alg.shortestpath.DijkstraShortestPath; import org.jgrapht.alg.shortestpath.DijkstraShortestPath;
import org.jgrapht.graph.SimpleWeightedGraph; import org.jgrapht.graph.SimpleWeightedGraph;
import org.jgrapht.traverse.ClosestFirstIterator; import org.jgrapht.traverse.ClosestFirstIterator;
@ -35,6 +29,7 @@ import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.function.Supplier;
public class PipeNetwork implements ICapabilitySerializable<CompoundNBT> { public class PipeNetwork implements ICapabilitySerializable<CompoundNBT> {
@ -104,8 +99,14 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundNBT> {
} }
public boolean tryInsertItem(BlockPos startPipePos, BlockPos originInv, ItemStack stack) { public boolean tryInsertItem(BlockPos startPipePos, BlockPos originInv, ItemStack stack) {
return this.routeItem(startPipePos, stack, () -> new PipeItem(stack, startPipePos, originInv));
}
public boolean routeItem(BlockPos startPipePos, ItemStack stack, Supplier<PipeItem> itemSupplier) {
if (!this.isNode(startPipePos)) if (!this.isNode(startPipePos))
return false; return false;
if (!this.world.isBlockLoaded(startPipePos))
return false;
PipeTileEntity startPipe = this.getPipe(startPipePos); PipeTileEntity startPipe = this.getPipe(startPipePos);
if (startPipe == null) if (startPipe == null)
return false; return false;
@ -116,16 +117,28 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundNBT> {
if (pipe == startPipe) if (pipe == startPipe)
continue; continue;
BlockPos dest = pipe.getAvailableDestination(stack); BlockPos dest = pipe.getAvailableDestination(stack);
if (dest != null) { if (dest != null)
GraphPath<BlockPos, NetworkEdge> path = this.dijkstra.getPath(startPipePos, pipe.getPos()); return this.routeItemToLocation(startPipePos, pipe.getPos(), dest, itemSupplier);
PipeItem item = new PipeItem(stack.copy(), startPipePos, originInv, pipe.getPos(), dest, path); }
return false;
}
public boolean routeItemToLocation(BlockPos startPipePos, BlockPos destPipe, BlockPos destInventory, Supplier<PipeItem> itemSupplier) {
if (!this.isNode(startPipePos))
return false;
if (!this.world.isBlockLoaded(startPipePos))
return false;
PipeTileEntity startPipe = this.getPipe(startPipePos);
if (startPipe == null)
return false;
GraphPath<BlockPos, NetworkEdge> path = this.dijkstra.getPath(startPipePos, destPipe);
PipeItem item = itemSupplier.get();
item.setDestination(startPipePos, destPipe, destInventory, path);
if (!startPipe.items.contains(item))
startPipe.items.add(item); startPipe.items.add(item);
PacketHandler.sendToAllLoaded(this.world, startPipePos, new PacketItemEnterPipe(startPipePos, item)); PacketHandler.sendToAllLoaded(this.world, startPipePos, new PacketItemEnterPipe(startPipePos, item));
return true; return true;
} }
}
return false;
}
public PipeTileEntity getPipe(BlockPos pos) { public PipeTileEntity getPipe(BlockPos pos) {
PipeTileEntity tile = this.tileCache.get(pos); PipeTileEntity tile = this.tileCache.get(pos);