diff --git a/gradle.properties b/gradle.properties index 6c591c002..34d1469c2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -31,8 +31,8 @@ mappings_mc_ver=1.21 mappings=2024.06.23 # Required Dependencies -zenith_version=1.2.05 -unity_version=0.0.7 +zenith_version=1.2.07 +unity_version=0.0.8 aether_version=1.5.1 nitrogen_version=1.1.22 cumulus_version=1.1.2 diff --git a/src/main/java/net/zepalesque/redux/Redux.java b/src/main/java/net/zepalesque/redux/Redux.java index c902a1305..99f804bf4 100644 --- a/src/main/java/net/zepalesque/redux/Redux.java +++ b/src/main/java/net/zepalesque/redux/Redux.java @@ -36,6 +36,7 @@ import net.zepalesque.redux.loot.modifer.ReduxLootModifiers; import net.zepalesque.redux.network.packet.AerjumpPacket; import net.zepalesque.redux.network.packet.ReduxPlayerSyncPacket; +import net.zepalesque.redux.network.packet.SliderSignalSyncPacket; import net.zepalesque.redux.pack.PackUtils; import net.zepalesque.redux.pack.ReduxPackConfig; import net.zepalesque.redux.recipe.ReduxRecipes; @@ -122,6 +123,7 @@ public void registerPackets(RegisterPayloadHandlersEvent event) { registrar.playToClient(AerjumpPacket.Accepted.TYPE, AerjumpPacket.Accepted.STREAM_CODEC, AerjumpPacket.Accepted::execute); registrar.playToClient(AerjumpPacket.Particles.TYPE, AerjumpPacket.Particles.STREAM_CODEC, AerjumpPacket.Particles::execute); registrar.playBidirectional(ReduxPlayerSyncPacket.TYPE, ReduxPlayerSyncPacket.STREAM_CODEC, ReduxPlayerSyncPacket::execute); + registrar.playToClient(SliderSignalSyncPacket.TYPE, SliderSignalSyncPacket.STREAM_CODEC, SliderSignalSyncPacket::execute); } private void registerDataMaps(RegisterDataMapTypesEvent event) { diff --git a/src/main/java/net/zepalesque/redux/attachment/AttachmentModule.java b/src/main/java/net/zepalesque/redux/attachment/AttachmentModule.java deleted file mode 100644 index 758d207cb..000000000 --- a/src/main/java/net/zepalesque/redux/attachment/AttachmentModule.java +++ /dev/null @@ -1,7 +0,0 @@ -package net.zepalesque.redux.attachment; - -public interface AttachmentModule { - - void tick(); - -} diff --git a/src/main/java/net/zepalesque/redux/attachment/ReduxDataAttachments.java b/src/main/java/net/zepalesque/redux/attachment/ReduxDataAttachments.java index a51fd028d..df6d556d6 100644 --- a/src/main/java/net/zepalesque/redux/attachment/ReduxDataAttachments.java +++ b/src/main/java/net/zepalesque/redux/attachment/ReduxDataAttachments.java @@ -11,5 +11,6 @@ public class ReduxDataAttachments { public static final DeferredRegister> ATTACHMENTS = DeferredRegister.create(NeoForgeRegistries.ATTACHMENT_TYPES, Redux.MODID); public static final DeferredHolder, AttachmentType> REDUX_PLAYER = ATTACHMENTS.register("redux_player", () -> AttachmentType.builder(ReduxPlayerAttachment::new).serialize(ReduxPlayerAttachment.CODEC).copyOnDeath().build()); + public static final DeferredHolder, AttachmentType> SLIDER_SIGNAL = ATTACHMENTS.register("slider_signal", () -> AttachmentType.builder(SliderSignalAttachment::new).build()); } diff --git a/src/main/java/net/zepalesque/redux/attachment/SliderSignalAttachment.java b/src/main/java/net/zepalesque/redux/attachment/SliderSignalAttachment.java new file mode 100644 index 000000000..ba5f8deef --- /dev/null +++ b/src/main/java/net/zepalesque/redux/attachment/SliderSignalAttachment.java @@ -0,0 +1,102 @@ +package net.zepalesque.redux.attachment; + +import com.aetherteam.aether.entity.monster.dungeon.boss.Slider; +import com.aetherteam.nitrogen.attachment.INBTSynchable; +import com.aetherteam.nitrogen.network.packet.SyncPacket; +import net.minecraft.sounds.SoundSource; +import net.zepalesque.redux.client.audio.ReduxSounds; +import org.apache.commons.lang3.tuple.Triple; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; +import java.util.function.Consumer; +import java.util.function.Supplier; + +public class SliderSignalAttachment implements INBTSynchable { + + private final Map, Supplier>> synchableFunctions = Map.ofEntries( + Map.entry("signal_tick", Triple.of(INBTSynchable.Type.INT, (object) -> this.setSignalTick((int) object), this::getSignalTick)), + Map.entry("move_trajectory", Triple.of(INBTSynchable.Type.INT, (object) -> this.setMoveTrajectory((int) object), this::getMoveTrajectoryIndex)) + ); + + protected int signalTick = 0; + + @Nullable + protected net.minecraft.core.Direction moveTrajectory = null; + + + public void onUpdate(Slider slider) { + this.tickSignal(slider); + } + + protected void tickSignal(Slider slider) { + if (this.signalTick > 0) { + this.signalTick--; + } + } + + public boolean shouldGlow(Slider slider) { + return this.signalTick == 6 || this.signalTick == 1; + } + + public void doBeep(Slider slider) { + if (!slider.level().isClientSide()) { + this.setSynched(slider.getId(), Direction.NEAR, "signal_tick", 6);; + slider.level().playSound(null, slider.getX(), slider.getY(), slider.getZ(), ReduxSounds.SLIDER_SIGNAL, SoundSource.HOSTILE, 1F, 1F); + } + } + + public void syncMoveDirection(Slider slider) { + if (!slider.level().isClientSide()) { + this.setSynched(slider.getId(), Direction.NEAR, "move_trajectory", slider.getMoveDirection()); + } + } + + public static @NotNull SliderSignalAttachment get(@NotNull Slider slider) { + return slider.getData(ReduxDataAttachments.SLIDER_SIGNAL.get()); + } + + public int getSignalTick() { + return signalTick; + } + + public void setSignalTick(int signalTick) { + this.signalTick = signalTick; + } + + + public net.minecraft.core.Direction getMoveTrajectory() { + return moveTrajectory; + } + + public int getMoveTrajectoryIndex() { + return moveTrajectory == null ? -1 : moveTrajectory.ordinal(); + } + + public void setMoveTrajectory(net.minecraft.core.Direction moveTrajectory) { + this.moveTrajectory = moveTrajectory; + } + + public void setMoveTrajectory(int index) { + net.minecraft.core.Direction[] array = net.minecraft.core.Direction.values(); + if (index >= array.length || index < 0) return; + this.moveTrajectory = net.minecraft.core.Direction.values()[index]; + } + + + @Override + public Map, Supplier>> getSynchableFunctions() { + return synchableFunctions; + } + + @Override + public SyncPacket getSyncPacket(int entityID, String key, Type type, Object value) { + return null; + } + + @Override + public void setSynched(int entityID, Direction direction, String key, Object value) { + INBTSynchable.super.setSynched(entityID, direction, key, value); + } +} diff --git a/src/main/java/net/zepalesque/redux/block/redstone/LogicatorBlock.java b/src/main/java/net/zepalesque/redux/block/redstone/LogicatorBlock.java index c483a0275..1a7af7e24 100644 --- a/src/main/java/net/zepalesque/redux/block/redstone/LogicatorBlock.java +++ b/src/main/java/net/zepalesque/redux/block/redstone/LogicatorBlock.java @@ -49,7 +49,7 @@ protected InteractionResult useWithoutItem(BlockState state, Level level, BlockP } else { state = StateUtil.mapValue(state, MODE, LogicatorMode::flipOperationType); float f = state.getValue(MODE).isOr() ? 0.55F : 0.5F; - level.playSound(player, pos, ReduxSounds.LOGICATOR_CLICK.get(), SoundSource.BLOCKS, 0.3F, f); + level.playSound(player, pos, ReduxSounds.SLIDER_SIGNAL.get(), SoundSource.BLOCKS, 0.3F, f); level.setBlock(pos, state, 2); this.refreshOutputState(level, state, pos); return InteractionResult.sidedSuccess(level.isClientSide); diff --git a/src/main/java/net/zepalesque/redux/client/audio/ReduxSounds.java b/src/main/java/net/zepalesque/redux/client/audio/ReduxSounds.java index 8622c5a0b..b89db724b 100644 --- a/src/main/java/net/zepalesque/redux/client/audio/ReduxSounds.java +++ b/src/main/java/net/zepalesque/redux/client/audio/ReduxSounds.java @@ -1,7 +1,5 @@ package net.zepalesque.redux.client.audio; -import com.aetherteam.aether.Aether; -import com.aetherteam.aether.client.AetherSoundEvents; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.resources.ResourceLocation; import net.minecraft.sounds.SoundEvent; @@ -22,6 +20,8 @@ public class ReduxSounds { public static final DeferredHolder LOGICATOR_CLICK = register("block.logicator.click"); + public static final DeferredHolder SLIDER_SIGNAL = register("entity.slider.signal"); + private static DeferredHolder register(String location) { diff --git a/src/main/java/net/zepalesque/redux/data/gen/ReduxLanguageData.java b/src/main/java/net/zepalesque/redux/data/gen/ReduxLanguageData.java index 2de65dace..7a42a3769 100644 --- a/src/main/java/net/zepalesque/redux/data/gen/ReduxLanguageData.java +++ b/src/main/java/net/zepalesque/redux/data/gen/ReduxLanguageData.java @@ -170,7 +170,8 @@ protected void addTranslations() { addSubtitle(ReduxSounds.INFUSE_ITEM, DatagenUtil::subtitleFor, "Item infuses"); addSubtitle(ReduxSounds.INFUSION_EXPIRE, DatagenUtil::subtitleFor, "Item infusion runs out"); - addSubtitle(ReduxSounds.LOGICATOR_CLICK, DatagenUtil::subtitleFor, "Logicator clicks"); + addSubtitle(ReduxSounds.SLIDER_SIGNAL, DatagenUtil::subtitleFor, "Logicator clicks"); addSubtitle(ReduxSounds.AERJUMP, DatagenUtil::subtitleFor, "Something aerjumps"); + addSubtitle(ReduxSounds.SLIDER_SIGNAL, DatagenUtil::subtitleFor, "Slider signals"); } } diff --git a/src/main/java/net/zepalesque/redux/data/gen/ReduxSoundsData.java b/src/main/java/net/zepalesque/redux/data/gen/ReduxSoundsData.java index 0001d5cd9..ba173bdd0 100644 --- a/src/main/java/net/zepalesque/redux/data/gen/ReduxSoundsData.java +++ b/src/main/java/net/zepalesque/redux/data/gen/ReduxSoundsData.java @@ -20,11 +20,14 @@ public void registerSounds() { this.add(ReduxSounds.INFUSION_EXPIRE, sound -> definition().with(sound("aether_redux:item/generic/infusion_expire")) .subtitle(DatagenUtil.subtitleFor(sound))); - this.add(ReduxSounds.LOGICATOR_CLICK, sound -> + this.add(ReduxSounds.SLIDER_SIGNAL, sound -> definition().with(sound("random/click")) .subtitle(DatagenUtil.subtitleFor(sound))); this.add(ReduxSounds.AERJUMP, sound -> definition().with(sound("aether_redux:item/aerbound_cape/aerjump")) .subtitle(DatagenUtil.subtitleFor(sound))); + this.add(ReduxSounds.SLIDER_SIGNAL, sound -> + definition().with(sound("aether_redux:entity/slider/signal")) + .subtitle(DatagenUtil.subtitleFor(sound))); } } diff --git a/src/main/java/net/zepalesque/redux/mixin/mixins/common/entity/EntityMixin.java b/src/main/java/net/zepalesque/redux/mixin/mixins/common/entity/EntityMixin.java new file mode 100644 index 000000000..a21dc7588 --- /dev/null +++ b/src/main/java/net/zepalesque/redux/mixin/mixins/common/entity/EntityMixin.java @@ -0,0 +1,11 @@ +package net.zepalesque.redux.mixin.mixins.common.entity; + +import net.minecraft.util.RandomSource; +import net.minecraft.world.entity.Entity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(Entity.class) +public abstract class EntityMixin { + @Shadow public abstract RandomSource getRandom(); +} diff --git a/src/main/java/net/zepalesque/redux/mixin/mixins/common/entity/LivingEntityMixin.java b/src/main/java/net/zepalesque/redux/mixin/mixins/common/entity/LivingEntityMixin.java index 8d54feb59..47bfd1289 100644 --- a/src/main/java/net/zepalesque/redux/mixin/mixins/common/entity/LivingEntityMixin.java +++ b/src/main/java/net/zepalesque/redux/mixin/mixins/common/entity/LivingEntityMixin.java @@ -13,7 +13,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(LivingEntity.class) -public abstract class LivingEntityMixin { +public abstract class LivingEntityMixin extends EntityMixin { @Inject(method = "makePoofParticles", at = @At("HEAD"), cancellable = true) protected void redux$Poof(CallbackInfo ci) {} diff --git a/src/main/java/net/zepalesque/redux/mixin/mixins/common/entity/SliderMixin.java b/src/main/java/net/zepalesque/redux/mixin/mixins/common/entity/SliderMixin.java index 165bb1d00..b0c5cf079 100644 --- a/src/main/java/net/zepalesque/redux/mixin/mixins/common/entity/SliderMixin.java +++ b/src/main/java/net/zepalesque/redux/mixin/mixins/common/entity/SliderMixin.java @@ -2,17 +2,41 @@ import com.aetherteam.aether.entity.monster.dungeon.boss.Slider; import net.minecraft.sounds.SoundEvent; +import net.zepalesque.redux.attachment.SliderSignalAttachment; 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; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(Slider.class) -public class SliderMixin extends LivingEntityMixin { +public abstract class SliderMixin extends LivingEntityMixin { + @Shadow public abstract boolean isCritical(); + + @Shadow private int moveDelay; + @Inject(method = "getAmbientSound", at = @At("RETURN"), cancellable = true) protected void redux$getAmbientSound(CallbackInfoReturnable cir) { if (((Slider) (Object) this).isAwake()) { cir.setReturnValue(null); } } + + @Inject(method = "calculateMoveDelay", at = @At("HEAD"), cancellable = true) + protected void redux$calculateMoveDelay(CallbackInfoReturnable cir) { + int adjusted = this.isCritical() ? 4 + this.getRandom().nextInt(7) : 6 + this.getRandom().nextInt(10); + cir.setReturnValue(adjusted); + } + + @Inject(method = "customServerAiStep", at = @At("TAIL")) + protected void redux$customServerAiStep(CallbackInfo ci) { + SliderSignalAttachment signal = SliderSignalAttachment.get((Slider) (Object) this); + if (!this.isCritical() && this.moveDelay == 6 || this.isCritical() && this.moveDelay == 4) { + signal.doBeep((Slider) (Object) this); + signal.syncMoveDirection((Slider) (Object) this); + } else if (this.moveDelay == 1) { + signal.syncMoveDirection((Slider) (Object) this); + } + } } diff --git a/src/main/java/net/zepalesque/redux/mixin/mixins/common/entity/ai/SliderMoveMixin.java b/src/main/java/net/zepalesque/redux/mixin/mixins/common/entity/ai/SliderMoveMixin.java new file mode 100644 index 000000000..719649349 --- /dev/null +++ b/src/main/java/net/zepalesque/redux/mixin/mixins/common/entity/ai/SliderMoveMixin.java @@ -0,0 +1,8 @@ +package net.zepalesque.redux.mixin.mixins.common.entity.ai; + +import com.aetherteam.aether.entity.monster.dungeon.boss.goal.SliderMoveGoal; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(SliderMoveGoal.class) +public class SliderMoveMixin { +} diff --git a/src/main/java/net/zepalesque/redux/network/packet/SliderSignalSyncPacket.java b/src/main/java/net/zepalesque/redux/network/packet/SliderSignalSyncPacket.java new file mode 100644 index 000000000..ed29539c7 --- /dev/null +++ b/src/main/java/net/zepalesque/redux/network/packet/SliderSignalSyncPacket.java @@ -0,0 +1,52 @@ +package net.zepalesque.redux.network.packet; + +import com.aetherteam.nitrogen.attachment.INBTSynchable; +import com.aetherteam.nitrogen.network.packet.SyncEntityPacket; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import net.neoforged.neoforge.attachment.AttachmentType; +import net.neoforged.neoforge.network.handling.IPayloadContext; +import net.zepalesque.redux.Redux; +import net.zepalesque.redux.attachment.ReduxDataAttachments; +import net.zepalesque.redux.attachment.ReduxPlayerAttachment; +import net.zepalesque.redux.attachment.SliderSignalAttachment; +import oshi.util.tuples.Quartet; + +import java.util.function.Supplier; + +public class SliderSignalSyncPacket extends SyncEntityPacket { + + public static final Type TYPE = new Type<>(Redux.loc("sync_slider_signal_attachment")); + + public static final StreamCodec STREAM_CODEC = CustomPacketPayload.codec( + SliderSignalSyncPacket::write, + SliderSignalSyncPacket::decode); + + public SliderSignalSyncPacket(Quartet values) { + super(values); + } + + public SliderSignalSyncPacket(int entityID, String key, INBTSynchable.Type type, Object value) { + super(entityID, key, type, value); + } + + + public static SliderSignalSyncPacket decode(RegistryFriendlyByteBuf buf) { + return new SliderSignalSyncPacket(SyncEntityPacket.decodeEntityValues(buf)); + } + + @Override + public Supplier> getAttachment() { + return ReduxDataAttachments.SLIDER_SIGNAL; + } + + @Override + public Type type() { + return TYPE; + } + + public static void execute(SliderSignalSyncPacket payload, IPayloadContext context) { + SyncEntityPacket.execute(payload, context.player()); + } +} diff --git a/src/main/resources/aether_redux.mixins.json b/src/main/resources/aether_redux.mixins.json index c756933d6..4a1d89f0a 100644 --- a/src/main/resources/aether_redux.mixins.json +++ b/src/main/resources/aether_redux.mixins.json @@ -10,14 +10,17 @@ "common.accessor.AetherNoiseBuildersMixin", "common.accessor.EntityAccessor", "common.accessor.MossyCarpetAccessor", + "common.accessor.SliderAccessor", "common.accessor.WallBlockAccessor", "common.block.BlockBehaviorMixin", "common.block.QuicksoilMixin", "common.entity.AbstractWhirlwindMixin", + "common.entity.EntityMixin", "common.entity.EvilWhirlwindMixin", "common.entity.LivingEntityMixin", "common.entity.PassiveWhirlwindMixin", "common.entity.SliderMixin", + "common.entity.ai.SliderMoveMixin", "common.item.DiggerItemMixin", "common.item.PickaxeItemMixin", "common.world.structure.AetherTemplateStructurePieceMixin", diff --git a/src/main/resources/assets/aether_redux/sounds/entity/slider/signal.ogg b/src/main/resources/assets/aether_redux/sounds/entity/slider/signal.ogg new file mode 100644 index 000000000..aa8f4853c Binary files /dev/null and b/src/main/resources/assets/aether_redux/sounds/entity/slider/signal.ogg differ