mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-10-22 08:07:42 +00:00
Fixed mining and timeout settings
- Pending biome reads no longer cancel block breaking - Custom loot resolves saved biome history after accepted breaks - Native drops survive failed reads and runtime teardown without duplication - Tree felling captures the original tool for fallback drops - Modded block loot resolves one historical biome context - Timeout settings persist atomically through the actual server configuration paths - Tests cover deferred loot, teardown and timeout persistence
This commit is contained in:
1 parent
2145e90b1c
commit
e3673afb1e
17 files changed
+1220
-329
No files matched your search
@@ -990,6 +990,7 @@ public class Iris extends VolmitPlugin implements Listener, ReloadAware {
|
||||
}
|
||||
|
||||
public void onDisable() {
|
||||
preservePendingBlockDrops();
|
||||
papiLifecycleActive = false;
|
||||
if (updateNotifier != null) {
|
||||
updateNotifier.close();
|
||||
@@ -1034,6 +1035,7 @@ public class Iris extends VolmitPlugin implements Listener, ReloadAware {
|
||||
|
||||
@Override
|
||||
public CompletionStage<Void> commitReload(ReloadAware.PreUnloadReason reason) {
|
||||
preservePendingBlockDrops();
|
||||
papiLifecycleActive = false;
|
||||
teardownPapi();
|
||||
if (IrisToolbelt.isServerStopping()) {
|
||||
@@ -1283,6 +1285,20 @@ public class Iris extends VolmitPlugin implements Listener, ReloadAware {
|
||||
&& preservation.hasActiveResources();
|
||||
}
|
||||
|
||||
private void preservePendingBlockDrops() {
|
||||
for (World world : Bukkit.getWorlds()) {
|
||||
PlatformChunkGenerator generator = IrisToolbelt.access(world);
|
||||
if (generator != null && generator.getEngine() != null
|
||||
&& generator.getEngine().getWorldManager() instanceof IrisWorldManager manager) {
|
||||
manager.flushPendingBlockDropsAsync().whenComplete((ignored, failure) -> {
|
||||
if (failure != null) {
|
||||
Iris.reportError("Failed to preserve pending block loot before Iris teardown.", failure);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void drainWorldGenerators(String reason, long timeoutSeconds) {
|
||||
List<World> irisWorlds = new ArrayList<>();
|
||||
List<PlatformChunkGenerator> generators = new ArrayList<>();
|
||||
|
||||
+18
-4
@@ -3,19 +3,33 @@ package art.arcane.iris.world.tree;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Objects;
|
||||
|
||||
final class RoutedBlockBreakEvent extends BlockBreakEvent implements BlockDropRouter {
|
||||
private final TreeFellerSVC service;
|
||||
private final FellingRun run;
|
||||
private final ItemStack tool;
|
||||
|
||||
RoutedBlockBreakEvent(Block block, Player player, FellingRun run, TreeFellerSVC service) {
|
||||
super(block, player);
|
||||
this.run = run;
|
||||
this.service = service;
|
||||
RoutedBlockBreakEvent(Options options) {
|
||||
super(options.block(), options.player());
|
||||
run = options.run();
|
||||
service = options.service();
|
||||
tool = Objects.requireNonNull(options.tool(), "tool").clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ItemStack> captureNativeDrops() {
|
||||
return getBlock().getDrops(tool);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean routeDrop(Object drop) {
|
||||
return service.isServiceEnabled() && run.presentation.routeDrop(drop);
|
||||
}
|
||||
|
||||
record Options(Block block, Player player, FellingRun run, TreeFellerSVC service, ItemStack tool) {
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -387,7 +387,8 @@ final class TreeFellingRunner {
|
||||
return;
|
||||
}
|
||||
|
||||
BlockBreakEvent probe = new RoutedBlockBreakEvent(block, run.candidate.player(), run, service);
|
||||
BlockBreakEvent probe = new RoutedBlockBreakEvent(new RoutedBlockBreakEvent.Options(
|
||||
block, run.candidate.player(), run, service, reservation.toolForDrops()));
|
||||
service.managedEvents.add(probe);
|
||||
try {
|
||||
Bukkit.getPluginManager().callEvent(probe);
|
||||
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package art.arcane.iris.world.tree;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class RoutedBlockBreakEventTest {
|
||||
@Test
|
||||
public void nativeLootUsesTheReservedToolCloneWithoutReadingPlayerInventory() {
|
||||
Block block = mock(Block.class);
|
||||
Player player = mock(Player.class);
|
||||
ItemStack reservedTool = mock(ItemStack.class);
|
||||
ItemStack capturedTool = mock(ItemStack.class);
|
||||
ItemStack drop = mock(ItemStack.class);
|
||||
Collection<ItemStack> expected = List.of(drop);
|
||||
when(reservedTool.clone()).thenReturn(capturedTool);
|
||||
when(block.getDrops(capturedTool)).thenReturn(expected);
|
||||
RoutedBlockBreakEvent event = new RoutedBlockBreakEvent(new RoutedBlockBreakEvent.Options(
|
||||
block, player, mock(FellingRun.class), mock(TreeFellerSVC.class), reservedTool));
|
||||
|
||||
reservedTool.setType(Material.AIR);
|
||||
|
||||
assertSame(expected, event.captureNativeDrops());
|
||||
verify(reservedTool).clone();
|
||||
verify(block).getDrops(capturedTool);
|
||||
verify(block, never()).getDrops(reservedTool);
|
||||
verifyNoInteractions(player);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user