From 4da33b8ecafcd8d341f48cbed62c793a06605086 Mon Sep 17 00:00:00 2001 From: isXander Date: Wed, 5 Apr 2023 16:36:41 +0100 Subject: [PATCH] explosion rumble --- .../dev/isxander/controlify/Controlify.java | 2 +- .../controlify/controller/Controller.java | 2 +- .../blockbreak/MultiPlayerGameModeMixin.java | 5 ++- .../explosion/ClientPacketListenerMixin.java | 42 +++++++++++++++++++ .../rumble/explosion/LightningBoltMixin.java | 27 ++++++++++++ .../controlify/rumble/RumbleSource.java | 1 + .../assets/controlify/lang/en_us.json | 2 + src/main/resources/controlify.mixins.json | 2 + 8 files changed, 79 insertions(+), 4 deletions(-) create mode 100644 src/main/java/dev/isxander/controlify/mixins/feature/rumble/explosion/ClientPacketListenerMixin.java create mode 100644 src/main/java/dev/isxander/controlify/mixins/feature/rumble/explosion/LightningBoltMixin.java diff --git a/src/main/java/dev/isxander/controlify/Controlify.java b/src/main/java/dev/isxander/controlify/Controlify.java index 8a80b77..4735796 100644 --- a/src/main/java/dev/isxander/controlify/Controlify.java +++ b/src/main/java/dev/isxander/controlify/Controlify.java @@ -244,7 +244,7 @@ public class Controlify implements ControlifyApi { private void onControllerDisconnect(int jid) { Controller.CONTROLLERS.values().stream().filter(controller -> controller.joystickId() == jid).findAny().ifPresent(controller -> { - Controller.CONTROLLERS.remove(controller.uid(), controller); + Controller.remove(controller); setCurrentController(Controller.CONTROLLERS.values().stream().findFirst().orElse(null)); LOGGER.info("Controller disconnected: " + controller.name()); diff --git a/src/main/java/dev/isxander/controlify/controller/Controller.java b/src/main/java/dev/isxander/controlify/controller/Controller.java index 913189a..bc7ddc8 100644 --- a/src/main/java/dev/isxander/controlify/controller/Controller.java +++ b/src/main/java/dev/isxander/controlify/controller/Controller.java @@ -67,7 +67,7 @@ public interface Controller controller) { - CONTROLLERS.remove(controller.uid()); + CONTROLLERS.remove(controller.uid(), controller); controller.close(); } diff --git a/src/main/java/dev/isxander/controlify/mixins/feature/rumble/blockbreak/MultiPlayerGameModeMixin.java b/src/main/java/dev/isxander/controlify/mixins/feature/rumble/blockbreak/MultiPlayerGameModeMixin.java index bfefedb..276f1c0 100644 --- a/src/main/java/dev/isxander/controlify/mixins/feature/rumble/blockbreak/MultiPlayerGameModeMixin.java +++ b/src/main/java/dev/isxander/controlify/mixins/feature/rumble/blockbreak/MultiPlayerGameModeMixin.java @@ -5,6 +5,7 @@ import dev.isxander.controlify.api.ControlifyApi; import dev.isxander.controlify.rumble.ContinuousRumbleEffect; import dev.isxander.controlify.rumble.RumbleSource; import dev.isxander.controlify.rumble.RumbleState; +import dev.isxander.controlify.utils.Easings; import net.minecraft.client.multiplayer.MultiPlayerGameMode; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -54,8 +55,8 @@ public class MultiPlayerGameModeMixin { private void startRumble(BlockState state) { ContinuousRumbleEffect effect = new ContinuousRumbleEffect(tick -> new RumbleState( - 0.02f + Math.min(1, state.getBlock().defaultDestroyTime() / 20f) * 0.25f, - 0.15f + 0.02f + Easings.easeInQuad(Math.min(1, state.getBlock().defaultDestroyTime() / 20f)) * 0.25f, + 0.01f ) ){ @Override diff --git a/src/main/java/dev/isxander/controlify/mixins/feature/rumble/explosion/ClientPacketListenerMixin.java b/src/main/java/dev/isxander/controlify/mixins/feature/rumble/explosion/ClientPacketListenerMixin.java new file mode 100644 index 0000000..0898392 --- /dev/null +++ b/src/main/java/dev/isxander/controlify/mixins/feature/rumble/explosion/ClientPacketListenerMixin.java @@ -0,0 +1,42 @@ +package dev.isxander.controlify.mixins.feature.rumble.explosion; + +import com.llamalad7.mixinextras.sugar.Local; +import dev.isxander.controlify.api.ControlifyApi; +import dev.isxander.controlify.rumble.BasicRumbleEffect; +import dev.isxander.controlify.rumble.RumbleSource; +import dev.isxander.controlify.rumble.RumbleState; +import dev.isxander.controlify.utils.Easings; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientPacketListener; +import net.minecraft.network.protocol.game.ClientboundExplodePacket; +import net.minecraft.world.level.Explosion; +import org.spongepowered.asm.mixin.Final; +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(ClientPacketListener.class) +public class ClientPacketListenerMixin { + @Shadow @Final private Minecraft minecraft; + + @Inject(method = "handleExplosion", at = @At("RETURN")) + private void onClientExplosion(ClientboundExplodePacket packet, CallbackInfo ci) { + float distanceSqr = Math.max( + (float)minecraft.player.distanceToSqr(packet.getX(), packet.getY(), packet.getZ()) + - packet.getPower() * packet.getPower(), // power is explosion radius + 0f); + float maxDistanceSqr = 4096f; // client only receives explosion packets within 64 blocks + + float magnitude = 1f - Easings.easeOutQuad(distanceSqr / maxDistanceSqr); + + ControlifyApi.get().currentController().rumbleManager().play( + RumbleSource.EXPLOSION, + BasicRumbleEffect.join( + BasicRumbleEffect.constant(magnitude, magnitude, 4), // initial boom + BasicRumbleEffect.byTime(t -> new RumbleState(0f, magnitude - t*magnitude), 20) // explosion + ) + ); + } +} diff --git a/src/main/java/dev/isxander/controlify/mixins/feature/rumble/explosion/LightningBoltMixin.java b/src/main/java/dev/isxander/controlify/mixins/feature/rumble/explosion/LightningBoltMixin.java new file mode 100644 index 0000000..d72925e --- /dev/null +++ b/src/main/java/dev/isxander/controlify/mixins/feature/rumble/explosion/LightningBoltMixin.java @@ -0,0 +1,27 @@ +package dev.isxander.controlify.mixins.feature.rumble.explosion; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import dev.isxander.controlify.api.ControlifyApi; +import dev.isxander.controlify.rumble.BasicRumbleEffect; +import dev.isxander.controlify.rumble.RumbleSource; +import dev.isxander.controlify.rumble.RumbleState; +import net.minecraft.world.entity.LightningBolt; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(LightningBolt.class) +public class LightningBoltMixin { + @ModifyExpressionValue(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;isClientSide()Z")) + private boolean onLightningStrike(boolean client) { + if (client) { + ControlifyApi.get().currentController().rumbleManager().play( + RumbleSource.EXPLOSION, + BasicRumbleEffect.join( + BasicRumbleEffect.constant(1f, 0.2f, 6), // initial boom + BasicRumbleEffect.byTime(t -> new RumbleState(0f, 1 - t*0.2f), 10) // explosion + ) + ); + } + return client; + } +} diff --git a/src/main/java/dev/isxander/controlify/rumble/RumbleSource.java b/src/main/java/dev/isxander/controlify/rumble/RumbleSource.java index a9036ad..ccb894d 100644 --- a/src/main/java/dev/isxander/controlify/rumble/RumbleSource.java +++ b/src/main/java/dev/isxander/controlify/rumble/RumbleSource.java @@ -15,6 +15,7 @@ public class RumbleSource { USE_ITEM = register("use_item"), ITEM_BREAK = register("item_break"), GUI = register("gui"), + EXPLOSION = register("explosion"), GLOBAL_EVENT = register("global_event"); private final ResourceLocation id; diff --git a/src/main/resources/assets/controlify/lang/en_us.json b/src/main/resources/assets/controlify/lang/en_us.json index e8c5f12..5c80b97 100644 --- a/src/main/resources/assets/controlify/lang/en_us.json +++ b/src/main/resources/assets/controlify/lang/en_us.json @@ -88,6 +88,8 @@ "controlify.vibration_strength.controlify.use_item.tooltip": "When you are using an item. For example:\n - pulling a bow or trident,\n - blocking with a shield,\n - eating or drinking, etc.", "controlify.vibration_strength.controlify.item_break": "Item Break", "controlify.vibration_strength.controlify.item_break.tooltip": "When an item breaks.", + "controlify.vibration_strength.controlify.explosion": "Explosion", + "controlify.vibration_strength.controlify.explosion.tooltip": "When an explosion occurs. For example, tnt, fireball, lightning etc.", "controlify.vibration_strength.controlify.gui": "GUI", "controlify.vibration_strength.controlify.gui.tooltip": "Various effects in GUIs such as anvil use.", "controlify.vibration_strength.controlify.global_event": "Global Event", diff --git a/src/main/resources/controlify.mixins.json b/src/main/resources/controlify.mixins.json index 63847cf..5e990aa 100644 --- a/src/main/resources/controlify.mixins.json +++ b/src/main/resources/controlify.mixins.json @@ -9,6 +9,7 @@ "compat.sodium.SliderControlElementMixin", "compat.sodium.TickBoxControlElementMixin", "core.GLXMixin", + "feature.rumble.explosion.LightningBoltMixin", "feature.rumble.itembreak.LivingEntityMixin", "feature.rumble.sounds.LevelRendererMixin", "feature.rumble.useitem.LivingEntityMixin" @@ -38,6 +39,7 @@ "feature.reacharound.GameRendererMixin", "feature.rumble.blockbreak.MultiPlayerGameModeMixin", "feature.rumble.damage.LocalPlayerMixin", + "feature.rumble.explosion.ClientPacketListenerMixin", "feature.rumble.itembreak.LocalPlayerMixin", "feature.rumble.useitem.LocalPlayerMixin", "feature.screenop.MinecraftMixin",