mirror of
https://github.com/Ellpeck/PrettyPipes.git
synced 2024-12-22 23:39:22 +01:00
finished basic pipe logistics!
This commit is contained in:
parent
a11693632d
commit
6abfec9c94
7 changed files with 160 additions and 59 deletions
|
@ -3,6 +3,7 @@ package de.ellpeck.prettypipes;
|
|||
import net.minecraft.inventory.InventoryHelper;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.items.IItemHandler;
|
||||
|
@ -22,4 +23,9 @@ public final class Utility {
|
|||
InventoryHelper.spawnItemStack(tile.getWorld(), pos.getX(), pos.getY(), pos.getZ(), stack);
|
||||
}
|
||||
}
|
||||
|
||||
public static Direction getDirectionFromOffset(BlockPos pos, BlockPos other) {
|
||||
BlockPos diff = pos.subtract(other);
|
||||
return Direction.getFacingFromVector(diff.getX(), diff.getY(), diff.getZ());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package de.ellpeck.prettypipes.blocks.pipe;
|
|||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import de.ellpeck.prettypipes.Utility;
|
||||
import de.ellpeck.prettypipes.network.PipeItem;
|
||||
import de.ellpeck.prettypipes.network.PipeNetwork;
|
||||
import net.minecraft.block.*;
|
||||
import net.minecraft.block.material.Material;
|
||||
|
@ -182,8 +183,11 @@ public class PipeBlock extends ContainerBlock {
|
|||
public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) {
|
||||
if (state.getBlock() != newState.getBlock()) {
|
||||
PipeTileEntity tile = Utility.getTileEntity(PipeTileEntity.class, worldIn, pos);
|
||||
if (tile != null)
|
||||
if (tile != null) {
|
||||
Utility.dropInventory(tile, tile.upgrades);
|
||||
for (PipeItem item : tile.items)
|
||||
item.drop(worldIn);
|
||||
}
|
||||
PipeNetwork network = PipeNetwork.get(worldIn);
|
||||
network.removeNode(pos);
|
||||
network.onPipeChanged(pos, state);
|
||||
|
|
|
@ -8,30 +8,70 @@ import net.minecraft.client.renderer.model.ItemCameraTransforms;
|
|||
import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
|
||||
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
|
||||
import net.minecraft.item.BlockItem;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class PipeRenderer extends TileEntityRenderer<PipeTileEntity> {
|
||||
|
||||
private final Random random = new Random();
|
||||
|
||||
public PipeRenderer(TileEntityRendererDispatcher disp) {
|
||||
super(disp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(PipeTileEntity tile, float v, MatrixStack matrixStack, IRenderTypeBuffer iRenderTypeBuffer, int i, int i1) {
|
||||
public void render(PipeTileEntity tile, float v, MatrixStack matrixStack, IRenderTypeBuffer iRenderTypeBuffer, int k, int i1) {
|
||||
BlockPos pos = tile.getPos();
|
||||
for (PipeItem item : tile.items) {
|
||||
matrixStack.push();
|
||||
matrixStack.translate(item.x - pos.getX(), item.y - pos.getY(), item.z - pos.getZ());
|
||||
matrixStack.translate(
|
||||
MathHelper.lerp(v, item.lastX, item.x) - pos.getX(),
|
||||
MathHelper.lerp(v, item.lastY, item.y) - pos.getY(),
|
||||
MathHelper.lerp(v, item.lastZ, item.z) - pos.getZ());
|
||||
|
||||
if (item.stack.getItem() instanceof BlockItem) {
|
||||
float scale = 0.65F;
|
||||
float scale = 0.7F;
|
||||
matrixStack.scale(scale, scale, scale);
|
||||
matrixStack.translate(0, -0.2F, 0);
|
||||
} else {
|
||||
float scale = 0.4F;
|
||||
float scale = 0.45F;
|
||||
matrixStack.scale(scale, scale, scale);
|
||||
matrixStack.translate(0, -0.1F, 0);
|
||||
}
|
||||
|
||||
this.random.setSeed(Item.getIdFromItem(item.stack.getItem()) + item.stack.getDamage());
|
||||
int amount = this.getModelCount(item.stack);
|
||||
|
||||
for (int i = 0; i < amount; i++) {
|
||||
matrixStack.push();
|
||||
if (amount > 1) {
|
||||
matrixStack.translate(
|
||||
(this.random.nextFloat() * 2.0F - 1.0F) * 0.25F * 0.5F,
|
||||
(this.random.nextFloat() * 2.0F - 1.0F) * 0.25F * 0.5F,
|
||||
(this.random.nextFloat() * 2.0F - 1.0F) * 0.25F * 0.5F);
|
||||
}
|
||||
Minecraft.getInstance().getItemRenderer().renderItem(item.stack, ItemCameraTransforms.TransformType.GROUND, k, i1, matrixStack, iRenderTypeBuffer);
|
||||
matrixStack.pop();
|
||||
}
|
||||
Minecraft.getInstance().getItemRenderer().renderItem(item.stack, ItemCameraTransforms.TransformType.GROUND, i, i1, matrixStack, iRenderTypeBuffer);
|
||||
matrixStack.pop();
|
||||
}
|
||||
}
|
||||
|
||||
protected int getModelCount(ItemStack stack) {
|
||||
int i = 1;
|
||||
if (stack.getCount() > 48) {
|
||||
i = 5;
|
||||
} else if (stack.getCount() > 32) {
|
||||
i = 4;
|
||||
} else if (stack.getCount() > 16) {
|
||||
i = 3;
|
||||
} else if (stack.getCount() > 1) {
|
||||
i = 2;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -111,6 +111,10 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide
|
|||
}
|
||||
|
||||
public BlockPos getAvailableDestination(ItemStack stack) {
|
||||
for (int i = 0; i < this.upgrades.getSlots(); i++) {
|
||||
if (this.upgrades.getStackInSlot(i).getItem() == Registry.extractionUpgradeItem)
|
||||
return null;
|
||||
}
|
||||
for (Direction dir : Direction.values()) {
|
||||
IItemHandler handler = this.getItemHandler(dir);
|
||||
if (handler == null)
|
||||
|
@ -128,6 +132,6 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide
|
|||
TileEntity tile = this.world.getTileEntity(this.pos.offset(dir));
|
||||
if (tile == null)
|
||||
return null;
|
||||
return tile.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY).orElse(null);
|
||||
return tile.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, dir.getOpposite()).orElse(null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,24 +22,14 @@ public class NetworkEdge extends DefaultWeightedEdge implements INBTSerializable
|
|||
public BlockPos startPipe;
|
||||
public BlockPos endPipe;
|
||||
public final List<BlockPos> pipes = new ArrayList<>();
|
||||
private final Map<Integer, PipeTileEntity> tileCache = new HashMap<>();
|
||||
|
||||
public NetworkEdge(){
|
||||
public NetworkEdge() {
|
||||
}
|
||||
|
||||
public NetworkEdge(CompoundNBT nbt){
|
||||
public NetworkEdge(CompoundNBT nbt) {
|
||||
this.deserializeNBT(nbt);
|
||||
}
|
||||
|
||||
public PipeTileEntity getPipe(World world, int index) {
|
||||
PipeTileEntity tile = this.tileCache.get(index);
|
||||
if (tile == null || tile.isRemoved()) {
|
||||
tile = Utility.getTileEntity(PipeTileEntity.class, world, this.pipes.get(index));
|
||||
this.tileCache.put(index, tile);
|
||||
}
|
||||
return tile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundNBT serializeNBT() {
|
||||
CompoundNBT nbt = new CompoundNBT();
|
||||
|
|
|
@ -1,36 +1,47 @@
|
|||
package de.ellpeck.prettypipes.network;
|
||||
|
||||
import de.ellpeck.prettypipes.Utility;
|
||||
import de.ellpeck.prettypipes.blocks.pipe.PipeTileEntity;
|
||||
import net.minecraft.entity.item.ItemEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.nbt.ListNBT;
|
||||
import net.minecraft.nbt.NBTUtil;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.util.Constants;
|
||||
import net.minecraftforge.common.util.INBTSerializable;
|
||||
import net.minecraftforge.items.CapabilityItemHandler;
|
||||
import net.minecraftforge.items.IItemHandler;
|
||||
import net.minecraftforge.items.ItemHandlerHelper;
|
||||
import org.jgrapht.Graph;
|
||||
import org.jgrapht.GraphPath;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class PipeItem implements INBTSerializable<CompoundNBT> {
|
||||
|
||||
public static final int PIPE_TIME = 40;
|
||||
public static final int PIPE_TIME = 20;
|
||||
|
||||
public ItemStack stack;
|
||||
public float x;
|
||||
public float y;
|
||||
public float z;
|
||||
public float lastX;
|
||||
public float lastY;
|
||||
public float lastZ;
|
||||
|
||||
private final List<NetworkEdge> pathEdges;
|
||||
private final List<BlockPos> path;
|
||||
private BlockPos startPipe;
|
||||
private BlockPos destPipe;
|
||||
private BlockPos destInventory;
|
||||
private int pipeTimer;
|
||||
private int currentEdge;
|
||||
private int currentTile;
|
||||
|
||||
public PipeItem(ItemStack stack, BlockPos startPipe, BlockPos startInventory, BlockPos destPipe, BlockPos destInventory, GraphPath<BlockPos, NetworkEdge> path) {
|
||||
|
@ -38,14 +49,14 @@ public class PipeItem implements INBTSerializable<CompoundNBT> {
|
|||
this.startPipe = startPipe;
|
||||
this.destPipe = destPipe;
|
||||
this.destInventory = destInventory;
|
||||
this.pathEdges = path.getEdgeList();
|
||||
this.path = compilePath(path);
|
||||
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.z = MathHelper.lerp(0.5F, startInventory.getZ(), startPipe.getZ()) + 0.5F;
|
||||
}
|
||||
|
||||
public PipeItem(CompoundNBT nbt) {
|
||||
this.pathEdges = new ArrayList<>();
|
||||
this.path = new ArrayList<>();
|
||||
this.deserializeNBT(nbt);
|
||||
}
|
||||
|
||||
|
@ -57,8 +68,16 @@ public class PipeItem implements INBTSerializable<CompoundNBT> {
|
|||
currPipe.items.remove(this);
|
||||
PipeTileEntity next = this.getNextTile(currPipe, true);
|
||||
if (next == null) {
|
||||
// ..or store in our destination container if there is no next one
|
||||
this.store(currPipe);
|
||||
if (!currPipe.getWorld().isRemote) {
|
||||
if (this.reachedDestination()) {
|
||||
// ..or store in our destination container if we reached our destination
|
||||
this.stack = this.store(currPipe);
|
||||
if (!this.stack.isEmpty())
|
||||
this.onPathObstructed(currPipe);
|
||||
} else {
|
||||
this.onPathObstructed(currPipe);
|
||||
}
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
next.items.add(this);
|
||||
|
@ -69,7 +88,14 @@ public class PipeItem implements INBTSerializable<CompoundNBT> {
|
|||
// we're past the start of the pipe, so move to the center of the next pipe
|
||||
PipeTileEntity next = this.getNextTile(currPipe, false);
|
||||
if (next == null) {
|
||||
goalPos = this.destInventory;
|
||||
if (this.reachedDestination()) {
|
||||
goalPos = this.destInventory;
|
||||
} else {
|
||||
currPipe.items.remove(this);
|
||||
if (!currPipe.getWorld().isRemote)
|
||||
this.onPathObstructed(currPipe);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
goalPos = next.getPos();
|
||||
}
|
||||
|
@ -78,6 +104,10 @@ public class PipeItem implements INBTSerializable<CompoundNBT> {
|
|||
goalPos = currPipe.getPos();
|
||||
}
|
||||
|
||||
this.lastX = this.x;
|
||||
this.lastY = this.y;
|
||||
this.lastZ = this.z;
|
||||
|
||||
float speed = 1 / (float) PIPE_TIME;
|
||||
Vec3d dist = new Vec3d(goalPos.getX() + 0.5F - this.x, goalPos.getY() + 0.5F - this.y, goalPos.getZ() + 0.5F - this.z);
|
||||
dist = dist.normalize();
|
||||
|
@ -86,35 +116,39 @@ public class PipeItem implements INBTSerializable<CompoundNBT> {
|
|||
this.z += dist.z * speed;
|
||||
}
|
||||
|
||||
private void store(PipeTileEntity currPipe) {
|
||||
if (currPipe.getWorld().isRemote)
|
||||
return;
|
||||
// TODO store in destination
|
||||
private void onPathObstructed(PipeTileEntity currPipe) {
|
||||
// TODO when the path is obstructed, try to turn back home first
|
||||
this.drop(currPipe.getWorld());
|
||||
}
|
||||
|
||||
public void drop(World world) {
|
||||
ItemEntity item = new ItemEntity(world, this.x, this.y, this.z, this.stack.copy());
|
||||
item.world.addEntity(item);
|
||||
}
|
||||
|
||||
private ItemStack store(PipeTileEntity currPipe) {
|
||||
TileEntity tile = currPipe.getWorld().getTileEntity(this.destInventory);
|
||||
if (tile == null)
|
||||
return this.stack;
|
||||
Direction dir = Utility.getDirectionFromOffset(this.destPipe, this.destInventory);
|
||||
IItemHandler handler = tile.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, dir).orElse(null);
|
||||
if (handler == null)
|
||||
return this.stack;
|
||||
return ItemHandlerHelper.insertItemStacked(handler, this.stack, false);
|
||||
}
|
||||
|
||||
private boolean reachedDestination() {
|
||||
return this.currentTile >= this.path.size() - 1;
|
||||
}
|
||||
|
||||
private PipeTileEntity getNextTile(PipeTileEntity currPipe, boolean progress) {
|
||||
NetworkEdge edge = this.pathEdges.get(this.currentEdge);
|
||||
int currTile = this.currentTile;
|
||||
if (edge.pipes.size() > currTile + 1) {
|
||||
currTile++;
|
||||
} else {
|
||||
// are we at the end of our path?
|
||||
if (this.pathEdges.size() <= this.currentEdge + 1)
|
||||
return null;
|
||||
edge = this.pathEdges.get(this.currentEdge + 1);
|
||||
// we're setting the current tile to 1 since the 0th index of
|
||||
// the next edge is also the last index of the current edge
|
||||
currTile = 1;
|
||||
if (progress)
|
||||
this.currentEdge++;
|
||||
}
|
||||
if (this.path.size() <= this.currentTile + 1)
|
||||
return null;
|
||||
BlockPos pos = this.path.get(this.currentTile + 1);
|
||||
if (progress)
|
||||
this.currentTile = currTile;
|
||||
|
||||
// TODO invert the current tile index if the current edge is the other way around
|
||||
|
||||
|
||||
return edge.getPipe(currPipe.getWorld(), currTile);
|
||||
this.currentTile++;
|
||||
PipeNetwork network = PipeNetwork.get(currPipe.getWorld());
|
||||
return network.getPipe(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -125,14 +159,13 @@ public class PipeItem implements INBTSerializable<CompoundNBT> {
|
|||
nbt.put("dest_pipe", NBTUtil.writeBlockPos(this.destPipe));
|
||||
nbt.put("dest_inv", NBTUtil.writeBlockPos(this.destInventory));
|
||||
nbt.putInt("timer", this.pipeTimer);
|
||||
nbt.putInt("edge", this.currentEdge);
|
||||
nbt.putInt("tile", this.currentTile);
|
||||
nbt.putFloat("x", this.x);
|
||||
nbt.putFloat("y", this.y);
|
||||
nbt.putFloat("z", this.z);
|
||||
ListNBT list = new ListNBT();
|
||||
for (NetworkEdge edge : this.pathEdges)
|
||||
list.add(edge.serializeNBT());
|
||||
for (BlockPos pos : this.path)
|
||||
list.add(NBTUtil.writeBlockPos(pos));
|
||||
nbt.put("path", list);
|
||||
return nbt;
|
||||
}
|
||||
|
@ -144,14 +177,39 @@ public class PipeItem implements INBTSerializable<CompoundNBT> {
|
|||
this.destPipe = NBTUtil.readBlockPos(nbt.getCompound("dest_pipe"));
|
||||
this.destInventory = NBTUtil.readBlockPos(nbt.getCompound("dest_inv"));
|
||||
this.pipeTimer = nbt.getInt("timer");
|
||||
this.currentEdge = nbt.getInt("edge");
|
||||
this.currentTile = nbt.getInt("tile");
|
||||
this.x = nbt.getFloat("x");
|
||||
this.y = nbt.getFloat("y");
|
||||
this.z = nbt.getFloat("z");
|
||||
this.pathEdges.clear();
|
||||
this.path.clear();
|
||||
ListNBT list = nbt.getList("path", Constants.NBT.TAG_COMPOUND);
|
||||
for (int i = 0; i < list.size(); i++)
|
||||
this.pathEdges.add(new NetworkEdge(list.getCompound(i)));
|
||||
this.path.add(NBTUtil.readBlockPos(list.getCompound(i)));
|
||||
}
|
||||
|
||||
private static List<BlockPos> compilePath(GraphPath<BlockPos, NetworkEdge> path) {
|
||||
Graph<BlockPos, NetworkEdge> graph = path.getGraph();
|
||||
List<BlockPos> ret = new ArrayList<>();
|
||||
List<BlockPos> nodes = path.getVertexList();
|
||||
for (int i = 0; i < nodes.size() - 1; i++) {
|
||||
BlockPos first = nodes.get(i);
|
||||
BlockPos second = nodes.get(i + 1);
|
||||
NetworkEdge edge = graph.getEdge(first, second);
|
||||
Consumer<Integer> add = j -> {
|
||||
BlockPos pos = edge.pipes.get(j);
|
||||
if (!ret.contains(pos))
|
||||
ret.add(pos);
|
||||
};
|
||||
// if the edge is the other way around, we need to loop through tiles
|
||||
// the other way also
|
||||
if (!graph.getEdgeSource(edge).equals(first)) {
|
||||
for (int j = edge.pipes.size() - 1; j >= 0; j--)
|
||||
add.accept(j);
|
||||
} else {
|
||||
for (int j = 0; j < edge.pipes.size(); j++)
|
||||
add.accept(j);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -118,7 +118,6 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundNBT> {
|
|||
BlockPos dest = pipe.getAvailableDestination(stack);
|
||||
if (dest != null) {
|
||||
GraphPath<BlockPos, NetworkEdge> path = this.dijkstra.getPath(startPipePos, pipe.getPos());
|
||||
System.out.println("Found path " + path + " from " + startPipePos + " to " + pipe.getPos());
|
||||
PipeItem item = new PipeItem(stack.copy(), startPipePos, originInv, pipe.getPos(), dest, path);
|
||||
startPipe.items.add(item);
|
||||
PacketHandler.sendToAllLoaded(this.world, startPipePos, new PacketItemEnterPipe(startPipePos, item));
|
||||
|
|
Loading…
Reference in a new issue