forked from Clones/Controlify
make explosion rumble distance change mid-way through
This commit is contained in:
@ -23,20 +23,27 @@ public class ClientPacketListenerMixin {
|
|||||||
|
|
||||||
@Inject(method = "handleExplosion", at = @At("RETURN"))
|
@Inject(method = "handleExplosion", at = @At("RETURN"))
|
||||||
private void onClientExplosion(ClientboundExplodePacket packet, CallbackInfo ci) {
|
private void onClientExplosion(ClientboundExplodePacket packet, CallbackInfo ci) {
|
||||||
float distanceSqr = Math.max(
|
float initialMagnitude = calculateMagnitude(packet);
|
||||||
(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(
|
ControlifyApi.get().currentController().rumbleManager().play(
|
||||||
RumbleSource.EXPLOSION,
|
RumbleSource.EXPLOSION,
|
||||||
BasicRumbleEffect.join(
|
BasicRumbleEffect.join(
|
||||||
BasicRumbleEffect.constant(magnitude, magnitude, 4), // initial boom
|
BasicRumbleEffect.constant(initialMagnitude, initialMagnitude, 4), // initial boom
|
||||||
BasicRumbleEffect.byTime(t -> new RumbleState(0f, magnitude - t*magnitude), 20) // explosion
|
BasicRumbleEffect.byTime(t -> {
|
||||||
|
float magnitude = calculateMagnitude(packet);
|
||||||
|
return new RumbleState(0f, magnitude - t * magnitude);
|
||||||
|
}, 20) // explosion
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private float calculateMagnitude(ClientboundExplodePacket packet) {
|
||||||
|
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
|
||||||
|
|
||||||
|
return 1f - Easings.easeOutQuad(distanceSqr / maxDistanceSqr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package dev.isxander.controlify.rumble;
|
package dev.isxander.controlify.rumble;
|
||||||
|
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.util.Mth;
|
||||||
|
import net.minecraft.world.phys.Vec3;
|
||||||
import org.apache.commons.lang3.Validate;
|
import org.apache.commons.lang3.Validate;
|
||||||
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
@ -60,6 +63,7 @@ public class ContinuousRumbleEffect implements RumbleEffect {
|
|||||||
private int priority;
|
private int priority;
|
||||||
private int timeout = -1;
|
private int timeout = -1;
|
||||||
private int minTime;
|
private int minTime;
|
||||||
|
private InWorldProperties inWorldProperties;
|
||||||
|
|
||||||
private Builder() {
|
private Builder() {
|
||||||
}
|
}
|
||||||
@ -97,11 +101,30 @@ public class ContinuousRumbleEffect implements RumbleEffect {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Builder inWorld(Vec3 sourceLocation, float minMagnitude, float maxMagnitude, float minDistance, float maxDistance, Function<Float, Float> fallofFunction) {
|
||||||
|
this.inWorldProperties = new InWorldProperties(sourceLocation, minMagnitude, maxMagnitude, minDistance, maxDistance, fallofFunction);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public ContinuousRumbleEffect build() {
|
public ContinuousRumbleEffect build() {
|
||||||
Validate.notNull(stateFunction, "stateFunction cannot be null!");
|
Validate.notNull(stateFunction, "stateFunction cannot be null!");
|
||||||
Validate.isTrue(minTime <= timeout || timeout == -1, "the minimum time cannot be greater than the timeout!");
|
Validate.isTrue(minTime <= timeout || timeout == -1, "the minimum time cannot be greater than the timeout!");
|
||||||
|
|
||||||
|
var stateFunction = this.stateFunction;
|
||||||
|
if (inWorldProperties != null)
|
||||||
|
stateFunction = inWorldProperties.modify(stateFunction);
|
||||||
|
|
||||||
return new ContinuousRumbleEffect(stateFunction, priority, timeout, minTime);
|
return new ContinuousRumbleEffect(stateFunction, priority, timeout, minTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private record InWorldProperties(Vec3 sourceLocation, float minMagnitude, float maxMagnitude, float minDistance, float maxDistance, Function<Float, Float> fallofFunction) {
|
||||||
|
private Function<Integer, RumbleState> modify(Function<Integer, RumbleState> stateFunction) {
|
||||||
|
return tick -> {
|
||||||
|
float distanceSqr = (float) Mth.clamp(Minecraft.getInstance().player.distanceToSqr(sourceLocation), minDistance, maxDistance);
|
||||||
|
float magnitude = Mth.lerp(1f - fallofFunction.apply(distanceSqr / (maxDistance * maxDistance)), minMagnitude, maxMagnitude);
|
||||||
|
return stateFunction.apply(tick).mul(magnitude);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
package dev.isxander.controlify.rumble;
|
package dev.isxander.controlify.rumble;
|
||||||
|
|
||||||
public record RumbleState(float strong, float weak) {
|
public record RumbleState(float strong, float weak) {
|
||||||
|
public RumbleState mul(float multiplier) {
|
||||||
|
return new RumbleState(strong * multiplier, weak * multiplier);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user