diff --git a/src/main/java/com/sk89q/craftbook/mechanics/pipe/Pipes.java b/src/main/java/com/sk89q/craftbook/mechanics/pipe/Pipes.java index 19b134e53..6a4a3d2b8 100644 --- a/src/main/java/com/sk89q/craftbook/mechanics/pipe/Pipes.java +++ b/src/main/java/com/sk89q/craftbook/mechanics/pipe/Pipes.java @@ -182,14 +182,21 @@ private void searchNearbyPipes(Block block, Set visitedPipes, List its = new ArrayList<>(event.getItems()); - if (juke.getPlaying() != Material.AIR) { + // Only an empty jukebox accepts a disc. The test was inverted, so + // an empty jukebox never took one, and a playing one had its disc + // overwritten by setPlaying and destroyed. Discs that do not fit + // stay in the list and flow on through the pipe. + if (juke.getPlaying() == Material.AIR) { Iterator iter = its.iterator(); while (iter.hasNext()) { ItemStack st = iter.next(); if (!st.getType().isRecord()) continue; juke.setPlaying(st.getType()); juke.update(); - iter.remove(); + if (st.getAmount() > 1) + st.setAmount(st.getAmount() - 1); + else + iter.remove(); break; } } @@ -429,28 +436,30 @@ private void startPipe(Block block, List items, boolean request) { Jukebox juke = (Jukebox) fac.getState(); if (juke.getPlaying() != Material.AIR) { + // Remove the disc before firing the event. Inferring "the disc left + // the jukebox" from the item list afterwards duplicated the disc + // whenever delivery was refused: a copy dropped at the piston while + // the original kept playing. items.add(new ItemStack(juke.getPlaying())); + juke.setPlaying(Material.AIR); + juke.update(); + } + if (!items.isEmpty()) { PipeSuckEvent event = new PipeSuckEvent(block, new ArrayList<>(items), fac); Bukkit.getPluginManager().callEvent(event); items.clear(); items.addAll(event.getItems()); - if (!event.isCancelled()) { + if (!event.isCancelled() && !items.isEmpty()) { visitedPipes.add(fac.getLocation().toVector()); searchNearbyPipes(block, visitedPipes, items); } - - if (!items.isEmpty()) { - for (ItemStack item : items) { - if (!ItemUtil.isStackValid(item)) continue; - block.getWorld().dropItem(BlockUtil.getBlockCentre(block), item); - } - } else { - juke.setPlaying(Material.AIR); - juke.update(); - } } + // Route undelivered items through leftovers like the other branches; + // this was the only branch that never fed it, so an empty jukebox + // destroyed any items a request delivered into it. + leftovers.addAll(items); } else { PipeSuckEvent event = new PipeSuckEvent(block, new ArrayList<>(items), fac); Bukkit.getPluginManager().callEvent(event);