mirror of
https://github.com/Ellpeck/PrettyPipes.git
synced 2025-01-09 22:57:44 +01:00
added a setting in the crafter to emit a redstone signal when all items have arrived
This commit is contained in:
parent
cee38be5cd
commit
c72d1cc09c
7 changed files with 70 additions and 24 deletions
|
@ -107,6 +107,12 @@ public record PacketButton(BlockPos pos, int result, List<Integer> data) impleme
|
|||
container.modified = true;
|
||||
}
|
||||
}),
|
||||
EMIT_REDSTONE_BUTTON((pos, data, player) -> {
|
||||
if (player.containerMenu instanceof CraftingModuleContainer container) {
|
||||
container.emitRedstone = !container.emitRedstone;
|
||||
container.modified = true;
|
||||
}
|
||||
}),
|
||||
STACK_SIZE_MODULE_BUTTON((pos, data, player) -> {
|
||||
var container = (AbstractPipeContainer<?>) player.containerMenu;
|
||||
var moduleData = container.moduleStack.getOrDefault(StackSizeModuleItem.Data.TYPE, StackSizeModuleItem.Data.DEFAULT);
|
||||
|
|
|
@ -298,6 +298,12 @@ public class PipeBlock extends BaseEntityBlock implements SimpleWaterloggedBlock
|
|||
return Math.min(15, pipe.getItems().size());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getSignal(BlockState blockState, BlockGetter blockAccess, BlockPos pos, Direction side) {
|
||||
var pipe = Utility.getBlockEntity(PipeBlockEntity.class, blockAccess, pos);
|
||||
return pipe.redstoneTicks > 0 ? 15 : 0;
|
||||
}
|
||||
|
||||
@org.jetbrains.annotations.Nullable
|
||||
@Override
|
||||
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
|
||||
|
|
|
@ -70,14 +70,18 @@ public class PipeBlockEntity extends BlockEntity implements MenuProvider, IPipeC
|
|||
PipeBlockEntity.this.setChanged();
|
||||
}
|
||||
};
|
||||
|
||||
public PressurizerBlockEntity pressurizer;
|
||||
public BlockState cover;
|
||||
public int moduleDropCheck;
|
||||
public int redstoneTicks;
|
||||
|
||||
private final Lazy<Integer> workRandomizer = Lazy.of(() -> this.level.random.nextInt(200));
|
||||
|
||||
private List<IPipeItem> itemCache;
|
||||
private List<ActiveCraft> activeCraftCache;
|
||||
private int lastItemAmount;
|
||||
private int priority;
|
||||
private final Lazy<Integer> workRandomizer = Lazy.of(() -> this.level.random.nextInt(200));
|
||||
|
||||
public PipeBlockEntity(BlockPos pos, BlockState state) {
|
||||
super(Registry.pipeBlockEntity, pos, state);
|
||||
|
@ -99,6 +103,7 @@ public class PipeBlockEntity extends BlockEntity implements MenuProvider, IPipeC
|
|||
compound.putInt("module_drop_check", this.moduleDropCheck);
|
||||
if (this.cover != null)
|
||||
compound.put("cover", NbtUtils.writeBlockState(this.cover));
|
||||
compound.putInt("priority", this.priority);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -106,6 +111,7 @@ public class PipeBlockEntity extends BlockEntity implements MenuProvider, IPipeC
|
|||
this.modules.deserializeNBT(provider, compound.getCompound("modules"));
|
||||
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.priority = compound.getInt("priority");
|
||||
super.loadAdditional(compound, provider);
|
||||
}
|
||||
|
||||
|
@ -404,6 +410,10 @@ public class PipeBlockEntity extends BlockEntity implements MenuProvider, IPipeC
|
|||
return stack;
|
||||
}
|
||||
|
||||
public void setRedstoneTicks(int ticks) {
|
||||
this.redstoneTicks = ticks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getDisplayName() {
|
||||
return Component.translatable("container." + PrettyPipes.ID + ".pipe");
|
||||
|
@ -433,6 +443,12 @@ public class PipeBlockEntity extends BlockEntity implements MenuProvider, IPipeC
|
|||
if (pipe.pressurizer != null && pipe.pressurizer.isRemoved())
|
||||
pipe.pressurizer = null;
|
||||
|
||||
if (pipe.redstoneTicks > 0) {
|
||||
pipe.redstoneTicks--;
|
||||
if (pipe.redstoneTicks <= 0)
|
||||
level.updateNeighborsAt(pos, state.getBlock());
|
||||
}
|
||||
|
||||
if (!pipe.level.isAreaLoaded(pipe.worldPosition, 1))
|
||||
return;
|
||||
var profiler = pipe.level.getProfiler();
|
||||
|
|
|
@ -17,6 +17,7 @@ public class CraftingModuleContainer extends AbstractPipeContainer<CraftingModul
|
|||
public ItemStackHandler output;
|
||||
public boolean ensureItemOrder;
|
||||
public boolean insertSingles;
|
||||
public boolean emitRedstone;
|
||||
public boolean modified;
|
||||
|
||||
public CraftingModuleContainer(MenuType<?> type, int id, Player player, BlockPos pos, int moduleIndex) {
|
||||
|
@ -28,6 +29,7 @@ public class CraftingModuleContainer extends AbstractPipeContainer<CraftingModul
|
|||
var contents = this.moduleStack.get(CraftingModuleItem.Contents.TYPE);
|
||||
this.ensureItemOrder = contents.ensureItemOrder();
|
||||
this.insertSingles = contents.insertSingles();
|
||||
this.emitRedstone = contents.emitRedstone();
|
||||
|
||||
this.input = Utility.copy(contents.input());
|
||||
for (var i = 0; i < this.input.getSlots(); i++) {
|
||||
|
@ -57,7 +59,7 @@ public class CraftingModuleContainer extends AbstractPipeContainer<CraftingModul
|
|||
public void removed(Player playerIn) {
|
||||
super.removed(playerIn);
|
||||
if (this.modified) {
|
||||
this.moduleStack.set(CraftingModuleItem.Contents.TYPE, new CraftingModuleItem.Contents(this.input, this.output, this.ensureItemOrder, this.insertSingles));
|
||||
this.moduleStack.set(CraftingModuleItem.Contents.TYPE, new CraftingModuleItem.Contents(this.input, this.output, this.ensureItemOrder, this.insertSingles, this.emitRedstone));
|
||||
this.tile.setChanged();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,6 +41,13 @@ public class CraftingModuleGui extends AbstractPipeGui<CraftingModuleContainer>
|
|||
button.setMessage(Component.translatable(singleText.get()));
|
||||
}).bounds(this.leftPos + this.imageWidth - 7 - 20 - 22, this.topPos + 17 + 32 + 18 * 2 + 2, 20, 20).tooltip(
|
||||
Tooltip.create(Component.translatable("info." + PrettyPipes.ID + ".insert_singles.description").withStyle(ChatFormatting.GRAY))).build());
|
||||
|
||||
var redstoneText = (Supplier<String>) () -> "info." + PrettyPipes.ID + ".emit_redstone_" + (this.menu.emitRedstone ? "on" : "off");
|
||||
this.addRenderableWidget(Button.builder(Component.translatable(redstoneText.get()), button -> {
|
||||
PacketButton.sendAndExecute(this.menu.tile.getBlockPos(), PacketButton.ButtonResult.EMIT_REDSTONE_BUTTON, List.of());
|
||||
button.setMessage(Component.translatable(redstoneText.get()));
|
||||
}).bounds(this.leftPos + 7, this.topPos + 17 + 32 + 18 * 2 + 2, 20, 20).tooltip(
|
||||
Tooltip.create(Component.translatable("info." + PrettyPipes.ID + ".emit_redstone.description").withStyle(ChatFormatting.GRAY))).build());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ public class CraftingModuleItem extends ModuleItem {
|
|||
private final int speed;
|
||||
|
||||
public CraftingModuleItem(String name, ModuleTier tier) {
|
||||
super(name, new Properties().component(Contents.TYPE, new Contents(new ItemStackHandler(tier.forTier(1, 4, 9)), new ItemStackHandler(tier.forTier(1, 2, 4)), false, false)));
|
||||
super(name, new Properties().component(Contents.TYPE, new Contents(new ItemStackHandler(tier.forTier(1, 4, 9)), new ItemStackHandler(tier.forTier(1, 2, 4)), false, false, false)));
|
||||
this.speed = tier.forTier(20, 10, 5);
|
||||
}
|
||||
|
||||
|
@ -172,6 +172,7 @@ public class CraftingModuleItem extends ModuleItem {
|
|||
if (craftableAmount <= 0)
|
||||
return Pair.of(stack, List.of());
|
||||
var slot = tile.getModuleSlot(module);
|
||||
var contents = module.get(Contents.TYPE);
|
||||
|
||||
var network = PipeNetwork.get(tile.getLevel());
|
||||
var items = network.getOrderedNetworkItems(tile.getBlockPos());
|
||||
|
@ -183,11 +184,10 @@ public class CraftingModuleItem extends ModuleItem {
|
|||
var craftableCrafts = Mth.ceil(craftableAmount / (float) resultAmount);
|
||||
var toCraft = Math.min(craftableCrafts, requiredCrafts);
|
||||
|
||||
var locks = new ArrayList<NetworkLock>();
|
||||
var crafts = new ArrayList<ActiveCraft>();
|
||||
var contents = module.get(Contents.TYPE);
|
||||
var allCrafts = new ArrayList<ActiveCraft>();
|
||||
// if we're ensuring item order, all items for a single recipe should be sent in order first before starting on the next one!
|
||||
for (var c = contents.ensureItemOrder ? toCraft : 1; c > 0; c--) {
|
||||
var locks = new ArrayList<NetworkLock>();
|
||||
for (var i = 0; i < contents.input.getSlots(); i++) {
|
||||
var in = contents.input.getStackInSlot(i);
|
||||
if (in.isEmpty())
|
||||
|
@ -196,29 +196,27 @@ public class CraftingModuleItem extends ModuleItem {
|
|||
if (!contents.ensureItemOrder)
|
||||
copy.setCount(in.getCount() * toCraft);
|
||||
var ret = network.requestLocksAndStartCrafting(tile.getBlockPos(), items, unavailableConsumer, copy, CraftingModuleItem.addDependency(dependencyChain, module), equalityTypes);
|
||||
// set crafting dependencies as in progress immediately so that, when canceling, they don't leave behind half-crafted inbetween dependencies
|
||||
// TODO to be more optimal, we should really do this when setting the main craft as in progress, but that would require storing references to all of the dependencies
|
||||
ret.getRight().forEach(a -> a.inProgress = true);
|
||||
locks.addAll(ret.getLeft());
|
||||
crafts.addAll(ret.getRight());
|
||||
allCrafts.addAll(ret.getRight());
|
||||
}
|
||||
var result = stack.copyWithCount(contents.ensureItemOrder ? resultAmount : resultAmount * toCraft);
|
||||
var activeCraft = new ActiveCraft(tile.getBlockPos(), slot, locks, destPipe, result);
|
||||
tile.getActiveCrafts().add(activeCraft);
|
||||
allCrafts.add(activeCraft);
|
||||
}
|
||||
// set crafting dependencies as in progress immediately so that, when canceling, they don't leave behind half-crafted inbetween dependencies
|
||||
// TODO to be more optimal, we should really do this when setting the main craft as in progress, but that would require storing references to all of the dependencies
|
||||
crafts.forEach(c -> c.inProgress = true);
|
||||
|
||||
var remain = stack.copy();
|
||||
remain.shrink(resultAmount * toCraft);
|
||||
var result = stack.copy();
|
||||
result.shrink(remain.getCount());
|
||||
|
||||
var activeCraft = new ActiveCraft(tile.getBlockPos(), slot, locks, destPipe, result);
|
||||
tile.getActiveCrafts().add(activeCraft);
|
||||
crafts.add(activeCraft);
|
||||
|
||||
return Pair.of(remain, crafts);
|
||||
return Pair.of(remain, allCrafts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack store(ItemStack module, PipeBlockEntity tile, ItemStack stack, Direction direction) {
|
||||
var slot = tile.getModuleSlot(module);
|
||||
var contents = module.get(Contents.TYPE);
|
||||
var equalityTypes = ItemFilter.getEqualityTypes(tile);
|
||||
var crafts = tile.getActiveCrafts();
|
||||
var craft = crafts.stream()
|
||||
|
@ -227,7 +225,7 @@ public class CraftingModuleItem extends ModuleItem {
|
|||
if (craft != null) {
|
||||
craft.travelingIngredients.remove(craft.getTravelingIngredient(stack, equalityTypes));
|
||||
|
||||
if (module.get(Contents.TYPE).insertSingles) {
|
||||
if (contents.insertSingles) {
|
||||
var handler = tile.getItemHandler(direction);
|
||||
if (handler != null) {
|
||||
while (!stack.isEmpty()) {
|
||||
|
@ -239,9 +237,16 @@ public class CraftingModuleItem extends ModuleItem {
|
|||
}
|
||||
}
|
||||
|
||||
// if we canceled the request and all input items are delivered (ie the machine actually got what it expected), remove it from the queue
|
||||
if (craft.canceled && craft.travelingIngredients.size() <= 0 && craft.ingredientsToRequest.size() <= 0)
|
||||
crafts.remove(craft);
|
||||
if (craft.travelingIngredients.size() <= 0 && craft.ingredientsToRequest.size() <= 0) {
|
||||
if (contents.emitRedstone) {
|
||||
tile.redstoneTicks = 5;
|
||||
tile.getLevel().updateNeighborsAt(tile.getBlockPos(), tile.getBlockState().getBlock());
|
||||
}
|
||||
|
||||
// if we canceled the request and all input items are delivered (ie the machine actually got what it expected), remove it from the queue
|
||||
if (craft.canceled)
|
||||
crafts.remove(craft);
|
||||
}
|
||||
}
|
||||
return stack;
|
||||
}
|
||||
|
@ -264,13 +269,14 @@ public class CraftingModuleItem extends ModuleItem {
|
|||
return deps;
|
||||
}
|
||||
|
||||
public record Contents(ItemStackHandler input, ItemStackHandler output, boolean ensureItemOrder, boolean insertSingles) {
|
||||
public record Contents(ItemStackHandler input, ItemStackHandler output, boolean ensureItemOrder, boolean insertSingles, boolean emitRedstone) {
|
||||
|
||||
public static final Codec<Contents> CODEC = RecordCodecBuilder.create(i -> i.group(
|
||||
Utility.ITEM_STACK_HANDLER_CODEC.fieldOf("input").forGetter(d -> d.input),
|
||||
Utility.ITEM_STACK_HANDLER_CODEC.fieldOf("output").forGetter(d -> d.output),
|
||||
Codec.BOOL.optionalFieldOf("ensure_item_order", false).forGetter(d -> d.ensureItemOrder),
|
||||
Codec.BOOL.optionalFieldOf("insert_singles", false).forGetter(d -> d.insertSingles)
|
||||
Codec.BOOL.optionalFieldOf("insert_singles", false).forGetter(d -> d.insertSingles),
|
||||
Codec.BOOL.optionalFieldOf("emit_redstone", false).forGetter(d -> d.emitRedstone)
|
||||
).apply(i, Contents::new));
|
||||
public static final DataComponentType<Contents> TYPE = DataComponentType.<Contents>builder().persistent(Contents.CODEC).cacheEncoding().build();
|
||||
|
||||
|
|
|
@ -72,6 +72,9 @@
|
|||
"info.prettypipes.ensure_item_order_on": "\u00A72O",
|
||||
"info.prettypipes.ensure_item_order_off": "\u00A74\u00A7mO",
|
||||
"info.prettypipes.ensure_item_order.description": "Whether the module should wait for items to be inserted in the order they appear in the input slots\n\u00A7oRecommended for use with the Crafter",
|
||||
"info.prettypipes.emit_redstone_on": "\u00A72R",
|
||||
"info.prettypipes.emit_redstone_off": "\u00A74\u00A7mR",
|
||||
"info.prettypipes.emit_redstone.description": "Whether a redstone signal should be emitted when all crafting items have arrived\nIf the module waits for items to be inserted in order, a redstone signal is emitted for each set of items required for a single craft\n\u00A7oRecommended for use with the Crafter",
|
||||
"info.prettypipes.shift": "Hold Shift for info",
|
||||
"info.prettypipes.populate": "P",
|
||||
"info.prettypipes.populate.description": "Populate filter slots with items from adjacent inventories",
|
||||
|
|
Loading…
Reference in a new issue