From a68cbbf4be76f999d2c871036c59739d3b7b49b5 Mon Sep 17 00:00:00 2001 From: raoulvdberge Date: Sat, 28 Dec 2024 14:01:13 +0100 Subject: [PATCH 01/10] feat: run autocrafting calculations in thread pool --- .../autocrafting/preview/PreviewProvider.java | 5 +- .../common/AbstractModInitializer.java | 5 +- .../common/RefinedStorageApiImpl.java | 4 +- .../common/grid/AbstractGridBlockEntity.java | 10 ++- .../grid/AbstractGridContainerMenu.java | 5 +- .../common/grid/ClientCraftingGrid.java | 7 +- .../common/grid/WirelessGrid.java | 13 ++- .../storage/portablegrid/PortableGrid.java | 9 +- ...tocraftingStorageMonitorContainerMenu.java | 5 +- .../StorageMonitorBlockEntity.java | 10 ++- ...craftingPreviewMaxAmountRequestPacket.java | 4 +- .../c2s/AutocraftingPreviewRequestPacket.java | 6 +- .../common/util/ServerEventQueue.java | 26 ------ .../common/util/ServerListener.java | 83 +++++++++++++++++++ .../fabric/ModInitializerImpl.java | 7 +- .../neoforge/ModInitializer.java | 18 +++- .../test/fixtures/NetworkTestFixtures.java | 5 +- .../AutocraftingNetworkComponentImpl.java | 30 ++++--- .../AutocraftingNetworkComponentImplTest.java | 12 ++- 19 files changed, 187 insertions(+), 77 deletions(-) delete mode 100644 refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/util/ServerEventQueue.java create mode 100644 refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/util/ServerListener.java diff --git a/refinedstorage-autocrafting-api/src/main/java/com/refinedmods/refinedstorage/api/autocrafting/preview/PreviewProvider.java b/refinedstorage-autocrafting-api/src/main/java/com/refinedmods/refinedstorage/api/autocrafting/preview/PreviewProvider.java index c274f4a76..de6c89a1f 100644 --- a/refinedstorage-autocrafting-api/src/main/java/com/refinedmods/refinedstorage/api/autocrafting/preview/PreviewProvider.java +++ b/refinedstorage-autocrafting-api/src/main/java/com/refinedmods/refinedstorage/api/autocrafting/preview/PreviewProvider.java @@ -3,14 +3,15 @@ import com.refinedmods.refinedstorage.api.resource.ResourceKey; import java.util.Optional; +import java.util.concurrent.CompletableFuture; import org.apiguardian.api.API; @API(status = API.Status.STABLE, since = "2.0.0-milestone.4.9") public interface PreviewProvider { - Optional getPreview(ResourceKey resource, long amount); + CompletableFuture> getPreview(ResourceKey resource, long amount); - long getMaxAmount(ResourceKey resource); + CompletableFuture getMaxAmount(ResourceKey resource); boolean startTask(ResourceKey resource, long amount); } diff --git a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/AbstractModInitializer.java b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/AbstractModInitializer.java index 18c443aa4..ace0b4849 100644 --- a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/AbstractModInitializer.java +++ b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/AbstractModInitializer.java @@ -151,6 +151,7 @@ import com.refinedmods.refinedstorage.common.upgrade.SimpleUpgradeItem; import com.refinedmods.refinedstorage.common.upgrade.UpgradeDestinations; import com.refinedmods.refinedstorage.common.upgrade.UpgradeWithEnchantedBookRecipeSerializer; +import com.refinedmods.refinedstorage.common.util.ServerListener; import java.util.Optional; import java.util.UUID; @@ -276,7 +277,9 @@ private void registerNetworkComponents() { AutocraftingNetworkComponent.class, network -> new AutocraftingNetworkComponentImpl( () -> network.getComponent(StorageNetworkComponent.class), - new TaskStatusProviderImpl()) + new TaskStatusProviderImpl(), + ServerListener.getAutocraftingPool() + ) ); } diff --git a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/RefinedStorageApiImpl.java b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/RefinedStorageApiImpl.java index 7b2682471..9c7013ddb 100644 --- a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/RefinedStorageApiImpl.java +++ b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/RefinedStorageApiImpl.java @@ -81,7 +81,7 @@ import com.refinedmods.refinedstorage.common.support.slotreference.InventorySlotReference; import com.refinedmods.refinedstorage.common.upgrade.UpgradeRegistryImpl; import com.refinedmods.refinedstorage.common.util.IdentifierUtil; -import com.refinedmods.refinedstorage.common.util.ServerEventQueue; +import com.refinedmods.refinedstorage.common.util.ServerListener; import java.util.ArrayList; import java.util.Arrays; @@ -302,7 +302,7 @@ public void initializeNetworkNodeContainer(final InWorldNetworkNodeContainer con return; } final ConnectionProviderImpl connectionProvider = new ConnectionProviderImpl(level); - ServerEventQueue.queue(() -> { + ServerListener.queue(() -> { // The container could've been removed by the time it has been placed, and by the time the event queue has // run. In that case, don't initialize the network node because it no longer exists. // This is a workaround for the "Carry On" mod. The mod places the block (which creates a block entity and diff --git a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/grid/AbstractGridBlockEntity.java b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/grid/AbstractGridBlockEntity.java index 17997f8e0..634386102 100644 --- a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/grid/AbstractGridBlockEntity.java +++ b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/grid/AbstractGridBlockEntity.java @@ -27,6 +27,7 @@ import java.util.List; import java.util.Optional; import java.util.Set; +import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; import net.minecraft.core.BlockPos; @@ -101,18 +102,19 @@ public void removeWatcher(final GridWatcher watcher) { } @Override - public Optional getPreview(final ResourceKey resource, final long amount) { + public CompletableFuture> getPreview(final ResourceKey resource, final long amount) { return Optional.ofNullable(mainNetworkNode.getNetwork()) .map(network -> network.getComponent(AutocraftingNetworkComponent.class)) - .flatMap(component -> component.getPreview(resource, amount)); + .map(component -> component.getPreview(resource, amount)) + .orElseGet(() -> CompletableFuture.completedFuture(Optional.empty())); } @Override - public long getMaxAmount(final ResourceKey resource) { + public CompletableFuture getMaxAmount(final ResourceKey resource) { return Optional.ofNullable(mainNetworkNode.getNetwork()) .map(network -> network.getComponent(AutocraftingNetworkComponent.class)) .map(component -> component.getMaxAmount(resource)) - .orElse(0L); + .orElseGet(() -> CompletableFuture.completedFuture(0L)); } @Override diff --git a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/grid/AbstractGridContainerMenu.java b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/grid/AbstractGridContainerMenu.java index ebde4fd05..31c5bca62 100644 --- a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/grid/AbstractGridContainerMenu.java +++ b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/grid/AbstractGridContainerMenu.java @@ -46,6 +46,7 @@ import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.concurrent.CompletableFuture; import java.util.function.BiPredicate; import javax.annotation.Nullable; @@ -459,12 +460,12 @@ protected ResourceKey getResourceForAutocraftableHint(final Slot slot) { } @Override - public Optional getPreview(final ResourceKey resource, final long amount) { + public CompletableFuture> getPreview(final ResourceKey resource, final long amount) { return requireNonNull(grid).getPreview(resource, amount); } @Override - public long getMaxAmount(final ResourceKey resource) { + public CompletableFuture getMaxAmount(final ResourceKey resource) { return requireNonNull(grid).getMaxAmount(resource); } diff --git a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/grid/ClientCraftingGrid.java b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/grid/ClientCraftingGrid.java index c4de47773..4b64fed77 100644 --- a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/grid/ClientCraftingGrid.java +++ b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/grid/ClientCraftingGrid.java @@ -16,6 +16,7 @@ import java.util.List; import java.util.Optional; import java.util.Set; +import java.util.concurrent.CompletableFuture; import net.minecraft.core.NonNullList; import net.minecraft.server.level.ServerPlayer; @@ -105,13 +106,13 @@ public GridOperations createOperations(final ResourceType resourceType, final Se } @Override - public Optional getPreview(final ResourceKey resource, final long amount) { + public CompletableFuture> getPreview(final ResourceKey resource, final long amount) { throw new UnsupportedOperationException(); } @Override - public long getMaxAmount(final ResourceKey resource) { - return 0; + public CompletableFuture getMaxAmount(final ResourceKey resource) { + return CompletableFuture.completedFuture(0L); } @Override diff --git a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/grid/WirelessGrid.java b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/grid/WirelessGrid.java index 88c5d046e..e9398d486 100644 --- a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/grid/WirelessGrid.java +++ b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/grid/WirelessGrid.java @@ -26,6 +26,7 @@ import java.util.List; import java.util.Optional; import java.util.Set; +import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; import net.minecraft.server.level.ServerPlayer; @@ -116,13 +117,17 @@ private GridOperations createGridOperations(final ResourceType resourceType, } @Override - public Optional getPreview(final ResourceKey resource, final long amount) { - return getAutocrafting().flatMap(component -> component.getPreview(resource, amount)); + public CompletableFuture> getPreview(final ResourceKey resource, final long amount) { + return getAutocrafting() + .map(component -> component.getPreview(resource, amount)) + .orElseGet(() -> CompletableFuture.completedFuture(Optional.empty())); } @Override - public long getMaxAmount(final ResourceKey resource) { - return getAutocrafting().map(component -> component.getMaxAmount(resource)).orElse(0L); + public CompletableFuture getMaxAmount(final ResourceKey resource) { + return getAutocrafting() + .map(component -> component.getMaxAmount(resource)) + .orElseGet(() -> CompletableFuture.completedFuture(0L)); } @Override diff --git a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/storage/portablegrid/PortableGrid.java b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/storage/portablegrid/PortableGrid.java index 6468b9fdb..3507bf04c 100644 --- a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/storage/portablegrid/PortableGrid.java +++ b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/storage/portablegrid/PortableGrid.java @@ -27,6 +27,7 @@ import java.util.List; import java.util.Optional; import java.util.Set; +import java.util.concurrent.CompletableFuture; import javax.annotation.Nullable; import net.minecraft.server.level.ServerPlayer; @@ -131,13 +132,13 @@ public GridOperations createOperations(final ResourceType resourceType, final Se } @Override - public Optional getPreview(final ResourceKey resource, final long amount) { - return Optional.empty(); + public CompletableFuture> getPreview(final ResourceKey resource, final long amount) { + return CompletableFuture.completedFuture(Optional.empty()); } @Override - public long getMaxAmount(final ResourceKey resource) { - return 0; + public CompletableFuture getMaxAmount(final ResourceKey resource) { + return CompletableFuture.completedFuture(0L); } @Override diff --git a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/storagemonitor/AutocraftingStorageMonitorContainerMenu.java b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/storagemonitor/AutocraftingStorageMonitorContainerMenu.java index d7d548d63..9f725d65b 100644 --- a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/storagemonitor/AutocraftingStorageMonitorContainerMenu.java +++ b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/storagemonitor/AutocraftingStorageMonitorContainerMenu.java @@ -11,6 +11,7 @@ import java.util.List; import java.util.Optional; +import java.util.concurrent.CompletableFuture; import javax.annotation.Nullable; import static java.util.Objects.requireNonNull; @@ -39,12 +40,12 @@ private static List getRequests(final PlatformResourceKey r } @Override - public Optional getPreview(final ResourceKey resource, final long amount) { + public CompletableFuture> getPreview(final ResourceKey resource, final long amount) { return requireNonNull(storageMonitor).getPreview(resource, amount); } @Override - public long getMaxAmount(final ResourceKey resource) { + public CompletableFuture getMaxAmount(final ResourceKey resource) { return requireNonNull(storageMonitor).getMaxAmount(resource); } diff --git a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/storagemonitor/StorageMonitorBlockEntity.java b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/storagemonitor/StorageMonitorBlockEntity.java index b11782669..b85af24ea 100644 --- a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/storagemonitor/StorageMonitorBlockEntity.java +++ b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/storagemonitor/StorageMonitorBlockEntity.java @@ -26,6 +26,7 @@ import com.refinedmods.refinedstorage.common.util.PlatformUtil; import java.util.Optional; +import java.util.concurrent.CompletableFuture; import javax.annotation.Nullable; import com.google.common.util.concurrent.RateLimiter; @@ -367,18 +368,19 @@ protected boolean doesBlockStateChangeWarrantNetworkNodeUpdate(final BlockState } @Override - public Optional getPreview(final ResourceKey resource, final long amount) { + public CompletableFuture> getPreview(final ResourceKey resource, final long amount) { return Optional.ofNullable(mainNetworkNode.getNetwork()) .map(network -> network.getComponent(AutocraftingNetworkComponent.class)) - .flatMap(component -> component.getPreview(resource, amount)); + .map(component -> component.getPreview(resource, amount)) + .orElseGet(() -> CompletableFuture.completedFuture(Optional.empty())); } @Override - public long getMaxAmount(final ResourceKey resource) { + public CompletableFuture getMaxAmount(final ResourceKey resource) { return Optional.ofNullable(mainNetworkNode.getNetwork()) .map(network -> network.getComponent(AutocraftingNetworkComponent.class)) .map(component -> component.getMaxAmount(resource)) - .orElse(0L); + .orElseGet(() -> CompletableFuture.completedFuture(0L)); } @Override diff --git a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/support/packet/c2s/AutocraftingPreviewMaxAmountRequestPacket.java b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/support/packet/c2s/AutocraftingPreviewMaxAmountRequestPacket.java index 9856a36a9..cf3216888 100644 --- a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/support/packet/c2s/AutocraftingPreviewMaxAmountRequestPacket.java +++ b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/support/packet/c2s/AutocraftingPreviewMaxAmountRequestPacket.java @@ -26,8 +26,8 @@ public record AutocraftingPreviewMaxAmountRequestPacket(PlatformResourceKey reso public static void handle(final AutocraftingPreviewMaxAmountRequestPacket packet, final PacketContext ctx) { if (ctx.getPlayer().containerMenu instanceof PreviewProvider provider) { final ServerPlayer player = (ServerPlayer) ctx.getPlayer(); - final long maxAmount = provider.getMaxAmount(packet.resource); - S2CPackets.sendAutocraftingPreviewMaxAmountResponse(player, maxAmount); + provider.getMaxAmount(packet.resource).thenAccept(maxAmount -> + S2CPackets.sendAutocraftingPreviewMaxAmountResponse(player, maxAmount)); } } diff --git a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/support/packet/c2s/AutocraftingPreviewRequestPacket.java b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/support/packet/c2s/AutocraftingPreviewRequestPacket.java index 2da3a407e..e4b9ef153 100644 --- a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/support/packet/c2s/AutocraftingPreviewRequestPacket.java +++ b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/support/packet/c2s/AutocraftingPreviewRequestPacket.java @@ -36,9 +36,9 @@ public record AutocraftingPreviewRequestPacket(UUID id, public static void handle(final AutocraftingPreviewRequestPacket packet, final PacketContext ctx) { if (ctx.getPlayer().containerMenu instanceof PreviewProvider provider) { final ServerPlayer player = (ServerPlayer) ctx.getPlayer(); - provider.getPreview(packet.resource(), packet.amount()).ifPresent( - preview -> S2CPackets.sendAutocraftingPreviewResponse(player, packet.id, preview) - ); + provider.getPreview(packet.resource(), packet.amount()).thenAccept(optionalPreview -> + optionalPreview.ifPresent(preview -> + S2CPackets.sendAutocraftingPreviewResponse(player, packet.id, preview))); } } diff --git a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/util/ServerEventQueue.java b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/util/ServerEventQueue.java deleted file mode 100644 index 10d8f625f..000000000 --- a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/util/ServerEventQueue.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.refinedmods.refinedstorage.common.util; - -import java.util.ArrayDeque; -import java.util.Deque; - -public final class ServerEventQueue { - private static final Deque ACTIONS = new ArrayDeque<>(); - - private ServerEventQueue() { - } - - public static void runQueuedActions() { - synchronized (ACTIONS) { - Runnable action; - while ((action = ACTIONS.poll()) != null) { - action.run(); - } - } - } - - public static void queue(final Runnable runnable) { - synchronized (ACTIONS) { - ACTIONS.add(runnable); - } - } -} diff --git a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/util/ServerListener.java b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/util/ServerListener.java new file mode 100644 index 000000000..d77fbf583 --- /dev/null +++ b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/util/ServerListener.java @@ -0,0 +1,83 @@ +package com.refinedmods.refinedstorage.common.util; + +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import javax.annotation.Nullable; + +import org.apache.commons.lang3.concurrent.BasicThreadFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static java.util.Objects.requireNonNull; + +public final class ServerListener { + @Nullable + private static ExecutorService autocraftingPool; + + private static final Logger LOGGER = LoggerFactory.getLogger(ServerListener.class); + private static final Deque ACTIONS = new ArrayDeque<>(); + + private ServerListener() { + } + + public static void tick() { + synchronized (ACTIONS) { + Runnable action; + while ((action = ACTIONS.poll()) != null) { + action.run(); + } + } + } + + public static void queue(final Runnable runnable) { + synchronized (ACTIONS) { + ACTIONS.add(runnable); + } + } + + private static ExecutorService createAutocraftingPool() { + return Executors.newFixedThreadPool(4, new BasicThreadFactory.Builder() + .namingPattern("refinedstorage-autocrafting-%d") + .build()); + } + + public static ExecutorService getAutocraftingPool() { + return requireNonNull(autocraftingPool, "Autocrafting pool is not initialized"); + } + + public static void starting() { + if (autocraftingPool != null) { + LOGGER.debug("Previous autocrafting pool is still active, stopping"); + stopPool(autocraftingPool); + autocraftingPool = null; + } + LOGGER.debug("Creating new autocrafting pool"); + autocraftingPool = createAutocraftingPool(); + } + + public static void stopped() { + if (autocraftingPool != null) { + LOGGER.debug("Stopping autocrafting pool"); + stopPool(autocraftingPool); + autocraftingPool = null; + } else { + LOGGER.debug("There was no autocrafting pool to stop?"); + } + } + + private static void stopPool(final ExecutorService pool) { + pool.shutdown(); + try { + if (!pool.awaitTermination(800, TimeUnit.MILLISECONDS)) { + LOGGER.warn("Autocrafting pool did not terminate in time, forcing shutdown"); + pool.shutdownNow(); + } + } catch (final InterruptedException e) { + LOGGER.warn("Interrupted while waiting for autocrafting pool to terminate", e); + pool.shutdownNow(); + } + } +} diff --git a/refinedstorage-fabric/src/main/java/com/refinedmods/refinedstorage/fabric/ModInitializerImpl.java b/refinedstorage-fabric/src/main/java/com/refinedmods/refinedstorage/fabric/ModInitializerImpl.java index df1bb4ebf..b4b2812f6 100644 --- a/refinedstorage-fabric/src/main/java/com/refinedmods/refinedstorage/fabric/ModInitializerImpl.java +++ b/refinedstorage-fabric/src/main/java/com/refinedmods/refinedstorage/fabric/ModInitializerImpl.java @@ -81,7 +81,7 @@ import com.refinedmods.refinedstorage.common.support.resource.FluidResource; import com.refinedmods.refinedstorage.common.support.resource.ItemResource; import com.refinedmods.refinedstorage.common.upgrade.RegulatorUpgradeItem; -import com.refinedmods.refinedstorage.common.util.ServerEventQueue; +import com.refinedmods.refinedstorage.common.util.ServerListener; import com.refinedmods.refinedstorage.fabric.api.RefinedStorageFabricApi; import com.refinedmods.refinedstorage.fabric.api.RefinedStorageFabricApiProxy; import com.refinedmods.refinedstorage.fabric.api.RefinedStoragePlugin; @@ -116,6 +116,7 @@ import me.shedaniel.autoconfig.AutoConfig; import me.shedaniel.autoconfig.serializer.Toml4jConfigSerializer; import net.fabricmc.api.ModInitializer; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; import net.fabricmc.fabric.api.event.player.PlayerBlockBreakEvents; import net.fabricmc.fabric.api.event.player.UseBlockCallback; @@ -867,7 +868,9 @@ private void registerEnergyItemProviders() { } private void registerTickHandler() { - ServerTickEvents.START_SERVER_TICK.register(server -> ServerEventQueue.runQueuedActions()); + ServerTickEvents.START_SERVER_TICK.register(server -> ServerListener.tick()); + ServerLifecycleEvents.SERVER_STARTING.register(server -> ServerListener.starting()); + ServerLifecycleEvents.SERVER_STOPPED.register(server -> ServerListener.stopped()); } private void registerWrenchingEvent() { diff --git a/refinedstorage-neoforge/src/main/java/com/refinedmods/refinedstorage/neoforge/ModInitializer.java b/refinedstorage-neoforge/src/main/java/com/refinedmods/refinedstorage/neoforge/ModInitializer.java index 3d2ee4ca3..d81ae69fc 100644 --- a/refinedstorage-neoforge/src/main/java/com/refinedmods/refinedstorage/neoforge/ModInitializer.java +++ b/refinedstorage-neoforge/src/main/java/com/refinedmods/refinedstorage/neoforge/ModInitializer.java @@ -81,7 +81,7 @@ import com.refinedmods.refinedstorage.common.support.packet.s2c.WirelessTransmitterDataPacket; import com.refinedmods.refinedstorage.common.upgrade.RegulatorUpgradeItem; import com.refinedmods.refinedstorage.common.util.IdentifierUtil; -import com.refinedmods.refinedstorage.common.util.ServerEventQueue; +import com.refinedmods.refinedstorage.common.util.ServerListener; import com.refinedmods.refinedstorage.neoforge.api.RefinedStorageNeoForgeApi; import com.refinedmods.refinedstorage.neoforge.api.RefinedStorageNeoForgeApiProxy; import com.refinedmods.refinedstorage.neoforge.constructordestructor.ForgeConstructorBlockEntity; @@ -148,6 +148,8 @@ import net.neoforged.neoforge.common.extensions.IMenuTypeExtension; import net.neoforged.neoforge.event.entity.player.PlayerInteractEvent; import net.neoforged.neoforge.event.level.BlockEvent; +import net.neoforged.neoforge.event.server.ServerStartingEvent; +import net.neoforged.neoforge.event.server.ServerStoppedEvent; import net.neoforged.neoforge.event.tick.ServerTickEvent; import net.neoforged.neoforge.items.wrapper.InvWrapper; import net.neoforged.neoforge.items.wrapper.RangedWrapper; @@ -559,6 +561,8 @@ private void registerRecipeSerializers(final IEventBus eventBus) { private void registerTickHandler() { NeoForge.EVENT_BUS.addListener(this::onServerTick); + NeoForge.EVENT_BUS.addListener(this::onServerStarting); + NeoForge.EVENT_BUS.addListener(this::onServerStopped); } @SubscribeEvent @@ -876,7 +880,17 @@ private static IPayloadHandler wrapHandler(fi @SubscribeEvent public void onServerTick(final ServerTickEvent.Pre e) { - ServerEventQueue.runQueuedActions(); + ServerListener.tick(); + } + + @SubscribeEvent + public void onServerStarting(final ServerStartingEvent e) { + ServerListener.starting(); + } + + @SubscribeEvent + public void onServerStopped(final ServerStoppedEvent e) { + ServerListener.stopped(); } private record ForgeRegistryCallback(DeferredRegister registry) implements RegistryCallback { diff --git a/refinedstorage-network-test/src/main/java/com/refinedmods/refinedstorage/network/test/fixtures/NetworkTestFixtures.java b/refinedstorage-network-test/src/main/java/com/refinedmods/refinedstorage/network/test/fixtures/NetworkTestFixtures.java index 56556166b..ad000b12a 100644 --- a/refinedstorage-network-test/src/main/java/com/refinedmods/refinedstorage/network/test/fixtures/NetworkTestFixtures.java +++ b/refinedstorage-network-test/src/main/java/com/refinedmods/refinedstorage/network/test/fixtures/NetworkTestFixtures.java @@ -16,6 +16,8 @@ import com.refinedmods.refinedstorage.api.network.storage.StorageNetworkComponent; import com.refinedmods.refinedstorage.api.resource.list.MutableResourceListImpl; +import java.util.concurrent.Executors; + public final class NetworkTestFixtures { public static final ComponentMapFactory NETWORK_COMPONENT_MAP_FACTORY = new ComponentMapFactory<>(); @@ -43,7 +45,8 @@ public final class NetworkTestFixtures { () -> { throw new UnsupportedOperationException("Storage not accessible from here (yet)"); }, - new FakeTaskStatusProvider() + new FakeTaskStatusProvider(), + Executors.newSingleThreadExecutor() ) ); } diff --git a/refinedstorage-network/src/main/java/com/refinedmods/refinedstorage/api/network/impl/autocrafting/AutocraftingNetworkComponentImpl.java b/refinedstorage-network/src/main/java/com/refinedmods/refinedstorage/api/network/impl/autocrafting/AutocraftingNetworkComponentImpl.java index 2a7865e2d..3647a273b 100644 --- a/refinedstorage-network/src/main/java/com/refinedmods/refinedstorage/api/network/impl/autocrafting/AutocraftingNetworkComponentImpl.java +++ b/refinedstorage-network/src/main/java/com/refinedmods/refinedstorage/api/network/impl/autocrafting/AutocraftingNetworkComponentImpl.java @@ -22,19 +22,24 @@ import java.util.List; import java.util.Optional; import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutorService; import java.util.function.Supplier; public class AutocraftingNetworkComponentImpl implements AutocraftingNetworkComponent, ParentContainer { private final Supplier rootStorageProvider; + private final TaskStatusProvider taskStatusProvider; + private final ExecutorService executorService; private final Set providers = new HashSet<>(); private final Set listeners = new HashSet<>(); private final PatternRepositoryImpl patternRepository = new PatternRepositoryImpl(); - private final TaskStatusProvider taskStatusProvider; public AutocraftingNetworkComponentImpl(final Supplier rootStorageProvider, - final TaskStatusProvider taskStatusProvider) { + final TaskStatusProvider taskStatusProvider, + final ExecutorService executorService) { this.rootStorageProvider = rootStorageProvider; this.taskStatusProvider = taskStatusProvider; + this.executorService = executorService; } @Override @@ -76,17 +81,22 @@ public boolean contains(final AutocraftingNetworkComponent component) { } @Override - public Optional getPreview(final ResourceKey resource, final long amount) { - final RootStorage rootStorage = rootStorageProvider.get(); - final CraftingCalculator craftingCalculator = new CraftingCalculatorImpl(patternRepository, rootStorage); - return Optional.of(PreviewCraftingCalculatorListener.calculatePreview(craftingCalculator, resource, amount)); + public CompletableFuture> getPreview(final ResourceKey resource, final long amount) { + return CompletableFuture.supplyAsync(() -> { + final RootStorage rootStorage = rootStorageProvider.get(); + final CraftingCalculator calculator = new CraftingCalculatorImpl(patternRepository, rootStorage); + final Preview preview = PreviewCraftingCalculatorListener.calculatePreview(calculator, resource, amount); + return Optional.of(preview); + }, executorService); } @Override - public long getMaxAmount(final ResourceKey resource) { - final RootStorage rootStorage = rootStorageProvider.get(); - final CraftingCalculator craftingCalculator = new CraftingCalculatorImpl(patternRepository, rootStorage); - return craftingCalculator.getMaxAmount(resource); + public CompletableFuture getMaxAmount(final ResourceKey resource) { + return CompletableFuture.supplyAsync(() -> { + final RootStorage rootStorage = rootStorageProvider.get(); + final CraftingCalculator craftingCalculator = new CraftingCalculatorImpl(patternRepository, rootStorage); + return craftingCalculator.getMaxAmount(resource); + }, executorService); } @Override diff --git a/refinedstorage-network/src/test/java/com/refinedmods/refinedstorage/api/network/impl/autocrafting/AutocraftingNetworkComponentImplTest.java b/refinedstorage-network/src/test/java/com/refinedmods/refinedstorage/api/network/impl/autocrafting/AutocraftingNetworkComponentImplTest.java index c4edd7920..6142383c1 100644 --- a/refinedstorage-network/src/test/java/com/refinedmods/refinedstorage/api/network/impl/autocrafting/AutocraftingNetworkComponentImplTest.java +++ b/refinedstorage-network/src/test/java/com/refinedmods/refinedstorage/api/network/impl/autocrafting/AutocraftingNetworkComponentImplTest.java @@ -23,6 +23,8 @@ import java.util.List; import java.util.Optional; import java.util.UUID; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executors; import org.assertj.core.api.recursive.comparison.RecursiveComparisonConfiguration; import org.junit.jupiter.api.BeforeEach; @@ -43,7 +45,11 @@ class AutocraftingNetworkComponentImplTest { @BeforeEach void setUp() { rootStorage = new RootStorageImpl(); - sut = new AutocraftingNetworkComponentImpl(() -> rootStorage, new FakeTaskStatusProvider()); + sut = new AutocraftingNetworkComponentImpl( + () -> rootStorage, + new FakeTaskStatusProvider(), + Executors.newSingleThreadExecutor() + ); } @Test @@ -147,7 +153,7 @@ void shouldStartTask() { } @Test - void shouldGetPreview() { + void shouldGetPreview() throws ExecutionException, InterruptedException { // Arrange rootStorage.addSource(new StorageImpl()); rootStorage.insert(A, 10, Action.EXECUTE, EmptyActor.INSTANCE); @@ -158,7 +164,7 @@ void shouldGetPreview() { )); // Act - final Optional preview = sut.getPreview(B, 2); + final Optional preview = sut.getPreview(B, 2).get(); // Assert assertThat(preview) From ecc8811f99ac276620b1dcce95eeef14484a7927 Mon Sep 17 00:00:00 2001 From: raoulvdberge Date: Sat, 28 Dec 2024 14:30:49 +0100 Subject: [PATCH 02/10] feat: option to notify when the autocrafting task is finished --- CHANGELOG.md | 1 + .../autocrafting/preview/PreviewProvider.java | 3 +- .../common/AbstractClientModInitializer.java | 2 +- .../refinedstorage/common/Config.java | 4 +++ .../patterngrid/AlternativesScreen.java | 12 +++---- .../CraftingPatternGridRenderer.java | 10 +++--- .../AutocraftingPreviewContainerMenu.java | 13 ++++++-- .../preview/AutocraftingPreviewScreen.java | 28 ++++++++++++++--- .../preview/AutocraftingRequest.java | 4 +-- .../common/grid/AbstractGridBlockEntity.java | 4 +-- .../grid/AbstractGridContainerMenu.java | 5 +-- .../common/grid/ClientCraftingGrid.java | 2 +- .../common/grid/WirelessGrid.java | 6 ++-- .../security/AbstractSecurityCardScreen.java | 20 ++++++------ .../storage/portablegrid/PortableGrid.java | 2 +- ...tocraftingStorageMonitorContainerMenu.java | 5 +-- .../StorageMonitorBlockEntity.java | 5 +-- .../packet/c2s/AutocraftingRequestPacket.java | 16 +++++++--- .../common/support/packet/c2s/C2SPackets.java | 5 +-- ...heckboxWidget.java => CheckboxWidget.java} | 31 +++++++++---------- .../assets/refinedstorage/lang/en_us.json | 4 +++ .../refinedstorage/fabric/ConfigImpl.java | 13 ++++++++ .../refinedstorage/neoforge/ConfigImpl.java | 17 ++++++++++ .../AutocraftingNetworkComponentImpl.java | 13 ++++++-- .../AutocraftingNetworkComponentImplTest.java | 2 +- 25 files changed, 158 insertions(+), 69 deletions(-) rename refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/support/widget/{CustomCheckboxWidget.java => CheckboxWidget.java} (85%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 05fc93c56..6a75eeec1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - Autocrafting engine. - The crafting preview now has the ability to fill out the maximum amount of a resource you can currently craft. +- In the crafting preview, you can now indicate whether you want to be notified when an autocrafting task is finished. ### Changed diff --git a/refinedstorage-autocrafting-api/src/main/java/com/refinedmods/refinedstorage/api/autocrafting/preview/PreviewProvider.java b/refinedstorage-autocrafting-api/src/main/java/com/refinedmods/refinedstorage/api/autocrafting/preview/PreviewProvider.java index de6c89a1f..b22c567d4 100644 --- a/refinedstorage-autocrafting-api/src/main/java/com/refinedmods/refinedstorage/api/autocrafting/preview/PreviewProvider.java +++ b/refinedstorage-autocrafting-api/src/main/java/com/refinedmods/refinedstorage/api/autocrafting/preview/PreviewProvider.java @@ -1,6 +1,7 @@ package com.refinedmods.refinedstorage.api.autocrafting.preview; import com.refinedmods.refinedstorage.api.resource.ResourceKey; +import com.refinedmods.refinedstorage.api.storage.Actor; import java.util.Optional; import java.util.concurrent.CompletableFuture; @@ -13,5 +14,5 @@ public interface PreviewProvider { CompletableFuture getMaxAmount(ResourceKey resource); - boolean startTask(ResourceKey resource, long amount); + boolean startTask(ResourceKey resource, long amount, Actor actor, boolean notify); } diff --git a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/AbstractClientModInitializer.java b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/AbstractClientModInitializer.java index 9c1d5a454..3d8616a89 100644 --- a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/AbstractClientModInitializer.java +++ b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/AbstractClientModInitializer.java @@ -129,7 +129,7 @@ public AbstractContainerScreen create(final AbstractConta public AutocraftingPreviewScreen create(final AutocraftingPreviewContainerMenu menu, final Inventory inventory, final Component title) { - return new AutocraftingPreviewScreen(menu, inventory, title); + return new AutocraftingPreviewScreen(menu, inventory); } }); registration.register(Menus.INSTANCE.getAutocrafterManager(), AutocrafterManagerScreen::new); diff --git a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/Config.java b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/Config.java index 1fd5fb666..98151de9c 100644 --- a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/Config.java +++ b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/Config.java @@ -25,6 +25,10 @@ public interface Config { int getMaxRowsStretch(); + boolean isAutocraftingNotification(); + + void setAutocraftingNotification(boolean autocraftingNotification); + GridEntry getGrid(); SimpleEnergyUsageEntry getPatternGrid(); diff --git a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/autocrafting/patterngrid/AlternativesScreen.java b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/autocrafting/patterngrid/AlternativesScreen.java index 334166aa1..c8bd53620 100644 --- a/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/autocrafting/patterngrid/AlternativesScreen.java +++ b/refinedstorage-common/src/main/java/com/refinedmods/refinedstorage/common/autocrafting/patterngrid/AlternativesScreen.java @@ -7,7 +7,7 @@ import com.refinedmods.refinedstorage.common.support.amount.AmountScreenConfiguration; import com.refinedmods.refinedstorage.common.support.amount.DoubleAmountOperations; import com.refinedmods.refinedstorage.common.support.containermenu.ResourceSlot; -import com.refinedmods.refinedstorage.common.support.widget.CustomCheckboxWidget; +import com.refinedmods.refinedstorage.common.support.widget.CheckboxWidget; import com.refinedmods.refinedstorage.common.support.widget.HoveredImageButton; import com.refinedmods.refinedstorage.common.support.widget.ScrollbarWidget; import com.refinedmods.refinedstorage.common.support.widget.SearchIconWidget; @@ -69,7 +69,7 @@ public class AlternativesScreen extends AbstractAmountScreen alternativeCheckboxes = new ArrayList<>(); + private final List alternativeCheckboxes = new ArrayList<>(); private final List