From 60994a08677d864f79de58d8912b02d2d7077289 Mon Sep 17 00:00:00 2001 From: Linnea Gräf Date: Sat, 27 Jul 2024 05:07:58 +0200 Subject: Add some carnival features --- .../mixins/EntityUpdateEventListener.java | 47 ++++++++++++++++++ .../nea/firmament/mixins/SlotUpdateListener.java | 58 ++++++++++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 src/main/java/moe/nea/firmament/mixins/EntityUpdateEventListener.java create mode 100644 src/main/java/moe/nea/firmament/mixins/SlotUpdateListener.java (limited to 'src/main/java/moe') diff --git a/src/main/java/moe/nea/firmament/mixins/EntityUpdateEventListener.java b/src/main/java/moe/nea/firmament/mixins/EntityUpdateEventListener.java new file mode 100644 index 0000000..b7476af --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/EntityUpdateEventListener.java @@ -0,0 +1,47 @@ +/* + * SPDX-FileCopyrightText: 2024 Linnea Gräf + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package moe.nea.firmament.mixins; + +import com.llamalad7.mixinextras.sugar.Local; +import moe.nea.firmament.events.EntityUpdateEvent; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientCommonNetworkHandler; +import net.minecraft.client.network.ClientConnectionState; +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.entity.Entity; +import net.minecraft.entity.LivingEntity; +import net.minecraft.network.ClientConnection; +import net.minecraft.network.packet.s2c.play.EntityAttributesS2CPacket; +import net.minecraft.network.packet.s2c.play.EntityTrackerUpdateS2CPacket; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(ClientPlayNetworkHandler.class) +public abstract class EntityUpdateEventListener extends ClientCommonNetworkHandler { + + @Shadow + private ClientWorld world; + + protected EntityUpdateEventListener(MinecraftClient client, ClientConnection connection, ClientConnectionState connectionState) { + super(client, connection, connectionState); + } + + @Inject(method = "onEntityAttributes", at = @At("TAIL")) + private void onAttributeUpdate(EntityAttributesS2CPacket packet, CallbackInfo ci) { + EntityUpdateEvent.Companion.publish(new EntityUpdateEvent.AttributeUpdate( + (LivingEntity) world.getEntityById(packet.getEntityId()), packet.getEntries())); + } + + @Inject(method = "onEntityTrackerUpdate", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/data/DataTracker;writeUpdatedEntries(Ljava/util/List;)V", shift = At.Shift.AFTER)) + private void onEntityTracker(EntityTrackerUpdateS2CPacket packet, CallbackInfo ci, @Local Entity entity) { + EntityUpdateEvent.Companion.publish(new EntityUpdateEvent.TrackedDataUpdate(entity, packet.trackedValues())); + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/SlotUpdateListener.java b/src/main/java/moe/nea/firmament/mixins/SlotUpdateListener.java new file mode 100644 index 0000000..ad2a919 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/SlotUpdateListener.java @@ -0,0 +1,58 @@ +/* + * SPDX-FileCopyrightText: 2024 Linnea Gräf + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package moe.nea.firmament.mixins; + +import com.llamalad7.mixinextras.sugar.Local; +import moe.nea.firmament.events.PlayerInventoryUpdate; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientCommonNetworkHandler; +import net.minecraft.client.network.ClientConnectionState; +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.network.ClientConnection; +import net.minecraft.network.packet.s2c.play.InventoryS2CPacket; +import net.minecraft.network.packet.s2c.play.ScreenHandlerSlotUpdateS2CPacket; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(ClientPlayNetworkHandler.class) +public abstract class SlotUpdateListener extends ClientCommonNetworkHandler { + protected SlotUpdateListener(MinecraftClient client, ClientConnection connection, ClientConnectionState connectionState) { + super(client, connection, connectionState); + } + + @Inject( + method = "onScreenHandlerSlotUpdate", + at = @At(value = "INVOKE", target = "Lnet/minecraft/client/tutorial/TutorialManager;onSlotUpdate(Lnet/minecraft/item/ItemStack;)V")) + private void onSingleSlotUpdate( + ScreenHandlerSlotUpdateS2CPacket packet, + CallbackInfo ci) { + var player = this.client.player; + assert player != null; + if (packet.getSyncId() == ScreenHandlerSlotUpdateS2CPacket.UPDATE_PLAYER_INVENTORY_SYNC_ID + || packet.getSyncId() == 0) { + PlayerInventoryUpdate.Companion.publish(new PlayerInventoryUpdate.Single(packet.getSlot(), packet.getStack())); + } else if (packet.getSyncId() == player.currentScreenHandler.syncId) { + // TODO: dispatch single chest slot + } + } + + @Inject(method = "onInventory", + at = @At(value = "INVOKE", target = "Lnet/minecraft/network/NetworkThreadUtils;forceMainThread(Lnet/minecraft/network/packet/Packet;Lnet/minecraft/network/listener/PacketListener;Lnet/minecraft/util/thread/ThreadExecutor;)V", + shift = At.Shift.AFTER)) + private void onMultiSlotUpdate(InventoryS2CPacket packet, CallbackInfo ci) { + var player = this.client.player; + assert player != null; + if (packet.getSyncId() == 0) { + PlayerInventoryUpdate.Companion.publish(new PlayerInventoryUpdate.Multi(packet.getContents())); + } else if (packet.getSyncId() == player.currentScreenHandler.syncId) { + // TODO: dispatch multi chest + } + } +} -- cgit