From 6264160631a40a17aec21f8c9f1f7a093c55ef65 Mon Sep 17 00:00:00 2001 From: Roelymole Date: Wed, 29 Apr 2026 22:05:12 +0100 Subject: [PATCH 1/3] feat: trigger client-side events when the status of machines change --- .../block/entity/ConfiguredBlockEntity.java | 5 ++ .../machinelib/api/machine/MachineStatus.java | 3 ++ .../client/api/event/MachineStatusEvents.java | 42 +++++++++++++++ .../impl/network/MachineLibPackets.java | 3 ++ .../s2c/MachineStatusUpdatePayload.java | 52 +++++++++++++++++++ 5 files changed, 105 insertions(+) create mode 100644 src/main/java/dev/galacticraft/machinelib/client/api/event/MachineStatusEvents.java create mode 100644 src/main/java/dev/galacticraft/machinelib/impl/network/s2c/MachineStatusUpdatePayload.java diff --git a/src/main/java/dev/galacticraft/machinelib/api/block/entity/ConfiguredBlockEntity.java b/src/main/java/dev/galacticraft/machinelib/api/block/entity/ConfiguredBlockEntity.java index d80fbb9b..a9c35407 100644 --- a/src/main/java/dev/galacticraft/machinelib/api/block/entity/ConfiguredBlockEntity.java +++ b/src/main/java/dev/galacticraft/machinelib/api/block/entity/ConfiguredBlockEntity.java @@ -32,6 +32,7 @@ import dev.galacticraft.machinelib.api.util.BlockFace; import dev.galacticraft.machinelib.impl.Constant; import dev.galacticraft.machinelib.impl.network.s2c.BaseMachineUpdatePayload; +import dev.galacticraft.machinelib.impl.network.s2c.MachineStatusUpdatePayload; import dev.galacticraft.machinelib.impl.network.s2c.SideConfigurationUpdatePayload; import net.fabricmc.fabric.api.blockview.v2.RenderDataBlockEntity; import net.minecraft.core.BlockPos; @@ -329,8 +330,12 @@ private class InternalMachineState extends MachineState { @Override public void setStatus(@Nullable MachineStatus status) { if (this.status != status) { + MachineStatus oldStatus = this.status; this.status = status; ConfiguredBlockEntity.this.setChanged(); + if (ConfiguredBlockEntity.this.level != null && !ConfiguredBlockEntity.this.level.isClientSide) { + ConfiguredBlockEntity.this.broadcastToPlayers(new MachineStatusUpdatePayload(ConfiguredBlockEntity.this.worldPosition, status, oldStatus)); + } } } diff --git a/src/main/java/dev/galacticraft/machinelib/api/machine/MachineStatus.java b/src/main/java/dev/galacticraft/machinelib/api/machine/MachineStatus.java index 4906b8ae..cf616c35 100644 --- a/src/main/java/dev/galacticraft/machinelib/api/machine/MachineStatus.java +++ b/src/main/java/dev/galacticraft/machinelib/api/machine/MachineStatus.java @@ -28,6 +28,7 @@ import net.minecraft.network.chat.Component; import net.minecraft.network.chat.ComponentSerialization; import net.minecraft.network.chat.Style; +import net.minecraft.network.codec.StreamCodec; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -38,6 +39,8 @@ * @see MachineStatuses */ public interface MachineStatus { + public static final StreamCodec STREAM_CODEC = StreamCodec.ofMember(MachineStatus::writePacket, MachineStatus::readPacket); + /** * Creates a new machine status. * diff --git a/src/main/java/dev/galacticraft/machinelib/client/api/event/MachineStatusEvents.java b/src/main/java/dev/galacticraft/machinelib/client/api/event/MachineStatusEvents.java new file mode 100644 index 00000000..fed65e06 --- /dev/null +++ b/src/main/java/dev/galacticraft/machinelib/client/api/event/MachineStatusEvents.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021-2025 Team Galacticraft + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package dev.galacticraft.machinelib.client.api.event; + +import dev.galacticraft.machinelib.api.machine.MachineStatus; +import net.fabricmc.fabric.api.event.Event; +import net.fabricmc.fabric.api.event.EventFactory; +import net.minecraft.core.BlockPos; +import net.minecraft.client.Minecraft; +import net.minecraft.client.player.LocalPlayer; +import org.jetbrains.annotations.Nullable; + +public interface MachineStatusEvents { + Event MACHINE_STATUS_CHANGED = EventFactory.createArrayBacked(MachineStatusChanged.class, callbacks -> (minecraft, player, pos, status, oldStatus) -> { + for (MachineStatusChanged callback : callbacks) + callback.onMachineStatusChanged(minecraft, player, pos, status, oldStatus); + }); + + interface MachineStatusChanged { + void onMachineStatusChanged(Minecraft minecraft, LocalPlayer player, BlockPos pos, @Nullable MachineStatus status, @Nullable MachineStatus oldStatus); + } +} diff --git a/src/main/java/dev/galacticraft/machinelib/impl/network/MachineLibPackets.java b/src/main/java/dev/galacticraft/machinelib/impl/network/MachineLibPackets.java index 6e5fe93e..d33ab589 100644 --- a/src/main/java/dev/galacticraft/machinelib/impl/network/MachineLibPackets.java +++ b/src/main/java/dev/galacticraft/machinelib/impl/network/MachineLibPackets.java @@ -27,6 +27,7 @@ import dev.galacticraft.machinelib.impl.network.c2s.SideConfigurationClickPayload; import dev.galacticraft.machinelib.impl.network.c2s.TankInteractionPayload; import dev.galacticraft.machinelib.impl.network.s2c.BaseMachineUpdatePayload; +import dev.galacticraft.machinelib.impl.network.s2c.MachineStatusUpdatePayload; import dev.galacticraft.machinelib.impl.network.s2c.MenuSyncPayload; import dev.galacticraft.machinelib.impl.network.s2c.SideConfigurationUpdatePayload; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; @@ -43,6 +44,7 @@ public static void registerServer() { public static void registerClient() { ClientPlayNetworking.registerGlobalReceiver(BaseMachineUpdatePayload.TYPE, BaseMachineUpdatePayload::apply); + ClientPlayNetworking.registerGlobalReceiver(MachineStatusUpdatePayload.TYPE, MachineStatusUpdatePayload::apply); ClientPlayNetworking.registerGlobalReceiver(SideConfigurationUpdatePayload.TYPE, SideConfigurationUpdatePayload::apply); ClientPlayNetworking.registerGlobalReceiver(MenuSyncPayload.TYPE, MenuSyncPayload::apply); } @@ -57,6 +59,7 @@ public static void registerChannels() { // s2c PayloadTypeRegistry.playS2C().register(BaseMachineUpdatePayload.TYPE, BaseMachineUpdatePayload.CODEC); PayloadTypeRegistry.playS2C().register(SideConfigurationUpdatePayload.TYPE, SideConfigurationUpdatePayload.CODEC); + PayloadTypeRegistry.playS2C().register(MachineStatusUpdatePayload.TYPE, MachineStatusUpdatePayload.CODEC); PayloadTypeRegistry.playS2C().register(MenuSyncPayload.TYPE, MenuSyncPayload.CODEC); } } diff --git a/src/main/java/dev/galacticraft/machinelib/impl/network/s2c/MachineStatusUpdatePayload.java b/src/main/java/dev/galacticraft/machinelib/impl/network/s2c/MachineStatusUpdatePayload.java new file mode 100644 index 00000000..48f2091f --- /dev/null +++ b/src/main/java/dev/galacticraft/machinelib/impl/network/s2c/MachineStatusUpdatePayload.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2021-2025 Team Galacticraft + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package dev.galacticraft.machinelib.impl.network.s2c; + +import dev.galacticraft.machinelib.api.machine.MachineStatus; +import dev.galacticraft.machinelib.client.api.event.MachineStatusEvents; +import dev.galacticraft.machinelib.impl.Constant; +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; +import net.minecraft.core.BlockPos; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import org.jetbrains.annotations.Nullable; + +public record MachineStatusUpdatePayload(BlockPos pos, @Nullable MachineStatus status, @Nullable MachineStatus oldStatus) implements CustomPacketPayload { + public static final Type TYPE = new Type<>(Constant.id("status_update")); + public static final StreamCodec CODEC = StreamCodec.composite( + BlockPos.STREAM_CODEC, p -> p.pos, + MachineStatus.STREAM_CODEC, p -> p.status, + MachineStatus.STREAM_CODEC, p -> p.oldStatus, + MachineStatusUpdatePayload::new + ); + + @Override + public Type type() { + return TYPE; + } + + public void apply(ClientPlayNetworking.Context context) { + MachineStatusEvents.MACHINE_STATUS_CHANGED.invoker().onMachineStatusChanged(context.client(), context.player(), this.pos, this.status, this.oldStatus); + } +} From 164d325f89ce4d65e02faf1a11d459fd6af9cd03 Mon Sep 17 00:00:00 2001 From: Roelymole Date: Wed, 3 Jun 2026 23:17:56 +0100 Subject: [PATCH 2/3] chore: document the MachineStatusEvents --- .../client/api/event/MachineStatusEvents.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/dev/galacticraft/machinelib/client/api/event/MachineStatusEvents.java b/src/main/java/dev/galacticraft/machinelib/client/api/event/MachineStatusEvents.java index fed65e06..19b0f79c 100644 --- a/src/main/java/dev/galacticraft/machinelib/client/api/event/MachineStatusEvents.java +++ b/src/main/java/dev/galacticraft/machinelib/client/api/event/MachineStatusEvents.java @@ -30,13 +30,23 @@ import net.minecraft.client.player.LocalPlayer; import org.jetbrains.annotations.Nullable; +/** + * Events related to the statuses of machines. + */ public interface MachineStatusEvents { + /** + * An event that is called on the client-side when the {@link MachineStatus} of a {@link ConfiguredBlockEntity} changes. + */ Event MACHINE_STATUS_CHANGED = EventFactory.createArrayBacked(MachineStatusChanged.class, callbacks -> (minecraft, player, pos, status, oldStatus) -> { for (MachineStatusChanged callback : callbacks) callback.onMachineStatusChanged(minecraft, player, pos, status, oldStatus); }); + @FunctionalInterface interface MachineStatusChanged { + /** + * Called on the client-side after the {@link MachineStatus} of a {@link ConfiguredBlockEntity} has changed. + */ void onMachineStatusChanged(Minecraft minecraft, LocalPlayer player, BlockPos pos, @Nullable MachineStatus status, @Nullable MachineStatus oldStatus); } } From 47ad9f61dc1d72c6a67a76a47fbb9857c3cf1ca1 Mon Sep 17 00:00:00 2001 From: Roelymole Date: Wed, 3 Jun 2026 23:37:45 +0100 Subject: [PATCH 3/3] fix: use the full path to ConfiguredBlockEntity in links --- .../machinelib/client/api/event/MachineStatusEvents.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/dev/galacticraft/machinelib/client/api/event/MachineStatusEvents.java b/src/main/java/dev/galacticraft/machinelib/client/api/event/MachineStatusEvents.java index 19b0f79c..bb3110c8 100644 --- a/src/main/java/dev/galacticraft/machinelib/client/api/event/MachineStatusEvents.java +++ b/src/main/java/dev/galacticraft/machinelib/client/api/event/MachineStatusEvents.java @@ -35,7 +35,7 @@ */ public interface MachineStatusEvents { /** - * An event that is called on the client-side when the {@link MachineStatus} of a {@link ConfiguredBlockEntity} changes. + * An event that is called on the client-side when the {@link MachineStatus} of a {@link dev.galacticraft.machinelib.api.block.entity.ConfiguredBlockEntity} changes. */ Event MACHINE_STATUS_CHANGED = EventFactory.createArrayBacked(MachineStatusChanged.class, callbacks -> (minecraft, player, pos, status, oldStatus) -> { for (MachineStatusChanged callback : callbacks) @@ -45,7 +45,7 @@ public interface MachineStatusEvents { @FunctionalInterface interface MachineStatusChanged { /** - * Called on the client-side after the {@link MachineStatus} of a {@link ConfiguredBlockEntity} has changed. + * Called on the client-side after the {@link MachineStatus} of a {@link dev.galacticraft.machinelib.api.block.entity.ConfiguredBlockEntity} has changed. */ void onMachineStatusChanged(Minecraft minecraft, LocalPlayer player, BlockPos pos, @Nullable MachineStatus status, @Nullable MachineStatus oldStatus); }