mirror of
https://github.com/Ellpeck/PrettyPipes.git
synced 2024-05-20 07:41:22 +02:00
153 lines
5.1 KiB
Java
153 lines
5.1 KiB
Java
package de.ellpeck.prettypipes.packets;
|
|
|
|
import com.google.common.collect.Streams;
|
|
import com.mojang.datafixers.util.Pair;
|
|
import de.ellpeck.prettypipes.Utility;
|
|
import de.ellpeck.prettypipes.terminal.CraftingTerminalBlockEntity;
|
|
import net.minecraft.client.Minecraft;
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.core.Registry;
|
|
import net.minecraft.network.FriendlyByteBuf;
|
|
import net.minecraft.resources.ResourceLocation;
|
|
import net.minecraft.tags.TagKey;
|
|
import net.minecraft.world.entity.player.Player;
|
|
import net.minecraft.world.item.Item;
|
|
import net.minecraft.world.item.ItemStack;
|
|
import net.minecraft.world.item.Items;
|
|
import net.minecraftforge.network.NetworkEvent;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.function.Consumer;
|
|
import java.util.function.Supplier;
|
|
import java.util.stream.Collectors;
|
|
|
|
public class PacketGhostSlot {
|
|
|
|
private BlockPos pos;
|
|
private Map<Integer, Entry> stacks;
|
|
|
|
public PacketGhostSlot(BlockPos pos, Map<Integer, Entry> stacks) {
|
|
this.pos = pos;
|
|
this.stacks = stacks;
|
|
}
|
|
|
|
private PacketGhostSlot() {
|
|
|
|
}
|
|
|
|
public static PacketGhostSlot fromBytes(FriendlyByteBuf buf) {
|
|
var packet = new PacketGhostSlot();
|
|
packet.pos = buf.readBlockPos();
|
|
packet.stacks = new HashMap<>();
|
|
for (var i = buf.readInt(); i > 0; i--)
|
|
packet.stacks.put(buf.readInt(), new Entry(buf));
|
|
return packet;
|
|
}
|
|
|
|
public static void toBytes(PacketGhostSlot packet, FriendlyByteBuf buf) {
|
|
buf.writeBlockPos(packet.pos);
|
|
buf.writeInt(packet.stacks.size());
|
|
for (var entry : packet.stacks.entrySet()) {
|
|
buf.writeInt(entry.getKey());
|
|
entry.getValue().write(buf);
|
|
}
|
|
}
|
|
|
|
@SuppressWarnings("Convert2Lambda")
|
|
public static void onMessage(PacketGhostSlot message, Supplier<NetworkEvent.Context> ctx) {
|
|
var doIt = (Consumer<Player>) p -> {
|
|
var tile = Utility.getBlockEntity(CraftingTerminalBlockEntity.class, p.level, message.pos);
|
|
if (tile != null)
|
|
tile.setGhostItems(message.stacks);
|
|
};
|
|
|
|
// this whole thing is a dirty hack for allowing the same packet to be used
|
|
// both client -> server and server -> client without any classloading issues
|
|
Player player = ctx.get().getSender();
|
|
// are we on the client?
|
|
if (player == null) {
|
|
ctx.get().enqueueWork(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
doIt.accept(Minecraft.getInstance().player);
|
|
}
|
|
});
|
|
} else {
|
|
ctx.get().enqueueWork(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
doIt.accept(player);
|
|
}
|
|
});
|
|
}
|
|
|
|
ctx.get().setPacketHandled(true);
|
|
}
|
|
|
|
public static class Entry {
|
|
|
|
private final List<ItemStack> stacks;
|
|
private final TagKey<Item> tag;
|
|
|
|
public Entry(List<ItemStack> stacks) {
|
|
var tag = Entry.getTagForStacks(stacks);
|
|
if (tag != null) {
|
|
this.stacks = null;
|
|
this.tag = tag;
|
|
} else {
|
|
this.stacks = stacks;
|
|
this.tag = null;
|
|
}
|
|
}
|
|
|
|
public Entry(FriendlyByteBuf buf) {
|
|
if (buf.readBoolean()) {
|
|
this.tag = null;
|
|
this.stacks = new ArrayList<>();
|
|
for (var i = buf.readInt(); i > 0; i--)
|
|
this.stacks.add(buf.readItem());
|
|
} else {
|
|
this.stacks = null;
|
|
this.tag = TagKey.create(Registry.ITEM_REGISTRY, new ResourceLocation(buf.readUtf()));
|
|
}
|
|
}
|
|
|
|
public List<ItemStack> getStacks() {
|
|
if (this.stacks != null)
|
|
return this.stacks;
|
|
return Streams.stream(Registry.ITEM.getTagOrEmpty(this.tag).iterator())
|
|
.filter(h -> h.value() != null & h.value() != Items.AIR)
|
|
.map(h -> new ItemStack(h.value())).collect(Collectors.toList());
|
|
}
|
|
|
|
public FriendlyByteBuf write(FriendlyByteBuf buf) {
|
|
if (this.stacks != null) {
|
|
buf.writeBoolean(true);
|
|
buf.writeInt(this.stacks.size());
|
|
for (var stack : this.stacks)
|
|
buf.writeItem(stack);
|
|
} else {
|
|
buf.writeBoolean(false);
|
|
buf.writeUtf(this.tag.location().toString());
|
|
}
|
|
return buf;
|
|
}
|
|
|
|
private static TagKey<Item> getTagForStacks(List<ItemStack> stacks) {
|
|
return Registry.ITEM.getTags().filter(e -> {
|
|
var tag = e.getSecond();
|
|
if (tag.size() != stacks.size())
|
|
return false;
|
|
for (var i = 0; i < tag.size(); i++) {
|
|
if (stacks.get(i).getItem() != tag.get(i).value())
|
|
return false;
|
|
}
|
|
return true;
|
|
}).map(Pair::getFirst).findFirst().orElse(null);
|
|
}
|
|
}
|
|
}
|