mirror of
https://github.com/Ellpeck/PrettyPipes.git
synced 2024-11-26 05:28:33 +01:00
item terminal, part 1
This commit is contained in:
parent
d4031c19e1
commit
ae74359ed5
19 changed files with 641 additions and 63 deletions
|
@ -23,6 +23,10 @@ import de.ellpeck.prettypipes.pipe.modules.retrieval.RetrievalModuleItem;
|
|||
import de.ellpeck.prettypipes.pipe.modules.stacksize.StackSizeModuleContainer;
|
||||
import de.ellpeck.prettypipes.pipe.modules.stacksize.StackSizeModuleGui;
|
||||
import de.ellpeck.prettypipes.pipe.modules.stacksize.StackSizeModuleItem;
|
||||
import de.ellpeck.prettypipes.terminal.ItemTerminalBlock;
|
||||
import de.ellpeck.prettypipes.terminal.ItemTerminalTileEntity;
|
||||
import de.ellpeck.prettypipes.terminal.containers.ItemTerminalContainer;
|
||||
import de.ellpeck.prettypipes.terminal.containers.ItemTerminalGui;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.client.gui.ScreenManager;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
|
@ -77,10 +81,14 @@ public final class Registry {
|
|||
|
||||
public static Block pipeBlock;
|
||||
public static TileEntityType<PipeTileEntity> pipeTileEntity;
|
||||
public static ContainerType<MainPipeContainer> pipeContainer;
|
||||
|
||||
public static Block itemTerminalBlock;
|
||||
public static TileEntityType<ItemTerminalTileEntity> itemTerminalTileEntity;
|
||||
public static ContainerType<ItemTerminalContainer> itemTerminalContainer;
|
||||
|
||||
public static EntityType<PipeFrameEntity> pipeFrameEntity;
|
||||
|
||||
public static ContainerType<MainPipeContainer> pipeContainer;
|
||||
public static ContainerType<ExtractionModuleContainer> extractionModuleContainer;
|
||||
public static ContainerType<FilterModuleContainer> filterModuleContainer;
|
||||
public static ContainerType<RetrievalModuleContainer> retrievalModuleContainer;
|
||||
|
@ -89,7 +97,8 @@ public final class Registry {
|
|||
@SubscribeEvent
|
||||
public static void registerBlocks(RegistryEvent.Register<Block> event) {
|
||||
event.getRegistry().registerAll(
|
||||
pipeBlock = new PipeBlock().setRegistryName("pipe")
|
||||
pipeBlock = new PipeBlock().setRegistryName("pipe"),
|
||||
itemTerminalBlock = new ItemTerminalBlock().setRegistryName("item_terminal")
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -118,7 +127,8 @@ public final class Registry {
|
|||
@SubscribeEvent
|
||||
public static void registerTiles(RegistryEvent.Register<TileEntityType<?>> event) {
|
||||
event.getRegistry().registerAll(
|
||||
pipeTileEntity = (TileEntityType<PipeTileEntity>) TileEntityType.Builder.create(PipeTileEntity::new, pipeBlock).build(null).setRegistryName("pipe")
|
||||
pipeTileEntity = (TileEntityType<PipeTileEntity>) TileEntityType.Builder.create(PipeTileEntity::new, pipeBlock).build(null).setRegistryName("pipe"),
|
||||
itemTerminalTileEntity = (TileEntityType<ItemTerminalTileEntity>) TileEntityType.Builder.create(ItemTerminalTileEntity::new, itemTerminalBlock).build(null).setRegistryName("item_terminal")
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -132,8 +142,8 @@ public final class Registry {
|
|||
@SubscribeEvent
|
||||
public static void registerContainers(RegistryEvent.Register<ContainerType<?>> event) {
|
||||
event.getRegistry().registerAll(
|
||||
// this needs to be registered manually since it doesn't send the module slot
|
||||
pipeContainer = (ContainerType<MainPipeContainer>) IForgeContainerType.create((windowId, inv, data) -> new MainPipeContainer(pipeContainer, windowId, inv.player, data.readBlockPos())).setRegistryName("pipe"),
|
||||
itemTerminalContainer = (ContainerType<ItemTerminalContainer>) IForgeContainerType.create((windowId, inv, data) -> new ItemTerminalContainer(itemTerminalContainer, windowId, inv.player, data.readBlockPos())).setRegistryName("item_terminal"),
|
||||
extractionModuleContainer = createPipeContainer("extraction_module"),
|
||||
filterModuleContainer = createPipeContainer("filter_module"),
|
||||
retrievalModuleContainer = createPipeContainer("retrieval_module"),
|
||||
|
@ -180,6 +190,7 @@ public final class Registry {
|
|||
RenderingRegistry.registerEntityRenderingHandler(pipeFrameEntity, PipeFrameRenderer::new);
|
||||
|
||||
ScreenManager.registerFactory(pipeContainer, MainPipeGui::new);
|
||||
ScreenManager.registerFactory(itemTerminalContainer, ItemTerminalGui::new);
|
||||
ScreenManager.registerFactory(extractionModuleContainer, ExtractionModuleGui::new);
|
||||
ScreenManager.registerFactory(filterModuleContainer, FilterModuleGui::new);
|
||||
ScreenManager.registerFactory(retrievalModuleContainer, RetrievalModuleGui::new);
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
package de.ellpeck.prettypipes;
|
||||
|
||||
import de.ellpeck.prettypipes.items.IModule;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.inventory.InventoryHelper;
|
||||
import net.minecraft.inventory.container.Container;
|
||||
import net.minecraft.inventory.container.Slot;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.Direction;
|
||||
|
@ -10,8 +14,11 @@ import net.minecraft.util.math.BlockPos;
|
|||
import net.minecraft.util.text.*;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.items.IItemHandler;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public final class Utility {
|
||||
|
||||
|
@ -43,4 +50,51 @@ public final class Utility {
|
|||
tooltip.add(new TranslationTextComponent("info." + PrettyPipes.ID + ".shift").setStyle(new Style().setColor(TextFormatting.DARK_GRAY)));
|
||||
}
|
||||
}
|
||||
|
||||
public static ItemStack transferStackInSlot(Container container, IMergeItemStack merge, PlayerEntity player, int slotIndex, Function<ItemStack, Pair<Integer, Integer>> predicate) {
|
||||
int inventoryStart = (int) container.inventorySlots.stream().filter(slot -> slot.inventory != player.inventory).count();
|
||||
int inventoryEnd = inventoryStart + 26;
|
||||
int hotbarStart = inventoryEnd + 1;
|
||||
int hotbarEnd = hotbarStart + 8;
|
||||
|
||||
Slot slot = container.inventorySlots.get(slotIndex);
|
||||
if (slot != null && slot.getHasStack()) {
|
||||
ItemStack newStack = slot.getStack();
|
||||
ItemStack currentStack = newStack.copy();
|
||||
|
||||
if (slotIndex >= inventoryStart) {
|
||||
// shift into this container here
|
||||
// mergeItemStack with the slots that newStack should go into
|
||||
// return an empty stack if mergeItemStack fails
|
||||
Pair<Integer, Integer> slots = predicate.apply(newStack);
|
||||
if (slots != null) {
|
||||
if (!merge.mergeItemStack(newStack, slots.getLeft(), slots.getRight(), false))
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
// end custom code
|
||||
else if (slotIndex >= inventoryStart && slotIndex <= inventoryEnd) {
|
||||
if (!merge.mergeItemStack(newStack, hotbarStart, hotbarEnd + 1, false))
|
||||
return ItemStack.EMPTY;
|
||||
} else if (slotIndex >= inventoryEnd + 1 && slotIndex < hotbarEnd + 1 && !merge.mergeItemStack(newStack, inventoryStart, inventoryEnd + 1, false)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
} else if (!merge.mergeItemStack(newStack, inventoryStart, hotbarEnd + 1, false)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
if (newStack.isEmpty()) {
|
||||
slot.putStack(ItemStack.EMPTY);
|
||||
} else {
|
||||
slot.onSlotChanged();
|
||||
}
|
||||
if (newStack.getCount() == currentStack.getCount())
|
||||
return ItemStack.EMPTY;
|
||||
slot.onTake(player, newStack);
|
||||
return currentStack;
|
||||
}
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
public interface IMergeItemStack {
|
||||
boolean mergeItemStack(ItemStack stack, int startIndex, int endIndex, boolean reverseDirection);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,7 +68,7 @@ public class PipeFrameEntity extends ItemFrameEntity implements IEntityAdditiona
|
|||
ItemStack stack = this.getDisplayedItem();
|
||||
if (!stack.isEmpty()) {
|
||||
List<NetworkLocation> items = network.getOrderedNetworkItems(node);
|
||||
int amount = items.stream().mapToInt(i -> i.getItemAmount(stack)).sum();
|
||||
int amount = items.stream().mapToInt(i -> i.getItemAmount(stack, false)).sum();
|
||||
this.dataManager.set(AMOUNT, amount);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
package de.ellpeck.prettypipes.misc;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class EquatableItemStack {
|
||||
|
||||
public final ItemStack stack;
|
||||
|
||||
public EquatableItemStack(ItemStack stack) {
|
||||
this.stack = stack;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (o instanceof EquatableItemStack) {
|
||||
ItemStack other = ((EquatableItemStack) o).stack;
|
||||
return ItemStack.areItemsEqual(this.stack, other) && ItemStack.areItemStackTagsEqual(this.stack, other);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.stack.getItem(), this.stack.getTag());
|
||||
}
|
||||
}
|
|
@ -7,16 +7,16 @@ import net.minecraft.item.ItemStack;
|
|||
import net.minecraftforge.items.IItemHandler;
|
||||
import net.minecraftforge.items.SlotItemHandler;
|
||||
|
||||
public class SlotFilter extends SlotItemHandler {
|
||||
public SlotFilter(IItemHandler itemHandler, int index, int xPosition, int yPosition) {
|
||||
public class FilterSlot extends SlotItemHandler {
|
||||
public FilterSlot(IItemHandler itemHandler, int index, int xPosition, int yPosition) {
|
||||
super(itemHandler, index, xPosition, yPosition);
|
||||
}
|
||||
|
||||
public static boolean checkFilter(Container container, int slotId, PlayerEntity player) {
|
||||
if (slotId >= 0 && slotId < container.inventorySlots.size()) {
|
||||
Slot slot = container.getSlot(slotId);
|
||||
if (slot instanceof SlotFilter) {
|
||||
((SlotFilter) slot).slotClick(player);
|
||||
if (slot instanceof FilterSlot) {
|
||||
((FilterSlot) slot).slotClick(player);
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
package de.ellpeck.prettypipes.misc;
|
||||
|
||||
import de.ellpeck.prettypipes.PrettyPipes;
|
||||
import de.ellpeck.prettypipes.items.IModule;
|
||||
import de.ellpeck.prettypipes.packets.PacketButton;
|
||||
import de.ellpeck.prettypipes.pipe.PipeTileEntity;
|
||||
import de.ellpeck.prettypipes.pipe.modules.FilterModifierModule;
|
||||
|
@ -25,7 +24,6 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class ItemFilter extends ItemStackHandler {
|
||||
|
||||
|
@ -47,7 +45,7 @@ public class ItemFilter extends ItemStackHandler {
|
|||
public List<Slot> getSlots(int x, int y) {
|
||||
List<Slot> slots = new ArrayList<>();
|
||||
for (int i = 0; i < this.getSlots(); i++)
|
||||
slots.add(new SlotFilter(this, i, x + i % 9 * 18, y + i / 9 * 18));
|
||||
slots.add(new FilterSlot(this, i, x + i % 9 * 18, y + i / 9 * 18));
|
||||
return slots;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
package de.ellpeck.prettypipes.misc;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import de.ellpeck.prettypipes.PrettyPipes;
|
||||
import de.ellpeck.prettypipes.terminal.containers.ItemTerminalGui;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.FontRenderer;
|
||||
import net.minecraft.client.gui.screen.inventory.ContainerScreen;
|
||||
import net.minecraft.client.gui.widget.Widget;
|
||||
import net.minecraft.client.renderer.ItemRenderer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.text.TextFormatting;
|
||||
import net.minecraftforge.fml.client.gui.GuiUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ItemTerminalWidget extends Widget {
|
||||
|
||||
private static final ResourceLocation FONT = new ResourceLocation(PrettyPipes.ID, "unicode");
|
||||
private final ItemStack stack;
|
||||
private final ItemTerminalGui screen;
|
||||
public final int gridX;
|
||||
public final int gridY;
|
||||
public boolean hidden;
|
||||
|
||||
public ItemTerminalWidget(int xIn, int yIn, int gridX, int gridY, ItemStack stack, ItemTerminalGui screen) {
|
||||
super(xIn, yIn, 16, 16, stack.getDisplayName().getFormattedText());
|
||||
this.gridX = gridX;
|
||||
this.gridY = gridY;
|
||||
this.stack = stack;
|
||||
this.screen = screen;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean clicked(double x, double y) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(int mouseX, int mouseY, float partialTicks) {
|
||||
if (!this.hidden)
|
||||
super.render(mouseX, mouseY, partialTicks);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderButton(int mouseX, int mouseY, float partialTicks) {
|
||||
Minecraft mc = this.screen.getMinecraft();
|
||||
ItemRenderer renderer = mc.getItemRenderer();
|
||||
this.setBlitOffset(100);
|
||||
renderer.zLevel = 100;
|
||||
RenderSystem.enableDepthTest();
|
||||
renderer.renderItemAndEffectIntoGUI(mc.player, this.stack, this.x, this.y);
|
||||
int amount = this.stack.getCount();
|
||||
String amountStrg = this.stack.getCount() >= 1000 ? amount / 1000 + "k" : String.valueOf(amount);
|
||||
FontRenderer font = mc.getFontResourceManager().getFontRenderer(FONT);
|
||||
renderer.renderItemOverlayIntoGUI(font, this.stack, this.x, this.y, amountStrg);
|
||||
renderer.zLevel = 0;
|
||||
this.setBlitOffset(0);
|
||||
|
||||
if (this.isHovered()) {
|
||||
RenderSystem.disableDepthTest();
|
||||
RenderSystem.colorMask(true, true, true, false);
|
||||
this.fillGradient(this.x, this.y, this.x + 16, this.y + 16, -2130706433, -2130706433);
|
||||
RenderSystem.colorMask(true, true, true, true);
|
||||
RenderSystem.enableDepthTest();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderToolTip(int mouseX, int mouseY) {
|
||||
if (this.isHovered()) {
|
||||
FontRenderer font = this.stack.getItem().getFontRenderer(this.stack);
|
||||
if (font == null)
|
||||
font = this.screen.getMinecraft().fontRenderer;
|
||||
GuiUtils.preItemToolTip(this.stack);
|
||||
List<String> tooltip = this.screen.getTooltipFromItem(this.stack);
|
||||
if (this.stack.getCount() >= 1000)
|
||||
tooltip.set(0, tooltip.get(0) + TextFormatting.BOLD + " (" + this.stack.getCount() + ')');
|
||||
this.screen.renderTooltip(tooltip, mouseX, mouseY, font);
|
||||
GuiUtils.postItemToolTip();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package de.ellpeck.prettypipes.network;
|
||||
|
||||
import de.ellpeck.prettypipes.misc.EquatableItemStack;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class NetworkItem {
|
||||
|
||||
private final Set<NetworkLocation> locations = new HashSet<>();
|
||||
private final EquatableItemStack item;
|
||||
private int amount;
|
||||
|
||||
public NetworkItem(EquatableItemStack item) {
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
public void add(NetworkLocation location, ItemStack stack) {
|
||||
this.locations.add(location);
|
||||
this.amount += stack.getCount();
|
||||
}
|
||||
|
||||
public ItemStack asStack() {
|
||||
ItemStack stack = this.item.stack.copy();
|
||||
stack.setCount(this.amount);
|
||||
return stack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NetworkItem{" + "locations=" + this.locations + ", item=" + this.item + ", amount=" + this.amount + '}';
|
||||
}
|
||||
}
|
|
@ -8,10 +8,7 @@ import net.minecraft.util.math.BlockPos;
|
|||
import net.minecraftforge.items.IItemHandler;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
public class NetworkLocation {
|
||||
|
||||
|
@ -44,12 +41,16 @@ public class NetworkLocation {
|
|||
return -1;
|
||||
}
|
||||
|
||||
public int getItemAmount(ItemStack stack) {
|
||||
public int getItemAmount(ItemStack stack, boolean compareTag) {
|
||||
return this.items.values().stream()
|
||||
.filter(i -> i.isItemEqual(stack))
|
||||
.filter(i -> ItemStack.areItemsEqual(i, stack) && (!compareTag || ItemStack.areItemStackTagsEqual(i, stack)))
|
||||
.mapToInt(ItemStack::getCount).sum();
|
||||
}
|
||||
|
||||
public Collection<ItemStack> getItems() {
|
||||
return this.items.values();
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return this.items == null || this.items.isEmpty();
|
||||
}
|
||||
|
|
|
@ -353,11 +353,11 @@ public class PipeNetwork implements ICapabilitySerializable<CompoundNBT>, GraphL
|
|||
public void vertexRemoved(GraphVertexChangeEvent<BlockPos> e) {
|
||||
}
|
||||
|
||||
private void startProfile(String name) {
|
||||
public void startProfile(String name) {
|
||||
this.world.getProfiler().startSection(() -> PrettyPipes.ID + ":pipe_network_" + name);
|
||||
}
|
||||
|
||||
private void endProfile() {
|
||||
public void endProfile() {
|
||||
this.world.getProfiler().endSection();
|
||||
}
|
||||
|
||||
|
|
|
@ -20,14 +20,15 @@ public final class PacketHandler {
|
|||
network = NetworkRegistry.newSimpleChannel(new ResourceLocation(PrettyPipes.ID, "network"), () -> VERSION, VERSION::equals, VERSION::equals);
|
||||
network.registerMessage(0, PacketItemEnterPipe.class, PacketItemEnterPipe::toBytes, PacketItemEnterPipe::fromBytes, PacketItemEnterPipe::onMessage);
|
||||
network.registerMessage(1, PacketButton.class, PacketButton::toBytes, PacketButton::fromBytes, PacketButton::onMessage);
|
||||
network.registerMessage(2, PacketNetworkItems.class, PacketNetworkItems::toBytes, PacketNetworkItems::fromBytes, PacketNetworkItems::onMessage);
|
||||
}
|
||||
|
||||
public static void sendToAllLoaded(World world, BlockPos pos, Object message) {
|
||||
network.send(PacketDistributor.TRACKING_CHUNK.with(() -> world.getChunkAt(pos)), message);
|
||||
}
|
||||
|
||||
public static void sendToAllAround(IWorld world, BlockPos pos, int range, Object message) {
|
||||
network.send(PacketDistributor.NEAR.with(() -> new PacketDistributor.TargetPoint(pos.getX(), pos.getY(), pos.getZ(), range, world.getDimension().getType())), message);
|
||||
public static void sendTo(PlayerEntity player, Object message) {
|
||||
network.send(PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) player), message);
|
||||
}
|
||||
|
||||
public static void sendToServer(Object message) {
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
package de.ellpeck.prettypipes.packets;
|
||||
|
||||
import de.ellpeck.prettypipes.Utility;
|
||||
import de.ellpeck.prettypipes.network.PipeItem;
|
||||
import de.ellpeck.prettypipes.pipe.PipeTileEntity;
|
||||
import de.ellpeck.prettypipes.terminal.containers.ItemTerminalContainer;
|
||||
import de.ellpeck.prettypipes.terminal.containers.ItemTerminalGui;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.inventory.container.Container;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraftforge.fml.network.NetworkEvent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class PacketNetworkItems {
|
||||
|
||||
private List<ItemStack> items;
|
||||
|
||||
public PacketNetworkItems(List<ItemStack> items) {
|
||||
this.items = items;
|
||||
}
|
||||
|
||||
private PacketNetworkItems() {
|
||||
|
||||
}
|
||||
|
||||
public static PacketNetworkItems fromBytes(PacketBuffer buf) {
|
||||
PacketNetworkItems client = new PacketNetworkItems();
|
||||
client.items = new ArrayList<>();
|
||||
for (int i = buf.readVarInt(); i > 0; i--) {
|
||||
ItemStack stack = buf.readItemStack();
|
||||
stack.setCount(buf.readVarInt());
|
||||
client.items.add(stack);
|
||||
}
|
||||
return client;
|
||||
}
|
||||
|
||||
public static void toBytes(PacketNetworkItems packet, PacketBuffer buf) {
|
||||
buf.writeVarInt(packet.items.size());
|
||||
for (ItemStack stack : packet.items) {
|
||||
buf.writeItemStack(stack);
|
||||
buf.writeVarInt(stack.getCount());
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("Convert2Lambda")
|
||||
public static void onMessage(PacketNetworkItems message, Supplier<NetworkEvent.Context> ctx) {
|
||||
ctx.get().enqueueWork(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
if (mc.currentScreen instanceof ItemTerminalGui)
|
||||
((ItemTerminalGui) mc.currentScreen).updateItemList(message.items);
|
||||
}
|
||||
});
|
||||
ctx.get().setPacketHandled(true);
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@ package de.ellpeck.prettypipes.pipe.containers;
|
|||
|
||||
import de.ellpeck.prettypipes.Utility;
|
||||
import de.ellpeck.prettypipes.items.IModule;
|
||||
import de.ellpeck.prettypipes.misc.SlotFilter;
|
||||
import de.ellpeck.prettypipes.misc.FilterSlot;
|
||||
import de.ellpeck.prettypipes.pipe.PipeTileEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.inventory.container.ClickType;
|
||||
|
@ -11,6 +11,7 @@ import net.minecraft.inventory.container.ContainerType;
|
|||
import net.minecraft.inventory.container.Slot;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
|
@ -45,50 +46,16 @@ public abstract class AbstractPipeContainer<T extends IModule> extends Container
|
|||
|
||||
@Override
|
||||
public ItemStack transferStackInSlot(PlayerEntity player, int slotIndex) {
|
||||
int inventoryStart = (int) this.inventorySlots.stream().filter(slot -> slot.inventory != player.inventory).count();
|
||||
int inventoryEnd = inventoryStart + 26;
|
||||
int hotbarStart = inventoryEnd + 1;
|
||||
int hotbarEnd = hotbarStart + 8;
|
||||
|
||||
Slot slot = this.inventorySlots.get(slotIndex);
|
||||
if (slot != null && slot.getHasStack()) {
|
||||
ItemStack newStack = slot.getStack();
|
||||
ItemStack currentStack = newStack.copy();
|
||||
|
||||
if (slotIndex >= inventoryStart) {
|
||||
// shift into this container here
|
||||
// mergeItemStack with the slots that newStack should go into
|
||||
// return an empty stack if mergeItemStack fails
|
||||
if (newStack.getItem() instanceof IModule) {
|
||||
if (!this.mergeItemStack(newStack, 0, 3, false))
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
// end custom code
|
||||
else if (slotIndex >= inventoryStart && slotIndex <= inventoryEnd) {
|
||||
if (!this.mergeItemStack(newStack, hotbarStart, hotbarEnd + 1, false))
|
||||
return ItemStack.EMPTY;
|
||||
} else if (slotIndex >= inventoryEnd + 1 && slotIndex < hotbarEnd + 1 && !this.mergeItemStack(newStack, inventoryStart, inventoryEnd + 1, false)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
} else if (!this.mergeItemStack(newStack, inventoryStart, hotbarEnd + 1, false)) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
if (newStack.isEmpty()) {
|
||||
slot.putStack(ItemStack.EMPTY);
|
||||
} else {
|
||||
slot.onSlotChanged();
|
||||
}
|
||||
if (newStack.getCount() == currentStack.getCount())
|
||||
return ItemStack.EMPTY;
|
||||
slot.onTake(player, newStack);
|
||||
return currentStack;
|
||||
}
|
||||
return ItemStack.EMPTY;
|
||||
return Utility.transferStackInSlot(this, this::mergeItemStack, player, slotIndex, stack -> {
|
||||
if (stack.getItem() instanceof IModule)
|
||||
return Pair.of(0, 3);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack slotClick(int slotId, int dragType, ClickType clickTypeIn, PlayerEntity player) {
|
||||
if (SlotFilter.checkFilter(this, slotId, player))
|
||||
if (FilterSlot.checkFilter(this, slotId, player))
|
||||
return ItemStack.EMPTY;
|
||||
return super.slotClick(slotId, dragType, clickTypeIn, player);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
package de.ellpeck.prettypipes.terminal;
|
||||
|
||||
import de.ellpeck.prettypipes.Utility;
|
||||
import de.ellpeck.prettypipes.pipe.ConnectionType;
|
||||
import de.ellpeck.prettypipes.pipe.IPipeConnectable;
|
||||
import de.ellpeck.prettypipes.pipe.PipeTileEntity;
|
||||
import net.minecraft.block.BlockRenderType;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.ContainerBlock;
|
||||
import net.minecraft.block.SoundType;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.ActionResultType;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.BlockRayTraceResult;
|
||||
import net.minecraft.world.IBlockReader;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.fml.network.NetworkHooks;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class ItemTerminalBlock extends ContainerBlock implements IPipeConnectable {
|
||||
public ItemTerminalBlock() {
|
||||
super(Properties.create(Material.ROCK).hardnessAndResistance(3).sound(SoundType.STONE));
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
if (tile == null)
|
||||
return ActionResultType.PASS;
|
||||
if (!worldIn.isRemote) {
|
||||
NetworkHooks.openGui((ServerPlayerEntity) player, tile, pos);
|
||||
tile.updateItems(player);
|
||||
}
|
||||
return ActionResultType.SUCCESS;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public TileEntity createNewTileEntity(IBlockReader worldIn) {
|
||||
return new ItemTerminalTileEntity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConnectionType getConnectionType(World world, BlockPos pos, BlockState state, BlockPos pipePos, Direction direction) {
|
||||
return ConnectionType.CONNECTED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockRenderType getRenderType(BlockState state) {
|
||||
return BlockRenderType.MODEL;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
package de.ellpeck.prettypipes.terminal;
|
||||
|
||||
import de.ellpeck.prettypipes.PrettyPipes;
|
||||
import de.ellpeck.prettypipes.Registry;
|
||||
import de.ellpeck.prettypipes.Utility;
|
||||
import de.ellpeck.prettypipes.misc.EquatableItemStack;
|
||||
import de.ellpeck.prettypipes.network.NetworkItem;
|
||||
import de.ellpeck.prettypipes.network.NetworkLocation;
|
||||
import de.ellpeck.prettypipes.network.PipeNetwork;
|
||||
import de.ellpeck.prettypipes.packets.PacketHandler;
|
||||
import de.ellpeck.prettypipes.packets.PacketNetworkItems;
|
||||
import de.ellpeck.prettypipes.pipe.PipeTileEntity;
|
||||
import de.ellpeck.prettypipes.terminal.containers.ItemTerminalContainer;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||
import net.minecraft.inventory.container.Container;
|
||||
import net.minecraft.inventory.container.INamedContainerProvider;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.tileentity.ITickableTileEntity;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.tileentity.TileEntityType;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
import net.minecraft.util.text.TranslationTextComponent;
|
||||
import net.minecraft.world.server.ServerWorld;
|
||||
import net.minecraftforge.items.ItemStackHandler;
|
||||
import org.apache.commons.lang3.mutable.MutableInt;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ItemTerminalTileEntity extends TileEntity implements INamedContainerProvider, ITickableTileEntity {
|
||||
|
||||
public final ItemStackHandler items = new ItemStackHandler(12) {
|
||||
@Override
|
||||
public boolean isItemValid(int slot, @Nonnull ItemStack stack) {
|
||||
return slot >= 6;
|
||||
}
|
||||
};
|
||||
public Collection<NetworkItem> networkItems;
|
||||
|
||||
public ItemTerminalTileEntity() {
|
||||
super(Registry.itemTerminalTileEntity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
if (this.world.isRemote)
|
||||
return;
|
||||
PipeNetwork network = PipeNetwork.get(this.world);
|
||||
PipeTileEntity pipe = this.getConnectedPipe();
|
||||
if (pipe == null)
|
||||
return;
|
||||
|
||||
if (this.world.getGameTime() % 10 == 0) {
|
||||
for (int i = 6; i < 12; i++) {
|
||||
ItemStack extracted = this.items.extractItem(i, Integer.MAX_VALUE, true);
|
||||
if (extracted.isEmpty())
|
||||
continue;
|
||||
if (!network.tryInsertItem(pipe.getPos(), this.pos, extracted, true))
|
||||
continue;
|
||||
this.items.extractItem(i, extracted.getCount(), false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.world.getGameTime() % 100 == 0) {
|
||||
PlayerEntity[] lookingPlayers = this.world.getPlayers().stream()
|
||||
.filter(p -> p.openContainer instanceof ItemTerminalContainer)
|
||||
.filter(p -> ((ItemTerminalContainer) p.openContainer).tile == this)
|
||||
.toArray(PlayerEntity[]::new);
|
||||
if (lookingPlayers.length > 0)
|
||||
this.updateItems(lookingPlayers);
|
||||
}
|
||||
}
|
||||
|
||||
private PipeTileEntity getConnectedPipe() {
|
||||
PipeNetwork network = PipeNetwork.get(this.world);
|
||||
for (Direction dir : Direction.values()) {
|
||||
PipeTileEntity pipe = network.getPipe(this.pos.offset(dir));
|
||||
if (pipe != null)
|
||||
return pipe;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void updateItems(PlayerEntity... playersToSync) {
|
||||
this.networkItems = this.collectItems();
|
||||
List<ItemStack> clientItems = this.networkItems.stream().map(NetworkItem::asStack).collect(Collectors.toList());
|
||||
for (PlayerEntity player : playersToSync) {
|
||||
if (!(player.openContainer instanceof ItemTerminalContainer))
|
||||
continue;
|
||||
ItemTerminalTileEntity tile = ((ItemTerminalContainer) player.openContainer).tile;
|
||||
if (tile != this)
|
||||
continue;
|
||||
PacketHandler.sendTo(player, new PacketNetworkItems(clientItems));
|
||||
}
|
||||
}
|
||||
|
||||
private Collection<NetworkItem> collectItems() {
|
||||
PipeNetwork network = PipeNetwork.get(this.world);
|
||||
network.startProfile("terminal_collect_items");
|
||||
PipeTileEntity pipe = this.getConnectedPipe();
|
||||
Map<EquatableItemStack, NetworkItem> items = new HashMap<>();
|
||||
for (NetworkLocation location : network.getOrderedNetworkItems(pipe.getPos())) {
|
||||
for (ItemStack stack : location.getItems()) {
|
||||
EquatableItemStack equatable = new EquatableItemStack(stack);
|
||||
NetworkItem item = items.computeIfAbsent(equatable, NetworkItem::new);
|
||||
item.add(location, stack);
|
||||
}
|
||||
}
|
||||
network.endProfile();
|
||||
return items.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundNBT write(CompoundNBT compound) {
|
||||
compound.put("items", this.items.serializeNBT());
|
||||
return super.write(compound);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(CompoundNBT compound) {
|
||||
this.items.deserializeNBT(compound.getCompound("items"));
|
||||
super.read(compound);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ITextComponent getDisplayName() {
|
||||
return new TranslationTextComponent("container." + PrettyPipes.ID + ".item_terminal");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Container createMenu(int window, PlayerInventory inv, PlayerEntity player) {
|
||||
return new ItemTerminalContainer(Registry.itemTerminalContainer, window, player, this.pos);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package de.ellpeck.prettypipes.terminal.containers;
|
||||
|
||||
import de.ellpeck.prettypipes.Utility;
|
||||
import de.ellpeck.prettypipes.network.NetworkItem;
|
||||
import de.ellpeck.prettypipes.packets.PacketHandler;
|
||||
import de.ellpeck.prettypipes.packets.PacketNetworkItems;
|
||||
import de.ellpeck.prettypipes.pipe.PipeTileEntity;
|
||||
import de.ellpeck.prettypipes.terminal.ItemTerminalTileEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||
import net.minecraft.inventory.container.ClickType;
|
||||
import net.minecraft.inventory.container.Container;
|
||||
import net.minecraft.inventory.container.ContainerType;
|
||||
import net.minecraft.inventory.container.Slot;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.server.ServerWorld;
|
||||
import net.minecraftforge.items.SlotItemHandler;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ItemTerminalContainer extends Container {
|
||||
|
||||
public final ItemTerminalTileEntity tile;
|
||||
|
||||
public ItemTerminalContainer(@Nullable ContainerType<?> type, int id, PlayerEntity player, BlockPos pos) {
|
||||
super(type, id);
|
||||
this.tile = Utility.getTileEntity(ItemTerminalTileEntity.class, player.world, pos);
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
this.addSlot(new SlotItemHandler(this.tile.items, i, 8 + i % 3 * 18, 102 + i / 3 * 18));
|
||||
for (int i = 0; i < 6; i++)
|
||||
this.addSlot(new SlotItemHandler(this.tile.items, i + 6, 116 + i % 3 * 18, 102 + i / 3 * 18));
|
||||
|
||||
for (int l = 0; l < 3; ++l)
|
||||
for (int j1 = 0; j1 < 9; ++j1)
|
||||
this.addSlot(new Slot(player.inventory, j1 + l * 9 + 9, 8 + j1 * 18, 154 + l * 18));
|
||||
for (int i1 = 0; i1 < 9; ++i1)
|
||||
this.addSlot(new Slot(player.inventory, i1, 8 + i1 * 18, 212));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack transferStackInSlot(PlayerEntity player, int slotIndex) {
|
||||
return Utility.transferStackInSlot(this, this::mergeItemStack, player, slotIndex, stack -> {
|
||||
return Pair.of(6, 12);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canInteractWith(PlayerEntity playerIn) {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
package de.ellpeck.prettypipes.terminal.containers;
|
||||
|
||||
import de.ellpeck.prettypipes.PrettyPipes;
|
||||
import de.ellpeck.prettypipes.misc.ItemTerminalWidget;
|
||||
import net.minecraft.client.gui.screen.inventory.ContainerScreen;
|
||||
import net.minecraft.client.gui.widget.Widget;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ItemTerminalGui extends ContainerScreen<ItemTerminalContainer> {
|
||||
private static final ResourceLocation TEXTURE = new ResourceLocation(PrettyPipes.ID, "textures/gui/item_terminal.png");
|
||||
|
||||
public ItemTerminalGui(ItemTerminalContainer screenContainer, PlayerInventory inv, ITextComponent titleIn) {
|
||||
super(screenContainer, inv, titleIn);
|
||||
this.xSize = 176 + 15;
|
||||
this.ySize = 236;
|
||||
}
|
||||
|
||||
public void updateItemList(List<ItemStack> items) {
|
||||
this.buttons.removeIf(w -> w instanceof ItemTerminalWidget);
|
||||
int x = 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));
|
||||
x++;
|
||||
if (x > 8) {
|
||||
x = 0;
|
||||
y++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(int mouseX, int mouseY, float partialTicks) {
|
||||
this.renderBackground();
|
||||
super.render(mouseX, mouseY, partialTicks);
|
||||
for (Widget widget : this.buttons) {
|
||||
if (widget instanceof ItemTerminalWidget)
|
||||
widget.renderToolTip(mouseX, mouseY);
|
||||
}
|
||||
this.renderHoveredToolTip(mouseX, mouseY);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) {
|
||||
this.font.drawString(this.playerInventory.getDisplayName().getFormattedText(), 8, this.ySize - 96 + 2, 4210752);
|
||||
this.font.drawString(this.title.getFormattedText(), 8, 6, 4210752);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) {
|
||||
this.getMinecraft().getTextureManager().bindTexture(TEXTURE);
|
||||
this.blit(this.guiLeft, this.guiTop, 0, 0, this.xSize, this.ySize);
|
||||
}
|
||||
|
||||
// public overload for ItemTerminalWidget
|
||||
@Override
|
||||
public void renderTooltip(ItemStack stack, int x, int y) {
|
||||
super.renderTooltip(stack, x, y);
|
||||
}
|
||||
}
|
10
src/main/resources/assets/prettypipes/font/unicode.json
Normal file
10
src/main/resources/assets/prettypipes/font/unicode.json
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"_comment": "Unicode fonts only",
|
||||
"providers": [
|
||||
{
|
||||
"type": "legacy_unicode",
|
||||
"sizes": "minecraft:font/glyph_sizes.bin",
|
||||
"template": "minecraft:font/unicode_page_%s.png"
|
||||
}
|
||||
]
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
Loading…
Reference in a new issue