forked from Clones/Controlify
🎮📳 Controller Vibration! (#38)
This commit is contained in:
@ -7,7 +7,7 @@ import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mixin(KeyBindingRegistryImpl.class)
|
||||
@Mixin(value = KeyBindingRegistryImpl.class, remap = false)
|
||||
public interface KeyBindingRegistryImplAccessor {
|
||||
@Accessor("MODDED_KEY_BINDINGS")
|
||||
static List<KeyMapping> getCustomKeys() {
|
||||
|
@ -28,13 +28,13 @@ public abstract class MinecraftMixin {
|
||||
@ModifyExpressionValue(method = "<init>", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/packs/resources/ReloadableResourceManager;createReload(Ljava/util/concurrent/Executor;Ljava/util/concurrent/Executor;Ljava/util/concurrent/CompletableFuture;Ljava/util/List;)Lnet/minecraft/server/packs/resources/ReloadInstance;"))
|
||||
private ReloadInstance onInputInitialized(ReloadInstance resourceReload) {
|
||||
// Controllers need to be initialized extremely late due to the data-driven nature of controllers.
|
||||
resourceReload.done().thenRun(() -> Controlify.instance().initializeControllers());
|
||||
resourceReload.done().thenRun(() -> Controlify.instance().initializeControlify());
|
||||
return resourceReload;
|
||||
}
|
||||
|
||||
@Inject(method = "<init>", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/KeyboardHandler;setup(J)V", shift = At.Shift.AFTER))
|
||||
private void onInputInitialized(CallbackInfo ci) {
|
||||
Controlify.instance().initializeControlify();
|
||||
Controlify.instance().preInitialiseControlify();
|
||||
}
|
||||
|
||||
@Inject(method = "runTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MouseHandler;turnPlayer()V"))
|
||||
|
@ -0,0 +1,31 @@
|
||||
package dev.isxander.controlify.mixins.feature.rumble.damage;
|
||||
|
||||
import dev.isxander.controlify.api.ControlifyApi;
|
||||
import dev.isxander.controlify.rumble.RumbleEffect;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
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(LocalPlayer.class)
|
||||
public class LocalPlayerMixin {
|
||||
@Inject(method = "hurtTo", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/player/LocalPlayer;setHealth(F)V", ordinal = 1))
|
||||
private void onClientHurt(float health, CallbackInfo ci) {
|
||||
// LivingEntity#hurt is server-side only, so we do it here
|
||||
doRumble();
|
||||
}
|
||||
|
||||
@Inject(method = "hurtTo", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/player/LocalPlayer;setHealth(F)V", ordinal = 0))
|
||||
private void onClientHealthUpdate(float health, CallbackInfo ci) {
|
||||
// for some reason fall damage calls hurtTo after the health has been updated at some point
|
||||
// this is called when hurtTo is set to the same health as the player already has
|
||||
doRumble();
|
||||
}
|
||||
|
||||
private void doRumble() {
|
||||
ControlifyApi.get().currentController().rumbleManager().play(
|
||||
RumbleEffect.constant(0.5f, 0f, 5)
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
package dev.isxander.controlify.mixins.feature.rumble.sounds;
|
||||
|
||||
import dev.isxander.controlify.api.ControlifyApi;
|
||||
import dev.isxander.controlify.rumble.RumbleEffect;
|
||||
import dev.isxander.controlify.rumble.RumbleState;
|
||||
import net.minecraft.client.renderer.LevelRenderer;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.block.LevelEvent;
|
||||
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(LevelRenderer.class)
|
||||
public class LevelRendererMixin {
|
||||
@Inject(method = "levelEvent", at = @At("HEAD"))
|
||||
private void onLevelEvent(int eventId, BlockPos pos, int data, CallbackInfo ci) {
|
||||
switch (eventId) {
|
||||
case LevelEvent.SOUND_ANVIL_USED -> rumble(
|
||||
RumbleEffect.join(
|
||||
RumbleEffect.constant(1f, 0.5f, 2),
|
||||
RumbleEffect.empty(5)
|
||||
).repeat(3)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "globalLevelEvent", at = @At("HEAD"))
|
||||
private void onGlobalLevelEvent(int eventId, BlockPos pos, int data, CallbackInfo ci) {
|
||||
switch (eventId) {
|
||||
case LevelEvent.SOUND_DRAGON_DEATH -> rumble(
|
||||
RumbleEffect.join(
|
||||
RumbleEffect.constant(1f, 1f, 194),
|
||||
RumbleEffect.byTime(t -> {
|
||||
float easeOutQuad = 1 - (1 - t) * (1 - t);
|
||||
return new RumbleState(1 - easeOutQuad, 1 - easeOutQuad);
|
||||
}, 63)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private void rumble(RumbleEffect effect) {
|
||||
ControlifyApi.get().currentController().rumbleManager().play(effect);
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package dev.isxander.controlify.mixins.feature.rumble.useitem;
|
||||
|
||||
import dev.isxander.controlify.api.ControlifyApi;
|
||||
import dev.isxander.controlify.rumble.RumbleEffect;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
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(LivingEntity.class)
|
||||
public abstract class LivingEntityMixin {
|
||||
@Shadow public abstract int getUseItemRemainingTicks();
|
||||
|
||||
@Inject(method = "updateUsingItem", at = @At("HEAD"))
|
||||
protected void onUpdateUsingItem(ItemStack stack, CallbackInfo ci) {
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package dev.isxander.controlify.mixins.feature.rumble.useitem;
|
||||
|
||||
import dev.isxander.controlify.api.ControlifyApi;
|
||||
import dev.isxander.controlify.rumble.RumbleEffect;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(LocalPlayer.class)
|
||||
public abstract class LocalPlayerMixin extends LivingEntityMixin {
|
||||
@Override
|
||||
protected void onUpdateUsingItem(ItemStack stack, CallbackInfo ci) {
|
||||
switch (stack.getUseAnimation()) {
|
||||
case BOW, CROSSBOW, SPEAR -> {
|
||||
var magnitude = Mth.clamp((stack.getUseDuration() - getUseItemRemainingTicks()) / 20f, 0f, 1f) * 0.5f;
|
||||
playRumble(RumbleEffect.constant(magnitude * 0.3f, magnitude, 1));
|
||||
}
|
||||
case BLOCK, SPYGLASS -> playRumble(RumbleEffect.constant(0f, 0.1f, 1));
|
||||
case EAT, DRINK -> playRumble(RumbleEffect.constant(0.05f, 0.1f, 1));
|
||||
case TOOT_HORN -> playRumble(RumbleEffect.constant(1f, 0.25f, 1));
|
||||
}
|
||||
}
|
||||
|
||||
private void playRumble(RumbleEffect effect) {
|
||||
ControlifyApi.get().currentController().rumbleManager().play(effect);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user