mirror of
https://github.com/Ellpeck/PrettyPipes.git
synced 2025-01-10 07:07:42 +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;
|
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) -> {
|
STACK_SIZE_MODULE_BUTTON((pos, data, player) -> {
|
||||||
var container = (AbstractPipeContainer<?>) player.containerMenu;
|
var container = (AbstractPipeContainer<?>) player.containerMenu;
|
||||||
var moduleData = container.moduleStack.getOrDefault(StackSizeModuleItem.Data.TYPE, StackSizeModuleItem.Data.DEFAULT);
|
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());
|
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
|
@org.jetbrains.annotations.Nullable
|
||||||
@Override
|
@Override
|
||||||
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
|
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
|
||||||
|
|
|
@ -70,14 +70,18 @@ public class PipeBlockEntity extends BlockEntity implements MenuProvider, IPipeC
|
||||||
PipeBlockEntity.this.setChanged();
|
PipeBlockEntity.this.setChanged();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public PressurizerBlockEntity pressurizer;
|
public PressurizerBlockEntity pressurizer;
|
||||||
public BlockState cover;
|
public BlockState cover;
|
||||||
public int moduleDropCheck;
|
public int moduleDropCheck;
|
||||||
|
public int redstoneTicks;
|
||||||
|
|
||||||
|
private final Lazy<Integer> workRandomizer = Lazy.of(() -> this.level.random.nextInt(200));
|
||||||
|
|
||||||
private List<IPipeItem> itemCache;
|
private List<IPipeItem> itemCache;
|
||||||
private List<ActiveCraft> activeCraftCache;
|
private List<ActiveCraft> activeCraftCache;
|
||||||
private int lastItemAmount;
|
private int lastItemAmount;
|
||||||
private int priority;
|
private int priority;
|
||||||
private final Lazy<Integer> workRandomizer = Lazy.of(() -> this.level.random.nextInt(200));
|
|
||||||
|
|
||||||
public PipeBlockEntity(BlockPos pos, BlockState state) {
|
public PipeBlockEntity(BlockPos pos, BlockState state) {
|
||||||
super(Registry.pipeBlockEntity, pos, 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);
|
compound.putInt("module_drop_check", this.moduleDropCheck);
|
||||||
if (this.cover != null)
|
if (this.cover != null)
|
||||||
compound.put("cover", NbtUtils.writeBlockState(this.cover));
|
compound.put("cover", NbtUtils.writeBlockState(this.cover));
|
||||||
|
compound.putInt("priority", this.priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -106,6 +111,7 @@ 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.priority = compound.getInt("priority");
|
||||||
super.loadAdditional(compound, provider);
|
super.loadAdditional(compound, provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -404,6 +410,10 @@ public class PipeBlockEntity extends BlockEntity implements MenuProvider, IPipeC
|
||||||
return stack;
|
return stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setRedstoneTicks(int ticks) {
|
||||||
|
this.redstoneTicks = ticks;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Component getDisplayName() {
|
public Component getDisplayName() {
|
||||||
return Component.translatable("container." + PrettyPipes.ID + ".pipe");
|
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())
|
if (pipe.pressurizer != null && pipe.pressurizer.isRemoved())
|
||||||
pipe.pressurizer = null;
|
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))
|
if (!pipe.level.isAreaLoaded(pipe.worldPosition, 1))
|
||||||
return;
|
return;
|
||||||
var profiler = pipe.level.getProfiler();
|
var profiler = pipe.level.getProfiler();
|
||||||
|
|
|
@ -17,6 +17,7 @@ public class CraftingModuleContainer extends AbstractPipeContainer<CraftingModul
|
||||||
public ItemStackHandler output;
|
public ItemStackHandler output;
|
||||||
public boolean ensureItemOrder;
|
public boolean ensureItemOrder;
|
||||||
public boolean insertSingles;
|
public boolean insertSingles;
|
||||||
|
public boolean emitRedstone;
|
||||||
public boolean modified;
|
public boolean modified;
|
||||||
|
|
||||||
public CraftingModuleContainer(MenuType<?> type, int id, Player player, BlockPos pos, int moduleIndex) {
|
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);
|
var contents = this.moduleStack.get(CraftingModuleItem.Contents.TYPE);
|
||||||
this.ensureItemOrder = contents.ensureItemOrder();
|
this.ensureItemOrder = contents.ensureItemOrder();
|
||||||
this.insertSingles = contents.insertSingles();
|
this.insertSingles = contents.insertSingles();
|
||||||
|
this.emitRedstone = contents.emitRedstone();
|
||||||
|
|
||||||
this.input = Utility.copy(contents.input());
|
this.input = Utility.copy(contents.input());
|
||||||
for (var i = 0; i < this.input.getSlots(); i++) {
|
for (var i = 0; i < this.input.getSlots(); i++) {
|
||||||
|
@ -57,7 +59,7 @@ public class CraftingModuleContainer extends AbstractPipeContainer<CraftingModul
|
||||||
public void removed(Player playerIn) {
|
public void removed(Player playerIn) {
|
||||||
super.removed(playerIn);
|
super.removed(playerIn);
|
||||||
if (this.modified) {
|
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();
|
this.tile.setChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,13 @@ public class CraftingModuleGui extends AbstractPipeGui<CraftingModuleContainer>
|
||||||
button.setMessage(Component.translatable(singleText.get()));
|
button.setMessage(Component.translatable(singleText.get()));
|
||||||
}).bounds(this.leftPos + this.imageWidth - 7 - 20 - 22, this.topPos + 17 + 32 + 18 * 2 + 2, 20, 20).tooltip(
|
}).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());
|
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;
|
private final int speed;
|
||||||
|
|
||||||
public CraftingModuleItem(String name, ModuleTier tier) {
|
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);
|
this.speed = tier.forTier(20, 10, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,6 +172,7 @@ public class CraftingModuleItem extends ModuleItem {
|
||||||
if (craftableAmount <= 0)
|
if (craftableAmount <= 0)
|
||||||
return Pair.of(stack, List.of());
|
return Pair.of(stack, List.of());
|
||||||
var slot = tile.getModuleSlot(module);
|
var slot = tile.getModuleSlot(module);
|
||||||
|
var contents = module.get(Contents.TYPE);
|
||||||
|
|
||||||
var network = PipeNetwork.get(tile.getLevel());
|
var network = PipeNetwork.get(tile.getLevel());
|
||||||
var items = network.getOrderedNetworkItems(tile.getBlockPos());
|
var items = network.getOrderedNetworkItems(tile.getBlockPos());
|
||||||
|
@ -183,11 +184,10 @@ public class CraftingModuleItem extends ModuleItem {
|
||||||
var craftableCrafts = Mth.ceil(craftableAmount / (float) resultAmount);
|
var craftableCrafts = Mth.ceil(craftableAmount / (float) resultAmount);
|
||||||
var toCraft = Math.min(craftableCrafts, requiredCrafts);
|
var toCraft = Math.min(craftableCrafts, requiredCrafts);
|
||||||
|
|
||||||
var locks = new ArrayList<NetworkLock>();
|
var allCrafts = new ArrayList<ActiveCraft>();
|
||||||
var crafts = new ArrayList<ActiveCraft>();
|
|
||||||
var contents = module.get(Contents.TYPE);
|
|
||||||
// if we're ensuring item order, all items for a single recipe should be sent in order first before starting on the next one!
|
// 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--) {
|
for (var c = contents.ensureItemOrder ? toCraft : 1; c > 0; c--) {
|
||||||
|
var locks = new ArrayList<NetworkLock>();
|
||||||
for (var i = 0; i < contents.input.getSlots(); i++) {
|
for (var i = 0; i < contents.input.getSlots(); i++) {
|
||||||
var in = contents.input.getStackInSlot(i);
|
var in = contents.input.getStackInSlot(i);
|
||||||
if (in.isEmpty())
|
if (in.isEmpty())
|
||||||
|
@ -196,29 +196,27 @@ public class CraftingModuleItem extends ModuleItem {
|
||||||
if (!contents.ensureItemOrder)
|
if (!contents.ensureItemOrder)
|
||||||
copy.setCount(in.getCount() * toCraft);
|
copy.setCount(in.getCount() * toCraft);
|
||||||
var ret = network.requestLocksAndStartCrafting(tile.getBlockPos(), items, unavailableConsumer, copy, CraftingModuleItem.addDependency(dependencyChain, module), equalityTypes);
|
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());
|
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();
|
var remain = stack.copy();
|
||||||
remain.shrink(resultAmount * toCraft);
|
remain.shrink(resultAmount * toCraft);
|
||||||
var result = stack.copy();
|
return Pair.of(remain, allCrafts);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@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 slot = tile.getModuleSlot(module);
|
||||||
|
var contents = module.get(Contents.TYPE);
|
||||||
var equalityTypes = ItemFilter.getEqualityTypes(tile);
|
var equalityTypes = ItemFilter.getEqualityTypes(tile);
|
||||||
var crafts = tile.getActiveCrafts();
|
var crafts = tile.getActiveCrafts();
|
||||||
var craft = crafts.stream()
|
var craft = crafts.stream()
|
||||||
|
@ -227,7 +225,7 @@ public class CraftingModuleItem extends ModuleItem {
|
||||||
if (craft != null) {
|
if (craft != null) {
|
||||||
craft.travelingIngredients.remove(craft.getTravelingIngredient(stack, equalityTypes));
|
craft.travelingIngredients.remove(craft.getTravelingIngredient(stack, equalityTypes));
|
||||||
|
|
||||||
if (module.get(Contents.TYPE).insertSingles) {
|
if (contents.insertSingles) {
|
||||||
var handler = tile.getItemHandler(direction);
|
var handler = tile.getItemHandler(direction);
|
||||||
if (handler != null) {
|
if (handler != null) {
|
||||||
while (!stack.isEmpty()) {
|
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.travelingIngredients.size() <= 0 && craft.ingredientsToRequest.size() <= 0) {
|
||||||
if (craft.canceled && craft.travelingIngredients.size() <= 0 && craft.ingredientsToRequest.size() <= 0)
|
if (contents.emitRedstone) {
|
||||||
crafts.remove(craft);
|
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;
|
return stack;
|
||||||
}
|
}
|
||||||
|
@ -264,13 +269,14 @@ public class CraftingModuleItem extends ModuleItem {
|
||||||
return deps;
|
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(
|
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("input").forGetter(d -> d.input),
|
||||||
Utility.ITEM_STACK_HANDLER_CODEC.fieldOf("output").forGetter(d -> d.output),
|
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("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));
|
).apply(i, Contents::new));
|
||||||
public static final DataComponentType<Contents> TYPE = DataComponentType.<Contents>builder().persistent(Contents.CODEC).cacheEncoding().build();
|
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_on": "\u00A72O",
|
||||||
"info.prettypipes.ensure_item_order_off": "\u00A74\u00A7mO",
|
"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.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.shift": "Hold Shift for info",
|
||||||
"info.prettypipes.populate": "P",
|
"info.prettypipes.populate": "P",
|
||||||
"info.prettypipes.populate.description": "Populate filter slots with items from adjacent inventories",
|
"info.prettypipes.populate.description": "Populate filter slots with items from adjacent inventories",
|
||||||
|
|
Loading…
Reference in a new issue