Skip to content

Commit

Permalink
Merge pull request #781 from refinedmods/feat/GH-612/autocrafting-notifs
Browse files Browse the repository at this point in the history
Autocrafting notifications
  • Loading branch information
raoulvdberge authored Jan 26, 2025
2 parents 7c6a881 + c69c9c5 commit a79bc0d
Show file tree
Hide file tree
Showing 20 changed files with 272 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import com.refinedmods.refinedstorage.api.autocrafting.status.TaskStatus;
import com.refinedmods.refinedstorage.api.resource.ResourceAmount;
import com.refinedmods.refinedstorage.api.resource.ResourceKey;
import com.refinedmods.refinedstorage.api.storage.Actor;
import com.refinedmods.refinedstorage.api.storage.root.RootStorage;
import com.refinedmods.refinedstorage.api.storage.root.RootStorageListener;

Expand All @@ -11,6 +13,14 @@

@API(status = API.Status.STABLE, since = "2.0.0-milestone.4.12")
public interface Task extends RootStorageListener {
Actor getActor();

boolean shouldNotify();

ResourceKey getResource();

long getAmount();

TaskId getId();

TaskState getState();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,26 @@ public class TaskImpl implements Task {
private final TaskId id = TaskId.create();
private final ResourceKey resource;
private final long amount;
private final Actor actor;
private final boolean notify;
private final long startTime = System.currentTimeMillis();
private final Map<Pattern, AbstractTaskPattern> patterns;
private final List<AbstractTaskPattern> completedPatterns = new ArrayList<>();
private final MutableResourceList initialRequirements = MutableResourceListImpl.create();
private final MutableResourceList internalStorage;
private TaskState state = TaskState.READY;
private boolean cancelled;

public TaskImpl(final TaskPlan plan) {
this(plan, MutableResourceListImpl.create());
public TaskImpl(final TaskPlan plan, final Actor actor, final boolean notify) {
this(plan, MutableResourceListImpl.create(), actor, notify);
}

TaskImpl(final TaskPlan plan, final MutableResourceList internalStorage) {
TaskImpl(final TaskPlan plan, final MutableResourceList internalStorage, final Actor actor, final boolean notify) {
this.internalStorage = internalStorage;
this.resource = plan.resource();
this.amount = plan.amount();
this.actor = actor;
this.notify = notify;
this.patterns = plan.patterns().entrySet().stream().collect(Collectors.toMap(
Map.Entry::getKey,
e -> createTaskPattern(e.getKey(), e.getValue()),
Expand All @@ -61,6 +66,26 @@ private static AbstractTaskPattern createTaskPattern(final Pattern pattern,
};
}

@Override
public Actor getActor() {
return actor;
}

@Override
public boolean shouldNotify() {
return notify && !cancelled;
}

@Override
public ResourceKey getResource() {
return resource;
}

@Override
public long getAmount() {
return amount;
}

@Override
public TaskId getId() {
return id;
Expand Down Expand Up @@ -92,6 +117,7 @@ public boolean step(final RootStorage rootStorage,
@Override
public void cancel() {
state = TaskState.RETURNING_INTERNAL_STORAGE;
cancelled = true;
}

@Override
Expand Down Expand Up @@ -225,7 +251,7 @@ public Collection<ResourceAmount> copyInternalStorageState() {
@Override
public InterceptResult beforeInsert(final ResourceKey insertedResource,
final long insertedAmount,
final Actor actor) {
final Actor insertActor) {
long reserved = 0;
long intercepted = 0;
for (final AbstractTaskPattern pattern : patterns.values()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ void testInitialState() {
assertThat(task.getState()).isEqualTo(TaskState.READY);
assertThat(task.getId()).isNotNull();
assertThat(task.getId().toString()).isEqualTo(task.getId().id().toString());
assertThat(task.shouldNotify()).isTrue();
assertThat(task.getActor()).isEqualTo(Actor.EMPTY);
assertThat(task.getResource()).isEqualTo(CRAFTING_TABLE);
assertThat(task.getAmount()).isEqualTo(3);
}

@Test
Expand All @@ -116,9 +120,14 @@ void shouldCancelTask() {
new ResourceAmount(OAK_PLANKS, 4)
);
assertThat(storage.getAll()).isEmpty();
assertThat(task.shouldNotify()).isTrue();
assertThat(task.getActor()).isEqualTo(Actor.EMPTY);

task.cancel();

assertThat(task.shouldNotify()).isFalse();
assertThat(task.getActor()).isEqualTo(Actor.EMPTY);

assertThat(task.getState()).isEqualTo(TaskState.RETURNING_INTERNAL_STORAGE);
assertThat(task.copyInternalStorageState())
.usingRecursiveFieldByFieldElementComparator()
Expand Down Expand Up @@ -1183,7 +1192,9 @@ private static Task getTask(final RootStorage storage,
final CraftingCalculator sut = new CraftingCalculatorImpl(patterns, storage);
final Task task = calculatePlan(sut, resource, amount).map(plan -> new TaskImpl(
plan,
MutableResourceListImpl.orderPreserving()
MutableResourceListImpl.orderPreserving(),
Actor.EMPTY,
true
)).orElseThrow();
storage.addListener(task);
return task;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,13 @@
import org.apiguardian.api.API;

@API(status = API.Status.STABLE, since = "2.0.0-milestone.2.1")
public final class PlayerActor implements Actor {
private final String playerName;

public record PlayerActor(String name) implements Actor {
public PlayerActor(final Player player) {
this(player.getGameProfile().getName());
}

public PlayerActor(final String playerName) {
this.playerName = playerName;
}

@Override
public String getName() {
return playerName;
return name;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import com.refinedmods.refinedstorage.api.network.autocrafting.AutocraftingNetworkComponent;
import com.refinedmods.refinedstorage.api.network.energy.EnergyNetworkComponent;
import com.refinedmods.refinedstorage.api.network.impl.autocrafting.AutocraftingNetworkComponentImpl;
import com.refinedmods.refinedstorage.api.network.impl.energy.EnergyNetworkComponentImpl;
import com.refinedmods.refinedstorage.api.network.impl.node.GraphNetworkComponentImpl;
import com.refinedmods.refinedstorage.api.network.impl.security.SecurityNetworkComponentImpl;
Expand All @@ -16,6 +15,7 @@
import com.refinedmods.refinedstorage.common.autocrafting.CraftingPatternState;
import com.refinedmods.refinedstorage.common.autocrafting.PatternItem;
import com.refinedmods.refinedstorage.common.autocrafting.PatternState;
import com.refinedmods.refinedstorage.common.autocrafting.PlatformAutocraftingNetworkComponent;
import com.refinedmods.refinedstorage.common.autocrafting.ProcessingPatternState;
import com.refinedmods.refinedstorage.common.autocrafting.SmithingTablePatternState;
import com.refinedmods.refinedstorage.common.autocrafting.StonecutterPatternState;
Expand Down Expand Up @@ -274,7 +274,7 @@ private void registerNetworkComponents() {
);
RefinedStorageApi.INSTANCE.getNetworkComponentMapFactory().addFactory(
AutocraftingNetworkComponent.class,
network -> new AutocraftingNetworkComponentImpl(
network -> new PlatformAutocraftingNetworkComponent(
() -> network.getComponent(StorageNetworkComponent.class),
ServerListener.getAutocraftingPool()
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ public void initializeNetworkNodeContainer(final InWorldNetworkNodeContainer con
return;
}
final ConnectionProviderImpl connectionProvider = new ConnectionProviderImpl(level);
ServerListener.queue(() -> {
ServerListener.queue(server -> {
// 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
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.refinedmods.refinedstorage.common.autocrafting;

import com.refinedmods.refinedstorage.api.autocrafting.task.Task;
import com.refinedmods.refinedstorage.api.network.impl.autocrafting.AutocraftingNetworkComponentImpl;
import com.refinedmods.refinedstorage.api.storage.root.RootStorage;
import com.refinedmods.refinedstorage.common.Platform;
import com.refinedmods.refinedstorage.common.api.storage.PlayerActor;
import com.refinedmods.refinedstorage.common.api.support.resource.PlatformResourceKey;
import com.refinedmods.refinedstorage.common.support.packet.s2c.AutocraftingTaskCompletedPacket;
import com.refinedmods.refinedstorage.common.util.ServerListener;

import java.util.concurrent.ExecutorService;
import java.util.function.Supplier;

import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerPlayer;

public class PlatformAutocraftingNetworkComponent extends AutocraftingNetworkComponentImpl {
public PlatformAutocraftingNetworkComponent(final Supplier<RootStorage> rootStorageProvider,
final ExecutorService executorService) {
super(rootStorageProvider, executorService);
}

@Override
public void taskRemoved(final Task task) {
super.taskRemoved(task);
if (task.shouldNotify()
&& task.getActor() instanceof PlayerActor(String name)
&& task.getResource() instanceof PlatformResourceKey resource) {
sendToClient(task, name, resource);
}
}

private static void sendToClient(final Task task, final String name, final PlatformResourceKey resource) {
ServerListener.queue(server -> sendToClient(task, name, resource, server));
}

private static void sendToClient(final Task task,
final String name,
final PlatformResourceKey resource,
final MinecraftServer server) {
final ServerPlayer player = server.getPlayerList().getPlayerByName(name);
if (player == null) {
return;
}
Platform.INSTANCE.sendPacketToClient(player, new AutocraftingTaskCompletedPacket(
resource,
task.getAmount()
));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.refinedmods.refinedstorage.common.autocrafting;

import com.refinedmods.refinedstorage.api.resource.ResourceKey;
import com.refinedmods.refinedstorage.common.api.RefinedStorageClientApi;
import com.refinedmods.refinedstorage.common.api.support.resource.ResourceRendering;

import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.toasts.Toast;
import net.minecraft.client.gui.components.toasts.ToastComponent;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.resources.ResourceLocation;

import static com.refinedmods.refinedstorage.common.util.IdentifierUtil.createIdentifier;
import static com.refinedmods.refinedstorage.common.util.IdentifierUtil.createTranslation;

public class TaskCompletedToast implements Toast {
private static final ResourceLocation SPRITE = createIdentifier("autocrafting_task_completed_toast");
private static final MutableComponent TITLE = createTranslation(
"misc",
"autocrafting_task_completed"
);

private static final long TIME_VISIBLE = 5000;
private static final int MARGIN = 4;

private final ResourceKey resource;
private final ResourceRendering rendering;
private final MutableComponent resourceTitle;

public TaskCompletedToast(final ResourceKey resource, final long amount) {
this.resource = resource;
this.rendering = RefinedStorageClientApi.INSTANCE.getResourceRendering(resource.getClass());
this.resourceTitle = Component.literal(rendering.formatAmount(amount, true))
.append(" ")
.append(rendering.getDisplayName(resource));
}

@Override
public Visibility render(final GuiGraphics graphics,
final ToastComponent toastComponent,
final long timeSinceLastVisible) {
graphics.blitSprite(SPRITE, 0, 0, width(), height());
rendering.render(resource, graphics, 8, 8);
final Font font = Minecraft.getInstance().font;
graphics.drawString(font, TITLE, 8 + 18 + MARGIN, 7, 0xFFFFA500);
graphics.drawString(font, resourceTitle, 8 + 18 + MARGIN, 7 + 2 + 9, 0xFFFFFFFF);
return timeSinceLastVisible >= TIME_VISIBLE ? Visibility.HIDE : Visibility.SHOW;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -433,19 +433,19 @@ private void tryUpdateKey() {
invalidateExternalPatternInputSinkKey();
return;
}
final BlockState state = connectedMachine.getBlockState();
final BlockState connectedMachineState = connectedMachine.getBlockState();
final Player fakePlayer = getFakePlayer(serverLevel);
final ItemStack stack = Platform.INSTANCE.getBlockAsItemStack(
state.getBlock(),
state,
final ItemStack connectedMachineStack = Platform.INSTANCE.getBlockAsItemStack(
connectedMachineState.getBlock(),
connectedMachineState,
direction.getOpposite(),
serverLevel,
connectedMachine.getBlockPos(),
fakePlayer
);
externalPatternInputSinkKey = new InWorldExternalPatternInputSinkKey(
getName().getString(),
stack
connectedMachineStack
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.refinedmods.refinedstorage.common.autocrafting.patterngrid;

import com.refinedmods.refinedstorage.api.network.autocrafting.AutocraftingNetworkComponent;
import com.refinedmods.refinedstorage.api.network.storage.StorageNetworkComponent;
import com.refinedmods.refinedstorage.api.resource.ResourceAmount;
import com.refinedmods.refinedstorage.api.resource.ResourceKey;
Expand Down Expand Up @@ -32,6 +33,7 @@
import com.refinedmods.refinedstorage.common.util.ContainerUtil;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
Expand Down Expand Up @@ -500,7 +502,11 @@ void transferCraftingRecipe(final Player player, final List<List<ItemResource>>
mainNetworkNode.getNetwork() != null
? mainNetworkNode.getNetwork().getComponent(StorageNetworkComponent.class)
: null,
player.getInventory()
mainNetworkNode.getNetwork() != null
? mainNetworkNode.getNetwork().getComponent(AutocraftingNetworkComponent.class).getPatterns()
: Collections.emptySet(),
player.getInventory(),
r -> r
);
getCraftingMatrix().clearContent();
for (int i = 0; i < getCraftingMatrix().getContainerSize(); ++i) {
Expand All @@ -523,6 +529,9 @@ void transferProcessingRecipe(final Player player,
mainNetworkNode.getNetwork() != null
? mainNetworkNode.getNetwork().getComponent(StorageNetworkComponent.class)
: null,
mainNetworkNode.getNetwork() != null
? mainNetworkNode.getNetwork().getComponent(AutocraftingNetworkComponent.class).getPatterns()
: Collections.emptySet(),
player.getInventory(),
ResourceAmount::resource
);
Expand Down Expand Up @@ -564,6 +573,9 @@ void transferSmithingTableRecipe(final Player player,
mainNetworkNode.getNetwork() != null
? mainNetworkNode.getNetwork().getComponent(StorageNetworkComponent.class)
: null,
mainNetworkNode.getNetwork() != null
? mainNetworkNode.getNetwork().getComponent(AutocraftingNetworkComponent.class).getPatterns()
: Collections.emptySet(),
player.getInventory(),
r -> r
);
Expand Down
Loading

0 comments on commit a79bc0d

Please sign in to comment.