store active craft request data a lot more cleanly

This commit is contained in:
Ell 2024-11-27 22:43:15 +01:00
parent e6e9d4358f
commit 704027c3dc
6 changed files with 165 additions and 136 deletions

View file

@ -122,13 +122,23 @@ public final class Utility {
return ItemStack.EMPTY; return ItemStack.EMPTY;
} }
public static ListTag serializeAll(HolderLookup.Provider provider, Collection<? extends INBTSerializable<CompoundTag>> items) { public static <T> ListTag serializeAll(Collection<T> items, Function<T, CompoundTag> serializer) {
var list = new ListTag(); var list = new ListTag();
for (INBTSerializable<CompoundTag> item : items) for (var item : items)
list.add(item.serializeNBT(provider)); list.add(serializer.apply(item));
return list; return list;
} }
public static <T> List<T> deserializeAll(ListTag list, Function<CompoundTag, T> deserializer) {
List<T> items = new ArrayList<>();
for (var i = 0; i < list.size(); i++) {
var item = deserializer.apply(list.getCompound(i));
if (item != null)
items.add(item);
}
return items;
}
public static void sendBlockEntityToClients(BlockEntity tile) { public static void sendBlockEntityToClients(BlockEntity tile) {
var world = (ServerLevel) tile.getLevel(); var world = (ServerLevel) tile.getLevel();
var entities = world.getChunkSource().chunkMap.getPlayers(new ChunkPos(tile.getBlockPos()), false); var entities = world.getChunkSource().chunkMap.getPlayers(new ChunkPos(tile.getBlockPos()), false);
@ -137,16 +147,6 @@ public final class Utility {
e.connection.send(packet); e.connection.send(packet);
} }
public static <T extends INBTSerializable<CompoundTag>> List<T> deserializeAll(ListTag list, Function<CompoundTag, T> supplier) {
List<T> items = new ArrayList<>();
for (var i = 0; i < list.size(); i++) {
var item = supplier.apply(list.getCompound(i));
if (item != null)
items.add(item);
}
return items;
}
public static IItemHandler getBlockItemHandler(Level world, BlockPos pos, Direction direction) { public static IItemHandler getBlockItemHandler(Level world, BlockPos pos, Direction direction) {
var state = world.getBlockState(pos); var state = world.getBlockState(pos);
var block = state.getBlock(); var block = state.getBlock();

View file

@ -118,8 +118,8 @@ public class PipeNetwork extends SavedData implements GraphListener<BlockPos, Ne
for (var edge : this.graph.edgeSet()) for (var edge : this.graph.edgeSet())
edges.add(edge.serializeNBT(provider)); edges.add(edge.serializeNBT(provider));
nbt.put("edges", edges); nbt.put("edges", edges);
nbt.put("items", Utility.serializeAll(provider, this.pipeItems.values())); nbt.put("items", Utility.serializeAll(this.pipeItems.values(), i -> i.serializeNBT(provider)));
nbt.put("locks", Utility.serializeAll(provider, this.networkLocks.values())); nbt.put("locks", Utility.serializeAll(this.networkLocks.values(), l -> l.serializeNBT(provider)));
return nbt; return nbt;
} }
@ -283,17 +283,16 @@ public class PipeNetwork extends SavedData implements GraphListener<BlockPos, Ne
var craftingPipes = this.getAllCraftables(node).stream().map(c -> this.getPipe(c.getLeft())).distinct().iterator(); var craftingPipes = this.getAllCraftables(node).stream().map(c -> this.getPipe(c.getLeft())).distinct().iterator();
while (craftingPipes.hasNext()) { while (craftingPipes.hasNext()) {
var pipe = craftingPipes.next(); var pipe = craftingPipes.next();
for (var request : pipe.craftResultRequests) { for (var craft : pipe.activeCrafts) {
var dest = request.getMiddle(); var data = craft.getRight();
var stack = request.getRight();
// add up all the items that should go to the same location // add up all the items that should go to the same location
var existing = items.stream() var existing = items.stream()
.filter(s -> s.getLeft().equals(dest) && ItemEquality.compareItems(s.getRight(), stack, equalityTypes)) .filter(s -> s.getLeft().equals(data.resultDestPipe) && ItemEquality.compareItems(s.getRight(), data.resultStackRemain, equalityTypes))
.findFirst(); .findFirst();
if (existing.isPresent()) { if (existing.isPresent()) {
existing.get().getRight().grow(stack.getCount()); existing.get().getRight().grow(data.resultStackRemain.getCount());
} else { } else {
items.add(Pair.of(dest, stack.copy())); items.add(Pair.of(data.resultDestPipe, data.resultStackRemain.copy()));
} }
} }
} }

View file

@ -270,8 +270,8 @@ public class PipeBlock extends BaseEntityBlock implements SimpleWaterloggedBlock
network.onPipeChanged(pos, state); network.onPipeChanged(pos, state);
if (worldIn.getBlockEntity(pos) instanceof PipeBlockEntity pipe) { if (worldIn.getBlockEntity(pos) instanceof PipeBlockEntity pipe) {
pipe.getItems().clear(); pipe.getItems().clear();
for (var locks : pipe.craftIngredientRequests) { for (var craft : pipe.activeCrafts) {
for (var lock : locks.getRight()) for (var lock : craft.getRight().ingredientsToRequest)
network.resolveNetworkLock(lock); network.resolveNetworkLock(lock);
} }
} }

View file

@ -8,6 +8,7 @@ import de.ellpeck.prettypipes.misc.ItemFilter;
import de.ellpeck.prettypipes.network.NetworkLock; import de.ellpeck.prettypipes.network.NetworkLock;
import de.ellpeck.prettypipes.network.PipeNetwork; import de.ellpeck.prettypipes.network.PipeNetwork;
import de.ellpeck.prettypipes.pipe.containers.MainPipeContainer; import de.ellpeck.prettypipes.pipe.containers.MainPipeContainer;
import de.ellpeck.prettypipes.pipe.modules.craft.CraftingModuleItem;
import de.ellpeck.prettypipes.pressurizer.PressurizerBlockEntity; import de.ellpeck.prettypipes.pressurizer.PressurizerBlockEntity;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
@ -71,11 +72,7 @@ public class PipeBlockEntity extends BlockEntity implements MenuProvider, IPipeC
PipeBlockEntity.this.setChanged(); PipeBlockEntity.this.setChanged();
} }
}; };
// TODO instead of having these loose lists, it would be nice to have a "ModuleData" system that allows modules to store an object of custom data on the pipe public final List<Pair<Integer, CraftingModuleItem.ActiveCraft>> activeCrafts = new ArrayList<>();
// crafting module slot, ingredient request network locks (one list for each recipe)
public final List<Pair<Integer, List<NetworkLock>>> craftIngredientRequests = new ArrayList<>();
// crafting module slot, destination pipe for the result, result item
public final List<Triple<Integer, BlockPos, ItemStack>> craftResultRequests = new ArrayList<>();
public PressurizerBlockEntity pressurizer; public PressurizerBlockEntity pressurizer;
public BlockState cover; public BlockState cover;
public int moduleDropCheck; public int moduleDropCheck;
@ -102,25 +99,16 @@ public class PipeBlockEntity extends BlockEntity implements MenuProvider, IPipeC
super.saveAdditional(compound, provider); super.saveAdditional(compound, provider);
compound.put("modules", this.modules.serializeNBT(provider)); compound.put("modules", this.modules.serializeNBT(provider));
compound.putInt("module_drop_check", this.moduleDropCheck); compound.putInt("module_drop_check", this.moduleDropCheck);
var requests = new ListTag();
for (var tuple : this.craftIngredientRequests) {
var nbt = new CompoundTag();
nbt.putInt("module_slot", tuple.getLeft());
nbt.put("locks", Utility.serializeAll(provider, tuple.getRight()));
requests.add(nbt);
}
compound.put("craft_requests", requests);
if (this.cover != null) if (this.cover != null)
compound.put("cover", NbtUtils.writeBlockState(this.cover)); compound.put("cover", NbtUtils.writeBlockState(this.cover));
var results = new ListTag(); var crafts = new ListTag();
for (var triple : this.craftResultRequests) { for (var craft : this.activeCrafts) {
var nbt = new CompoundTag(); var tag = new CompoundTag();
nbt.putInt("module_slot", triple.getLeft()); tag.putInt("module_slot", craft.getLeft());
nbt.putLong("dest_pipe", triple.getMiddle().asLong()); tag.put("data", craft.getRight().serializeNBT(provider));
nbt.put("item", triple.getRight().save(provider)); crafts.add(tag);
results.add(nbt);
} }
compound.put("craft_results", results); compound.put("active_crafts", crafts);
} }
@Override @Override
@ -128,22 +116,11 @@ public class PipeBlockEntity extends BlockEntity implements MenuProvider, IPipeC
this.modules.deserializeNBT(provider, compound.getCompound("modules")); this.modules.deserializeNBT(provider, compound.getCompound("modules"));
this.moduleDropCheck = compound.getInt("module_drop_check"); this.moduleDropCheck = compound.getInt("module_drop_check");
this.cover = compound.contains("cover") ? NbtUtils.readBlockState(this.level != null ? this.level.holderLookup(Registries.BLOCK) : BuiltInRegistries.BLOCK.asLookup(), compound.getCompound("cover")) : null; this.cover = compound.contains("cover") ? NbtUtils.readBlockState(this.level != null ? this.level.holderLookup(Registries.BLOCK) : BuiltInRegistries.BLOCK.asLookup(), compound.getCompound("cover")) : null;
this.craftIngredientRequests.clear(); this.activeCrafts.clear();
var requests = compound.getList("craft_requests", Tag.TAG_COMPOUND); var crafts = compound.getList("active_crafts", Tag.TAG_COMPOUND);
for (var i = 0; i < requests.size(); i++) { for (var i = 0; i < crafts.size(); i++) {
var nbt = requests.getCompound(i); var tag = crafts.getCompound(i);
this.craftIngredientRequests.add(Pair.of( this.activeCrafts.add(Pair.of(tag.getInt("module_slot"), new CraftingModuleItem.ActiveCraft(provider, tag.getCompound("data"))));
nbt.getInt("module_slot"),
Utility.deserializeAll(nbt.getList("locks", Tag.TAG_COMPOUND), c -> new NetworkLock(provider, c))));
}
this.craftResultRequests.clear();
var results = compound.getList("craft_results", Tag.TAG_COMPOUND);
for (var i = 0; i < results.size(); i++) {
var nbt = results.getCompound(i);
this.craftResultRequests.add(Triple.of(
nbt.getInt("module_slot"),
BlockPos.of(nbt.getLong("dest_pipe")),
ItemStack.parseOptional(provider, nbt.getCompound("item"))));
} }
super.loadAdditional(compound, provider); super.loadAdditional(compound, provider);
} }
@ -152,7 +129,7 @@ public class PipeBlockEntity extends BlockEntity implements MenuProvider, IPipeC
public CompoundTag getUpdateTag(HolderLookup.Provider provider) { public CompoundTag getUpdateTag(HolderLookup.Provider provider) {
// sync pipe items on load // sync pipe items on load
var nbt = this.saveWithoutMetadata(provider); var nbt = this.saveWithoutMetadata(provider);
nbt.put("items", Utility.serializeAll(provider, this.getItems())); nbt.put("items", Utility.serializeAll(this.getItems(), i -> i.serializeNBT(provider)));
return nbt; return nbt;
} }

View file

@ -7,6 +7,7 @@ import de.ellpeck.prettypipes.Utility;
import de.ellpeck.prettypipes.items.IModule; import de.ellpeck.prettypipes.items.IModule;
import de.ellpeck.prettypipes.items.ModuleItem; import de.ellpeck.prettypipes.items.ModuleItem;
import de.ellpeck.prettypipes.items.ModuleTier; import de.ellpeck.prettypipes.items.ModuleTier;
import de.ellpeck.prettypipes.misc.EquatableItemStack;
import de.ellpeck.prettypipes.misc.ItemEquality; import de.ellpeck.prettypipes.misc.ItemEquality;
import de.ellpeck.prettypipes.misc.ItemFilter; import de.ellpeck.prettypipes.misc.ItemFilter;
import de.ellpeck.prettypipes.network.NetworkLock; import de.ellpeck.prettypipes.network.NetworkLock;
@ -17,16 +18,21 @@ import de.ellpeck.prettypipes.terminal.CraftingTerminalBlockEntity;
import de.ellpeck.prettypipes.terminal.ItemTerminalBlockEntity; import de.ellpeck.prettypipes.terminal.ItemTerminalBlockEntity;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.component.DataComponentType; import net.minecraft.core.component.DataComponentType;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
import net.minecraft.util.Mth; import net.minecraft.util.Mth;
import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.neoforged.neoforge.common.util.INBTSerializable;
import net.neoforged.neoforge.items.IItemHandler; import net.neoforged.neoforge.items.IItemHandler;
import net.neoforged.neoforge.items.ItemHandlerHelper; import net.neoforged.neoforge.items.ItemHandlerHelper;
import net.neoforged.neoforge.items.ItemStackHandler; import net.neoforged.neoforge.items.ItemStackHandler;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.lang3.tuple.Triple; import org.apache.commons.lang3.tuple.Triple;
import org.jetbrains.annotations.UnknownNullability;
import java.util.*; import java.util.*;
import java.util.function.Consumer; import java.util.function.Consumer;
@ -71,13 +77,15 @@ public class CraftingModuleItem extends ModuleItem {
return; return;
var slot = tile.getModuleSlot(module); var slot = tile.getModuleSlot(module);
var network = PipeNetwork.get(tile.getLevel()); var network = PipeNetwork.get(tile.getLevel());
if (!tile.activeCrafts.isEmpty()) {
var activeCraft = tile.activeCrafts.getFirst();
if (activeCraft.getLeft() == slot) {
var craftData = activeCraft.getRight();
// process crafting ingredient requests // process crafting ingredient requests
if (!tile.craftIngredientRequests.isEmpty()) { if (!craftData.ingredientsToRequest.isEmpty()) {
network.startProfile("crafting_ingredients"); network.startProfile("crafting_ingredients");
var request = tile.craftIngredientRequests.getFirst(); var lock = craftData.ingredientsToRequest.getFirst();
if (request.getLeft() == slot) {
var locks = request.getRight();
var lock = locks.getFirst();
var equalityTypes = ItemFilter.getEqualityTypes(tile); var equalityTypes = ItemFilter.getEqualityTypes(tile);
var dest = tile.getAvailableDestination(Direction.values(), lock.stack, true, true); var dest = tile.getAvailableDestination(Direction.values(), lock.stack, true, true);
if (dest != null) { if (dest != null) {
@ -86,7 +94,11 @@ public class CraftingModuleItem extends ModuleItem {
if (!ensureItemOrder || network.getPipeItemsOnTheWay(dest.getLeft()).findAny().isEmpty()) { if (!ensureItemOrder || network.getPipeItemsOnTheWay(dest.getLeft()).findAny().isEmpty()) {
var requestRemain = network.requestExistingItem(lock.location, tile.getBlockPos(), dest.getLeft(), lock, dest.getRight(), equalityTypes); var requestRemain = network.requestExistingItem(lock.location, tile.getBlockPos(), dest.getLeft(), lock, dest.getRight(), equalityTypes);
network.resolveNetworkLock(lock); network.resolveNetworkLock(lock);
locks.remove(lock); craftData.ingredientsToRequest.remove(lock);
var traveling = lock.stack.copy();
traveling.shrink(requestRemain.getCount());
craftData.travelingIngredients.add(traveling);
// if we couldn't fit all items into the destination, create another request for the rest // if we couldn't fit all items into the destination, create another request for the rest
var remain = lock.stack.copy(); var remain = lock.stack.copy();
@ -94,51 +106,39 @@ public class CraftingModuleItem extends ModuleItem {
if (!remain.isEmpty()) { if (!remain.isEmpty()) {
var remainRequest = new NetworkLock(lock.location, remain); var remainRequest = new NetworkLock(lock.location, remain);
// if we're ensuring item order, we need to insert the remaining request at the start so that it gets processed first // if we're ensuring item order, we need to insert the remaining request at the start so that it gets processed first
var index = ensureItemOrder ? 0 : locks.size(); var index = ensureItemOrder ? 0 : craftData.ingredientsToRequest.size();
locks.add(index, remainRequest); craftData.ingredientsToRequest.add(index, remainRequest);
network.createNetworkLock(remainRequest); network.createNetworkLock(remainRequest);
} }
if (locks.isEmpty())
tile.craftIngredientRequests.remove(request);
}
} }
} }
network.endProfile(); network.endProfile();
} }
// pull requested crafting results from the network once they are stored // pull requested crafting results from the network once they are stored
if (!tile.craftResultRequests.isEmpty()) { if (!craftData.resultStackRemain.isEmpty()) {
network.startProfile("crafting_results"); network.startProfile("crafting_results");
var items = network.getOrderedNetworkItems(tile.getBlockPos()); var items = network.getOrderedNetworkItems(tile.getBlockPos());
var equalityTypes = ItemFilter.getEqualityTypes(tile); var equalityTypes = ItemFilter.getEqualityTypes(tile);
for (var request : tile.craftResultRequests) { var destPipe = network.getPipe(craftData.resultDestPipe);
if (request.getLeft() == slot) {
var remain = request.getRight().copy();
var destPipe = network.getPipe(request.getMiddle());
if (destPipe != null) { if (destPipe != null) {
var dest = destPipe.getAvailableDestinationOrConnectable(remain, true, true); var dest = destPipe.getAvailableDestinationOrConnectable(craftData.resultStackRemain, true, true);
if (dest == null) if (dest != null) {
continue;
for (var item : items) { for (var item : items) {
var requestRemain = network.requestExistingItem(item, request.getMiddle(), dest.getLeft(), null, dest.getRight(), equalityTypes); var requestRemain = network.requestExistingItem(item, craftData.resultDestPipe, dest.getLeft(), null, dest.getRight(), equalityTypes);
remain.shrink(dest.getRight().getCount() - requestRemain.getCount()); craftData.resultStackRemain.shrink(dest.getRight().getCount() - requestRemain.getCount());
if (remain.isEmpty()) if (craftData.resultStackRemain.isEmpty()) {
tile.activeCrafts.remove(activeCraft);
break; break;
} }
if (remain.getCount() != request.getRight().getCount()) {
tile.craftResultRequests.remove(request);
// if we couldn't pull everything, log a new request
if (!remain.isEmpty())
tile.craftResultRequests.add(Triple.of(slot, request.getMiddle(), remain));
network.endProfile();
return;
}
} }
} }
} }
network.endProfile(); network.endProfile();
} }
} }
}
}
@Override @Override
public List<ItemStack> getAllCraftables(ItemStack module, PipeBlockEntity tile) { public List<ItemStack> getAllCraftables(ItemStack module, PipeBlockEntity tile) {
@ -205,20 +205,27 @@ public class CraftingModuleItem extends ModuleItem {
locks.addAll(ret.getLeft()); locks.addAll(ret.getLeft());
} }
} }
tile.craftIngredientRequests.add(Pair.of(slot, locks));
var remain = stack.copy(); var remain = stack.copy();
remain.shrink(resultAmount * toCraft); remain.shrink(resultAmount * toCraft);
var result = stack.copy(); var result = stack.copy();
result.shrink(remain.getCount()); result.shrink(remain.getCount());
tile.craftResultRequests.add(Triple.of(slot, destPipe, result));
var activeCraft = new ActiveCraft(locks, new ArrayList<>(), destPipe, result);
tile.activeCrafts.add(Pair.of(slot, activeCraft));
return remain; return remain;
} }
@Override @Override
public ItemStack store(ItemStack module, PipeBlockEntity tile, ItemStack stack, Direction direction) { public ItemStack store(ItemStack module, PipeBlockEntity tile, ItemStack stack, Direction direction) {
var slot = tile.getModuleSlot(module);
var equalityTypes = ItemFilter.getEqualityTypes(tile);
var matchingCraft = tile.activeCrafts.stream()
.filter(c -> c.getLeft() == slot && c.getRight().isMatchingIngredient(stack, equalityTypes))
.findAny().orElse(null);
if (matchingCraft != null) {
matchingCraft.getRight().travelingIngredients.removeIf(s -> ItemEquality.compareItems(stack, s, equalityTypes));
if (module.get(Contents.TYPE).insertSingles) { if (module.get(Contents.TYPE).insertSingles) {
var handler = tile.getItemHandler(direction); var handler = tile.getItemHandler(direction);
if (handler != null) { if (handler != null) {
@ -230,6 +237,7 @@ public class CraftingModuleItem extends ModuleItem {
} }
} }
} }
}
return stack; return stack;
} }
@ -262,4 +270,50 @@ public class CraftingModuleItem extends ModuleItem {
} }
public static class ActiveCraft implements INBTSerializable<CompoundTag> {
public List<NetworkLock> ingredientsToRequest;
public List<ItemStack> travelingIngredients;
public BlockPos resultDestPipe;
public ItemStack resultStackRemain;
public ActiveCraft(List<NetworkLock> ingredientsToRequest, List<ItemStack> travelingIngredients, BlockPos resultDestPipe, ItemStack resultStackRemain) {
this.ingredientsToRequest = ingredientsToRequest;
this.travelingIngredients = travelingIngredients;
this.resultDestPipe = resultDestPipe;
this.resultStackRemain = resultStackRemain;
}
public ActiveCraft(HolderLookup.Provider provider, CompoundTag tag) {
this.deserializeNBT(provider, tag);
}
@Override
public @UnknownNullability CompoundTag serializeNBT(HolderLookup.Provider provider) {
var ret = new CompoundTag();
ret.put("ingredients_to_request", Utility.serializeAll(this.ingredientsToRequest, n -> n.serializeNBT(provider)));
ret.put("traveling_ingredients", Utility.serializeAll(this.travelingIngredients, s -> (CompoundTag) s.save(provider, new CompoundTag())));
ret.putLong("result_dest_pipe", this.resultDestPipe.asLong());
ret.put("result_stack_remain", this.resultStackRemain.saveOptional(provider));
return ret;
}
@Override
public void deserializeNBT(HolderLookup.Provider provider, CompoundTag nbt) {
this.ingredientsToRequest = Utility.deserializeAll(nbt.getList("ingredients_to_request", Tag.TAG_COMPOUND), t -> new NetworkLock(provider, t));
this.travelingIngredients = Utility.deserializeAll(nbt.getList("traveling_ingredients", Tag.TAG_COMPOUND), t -> ItemStack.parse(provider, t).orElseThrow());
this.resultDestPipe = BlockPos.of(nbt.getLong("result_dest_pipe"));
this.resultStackRemain = ItemStack.parseOptional(provider, nbt.getCompound("result_stack_remain"));
}
public boolean isMatchingIngredient(ItemStack stack, ItemEquality... equalityTypes) {
for (var traveling : this.travelingIngredients) {
if (ItemEquality.compareItems(stack, traveling, equalityTypes))
return true;
}
return false;
}
}
} }

View file

@ -217,12 +217,11 @@ public class ItemTerminalBlockEntity extends BlockEntity implements IPipeConnect
for (var craftable : network.getAllCraftables(pipe.getBlockPos())) { for (var craftable : network.getAllCraftables(pipe.getBlockPos())) {
var otherPipe = network.getPipe(craftable.getLeft()); var otherPipe = network.getPipe(craftable.getLeft());
if (otherPipe != null) { if (otherPipe != null) {
for (var locks : otherPipe.craftIngredientRequests) { for (var craft : otherPipe.activeCrafts) {
for (var lock : locks.getRight()) for (var lock : craft.getRight().ingredientsToRequest)
network.resolveNetworkLock(lock); network.resolveNetworkLock(lock);
} }
otherPipe.craftIngredientRequests.clear(); otherPipe.activeCrafts.clear();
otherPipe.craftResultRequests.clear();
} }
} }
var lookingPlayers = this.getLookingPlayers(); var lookingPlayers = this.getLookingPlayers();
@ -234,7 +233,7 @@ public class ItemTerminalBlockEntity extends BlockEntity implements IPipeConnect
public void saveAdditional(CompoundTag compound, HolderLookup.Provider pRegistries) { public void saveAdditional(CompoundTag compound, HolderLookup.Provider pRegistries) {
super.saveAdditional(compound, pRegistries); super.saveAdditional(compound, pRegistries);
compound.put("items", this.items.serializeNBT(pRegistries)); compound.put("items", this.items.serializeNBT(pRegistries));
compound.put("requests", Utility.serializeAll(pRegistries, this.existingRequests)); compound.put("requests", Utility.serializeAll(this.existingRequests, i -> i.serializeNBT(pRegistries)));
} }
@Override @Override