IT'S DONE

This commit is contained in:
Ellpeck 2020-05-07 21:10:29 +02:00
parent ae74359ed5
commit fe3d4380f3
18 changed files with 299 additions and 93 deletions

View file

@ -76,7 +76,7 @@ public class ItemFilter extends ItemStackHandler {
} else if (id == 1 && this.canPopulateFromInventories) { } else if (id == 1 && this.canPopulateFromInventories) {
// populate filter from inventories // populate filter from inventories
for (Direction direction : Direction.values()) { for (Direction direction : Direction.values()) {
IItemHandler handler = this.pipe.getItemHandler(direction); IItemHandler handler = this.pipe.getItemHandler(direction, false);
if (handler == null) if (handler == null)
continue; continue;
for (int i = 0; i < handler.getSlots(); i++) { for (int i = 0; i < handler.getSlots(); i++) {
@ -104,7 +104,7 @@ public class ItemFilter extends ItemStackHandler {
.collect(Collectors.toList()); .collect(Collectors.toList());
for (int i = 0; i < this.getSlots(); i++) { for (int i = 0; i < this.getSlots(); i++) {
ItemStack filter = this.getStackInSlot(i); ItemStack filter = this.getStackInSlot(i);
if(filter.isEmpty()) if (filter.isEmpty())
continue; continue;
boolean equal = ItemStack.areItemsEqual(stack, filter); boolean equal = ItemStack.areItemsEqual(stack, filter);
if (modifiers.isEmpty()) { if (modifiers.isEmpty()) {

View file

@ -18,29 +18,23 @@ import java.util.List;
public class ItemTerminalWidget extends Widget { public class ItemTerminalWidget extends Widget {
private static final ResourceLocation FONT = new ResourceLocation(PrettyPipes.ID, "unicode"); private static final ResourceLocation FONT = new ResourceLocation(PrettyPipes.ID, "unicode");
private final ItemStack stack;
private final ItemTerminalGui screen; private final ItemTerminalGui screen;
public final int gridX; public final int gridX;
public final int gridY; public final int gridY;
public boolean hidden; public boolean selected;
public ItemStack stack = ItemStack.EMPTY;
public ItemTerminalWidget(int xIn, int yIn, int gridX, int gridY, ItemStack stack, ItemTerminalGui screen) { public ItemTerminalWidget(int xIn, int yIn, int gridX, int gridY, ItemTerminalGui screen) {
super(xIn, yIn, 16, 16, stack.getDisplayName().getFormattedText()); super(xIn, yIn, 16, 16, "");
this.gridX = gridX; this.gridX = gridX;
this.gridY = gridY; this.gridY = gridY;
this.stack = stack;
this.screen = screen; this.screen = screen;
} }
@Override @Override
protected boolean clicked(double x, double y) { public void onClick(double x, double y) {
return false; this.screen.streamWidgets().forEach(w -> w.selected = false);
} this.selected = true;
@Override
public void render(int mouseX, int mouseY, float partialTicks) {
if (!this.hidden)
super.render(mouseX, mouseY, partialTicks);
} }
@Override @Override
@ -49,6 +43,8 @@ public class ItemTerminalWidget extends Widget {
ItemRenderer renderer = mc.getItemRenderer(); ItemRenderer renderer = mc.getItemRenderer();
this.setBlitOffset(100); this.setBlitOffset(100);
renderer.zLevel = 100; renderer.zLevel = 100;
if (this.selected)
fill(this.x, this.y, this.x + 16, this.y + 16, -2130706433);
RenderSystem.enableDepthTest(); RenderSystem.enableDepthTest();
renderer.renderItemAndEffectIntoGUI(mc.player, this.stack, this.x, this.y); renderer.renderItemAndEffectIntoGUI(mc.player, this.stack, this.x, this.y);
int amount = this.stack.getCount(); int amount = this.stack.getCount();
@ -69,7 +65,7 @@ public class ItemTerminalWidget extends Widget {
@Override @Override
public void renderToolTip(int mouseX, int mouseY) { public void renderToolTip(int mouseX, int mouseY) {
if (this.isHovered()) { if (this.visible && this.isHovered()) {
FontRenderer font = this.stack.getItem().getFontRenderer(this.stack); FontRenderer font = this.stack.getItem().getFontRenderer(this.stack);
if (font == null) if (font == null)
font = this.screen.getMinecraft().fontRenderer; font = this.screen.getMinecraft().fontRenderer;

View file

@ -3,14 +3,11 @@ package de.ellpeck.prettypipes.network;
import de.ellpeck.prettypipes.misc.EquatableItemStack; import de.ellpeck.prettypipes.misc.EquatableItemStack;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import java.util.ArrayList; import java.util.*;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class NetworkItem { public class NetworkItem {
private final Set<NetworkLocation> locations = new HashSet<>(); private final List<NetworkLocation> locations = new ArrayList<>();
private final EquatableItemStack item; private final EquatableItemStack item;
private int amount; private int amount;
@ -19,8 +16,13 @@ public class NetworkItem {
} }
public void add(NetworkLocation location, ItemStack stack) { public void add(NetworkLocation location, ItemStack stack) {
this.locations.add(location);
this.amount += stack.getCount(); this.amount += stack.getCount();
if (!this.locations.contains(location))
this.locations.add(location);
}
public Collection<NetworkLocation> getLocations() {
return this.locations;
} }
public ItemStack asStack() { public ItemStack asStack() {

View file

@ -9,6 +9,7 @@ import net.minecraftforge.items.IItemHandler;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import java.util.*; import java.util.*;
import java.util.stream.Collectors;
public class NetworkLocation { public class NetworkLocation {
@ -31,14 +32,13 @@ public class NetworkLocation {
this.items.put(slot, stack); this.items.put(slot, stack);
} }
public int getStackSlot(ItemStack stack) { public List<Integer> getStackSlots(ItemStack stack) {
if (this.isEmpty()) if (this.isEmpty())
return -1; return Collections.emptyList();
for (Map.Entry<Integer, ItemStack> entry : this.items.entrySet()) { return this.items.entrySet().stream()
if (entry.getValue().isItemEqual(stack)) .filter(e -> e.getValue().isItemEqual(stack))
return entry.getKey(); .map(Map.Entry::getKey)
} .collect(Collectors.toList());
return -1;
} }
public int getItemAmount(ItemStack stack, boolean compareTag) { public int getItemAmount(ItemStack stack, boolean compareTag) {

View file

@ -172,7 +172,7 @@ public class PipeItem implements INBTSerializable<CompoundNBT>, ILiquidContainer
private ItemStack store(PipeTileEntity currPipe) { private ItemStack store(PipeTileEntity currPipe) {
Direction dir = Utility.getDirectionFromOffset(this.destInventory, this.getDestPipe()); Direction dir = Utility.getDirectionFromOffset(this.destInventory, this.getDestPipe());
IItemHandler handler = currPipe.getItemHandler(dir); IItemHandler handler = currPipe.getItemHandler(dir, true);
if (handler == null) if (handler == null)
return this.stack; return this.stack;
return ItemHandlerHelper.insertItemStacked(handler, this.stack, false); return ItemHandlerHelper.insertItemStacked(handler, this.stack, false);

View file

@ -188,7 +188,7 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundNBT>, GraphL
if (!pipe.canNetworkSee()) if (!pipe.canNetworkSee())
continue; continue;
for (Direction dir : Direction.values()) { for (Direction dir : Direction.values()) {
IItemHandler handler = pipe.getItemHandler(dir); IItemHandler handler = pipe.getItemHandler(dir, false);
if (handler == null) if (handler == null)
continue; continue;
// check if this handler already exists (double-connected pipes, double chests etc.) // check if this handler already exists (double-connected pipes, double chests etc.)

View file

@ -21,6 +21,7 @@ public final class PacketHandler {
network.registerMessage(0, PacketItemEnterPipe.class, PacketItemEnterPipe::toBytes, PacketItemEnterPipe::fromBytes, PacketItemEnterPipe::onMessage); network.registerMessage(0, PacketItemEnterPipe.class, PacketItemEnterPipe::toBytes, PacketItemEnterPipe::fromBytes, PacketItemEnterPipe::onMessage);
network.registerMessage(1, PacketButton.class, PacketButton::toBytes, PacketButton::fromBytes, PacketButton::onMessage); network.registerMessage(1, PacketButton.class, PacketButton::toBytes, PacketButton::fromBytes, PacketButton::onMessage);
network.registerMessage(2, PacketNetworkItems.class, PacketNetworkItems::toBytes, PacketNetworkItems::fromBytes, PacketNetworkItems::onMessage); network.registerMessage(2, PacketNetworkItems.class, PacketNetworkItems::toBytes, PacketNetworkItems::fromBytes, PacketNetworkItems::onMessage);
network.registerMessage(3, PacketRequest.class, PacketRequest::toBytes, PacketRequest::fromBytes, PacketRequest::onMessage);
} }
public static void sendToAllLoaded(World world, BlockPos pos, Object message) { public static void sendToAllLoaded(World world, BlockPos pos, Object message) {

View file

@ -44,7 +44,9 @@ public class PacketNetworkItems {
public static void toBytes(PacketNetworkItems packet, PacketBuffer buf) { public static void toBytes(PacketNetworkItems packet, PacketBuffer buf) {
buf.writeVarInt(packet.items.size()); buf.writeVarInt(packet.items.size());
for (ItemStack stack : packet.items) { for (ItemStack stack : packet.items) {
buf.writeItemStack(stack); ItemStack copy = stack.copy();
copy.setCount(1);
buf.writeItemStack(copy);
buf.writeVarInt(stack.getCount()); buf.writeVarInt(stack.getCount());
} }
} }

View file

@ -0,0 +1,56 @@
package de.ellpeck.prettypipes.packets;
import de.ellpeck.prettypipes.Utility;
import de.ellpeck.prettypipes.terminal.ItemTerminalTileEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.fml.network.NetworkEvent;
import java.util.function.Supplier;
public class PacketRequest {
private BlockPos pos;
private ItemStack stack;
private int amount;
public PacketRequest(BlockPos pos, ItemStack stack, int amount) {
this.pos = pos;
this.stack = stack;
this.amount = amount;
}
private PacketRequest() {
}
public static PacketRequest fromBytes(PacketBuffer buf) {
PacketRequest packet = new PacketRequest();
packet.pos = buf.readBlockPos();
packet.stack = buf.readItemStack();
packet.amount = buf.readVarInt();
return packet;
}
public static void toBytes(PacketRequest packet, PacketBuffer buf) {
buf.writeBlockPos(packet.pos);
buf.writeItemStack(packet.stack);
buf.writeVarInt(packet.amount);
}
@SuppressWarnings("Convert2Lambda")
public static void onMessage(PacketRequest message, Supplier<NetworkEvent.Context> ctx) {
ctx.get().enqueueWork(new Runnable() {
@Override
public void run() {
PlayerEntity player = ctx.get().getSender();
ItemTerminalTileEntity tile = Utility.getTileEntity(ItemTerminalTileEntity.class, player.world, message.pos);
message.stack.setCount(message.amount);
tile.requestItem(player, message.stack);
}
});
ctx.get().setPacketHandled(true);
}
}

View file

@ -4,9 +4,13 @@ import net.minecraft.block.BlockState;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
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.items.IItemHandler;
public interface IPipeConnectable { public interface IPipeConnectable {
ConnectionType getConnectionType(World world, BlockPos pos, BlockState state, BlockPos pipePos, Direction direction); ConnectionType getConnectionType(World world, BlockPos pos, BlockState state, BlockPos pipePos, Direction direction);
default IItemHandler getItemHandler(World world, BlockPos pos, BlockState state, BlockPos pipePos, Direction direction, boolean force) {
return null;
}
} }

View file

@ -72,7 +72,7 @@ public class PipeBlock extends ContainerBlock implements IPipeConnectable {
PipeTileEntity tile = Utility.getTileEntity(PipeTileEntity.class, worldIn, pos); PipeTileEntity tile = Utility.getTileEntity(PipeTileEntity.class, worldIn, pos);
if (tile == null) if (tile == null)
return ActionResultType.PASS; return ActionResultType.PASS;
if (!tile.isConnectedInventory()) if (!tile.isConnectedInventory(false))
return ActionResultType.PASS; return ActionResultType.PASS;
if (!worldIn.isRemote) if (!worldIn.isRemote)
NetworkHooks.openGui((ServerPlayerEntity) player, tile, pos); NetworkHooks.openGui((ServerPlayerEntity) player, tile, pos);
@ -185,7 +185,7 @@ public class PipeBlock extends ContainerBlock implements IPipeConnectable {
public static void onStateChanged(World world, BlockPos pos, BlockState newState) { public static void onStateChanged(World world, BlockPos pos, BlockState newState) {
PipeTileEntity tile = Utility.getTileEntity(PipeTileEntity.class, world, pos); PipeTileEntity tile = Utility.getTileEntity(PipeTileEntity.class, world, pos);
if (tile != null && !tile.isConnectedInventory()) if (tile != null && !tile.isConnectedInventory(false))
Utility.dropInventory(tile, tile.modules); Utility.dropInventory(tile, tile.modules);
PipeNetwork network = PipeNetwork.get(world); PipeNetwork network = PipeNetwork.get(world);

View file

@ -133,13 +133,13 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide
return this.getBlockState().get(PipeBlock.DIRECTIONS.get(dir)).isConnected(); return this.getBlockState().get(PipeBlock.DIRECTIONS.get(dir)).isConnected();
} }
public BlockPos getAvailableDestination(ItemStack stack, boolean internal, boolean preventOversending) { public BlockPos getAvailableDestination(ItemStack stack, boolean force, boolean preventOversending) {
if (!this.canWork()) if (!this.canWork())
return null; return null;
if (!internal && this.streamModules().anyMatch(m -> !m.getRight().canAcceptItem(m.getLeft(), this, stack))) if (!force && this.streamModules().anyMatch(m -> !m.getRight().canAcceptItem(m.getLeft(), this, stack)))
return null; return null;
for (Direction dir : Direction.values()) { for (Direction dir : Direction.values()) {
IItemHandler handler = this.getItemHandler(dir); IItemHandler handler = this.getItemHandler(dir, force);
if (handler == null) if (handler == null)
continue; continue;
if (!ItemHandlerHelper.insertItem(handler, stack, true).isEmpty()) if (!ItemHandlerHelper.insertItem(handler, stack, true).isEmpty())
@ -185,27 +185,37 @@ public class PipeTileEntity extends TileEntity implements INamedContainerProvide
return this.streamModules().allMatch(m -> m.getRight().canPipeWork(m.getLeft(), this)); return this.streamModules().allMatch(m -> m.getRight().canPipeWork(m.getLeft(), this));
} }
public IItemHandler getItemHandler(Direction dir) { public IItemHandler getItemHandler(Direction dir, boolean force) {
if (!this.isConnected(dir)) if (!this.isConnected(dir))
return null; return null;
TileEntity tile = this.world.getTileEntity(this.pos.offset(dir)); BlockPos pos = this.pos.offset(dir);
if (tile == null) TileEntity tile = this.world.getTileEntity(pos);
return null; if (tile != null) {
// if we don't do this, then chests get really weird // if we don't do this, then chests get really weird
if (tile instanceof ChestTileEntity) { if (tile instanceof ChestTileEntity) {
BlockState state = this.world.getBlockState(tile.getPos()); BlockState state = this.world.getBlockState(tile.getPos());
if (state.getBlock() instanceof ChestBlock) if (state.getBlock() instanceof ChestBlock)
return new InvWrapper(ChestBlock.func_226916_a_((ChestBlock) state.getBlock(), state, this.world, tile.getPos(), true)); return new InvWrapper(ChestBlock.func_226916_a_((ChestBlock) state.getBlock(), state, this.world, tile.getPos(), true));
}
IItemHandler handler = tile.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, dir.getOpposite()).orElse(null);
if (handler != null)
return handler;
} }
return tile.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, dir.getOpposite()).orElse(null); BlockState state = this.world.getBlockState(pos);
if (state.getBlock() instanceof IPipeConnectable) {
IItemHandler handler = ((IPipeConnectable) state.getBlock()).getItemHandler(this.world, pos, state, this.pos, dir, force);
if (handler != null)
return handler;
}
return null;
} }
public boolean isConnectedInventory(Direction dir) { public boolean isConnectedInventory(Direction dir, boolean force) {
return this.getItemHandler(dir) != null; return this.getItemHandler(dir, force) != null;
} }
public boolean isConnectedInventory() { public boolean isConnectedInventory(boolean force) {
return Arrays.stream(Direction.values()).anyMatch(this::isConnectedInventory); return Arrays.stream(Direction.values()).anyMatch(dir -> this.isConnectedInventory(dir, force));
} }
public boolean canNetworkSee() { public boolean canNetworkSee() {

View file

@ -33,13 +33,13 @@ public class ExtractionModuleItem extends ModuleItem {
public void tick(ItemStack module, PipeTileEntity tile) { public void tick(ItemStack module, PipeTileEntity tile) {
if (tile.getWorld().getGameTime() % this.speed != 0) if (tile.getWorld().getGameTime() % this.speed != 0)
return; return;
if(!tile.canWork()) if (!tile.canWork())
return; return;
ItemFilter filter = new ItemFilter(this.filterSlots, module, tile); ItemFilter filter = new ItemFilter(this.filterSlots, module, tile);
PipeNetwork network = PipeNetwork.get(tile.getWorld()); PipeNetwork network = PipeNetwork.get(tile.getWorld());
for (Direction dir : Direction.values()) { for (Direction dir : Direction.values()) {
IItemHandler handler = tile.getItemHandler(dir); IItemHandler handler = tile.getItemHandler(dir, false);
if (handler == null) if (handler == null)
continue; continue;
for (int j = 0; j < handler.getSlots(); j++) { for (int j = 0; j < handler.getSlots(); j++) {

View file

@ -58,14 +58,13 @@ public class RetrievalModuleItem extends ModuleItem {
for (NetworkLocation location : locations) { for (NetworkLocation location : locations) {
if (location.pipePos.equals(tile.getPos())) if (location.pipePos.equals(tile.getPos()))
continue; continue;
int slot = location.getStackSlot(filtered); for (int slot : location.getStackSlots(filtered)) {
if (slot < 0) // try to extract from that location's inventory and send the item
continue; ItemStack stack = location.handler.extractItem(slot, this.maxExtraction, true);
// try to extract from that location's inventory and send the item if (network.routeItemToLocation(location.pipePos, location.pos, tile.getPos(), dest, speed -> new PipeItem(stack, speed))) {
ItemStack stack = location.handler.extractItem(slot, this.maxExtraction, true); location.handler.extractItem(slot, stack.getCount(), false);
if (network.routeItemToLocation(location.pipePos, location.pos, tile.getPos(), dest, speed -> new PipeItem(stack, speed))) { return;
location.handler.extractItem(slot, stack.getCount(), false); }
return;
} }
} }
} }

View file

@ -20,6 +20,7 @@ import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.world.IBlockReader; import net.minecraft.world.IBlockReader;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.fml.network.NetworkHooks; import net.minecraftforge.fml.network.NetworkHooks;
import net.minecraftforge.items.IItemHandler;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -30,8 +31,6 @@ public class ItemTerminalBlock extends ContainerBlock implements IPipeConnectabl
@Override @Override
public ActionResultType onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, BlockRayTraceResult result) { public ActionResultType onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, BlockRayTraceResult result) {
if (!player.getHeldItem(handIn).isEmpty())
return ActionResultType.PASS;
ItemTerminalTileEntity tile = Utility.getTileEntity(ItemTerminalTileEntity.class, worldIn, pos); ItemTerminalTileEntity tile = Utility.getTileEntity(ItemTerminalTileEntity.class, worldIn, pos);
if (tile == null) if (tile == null)
return ActionResultType.PASS; return ActionResultType.PASS;
@ -53,6 +52,16 @@ public class ItemTerminalBlock extends ContainerBlock implements IPipeConnectabl
return ConnectionType.CONNECTED; return ConnectionType.CONNECTED;
} }
@Override
public IItemHandler getItemHandler(World world, BlockPos pos, BlockState state, BlockPos pipePos, Direction direction, boolean force) {
if (force) {
ItemTerminalTileEntity tile = Utility.getTileEntity(ItemTerminalTileEntity.class, world, pos);
if (tile != null)
return tile.items;
}
return null;
}
@Override @Override
public BlockRenderType getRenderType(BlockState state) { public BlockRenderType getRenderType(BlockState state) {
return BlockRenderType.MODEL; return BlockRenderType.MODEL;

View file

@ -6,6 +6,7 @@ import de.ellpeck.prettypipes.Utility;
import de.ellpeck.prettypipes.misc.EquatableItemStack; import de.ellpeck.prettypipes.misc.EquatableItemStack;
import de.ellpeck.prettypipes.network.NetworkItem; import de.ellpeck.prettypipes.network.NetworkItem;
import de.ellpeck.prettypipes.network.NetworkLocation; import de.ellpeck.prettypipes.network.NetworkLocation;
import de.ellpeck.prettypipes.network.PipeItem;
import de.ellpeck.prettypipes.network.PipeNetwork; import de.ellpeck.prettypipes.network.PipeNetwork;
import de.ellpeck.prettypipes.packets.PacketHandler; import de.ellpeck.prettypipes.packets.PacketHandler;
import de.ellpeck.prettypipes.packets.PacketNetworkItems; import de.ellpeck.prettypipes.packets.PacketNetworkItems;
@ -24,10 +25,14 @@ import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.Style;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.util.text.TranslationTextComponent; import net.minecraft.util.text.TranslationTextComponent;
import net.minecraft.world.server.ServerWorld; import net.minecraft.world.server.ServerWorld;
import net.minecraftforge.items.ItemStackHandler; import net.minecraftforge.items.ItemStackHandler;
import org.apache.commons.lang3.mutable.MutableInt; import org.apache.commons.lang3.mutable.MutableInt;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.lang3.tuple.Triple;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -39,10 +44,11 @@ public class ItemTerminalTileEntity extends TileEntity implements INamedContaine
public final ItemStackHandler items = new ItemStackHandler(12) { public final ItemStackHandler items = new ItemStackHandler(12) {
@Override @Override
public boolean isItemValid(int slot, @Nonnull ItemStack stack) { public boolean isItemValid(int slot, @Nonnull ItemStack stack) {
return slot >= 6; return true;
} }
}; };
public Collection<NetworkItem> networkItems; public Map<EquatableItemStack, NetworkItem> networkItems;
private Queue<Triple<NetworkLocation, Integer, Integer>> pendingRequests = new ArrayDeque<>();
public ItemTerminalTileEntity() { public ItemTerminalTileEntity() {
super(Registry.itemTerminalTileEntity); super(Registry.itemTerminalTileEntity);
@ -67,13 +73,20 @@ public class ItemTerminalTileEntity extends TileEntity implements INamedContaine
this.items.extractItem(i, extracted.getCount(), false); this.items.extractItem(i, extracted.getCount(), false);
break; break;
} }
if (!this.pendingRequests.isEmpty()) {
Triple<NetworkLocation, Integer, Integer> request = this.pendingRequests.remove();
NetworkLocation location = request.getLeft();
int slot = request.getMiddle();
int amount = request.getRight();
ItemStack extracted = location.handler.extractItem(slot, amount, true);
if (network.routeItemToLocation(location.pipePos, location.pos, pipe.getPos(), this.pos, speed -> new PipeItem(extracted, speed)))
location.handler.extractItem(slot, extracted.getCount(), false);
}
} }
if (this.world.getGameTime() % 100 == 0) { if (this.world.getGameTime() % 100 == 0) {
PlayerEntity[] lookingPlayers = this.world.getPlayers().stream() PlayerEntity[] lookingPlayers = this.getLookingPlayers();
.filter(p -> p.openContainer instanceof ItemTerminalContainer)
.filter(p -> ((ItemTerminalContainer) p.openContainer).tile == this)
.toArray(PlayerEntity[]::new);
if (lookingPlayers.length > 0) if (lookingPlayers.length > 0)
this.updateItems(lookingPlayers); this.updateItems(lookingPlayers);
} }
@ -91,18 +104,54 @@ public class ItemTerminalTileEntity extends TileEntity implements INamedContaine
public void updateItems(PlayerEntity... playersToSync) { public void updateItems(PlayerEntity... playersToSync) {
this.networkItems = this.collectItems(); this.networkItems = this.collectItems();
List<ItemStack> clientItems = this.networkItems.stream().map(NetworkItem::asStack).collect(Collectors.toList()); if (playersToSync.length > 0) {
for (PlayerEntity player : playersToSync) { List<ItemStack> clientItems = this.networkItems.values().stream().map(NetworkItem::asStack).collect(Collectors.toList());
if (!(player.openContainer instanceof ItemTerminalContainer)) for (PlayerEntity player : playersToSync) {
continue; if (!(player.openContainer instanceof ItemTerminalContainer))
ItemTerminalTileEntity tile = ((ItemTerminalContainer) player.openContainer).tile; continue;
if (tile != this) ItemTerminalTileEntity tile = ((ItemTerminalContainer) player.openContainer).tile;
continue; if (tile != this)
PacketHandler.sendTo(player, new PacketNetworkItems(clientItems)); continue;
PacketHandler.sendTo(player, new PacketNetworkItems(clientItems));
}
} }
} }
private Collection<NetworkItem> collectItems() { public void requestItem(PlayerEntity player, ItemStack stack) {
PipeNetwork network = PipeNetwork.get(this.world);
network.startProfile("terminal_request_item");
EquatableItemStack equatable = new EquatableItemStack(stack);
NetworkItem item = this.networkItems.get(equatable);
if (item != null) {
int remain = stack.getCount();
locations:
for (NetworkLocation location : item.getLocations()) {
for (int slot : location.getStackSlots(stack)) {
ItemStack extracted = location.handler.extractItem(slot, remain, true);
if (!extracted.isEmpty()) {
this.pendingRequests.add(Triple.of(location, slot, extracted.getCount()));
remain -= extracted.getCount();
if (remain <= 0)
break locations;
}
}
}
player.sendMessage(new TranslationTextComponent("info." + PrettyPipes.ID + ".sending", stack.getCount() - remain, stack.getDisplayName()).setStyle(new Style().setColor(TextFormatting.GREEN)));
this.updateItems(player);
} else {
player.sendMessage(new TranslationTextComponent("info." + PrettyPipes.ID + ".not_found", stack.getDisplayName()).setStyle(new Style().setColor(TextFormatting.RED)));
}
network.endProfile();
}
private PlayerEntity[] getLookingPlayers() {
return this.world.getPlayers().stream()
.filter(p -> p.openContainer instanceof ItemTerminalContainer)
.filter(p -> ((ItemTerminalContainer) p.openContainer).tile == this)
.toArray(PlayerEntity[]::new);
}
private Map<EquatableItemStack, NetworkItem> collectItems() {
PipeNetwork network = PipeNetwork.get(this.world); PipeNetwork network = PipeNetwork.get(this.world);
network.startProfile("terminal_collect_items"); network.startProfile("terminal_collect_items");
PipeTileEntity pipe = this.getConnectedPipe(); PipeTileEntity pipe = this.getConnectedPipe();
@ -115,7 +164,7 @@ public class ItemTerminalTileEntity extends TileEntity implements INamedContaine
} }
} }
network.endProfile(); network.endProfile();
return items.values(); return items;
} }
@Override @Override

View file

@ -2,17 +2,29 @@ package de.ellpeck.prettypipes.terminal.containers;
import de.ellpeck.prettypipes.PrettyPipes; import de.ellpeck.prettypipes.PrettyPipes;
import de.ellpeck.prettypipes.misc.ItemTerminalWidget; import de.ellpeck.prettypipes.misc.ItemTerminalWidget;
import de.ellpeck.prettypipes.packets.PacketHandler;
import de.ellpeck.prettypipes.packets.PacketRequest;
import net.minecraft.client.gui.screen.inventory.ContainerScreen; import net.minecraft.client.gui.screen.inventory.ContainerScreen;
import net.minecraft.client.gui.widget.Widget; import net.minecraft.client.gui.widget.Widget;
import net.minecraft.client.gui.widget.button.Button;
import net.minecraft.client.resources.I18n;
import net.minecraft.entity.player.PlayerInventory; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.ITextComponent;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class ItemTerminalGui extends ContainerScreen<ItemTerminalContainer> { public class ItemTerminalGui extends ContainerScreen<ItemTerminalContainer> {
private static final ResourceLocation TEXTURE = new ResourceLocation(PrettyPipes.ID, "textures/gui/item_terminal.png"); private static final ResourceLocation TEXTURE = new ResourceLocation(PrettyPipes.ID, "textures/gui/item_terminal.png");
private List<ItemStack> items;
private Button minusButton;
private Button plusButton;
private Button requestButton;
private int requestAmount = 1;
public ItemTerminalGui(ItemTerminalContainer screenContainer, PlayerInventory inv, ITextComponent titleIn) { public ItemTerminalGui(ItemTerminalContainer screenContainer, PlayerInventory inv, ITextComponent titleIn) {
super(screenContainer, inv, titleIn); super(screenContainer, inv, titleIn);
@ -20,16 +32,65 @@ public class ItemTerminalGui extends ContainerScreen<ItemTerminalContainer> {
this.ySize = 236; this.ySize = 236;
} }
@Override
protected void init() {
super.init();
this.plusButton = this.addButton(new Button(this.guiLeft + this.xSize / 2 - 7 + 12, this.guiTop + 103, 12, 12, "+", button -> {
int modifier = requestModifier();
if (modifier > 1 && this.requestAmount == 1) {
this.requestAmount = modifier;
} else {
this.requestAmount += modifier;
}
if (this.requestAmount > 384)
this.requestAmount = 384;
}));
this.minusButton = this.addButton(new Button(this.guiLeft + this.xSize / 2 - 7 - 24, this.guiTop + 103, 12, 12, "-", button -> {
this.requestAmount -= requestModifier();
if (this.requestAmount < 1)
this.requestAmount = 1;
}));
this.minusButton.active = false;
this.requestButton = this.addButton(new Button(this.guiLeft + this.xSize / 2 - 7 - 25, this.guiTop + 115, 50, 20, I18n.format("info." + PrettyPipes.ID + ".request"), button -> {
Optional<ItemTerminalWidget> widget = this.streamWidgets().filter(w -> w.selected).findFirst();
if (!widget.isPresent())
return;
ItemStack stack = widget.get().stack.copy();
stack.setCount(1);
PacketHandler.sendToServer(new PacketRequest(this.container.tile.getPos(), stack, this.requestAmount));
this.requestAmount = 1;
}));
this.requestButton.active = false;
for (int y = 0; y < 4; y++) {
for (int x = 0; x < 9; x++)
this.addButton(new ItemTerminalWidget(this.guiLeft + 8 + x * 18, this.guiTop + 18 + y * 18, x, y, this));
}
}
@Override
public void tick() {
super.tick();
this.requestButton.active = this.streamWidgets().anyMatch(w -> w.selected);
this.plusButton.active = this.requestAmount < 384;
this.minusButton.active = this.requestAmount > 1;
}
public void updateItemList(List<ItemStack> items) { public void updateItemList(List<ItemStack> items) {
this.buttons.removeIf(w -> w instanceof ItemTerminalWidget); this.items = items;
int x = 0; this.updateWidgets(0);
int y = 0; }
for (ItemStack stack : items) {
this.buttons.add(new ItemTerminalWidget(this.guiLeft + 8 + x * 18, this.guiTop + 18 + y * 18, x, y, stack, this)); private void updateWidgets(int scrollOffset) {
x++; List<ItemTerminalWidget> widgets = this.streamWidgets().collect(Collectors.toList());
if (x > 8) { for (int i = 0; i < widgets.size(); i++) {
x = 0; ItemTerminalWidget widget = widgets.get(i);
y++; int index = i + scrollOffset * 9;
if (index >= this.items.size()) {
widget.stack = ItemStack.EMPTY;
widget.visible = false;
} else {
widget.stack = this.items.get(index);
widget.visible = true;
} }
} }
} }
@ -49,6 +110,9 @@ public class ItemTerminalGui extends ContainerScreen<ItemTerminalContainer> {
protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) { protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) {
this.font.drawString(this.playerInventory.getDisplayName().getFormattedText(), 8, this.ySize - 96 + 2, 4210752); this.font.drawString(this.playerInventory.getDisplayName().getFormattedText(), 8, this.ySize - 96 + 2, 4210752);
this.font.drawString(this.title.getFormattedText(), 8, 6, 4210752); this.font.drawString(this.title.getFormattedText(), 8, 6, 4210752);
String amount = String.valueOf(this.requestAmount);
this.font.drawString(amount, (this.xSize - this.font.getStringWidth(amount)) / 2F - 7, 106, 4210752);
} }
@Override @Override
@ -57,9 +121,19 @@ public class ItemTerminalGui extends ContainerScreen<ItemTerminalContainer> {
this.blit(this.guiLeft, this.guiTop, 0, 0, this.xSize, this.ySize); this.blit(this.guiLeft, this.guiTop, 0, 0, this.xSize, this.ySize);
} }
// public overload for ItemTerminalWidget public Stream<ItemTerminalWidget> streamWidgets() {
@Override return this.buttons.stream()
public void renderTooltip(ItemStack stack, int x, int y) { .filter(w -> w instanceof ItemTerminalWidget)
super.renderTooltip(stack, x, y); .map(w -> (ItemTerminalWidget) w);
}
private static int requestModifier() {
if (hasControlDown()) {
return 10;
} else if (hasShiftDown()) {
return 64;
} else {
return 1;
}
} }
} }

View file

@ -36,6 +36,7 @@
"block.prettypipes.pipe": "Pipe", "block.prettypipes.pipe": "Pipe",
"itemGroup.prettypipes": "Pretty Pipes", "itemGroup.prettypipes": "Pretty Pipes",
"container.prettypipes.pipe": "Pipe", "container.prettypipes.pipe": "Pipe",
"container.prettypipes.item_terminal": "Item Terminal",
"info.prettypipes.whitelist": "Allowed", "info.prettypipes.whitelist": "Allowed",
"info.prettypipes.blacklist": "Disallowed", "info.prettypipes.blacklist": "Disallowed",
"info.prettypipes.shift": "Hold Shift for info", "info.prettypipes.shift": "Hold Shift for info",
@ -43,5 +44,8 @@
"info.prettypipes.populate.description": "Filters items from adjacent inventories", "info.prettypipes.populate.description": "Filters items from adjacent inventories",
"info.prettypipes.max_stack_size": "Maximum item amount", "info.prettypipes.max_stack_size": "Maximum item amount",
"info.prettypipes.limit_to_max_on": "Limit to one stack", "info.prettypipes.limit_to_max_on": "Limit to one stack",
"info.prettypipes.limit_to_max_off": "Don't limit to one stack" "info.prettypipes.limit_to_max_off": "Don't limit to one stack",
"info.prettypipes.request": "Request",
"info.prettypipes.not_found": "%s not found",
"info.prettypipes.sending": "Sending %s %s"
} }