diff --git a/src/main/java/com/floralquafloral/VoiceLine.java b/src/main/java/com/floralquafloral/VoiceLine.java index 1f5a961..fa2d13f 100644 --- a/src/main/java/com/floralquafloral/VoiceLine.java +++ b/src/main/java/com/floralquafloral/VoiceLine.java @@ -64,30 +64,17 @@ public enum VoiceLine { } public void play(MarioData data, long seed) { - MarioQuaMario.LOGGER.info("UWU: {}", SOUND_EVENTS.get(data.getCharacter())); - PlayerEntity mario = data.getMario(); if(mario.getWorld().isClient) { ClientSoundPlayer.SOUND_MANAGER.stop(PLAYER_VOICE_LINES.get(mario)); -// PositionedSoundInstance voiceSound = new PositionedSoundInstance( -// SOUND_EVENTS.get(data.getCharacter()), -// SoundCategory.VOICE, -// 1.0F, -// 1.0F, -// Random.create(seed), -// data.getMario().getX(), -// data.getMario().getY(), -// data.getMario().getZ() -// ); -// ClientSoundPlayer.SOUND_MANAGER.play(voiceSound); PLAYER_VOICE_LINES.put(mario, ClientSoundPlayer.playSound( SOUND_EVENTS.get(data.getCharacter()), SoundCategory.VOICE, mario, 1.0F, - 1.0F, + data.getPowerUp().VOICE_PITCH, seed )); } diff --git a/src/main/java/com/floralquafloral/mariodata/MarioDataPackets.java b/src/main/java/com/floralquafloral/mariodata/MarioDataPackets.java index 865e14d..f112d4d 100644 --- a/src/main/java/com/floralquafloral/mariodata/MarioDataPackets.java +++ b/src/main/java/com/floralquafloral/mariodata/MarioDataPackets.java @@ -215,7 +215,6 @@ private record SetActionC2SPayload(int newAction, long seed) implements CustomPa ); public SetActionC2SPayload(@NotNull ParsedAction newAction, long seed) { this(RegistryManager.ACTIONS.getRawIdOrThrow(newAction), seed); - MarioQuaMario.LOGGER.info("Made new SetActionC2S packet"); } public static void registerReceiver() { ServerPlayNetworking.registerGlobalReceiver(ID, (payload, context) -> diff --git a/src/main/java/com/floralquafloral/mariodata/MarioPlayerData.java b/src/main/java/com/floralquafloral/mariodata/MarioPlayerData.java index 7981433..addefe1 100644 --- a/src/main/java/com/floralquafloral/mariodata/MarioPlayerData.java +++ b/src/main/java/com/floralquafloral/mariodata/MarioPlayerData.java @@ -12,16 +12,10 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.sound.*; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.sound.BlockSoundGroup; import net.minecraft.sound.SoundCategory; import net.minecraft.sound.SoundEvent; import net.minecraft.util.Identifier; import net.minecraft.util.math.Vec3d; -import net.minecraft.util.math.random.Random; -import org.joml.Vector2d; - -import java.util.List; public class MarioPlayerData implements MarioData { private boolean enabled; @@ -134,9 +128,9 @@ private void apply() { // private double prevY; public void tick() { if(this.getMario().getWorld().isClient) { - this.action.otherClientsTick(this); - this.powerUp.otherClientsTick(this); - this.character.otherClientsTick(this); + this.action.clientTick(this, false); + this.powerUp.clientTick(this, false); + this.character.clientTick(this, false); } else { this.action.serverTick(this); @@ -165,12 +159,14 @@ public void tick() { private class SkidSoundInstance extends MovingSoundInstance { private final boolean IS_WALL; + private final boolean SPEED_SCALING; private final SkidMaterial MATERIAL; private int ticks; - protected SkidSoundInstance(boolean isWall, SkidMaterial material) { + protected SkidSoundInstance(boolean isWall, SkidMaterial material, boolean scaling) { super(isWall ? MarioSFX.SKID_WALL : material.EVENT, SoundCategory.PLAYERS, SoundInstance.createRandom()); this.IS_WALL = isWall; + this.SPEED_SCALING = scaling; this.MATERIAL = material; this.updatePos(); this.repeat = true; @@ -202,7 +198,7 @@ private enum SkidMaterial { SkidMaterial newMaterial = getFloorSkidMaterial(getMario()); if(newMaterial != this.MATERIAL && !this.IS_WALL) { MarioQuaMario.LOGGER.info("Switching skid material from {} to {}!", this.MATERIAL, newMaterial); - makeSkidSFX(false, newMaterial); + makeSkidSFX(false, newMaterial, this.SPEED_SCALING); } else this.updatePos(); @@ -215,9 +211,16 @@ private void updatePos() { this.y = getMario().getY(); this.z = getMario().getZ(); if(this.IS_WALL) return; - float slidingSpeed = (float) getMario().getVelocity().horizontalLengthSquared(); - this.volume = Math.min(1.0F, ((float) ticks) / 3.0F) * Math.min(1.0F, 0.7F * slidingSpeed); - this.pitch = 1.0F + Math.min(0.15F, 0.5F * slidingSpeed); + if(this.SPEED_SCALING) { + float slidingSpeed = (float) getMario().getVelocity().horizontalLengthSquared(); + this.volume = Math.min(1.0F, ((float) ticks) / 3.0F) * Math.min(1.0F, 0.7F * slidingSpeed); + this.pitch = 1.0F + Math.min(0.15F, 0.5F * slidingSpeed); + } + else { + float slidingSpeed = (float) getMario().getVelocity().horizontalLengthSquared(); + this.volume = Math.min(1.0F, ((float) ticks) / 3.0F) * Math.min(1.0F, 0.4F + 0.7F * slidingSpeed); + this.pitch = 1.0F + Math.min(0.15F, 0.5F * slidingSpeed); + } } @Override public boolean shouldAlwaysPlay() { @@ -230,13 +233,13 @@ private void kill() { } } private SkidSoundInstance skidSFX; - private void makeSkidSFX(boolean isWall, SkidSoundInstance.SkidMaterial material) { + private void makeSkidSFX(boolean isWall, SkidSoundInstance.SkidMaterial material, boolean scaling) { if(this.skidSFX != null) this.skidSFX.kill(); - this.skidSFX = new SkidSoundInstance(isWall, material); + this.skidSFX = new SkidSoundInstance(isWall, material, scaling); MinecraftClient.getInstance().getSoundManager().playNextTick(this.skidSFX); } - private void makeSkidSFX(boolean isWall) { - this.makeSkidSFX(isWall, SkidSoundInstance.getFloorSkidMaterial(this.getMario())); + private void makeSkidSFX(boolean isWall, boolean scaling) { + this.makeSkidSFX(isWall, SkidSoundInstance.getFloorSkidMaterial(this.getMario()), scaling); } @Override public void setAction(ParsedAction action, long seed) { @@ -248,7 +251,7 @@ private void makeSkidSFX(boolean isWall) { // Skid SFX if(this.skidSFX != null) this.skidSFX.kill(); if(action.SLIDING_STATUS.doSlideSfx() || action.SLIDING_STATUS.doWallSlideSfx()) { - makeSkidSFX(action.SLIDING_STATUS.doWallSlideSfx()); + makeSkidSFX(action.SLIDING_STATUS.doWallSlideSfx(), action.SLIDING_STATUS.doSpeedScaling()); } } else { @@ -258,7 +261,8 @@ private void makeSkidSFX(boolean isWall) { CPMIntegration.commonAPI.playAnimation(PlayerEntity.class, this.mario, action.ANIMATION, 1); } this.action = action; - MarioQuaMario.LOGGER.info("SFX? " + this.skidSFX); + this.mario.setPose(this.mario.getPose()); + } @Override public ParsedPowerUp getPowerUp() { return powerUp; diff --git a/src/main/java/com/floralquafloral/mariodata/client/Input.java b/src/main/java/com/floralquafloral/mariodata/client/Input.java index 112070a..d4a663c 100644 --- a/src/main/java/com/floralquafloral/mariodata/client/Input.java +++ b/src/main/java/com/floralquafloral/mariodata/client/Input.java @@ -28,6 +28,11 @@ public boolean isHeld() { return this.isHeld; } public boolean isPressed() { + boolean result = this.isPressedNoUnbuffer(); + if(result) this.unbuffer(); + return result; + } + public boolean isPressedNoUnbuffer() { return this.pressBuffer > 0; } public void unbuffer() { diff --git a/src/main/java/com/floralquafloral/mariodata/client/MarioClientData.java b/src/main/java/com/floralquafloral/mariodata/client/MarioClientData.java index fe00e6c..fd92f58 100644 --- a/src/main/java/com/floralquafloral/mariodata/client/MarioClientData.java +++ b/src/main/java/com/floralquafloral/mariodata/client/MarioClientData.java @@ -54,12 +54,14 @@ public MarioClientData(ClientPlayerEntity mario) { public boolean travel(Vec3d movementInput) { Input.updateDirections(movementInput.z, movementInput.x); + // TODO: Levitation effect functionality + getAction().attemptTransitions(this, TransitionPhase.PRE_TICK); - getAction().selfTick(this); + getAction().travelHook(this); getAction().attemptTransitions(this, TransitionPhase.POST_TICK); applyModifiedVelocity(); - marioClient.move(MovementType.PLAYER, marioClient.getVelocity()); + marioClient.move(MovementType.SELF, marioClient.getVelocity()); if(getAction().attemptTransitions(this, TransitionPhase.POST_MOVE)) applyModifiedVelocity(); diff --git a/src/main/java/com/floralquafloral/mixin/DamageSourceMixin.java b/src/main/java/com/floralquafloral/mixin/DamageSourceMixin.java new file mode 100644 index 0000000..fd3c60e --- /dev/null +++ b/src/main/java/com/floralquafloral/mixin/DamageSourceMixin.java @@ -0,0 +1,26 @@ +package com.floralquafloral.mixin; + +import com.floralquafloral.registries.stomp.StompHandler; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import net.minecraft.entity.EquipmentSlot; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.damage.DamageSource; +import net.minecraft.entity.damage.DamageType; +import net.minecraft.item.ItemStack; +import net.minecraft.registry.tag.TagKey; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(DamageSource.class) +public abstract class DamageSourceMixin { + @Shadow public abstract boolean isIn(TagKey tag); + + @WrapOperation(method = "getDeathMessage", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;getMainHandStack()Lnet/minecraft/item/ItemStack;")) + protected ItemStack uwu(LivingEntity instance, Operation original) { + if(isIn(StompHandler.USES_FEET_ITEM_TAG)) return instance.getEquippedStack(EquipmentSlot.FEET); + if(isIn(StompHandler.USES_LEGS_ITEM_TAG)) return instance.getEquippedStack(EquipmentSlot.LEGS); + return original.call(instance); + } +} diff --git a/src/main/java/com/floralquafloral/mixin/EntityMixin.java b/src/main/java/com/floralquafloral/mixin/EntityMixin.java index c7af2d6..0293b1f 100644 --- a/src/main/java/com/floralquafloral/mixin/EntityMixin.java +++ b/src/main/java/com/floralquafloral/mixin/EntityMixin.java @@ -40,8 +40,13 @@ private void isInSneakingPose(CallbackInfoReturnable cir) { @Inject(method = "setPose", at = @At("HEAD"), cancellable = true) private void preventSettingSneakPose(EntityPose pose, CallbackInfo ci) { if((Entity) (Object) this instanceof PlayerEntity player && pose == EntityPose.CROUCHING) { - if(MarioDataManager.getMarioData(player).getSneakProhibited()) +// MarioQuaMario.LOGGER.info("setPose called on player! Pose == {}", pose); + if(MarioDataManager.getMarioData(player).getSneakProhibited()) { + + if(player.getPose() == EntityPose.CROUCHING) + player.setPose(EntityPose.STANDING); ci.cancel(); + } } } @@ -57,7 +62,7 @@ private void preventStepSounds(BlockPos pos, BlockState state, CallbackInfo ci) @Unique private static boolean shouldStompHook = true; - @Inject(method = "move", at = @At("HEAD")) + @Inject(method = "move", at = @At("HEAD"), cancellable = true) private void executeStompsOnServer(MovementType movementType, Vec3d movement, CallbackInfo ci) { if((Entity) (Object) this instanceof ServerPlayerEntity player && shouldStompHook) { MarioData data = MarioDataManager.getMarioData(player); @@ -65,7 +70,7 @@ private void executeStompsOnServer(MovementType movementType, Vec3d movement, Ca ParsedAction action = data.getAction(); if(action.STOMP != null) { shouldStompHook = false; - action.STOMP.attempt(data, movement); + if(action.STOMP.attempt(data, movement)) ci.cancel(); shouldStompHook = true; } } diff --git a/src/main/java/com/floralquafloral/mixin/InGameHudMixin.java b/src/main/java/com/floralquafloral/mixin/InGameHudMixin.java index abd48b8..d085757 100644 --- a/src/main/java/com/floralquafloral/mixin/InGameHudMixin.java +++ b/src/main/java/com/floralquafloral/mixin/InGameHudMixin.java @@ -4,10 +4,25 @@ import com.floralquafloral.registries.states.powerup.PowerUpDefinition; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.DrawContext; import net.minecraft.client.gui.hud.InGameHud; +import net.minecraft.client.render.RenderTickCounter; +import net.minecraft.client.util.Window; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.server.integrated.IntegratedServer; +import net.minecraft.util.Colors; import net.minecraft.util.Identifier; +import org.joml.Vector2d; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.Objects; @Mixin(InGameHud.class) public abstract class InGameHudMixin { @@ -28,4 +43,47 @@ else if(hardcore) { return data.getPowerUp().HEART.getTexture(half, blinking); } } + + @Inject(method = "render", at = @At("TAIL")) + public void renderSpeedometerWithServerData(DrawContext context, RenderTickCounter tickCounter, CallbackInfo ci) { + MinecraftClient client = MinecraftClient.getInstance(); + PlayerEntity mario = client.player; + if(mario == null) return; + + double horizontalSpeed = Vector2d.distance(mario.getX(), mario.getZ(), mario.prevX, mario.prevZ); + double verticalSpeed = mario.getY() - mario.prevY; + + renderText(context, 3, "C: ", horizontalSpeed); + renderText(context, 1, "C(v): ", verticalSpeed); + + IntegratedServer integratedServer = MinecraftClient.getInstance().getServer(); + if(integratedServer == null) return; + Entity serverMario = Objects.requireNonNull(integratedServer.getWorld(mario.getWorld().getRegistryKey())).getEntityById(mario.getId()); + if(serverMario == null) return; + + renderText(context, 2, "S: ", serverMario.getVelocity().horizontalLength()); + renderText(context, 0, "S(v): ", serverMario.getVelocity().y); + + renderText(context, 6, mario.getHeight() + " VS " + mario.getHeight()); + renderText(context, 5, mario.getPose() + " VS " + mario.getPose()); + } + + @Unique + private void renderText(DrawContext context, int linesFromBottom, String label, double value) { + renderText(context, linesFromBottom, String.format(label + "%.2f", value)); + } + + @Unique + private void renderText(DrawContext context, int linesFromBottom, String text) { + Window window = MinecraftClient.getInstance().getWindow(); + TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; + +// String text = String.format(label + "%.2f", value); + + int length = textRenderer.getWidth(text); + int x = window.getScaledWidth() - length - 2; + int y = window.getScaledHeight() - (linesFromBottom + 1) * (textRenderer.fontHeight + 3); + + context.drawTextWithShadow(textRenderer, text, x, y, Colors.WHITE); + } } diff --git a/src/main/java/com/floralquafloral/registries/states/MarioStateDefinition.java b/src/main/java/com/floralquafloral/registries/states/MarioStateDefinition.java index ef605ce..3e85822 100644 --- a/src/main/java/com/floralquafloral/registries/states/MarioStateDefinition.java +++ b/src/main/java/com/floralquafloral/registries/states/MarioStateDefinition.java @@ -8,7 +8,6 @@ public interface MarioStateDefinition { @NotNull Identifier getID(); - void selfTick(MarioClientData data); - void otherClientsTick(MarioPlayerData data); + void clientTick(MarioPlayerData data, boolean isSelf); void serverTick(MarioPlayerData data); } diff --git a/src/main/java/com/floralquafloral/registries/states/ParsedMarioState.java b/src/main/java/com/floralquafloral/registries/states/ParsedMarioState.java index 1924b8f..8b2ac85 100644 --- a/src/main/java/com/floralquafloral/registries/states/ParsedMarioState.java +++ b/src/main/java/com/floralquafloral/registries/states/ParsedMarioState.java @@ -13,11 +13,8 @@ protected ParsedMarioState(MarioStateDefinition definition) { this.DEFINITION = definition; } - public void selfTick(MarioClientData data) { - this.DEFINITION.selfTick(data); - } - public void otherClientsTick(MarioPlayerData data) { - this.DEFINITION.otherClientsTick(data); + public void clientTick(MarioPlayerData data, boolean isSelf) { + this.DEFINITION.clientTick(data, isSelf); } public void serverTick(MarioPlayerData data) { this.DEFINITION.serverTick(data); diff --git a/src/main/java/com/floralquafloral/registries/states/action/ActionDefinition.java b/src/main/java/com/floralquafloral/registries/states/action/ActionDefinition.java index 5256ef7..3a9a528 100644 --- a/src/main/java/com/floralquafloral/registries/states/action/ActionDefinition.java +++ b/src/main/java/com/floralquafloral/registries/states/action/ActionDefinition.java @@ -3,6 +3,8 @@ import com.floralquafloral.mariodata.client.MarioClientData; import com.floralquafloral.mariodata.MarioPlayerData; import com.floralquafloral.registries.states.MarioStateDefinition; +import com.floralquafloral.stats.CharaStat; +import com.floralquafloral.stats.StatCategory; import net.minecraft.util.Identifier; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -15,6 +17,27 @@ public interface ActionDefinition extends MarioStateDefinition { SlidingStatus getConstantSlidingStatus(); @Nullable Identifier getStompType(); + void travelHook(MarioClientData data); + +// class GravityProfile { +// public final @NotNull CharaStat GRAVITATIONAL_ACCELERATION; +// public final @NotNull CharaStat TERMINAL_VELOCITY; +// public final @NotNull CharaStat JUMPING_GRAVITATIONAL_ACCELERATION; +// +// public GravityProfile(double gravitationalAccel, double terminalVelocity) { +// this.GRAVITATIONAL_ACCELERATION = new CharaStat(gravitationalAccel, StatCategory.NORMAL_GRAVITY); +// this.TERMINAL_VELOCITY = new CharaStat(terminalVelocity, StatCategory.TERMINAL_VELOCITY); +// +// this.JUMPING_GRAVITATIONAL_ACCELERATION = this.GRAVITATIONAL_ACCELERATION; +// } +// +// public GravityProfile(double gravitationalAccel, double terminalVelocity, double jumpingGravityAccel) { +// this.GRAVITATIONAL_ACCELERATION = new CharaStat(gravitationalAccel, StatCategory.NORMAL_GRAVITY); +// this.TERMINAL_VELOCITY = new CharaStat(terminalVelocity, StatCategory.TERMINAL_VELOCITY); +// this.JUMPING_GRAVITATIONAL_ACCELERATION = new CharaStat(jumpingGravityAccel, StatCategory.JUMPING_GRAVITY); +// } +// } + List getPreTickTransitions(); List getPostTickTransitions(); List getPostMoveTransitions(); @@ -39,25 +62,28 @@ public boolean slipOffLedges() { } } enum SlidingStatus { - SLIDING(false, false, true, true, false), // No view bobbing or footsteps, with sliding sound & block particles - SLIDING_NO_PARTICLES(false, false, true, false, false), // No view bobbing or footsteps, with sliding sound - WALL_SLIDING(false, false, false, false, true), // No view bobbing or footsteps, with alternate sliding sound - SLIDING_SILENT(false, false, false, false, false), // No view bobbing or footsteps. - NOT_SLIDING_SMOOTH(true, false, false, false, false), // Footsteps, but no view bobbing - NOT_SLIDING(true, true, false, false, false); // Vanilla view bobbing & footstep sounds - - private final boolean DO_FOOTSTEPS; - private final boolean DO_VIEW_BOBBING; - private final boolean DO_SLIDE_SFX; - private final boolean DO_ALT_SLIDE_SFX; - private final boolean DO_SLIDE_PARTICLES; - - SlidingStatus(boolean doFootsteps, boolean doViewBobbing, boolean doSfx, boolean doParticles, boolean isWall) { + SLIDING(false, false, true, true, false, true), // No view bobbing or footsteps, with sliding sound & block particles + SKIDDING(false, false, true, true, false, false), // Same as SLIDING, but the sound doesn't fade with reduced speed + SLIDING_NO_PARTICLES(false, false, true, false, false, true), // No view bobbing or footsteps, with sliding sound + WALL_SLIDING(false, false, false, false, true, true), // No view bobbing or footsteps, with alternate sliding sound + SLIDING_SILENT(false, false, false, false, false, true), // No view bobbing or footsteps. + NOT_SLIDING_SMOOTH(true, false, false, false, false, true), // Footsteps, but no view bobbing + NOT_SLIDING(true, true, false, false, false, true); // Vanilla view bobbing & footstep sounds + + public final boolean DO_FOOTSTEPS; + public final boolean DO_VIEW_BOBBING; + public final boolean DO_SLIDE_SFX; + public final boolean DO_ALT_SLIDE_SFX; + public final boolean DO_SLIDE_PARTICLES; + public final boolean DO_FADING; + + SlidingStatus(boolean doFootsteps, boolean doViewBobbing, boolean doSfx, boolean doParticles, boolean isWall, boolean speedScaling) { this.DO_FOOTSTEPS = doFootsteps; this.DO_VIEW_BOBBING = doViewBobbing; this.DO_SLIDE_SFX = doSfx; this.DO_SLIDE_PARTICLES = doParticles; this.DO_ALT_SLIDE_SFX = isWall; + this.DO_FADING = speedScaling; } public boolean doFootsteps() { return this.DO_FOOTSTEPS; @@ -74,6 +100,9 @@ public boolean doWallSlideSfx() { public boolean doParticles() { return this.DO_SLIDE_PARTICLES; } + public boolean doSpeedScaling() { + return this.DO_FADING; + } } class ActionTransitionInjection { diff --git a/src/main/java/com/floralquafloral/registries/states/action/AirborneActionDefinition.java b/src/main/java/com/floralquafloral/registries/states/action/AirborneActionDefinition.java index b305faa..b6706b6 100644 --- a/src/main/java/com/floralquafloral/registries/states/action/AirborneActionDefinition.java +++ b/src/main/java/com/floralquafloral/registries/states/action/AirborneActionDefinition.java @@ -39,6 +39,13 @@ public abstract static class AerialTransitions { null ); + public static final ActionTransitionDefinition DUCKING_LANDING = new ActionTransitionDefinition( + "qua_mario:duck_waddle", + data -> Input.DUCK.isHeld() && AerialTransitions.BASIC_LANDING.EVALUATOR.shouldTransition(data), + (data, isSelf, seed) -> data.setForwardStrafeVel(0.0, 0.0), + null + ); + public static final ActionTransitionDefinition GROUND_POUND = new ActionTransitionDefinition( "qua_mario:ground_pound", data -> Input.DUCK.isPressed(), @@ -52,16 +59,16 @@ public abstract static class AerialStats { public static final CharaStat TERMINAL_VELOCITY = new CharaStat(-3.25, StatCategory.TERMINAL_VELOCITY); public static final CharaStat JUMP_GRAVITY = new CharaStat(-0.095, JUMPING_GRAVITY); - public static final CharaStat JUMP_CAP = new CharaStat(0.39, StatCategory.JUMP_CAP); - public static final CharaStat FORWARD_DRIFT_ACCEL = new CharaStat(0.04, DRIFTING, FORWARD, ACCELERATION); + public static final CharaStat FORWARD_DRIFT_ACCEL = new CharaStat(0.045, DRIFTING, FORWARD, ACCELERATION); public static final CharaStat FORWARD_DRIFT_SPEED = new CharaStat(0.275, DRIFTING, FORWARD, SPEED); + public static final CharaStat FORWARD_DRIFT_SPRINT_SPEED = new CharaStat(0.44, DRIFTING, FORWARD, SPEED); - public static final CharaStat BACKWARD_DRIFT_ACCEL = new CharaStat(0.05, DRIFTING, BACKWARD, ACCELERATION); + public static final CharaStat BACKWARD_DRIFT_ACCEL = new CharaStat(0.055, DRIFTING, BACKWARD, ACCELERATION); public static final CharaStat BACKWARD_DRIFT_SPEED = new CharaStat(0.2, DRIFTING, BACKWARD, SPEED); - public static final CharaStat STRAFE_DRIFT_ACCEL = new CharaStat(0.04, DRIFTING, STRAFE, ACCELERATION); - public static final CharaStat STRAFE_DRIFT_SPEED = new CharaStat(0.2, DRIFTING, STRAFE, SPEED); + public static final CharaStat STRAFE_DRIFT_ACCEL = new CharaStat(0.065, DRIFTING, STRAFE, ACCELERATION); + public static final CharaStat STRAFE_DRIFT_SPEED = new CharaStat(0.25, DRIFTING, STRAFE, SPEED); public static final CharaStat DRIFT_REDIRECTION = new CharaStat(6.0, DRIFTING, REDIRECTION); } @@ -76,7 +83,7 @@ public abstract static class AerialStats { protected abstract @NotNull CharaStat getTerminalVelocity(); protected abstract @Nullable CharaStat getJumpCap(); - @Override public final void selfTick(MarioClientData data) { + @Override public final void travelHook(MarioClientData data) { double yVel = data.getYVel(); double terminalVelocity = ACTION_TERMINAL_VELOCITY.get(data); @@ -101,10 +108,10 @@ else if(!Input.JUMP.isHeld()) { data.setYVel(Math.max(terminalVelocity, yVel)); } - aerialSelfTick(data); + airborneTravel(data); } - public abstract void aerialSelfTick(MarioClientData data); + public abstract void airborneTravel(MarioClientData data); public static void airborneAccel( MarioClientData data, @@ -157,7 +164,7 @@ public static void airborneAccel(MarioClientData data) { AerialStats.FORWARD_DRIFT_ACCEL, AerialStats.FORWARD_DRIFT_SPEED, AerialStats.BACKWARD_DRIFT_ACCEL, AerialStats.BACKWARD_DRIFT_SPEED, AerialStats.STRAFE_DRIFT_ACCEL, AerialStats.STRAFE_DRIFT_SPEED, - Input.getForwardInput(), Input.getStrafeInput(), AerialStats.DRIFT_REDIRECTION + 1, 1, AerialStats.DRIFT_REDIRECTION ); } } diff --git a/src/main/java/com/floralquafloral/registries/states/action/GroundedActionDefinition.java b/src/main/java/com/floralquafloral/registries/states/action/GroundedActionDefinition.java index c157d2b..5467d1c 100644 --- a/src/main/java/com/floralquafloral/registries/states/action/GroundedActionDefinition.java +++ b/src/main/java/com/floralquafloral/registries/states/action/GroundedActionDefinition.java @@ -10,13 +10,10 @@ import com.floralquafloral.util.ClientSoundPlayer; import com.floralquafloral.util.JumpSoundPlayer; import com.floralquafloral.util.MarioSFX; -import net.minecraft.sound.SoundCategory; import net.minecraft.util.math.BlockPos; import org.jetbrains.annotations.Nullable; import org.joml.Vector2d; -import static com.floralquafloral.MarioQuaMario.LOGGER; - public abstract class GroundedActionDefinition implements ActionDefinition { public static final CharaStat ZERO = new CharaStat(0.0); @@ -58,13 +55,13 @@ public static void performJump(MarioData data, CharaStat velocityStat, @Nullable ); } - @Override public final void selfTick(MarioClientData data) { - data.setYVel(data.getYVel() - 0.01); + @Override public final void travelHook(MarioClientData data) { + data.setYVel(data.getYVel() + AirborneActionDefinition.AerialStats.GRAVITY.get(data)); AirborneActionDefinition.jumpCapped = false; - this.groundedSelfTick(data); + this.groundedTravel(data); } - public abstract void groundedSelfTick(MarioClientData data); + public abstract void groundedTravel(MarioClientData data); public void groundAccel( MarioClientData data, @@ -72,6 +69,7 @@ public void groundAccel( double forwardAngleContribution, double strafeAngleContribution, CharaStat redirectDelta ) { double slipFactor = getSlipFactor(data); + data.approachAngleAndAccel( forwardAccel.get(data) * slipFactor, forwardTarget.get(data) * Input.getForwardInput(), strafeAccel.get(data) * slipFactor, strafeTarget.get(data) * Input.getStrafeInput(), diff --git a/src/main/java/com/floralquafloral/registries/states/action/ParsedAction.java b/src/main/java/com/floralquafloral/registries/states/action/ParsedAction.java index bc4f2e1..0f7885f 100644 --- a/src/main/java/com/floralquafloral/registries/states/action/ParsedAction.java +++ b/src/main/java/com/floralquafloral/registries/states/action/ParsedAction.java @@ -7,6 +7,7 @@ import com.floralquafloral.registries.states.ParsedMarioState; import com.floralquafloral.registries.RegistryManager; import com.floralquafloral.registries.stomp.ParsedStomp; +import com.floralquafloral.stats.CharaStat; import net.minecraft.util.Identifier; import net.minecraft.util.math.random.RandomSeed; import org.jetbrains.annotations.Nullable; @@ -19,6 +20,8 @@ public class ParsedAction extends ParsedMarioState { public final String ANIMATION; + private final ActionDefinition ACTION_DEFINITION; + public final ActionDefinition.SneakLegalityRule SNEAK_LEGALITY; public final ActionDefinition.SlidingStatus SLIDING_STATUS; public final ParsedStomp STOMP; @@ -27,7 +30,7 @@ public class ParsedAction extends ParsedMarioState { public ParsedAction(ActionDefinition definition) { super(definition); -// this.DEFINITION = definition; + this.ACTION_DEFINITION = definition; this.ANIMATION = definition.getAnimationName(); this.SNEAK_LEGALITY = definition.getSneakLegalityRule(); this.SLIDING_STATUS = definition.getConstantSlidingStatus(); @@ -37,6 +40,10 @@ public ParsedAction(ActionDefinition definition) { this.TRANSITION_LISTS = new EnumMap<>(TransitionPhase.class); } + public void travelHook(MarioClientData data) { + this.ACTION_DEFINITION.travelHook(data); + } + public boolean attemptTransitions(MarioClientData data, TransitionPhase phase) { for(ParsedTransition transition : this.TRANSITION_LISTS.get(phase)) { if(transition.EVALUATOR.shouldTransition(data)) { diff --git a/src/main/java/com/floralquafloral/registries/states/action/baseactions/ActionDebug.java b/src/main/java/com/floralquafloral/registries/states/action/baseactions/ActionDebug.java index 29e45f7..cf32cb3 100644 --- a/src/main/java/com/floralquafloral/registries/states/action/baseactions/ActionDebug.java +++ b/src/main/java/com/floralquafloral/registries/states/action/baseactions/ActionDebug.java @@ -22,14 +22,14 @@ public class ActionDebug implements ActionDefinition { } @Override - public void selfTick(MarioClientData data) { + public void travelHook(MarioClientData data) { data.actionTimer++; data.setForwardStrafeVel(Input.getForwardInput() * 0.5, Input.getStrafeInput() * 0.5); data.setYVel(Input.JUMP.isHeld() ? 0.4 : (Input.DUCK.isHeld() ? -0.4 : (0.03 * Math.sin((double) data.actionTimer / 16)))); } @Override - public void otherClientsTick(MarioPlayerData data) {} + public void clientTick(MarioPlayerData data, boolean isSelf) {} @Override public void serverTick(MarioPlayerData data) { diff --git a/src/main/java/com/floralquafloral/registries/states/action/baseactions/ActionDebugAlt.java b/src/main/java/com/floralquafloral/registries/states/action/baseactions/ActionDebugAlt.java index 15c869a..62a1afd 100644 --- a/src/main/java/com/floralquafloral/registries/states/action/baseactions/ActionDebugAlt.java +++ b/src/main/java/com/floralquafloral/registries/states/action/baseactions/ActionDebugAlt.java @@ -22,7 +22,7 @@ public class ActionDebugAlt implements ActionDefinition { } @Override - public void selfTick(MarioClientData data) { + public void travelHook(MarioClientData data) { data.actionTimer++; data.setStrafeVel(Input.getStrafeInput() * 0.5); @@ -32,7 +32,7 @@ public void selfTick(MarioClientData data) { } @Override - public void otherClientsTick(MarioPlayerData data) {} + public void clientTick(MarioPlayerData data, boolean isSelf) {} @Override public void serverTick(MarioPlayerData data) { diff --git a/src/main/java/com/floralquafloral/registries/states/action/baseactions/airborne/DuckFall.java b/src/main/java/com/floralquafloral/registries/states/action/baseactions/airborne/DuckFall.java index c3cf1e5..bdb1fc3 100644 --- a/src/main/java/com/floralquafloral/registries/states/action/baseactions/airborne/DuckFall.java +++ b/src/main/java/com/floralquafloral/registries/states/action/baseactions/airborne/DuckFall.java @@ -23,9 +23,7 @@ public class DuckFall extends Fall { @Override public List getPreTickTransitions() { return List.of( - new ActionTransitionDefinition("qua_mario:duck_waddle", - AerialTransitions.BASIC_LANDING.EVALUATOR - ) + AerialTransitions.DUCKING_LANDING ); } diff --git a/src/main/java/com/floralquafloral/registries/states/action/baseactions/airborne/DuckJump.java b/src/main/java/com/floralquafloral/registries/states/action/baseactions/airborne/DuckJump.java index 88c3371..43b7a4f 100644 --- a/src/main/java/com/floralquafloral/registries/states/action/baseactions/airborne/DuckJump.java +++ b/src/main/java/com/floralquafloral/registries/states/action/baseactions/airborne/DuckJump.java @@ -2,8 +2,11 @@ import com.floralquafloral.MarioQuaMario; import com.floralquafloral.registries.states.action.baseactions.grounded.DuckWaddle; +import com.floralquafloral.stats.CharaStat; +import com.floralquafloral.stats.StatCategory; import net.minecraft.util.Identifier; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.List; @@ -12,15 +15,19 @@ public class DuckJump extends Jump { return Identifier.of(MarioQuaMario.MOD_ID, "duck_jump"); } + public static final CharaStat CAP = new CharaStat(0.14, StatCategory.JUMP_CAP); + + @Override protected @Nullable CharaStat getJumpCap() { + return CAP; + } + @Override public SneakLegalityRule getSneakLegalityRule() { return SneakLegalityRule.ALLOW; } @Override public List getPreTickTransitions() { return List.of( - new ActionTransitionDefinition("qua_mario:duck_waddle", - AerialTransitions.BASIC_LANDING.EVALUATOR - ) + AerialTransitions.DUCKING_LANDING ); } diff --git a/src/main/java/com/floralquafloral/registries/states/action/baseactions/airborne/Fall.java b/src/main/java/com/floralquafloral/registries/states/action/baseactions/airborne/Fall.java index e294881..17f1d37 100644 --- a/src/main/java/com/floralquafloral/registries/states/action/baseactions/airborne/Fall.java +++ b/src/main/java/com/floralquafloral/registries/states/action/baseactions/airborne/Fall.java @@ -42,11 +42,11 @@ public class Fall extends AirborneActionDefinition { return null; } - @Override public void aerialSelfTick(MarioClientData data) { + @Override public void airborneTravel(MarioClientData data) { airborneAccel(data); } - @Override public void otherClientsTick(MarioPlayerData data) { + @Override public void clientTick(MarioPlayerData data, boolean isSelf) { } diff --git a/src/main/java/com/floralquafloral/registries/states/action/baseactions/airborne/Jump.java b/src/main/java/com/floralquafloral/registries/states/action/baseactions/airborne/Jump.java index 813ac27..09f3c20 100644 --- a/src/main/java/com/floralquafloral/registries/states/action/baseactions/airborne/Jump.java +++ b/src/main/java/com/floralquafloral/registries/states/action/baseactions/airborne/Jump.java @@ -13,9 +13,6 @@ import java.util.List; public class Jump extends AirborneActionDefinition { - public static final CharaStat JUMP_VEL = new CharaStat(0.858, StatCategory.JUMP_VELOCITY); - public static final CharaStat JUMP_ADDEND = new CharaStat(0.117, StatCategory.JUMP_VELOCITY); - @Override public @NotNull Identifier getID() { return Identifier.of(MarioQuaMario.MOD_ID, "jump"); } @@ -23,6 +20,10 @@ public class Jump extends AirborneActionDefinition { return null; } + public static final CharaStat JUMP_VEL = new CharaStat(0.858, StatCategory.JUMP_VELOCITY); + public static final CharaStat JUMP_ADDEND = new CharaStat(0.117, StatCategory.JUMP_VELOCITY); + public static final CharaStat JUMP_CAP = new CharaStat(0.39, StatCategory.JUMP_CAP); + @Override public SneakLegalityRule getSneakLegalityRule() { return SneakLegalityRule.PROHIBIT; } @@ -43,14 +44,14 @@ public class Jump extends AirborneActionDefinition { return AerialStats.TERMINAL_VELOCITY; } @Override protected @Nullable CharaStat getJumpCap() { - return AerialStats.JUMP_CAP; + return JUMP_CAP; } - @Override public void aerialSelfTick(MarioClientData data) { + @Override public void airborneTravel(MarioClientData data) { airborneAccel(data); } - @Override public void otherClientsTick(MarioPlayerData data) { + @Override public void clientTick(MarioPlayerData data, boolean isSelf) { } diff --git a/src/main/java/com/floralquafloral/registries/states/action/baseactions/airborne/LongJump.java b/src/main/java/com/floralquafloral/registries/states/action/baseactions/airborne/LongJump.java new file mode 100644 index 0000000..a822208 --- /dev/null +++ b/src/main/java/com/floralquafloral/registries/states/action/baseactions/airborne/LongJump.java @@ -0,0 +1,81 @@ +package com.floralquafloral.registries.states.action.baseactions.airborne; + +import com.floralquafloral.MarioQuaMario; +import com.floralquafloral.mariodata.MarioPlayerData; +import com.floralquafloral.mariodata.client.MarioClientData; +import com.floralquafloral.registries.states.action.AirborneActionDefinition; +import com.floralquafloral.stats.CharaStat; +import com.floralquafloral.stats.StatCategory; +import net.minecraft.util.Identifier; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public class LongJump extends AirborneActionDefinition { + @Override public @NotNull Identifier getID() { + return Identifier.of(MarioQuaMario.MOD_ID, "long_jump"); + } + @Override public @Nullable String getAnimationName() { + return "long-jump"; + } + + public static final CharaStat GRAVITY = new CharaStat(-0.0735, StatCategory.NORMAL_GRAVITY); + + public static final CharaStat LONG_JUMP_VEL = new CharaStat(0.67, StatCategory.JUMP_VELOCITY); + public static final CharaStat LONG_JUMP_THRESHOLD = new CharaStat(0.3, StatCategory.THRESHOLD); + + @Override public SneakLegalityRule getSneakLegalityRule() { + return SneakLegalityRule.PROHIBIT; + } + @Override public SlidingStatus getConstantSlidingStatus() { + return SlidingStatus.NOT_SLIDING; + } + @Override public @Nullable Identifier getStompType() { + return Identifier.of("qua_mario", "stomp"); + } + + @Override protected @NotNull CharaStat getGravity() { + return GRAVITY; + } + @Override protected @Nullable CharaStat getJumpGravity() { + return GRAVITY; + } + @Override protected @NotNull CharaStat getTerminalVelocity() { + return AerialStats.TERMINAL_VELOCITY; + } + @Override protected @Nullable CharaStat getJumpCap() { + return null; + } + + @Override public void airborneTravel(MarioClientData data) { + airborneAccel(data); + } + + @Override public void clientTick(MarioPlayerData data, boolean isSelf) { + + } + + @Override public void serverTick(MarioPlayerData data) { + + } + + @Override public List getPreTickTransitions() { + return List.of( + AerialTransitions.DUCKING_LANDING, + AerialTransitions.DOUBLE_JUMPABLE_LANDING + ); + } + + @Override public List getPostTickTransitions() { + return List.of(); + } + + @Override public List getPostMoveTransitions() { + return List.of(); + } + + @Override public List getTransitionInjections() { + return List.of(); + } +} diff --git a/src/main/java/com/floralquafloral/registries/states/action/baseactions/airborne/PJump.java b/src/main/java/com/floralquafloral/registries/states/action/baseactions/airborne/PJump.java index ef0755f..c1f3653 100644 --- a/src/main/java/com/floralquafloral/registries/states/action/baseactions/airborne/PJump.java +++ b/src/main/java/com/floralquafloral/registries/states/action/baseactions/airborne/PJump.java @@ -4,6 +4,7 @@ import com.floralquafloral.mariodata.MarioPlayerData; import com.floralquafloral.mariodata.client.MarioClientData; import com.floralquafloral.registries.states.action.AirborneActionDefinition; +import com.floralquafloral.registries.states.action.baseactions.grounded.ActionBasic; import com.floralquafloral.stats.CharaStat; import com.floralquafloral.stats.StatCategory; import net.minecraft.util.Identifier; @@ -19,4 +20,17 @@ public class PJump extends Jump { @Override public @Nullable String getAnimationName() { return "p-jump"; } + + @Override + public List getPreTickTransitions() { + return List.of( + new ActionTransitionDefinition( + "qua_mario:basic", + (data) -> data.getMario().isOnGround() && data.getForwardVel() >= ActionBasic.RUN_SPEED.getAsThreshold(data), + AerialTransitions.DOUBLE_JUMPABLE_LANDING.EXECUTOR_CLIENT, + AerialTransitions.DOUBLE_JUMPABLE_LANDING.EXECUTOR_SERVER + ), + AerialTransitions.DOUBLE_JUMPABLE_LANDING + ); + } } diff --git a/src/main/java/com/floralquafloral/registries/states/action/baseactions/grounded/ActionBasic.java b/src/main/java/com/floralquafloral/registries/states/action/baseactions/grounded/ActionBasic.java index 4912da8..e91dbf9 100644 --- a/src/main/java/com/floralquafloral/registries/states/action/baseactions/grounded/ActionBasic.java +++ b/src/main/java/com/floralquafloral/registries/states/action/baseactions/grounded/ActionBasic.java @@ -9,6 +9,7 @@ import net.minecraft.util.Identifier; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.joml.Vector2d; import static com.floralquafloral.stats.StatCategory.*; @@ -47,10 +48,12 @@ public class ActionBasic extends GroundedActionDefinition { public static final CharaStat STRAFE_SPEED = new CharaStat(0.275, WALKING, STRAFE, SPEED); @Override - public void groundedSelfTick(MarioClientData data) { + public void groundedTravel(MarioClientData data) { if(Input.getForwardInput() > 0) { + double walkThreshold = WALK_SPEED.getAsThreshold(data); boolean isRunning = data.getMario().isSprinting() - && data.getForwardVel() > WALK_SPEED.getAsThreshold(data); + && data.getForwardVel() > WALK_STANDSTILL_THRESHOLD.get(data) + && Vector2d.lengthSquared(data.getForwardVel(), data.getStrafeVel()) > walkThreshold * walkThreshold; if(isRunning) { if(data.getForwardVel() > RUN_SPEED.getAsLimit(data)) { @@ -141,7 +144,7 @@ else if(data.getForwardVel() < BACKPEDAL_SPEED.getAsLimit(data)) { } } - @Override public void otherClientsTick(MarioPlayerData data) {} + @Override public void clientTick(MarioPlayerData data, boolean isSelf) {} @Override public void serverTick(MarioPlayerData data) {} @@ -152,7 +155,7 @@ else if(data.getForwardVel() < BACKPEDAL_SPEED.getAsLimit(data)) { return SlidingStatus.NOT_SLIDING; } @Override public @Nullable Identifier getStompType() { - return Identifier.of("qua_mario:stomp"); + return null; } @Override @@ -168,7 +171,8 @@ public List getPreTickTransitions() { (data, seed) -> { } - ) + ), + Skid.SKID_TRANSITION ); } diff --git a/src/main/java/com/floralquafloral/registries/states/action/baseactions/grounded/DuckSlide.java b/src/main/java/com/floralquafloral/registries/states/action/baseactions/grounded/DuckSlide.java index 55a057c..e7a7ce0 100644 --- a/src/main/java/com/floralquafloral/registries/states/action/baseactions/grounded/DuckSlide.java +++ b/src/main/java/com/floralquafloral/registries/states/action/baseactions/grounded/DuckSlide.java @@ -1,10 +1,12 @@ package com.floralquafloral.registries.states.action.baseactions.grounded; import com.floralquafloral.MarioQuaMario; +import com.floralquafloral.VoiceLine; import com.floralquafloral.mariodata.MarioPlayerData; import com.floralquafloral.mariodata.client.Input; import com.floralquafloral.mariodata.client.MarioClientData; import com.floralquafloral.registries.states.action.GroundedActionDefinition; +import com.floralquafloral.registries.states.action.baseactions.airborne.LongJump; import com.floralquafloral.stats.CharaStat; import net.minecraft.util.Identifier; import net.minecraft.util.math.MathHelper; @@ -32,7 +34,8 @@ public class DuckSlide extends GroundedActionDefinition { public static final CharaStat SLIDE_REDIRECTION = new CharaStat(4.0, DUCKING, REDIRECTION); @Override - public void groundedSelfTick(MarioClientData data) { + public void groundedTravel(MarioClientData data) { + data.actionTimer++; applyDrag(data, SLIDE_DRAG, SLIDE_DRAG_MIN, @@ -42,7 +45,7 @@ public void groundedSelfTick(MarioClientData data) { ); } - @Override public void otherClientsTick(MarioPlayerData data) {} + @Override public void clientTick(MarioPlayerData data, boolean isSelf) {} @Override public void serverTick(MarioPlayerData data) {} @@ -59,17 +62,28 @@ public void groundedSelfTick(MarioClientData data) { @Override public List getPreTickTransitions() { return List.of( - DuckWaddle.UNDUCK, - new ActionTransitionDefinition( // Run out of speed - "qua_mario:duck_waddle", - (data) -> MathHelper.approximatelyEquals(Vector2d.lengthSquared(data.getForwardVel(), data.getStrafeVel()), 0.0) - ) + DuckWaddle.DUCK_FALL ); } @Override public List getPostTickTransitions() { - return List.of(); + return List.of( + DuckWaddle.UNDUCK, + new ActionTransitionDefinition("qua_mario:long_jump", + data -> Input.JUMP.isPressed() && data.getForwardVel() > LongJump.LONG_JUMP_THRESHOLD.get(data), + (data, isSelf, seed) -> { + GroundedTransitions.performJump(data, LongJump.LONG_JUMP_VEL, null, seed, true); + data.setForwardVel(data.getForwardVel() * 1.4); + VoiceLine.LONG_JUMP.play(data, seed); + }, + (data, seed) -> GroundedTransitions.performJump(data, LongJump.LONG_JUMP_VEL, null, seed, false) + ), + DuckWaddle.DUCK_JUMP, + new ActionTransitionDefinition("qua_mario:duck_waddle", + (data) -> MathHelper.approximatelyEquals(Vector2d.lengthSquared(data.getForwardVel(), data.getStrafeVel()), 0.0) + ) + ); } @Override @@ -79,31 +93,41 @@ public List getPostMoveTransitions() { @Override public List getTransitionInjections() { - final ActionTransitionDefinition.TransitionEvaluator SLIDE_EVALUATOR = (data) -> { - double threshold = SLIDE_THRESHOLD.get(data); - return - Input.DUCK.isHeld() - && Vector2d.lengthSquared(data.getForwardVel(), data.getStrafeVel()) > threshold * threshold - && !data.getAction().ID.equals(getID()); - }; return List.of( new ActionTransitionInjection( + ActionTransitionInjection.InjectionPlacement.BEFORE, "qua_mario:duck_waddle", ActionTransitionInjection.ActionCategory.GROUNDED, new ActionTransitionDefinition( "qua_mario:duck_slide", - SLIDE_EVALUATOR, + (data) -> { + double threshold = SLIDE_THRESHOLD.get(data); + return + Input.DUCK.isHeld() + && Vector2d.lengthSquared(data.getForwardVel(), data.getStrafeVel()) > threshold * threshold + && !data.getAction().ID.equals(getID()); + }, GroundedTransitions.DUCK_WADDLE.EXECUTOR_CLIENT, GroundedTransitions.DUCK_WADDLE.EXECUTOR_SERVER ) ), new ActionTransitionInjection( + ActionTransitionInjection.InjectionPlacement.BEFORE, "qua_mario:duck_waddle", ActionTransitionInjection.ActionCategory.AIRBORNE, new ActionTransitionDefinition( "qua_mario:duck_slide", - SLIDE_EVALUATOR, + (data) -> { + double threshold = SLIDE_THRESHOLD.get(data); + return + Input.DUCK.isHeld() + && data.getMario().isOnGround() + && !(MathHelper.approximatelyEquals(Input.getForwardInput(), 0) + && MathHelper.approximatelyEquals(Input.getStrafeInput(), 0)) + && Vector2d.lengthSquared(data.getForwardVel(), data.getStrafeVel()) > threshold * threshold + && !data.getAction().ID.equals(getID()); + }, null, null ) diff --git a/src/main/java/com/floralquafloral/registries/states/action/baseactions/grounded/DuckWaddle.java b/src/main/java/com/floralquafloral/registries/states/action/baseactions/grounded/DuckWaddle.java index c64e7d6..4b82855 100644 --- a/src/main/java/com/floralquafloral/registries/states/action/baseactions/grounded/DuckWaddle.java +++ b/src/main/java/com/floralquafloral/registries/states/action/baseactions/grounded/DuckWaddle.java @@ -1,14 +1,15 @@ package com.floralquafloral.registries.states.action.baseactions.grounded; import com.floralquafloral.MarioQuaMario; +import com.floralquafloral.VoiceLine; import com.floralquafloral.mariodata.MarioPlayerData; import com.floralquafloral.mariodata.client.Input; import com.floralquafloral.mariodata.client.MarioClientData; import com.floralquafloral.registries.states.action.GroundedActionDefinition; +import com.floralquafloral.registries.states.action.baseactions.airborne.Jump; import com.floralquafloral.stats.CharaStat; import com.floralquafloral.util.ClientSoundPlayer; import com.floralquafloral.util.MarioSFX; -import net.minecraft.sound.SoundCategory; import net.minecraft.util.Identifier; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -28,15 +29,28 @@ public class DuckWaddle extends GroundedActionDefinition { public static final ActionTransitionDefinition UNDUCK = new ActionTransitionDefinition( "qua_mario:basic", (data) -> !Input.DUCK.isHeld(), - (data, isSelf, seed) -> { - ClientSoundPlayer.playSound(MarioSFX.UNDUCK, data, seed); - }, + (data, isSelf, seed) -> ClientSoundPlayer.playSound(MarioSFX.UNDUCK, data, seed), null ); public static final ActionTransitionDefinition DUCK_FALL = new ActionTransitionDefinition( "qua_mario:duck_fall", GroundedTransitions.FALL.EVALUATOR ); + public static final ActionTransitionDefinition DUCK_JUMP = new ActionTransitionDefinition( + "qua_mario:duck_jump", + GroundedTransitions.JUMP.EVALUATOR, + (data, isSelf, seed) -> { + GroundedTransitions.performJump(data, Jump.JUMP_VEL, null, seed, true); + VoiceLine.DUCK_JUMP.play(data, seed); + }, + (data, seed) -> GroundedTransitions.performJump(data, Jump.JUMP_VEL, null, seed, false) + ); + public static final ActionTransitionDefinition BACKFLIP = new ActionTransitionDefinition( + "qua_mario:backflip", + data -> Input.JUMP.isPressed() && data.getForwardVel() < -0.05 && Input.getForwardInput() < 0.5, + (data, isSelf, seed) -> {}, + (data, seed) -> {} + ); public static final CharaStat WADDLE_ACCEL = new CharaStat(0.06, DUCKING, FORWARD, ACCELERATION); public static final CharaStat WADDLE_SPEED = new CharaStat(0.08, DUCKING, FORWARD, SPEED); @@ -50,7 +64,7 @@ public class DuckWaddle extends GroundedActionDefinition { public static final CharaStat WADDLE_REDIRECTION = new CharaStat(0.0, DUCKING, REDIRECTION); @Override - public void groundedSelfTick(MarioClientData data) { + public void groundedTravel(MarioClientData data) { boolean waddlingForward = data.getForwardVel() > 0; groundAccel(data, waddlingForward ? WADDLE_ACCEL : WADDLE_BACKPEDAL_ACCEL, @@ -60,7 +74,7 @@ public void groundedSelfTick(MarioClientData data) { ); } - @Override public void otherClientsTick(MarioPlayerData data) {} + @Override public void clientTick(MarioPlayerData data, boolean isSelf) {} @Override public void serverTick(MarioPlayerData data) {} @@ -84,7 +98,8 @@ public List getPreTickTransitions() { @Override public List getPostTickTransitions() { return List.of( - UNDUCK + UNDUCK, + DUCK_JUMP ); } diff --git a/src/main/java/com/floralquafloral/registries/states/action/baseactions/grounded/PRun.java b/src/main/java/com/floralquafloral/registries/states/action/baseactions/grounded/PRun.java index d157372..1de8a17 100644 --- a/src/main/java/com/floralquafloral/registries/states/action/baseactions/grounded/PRun.java +++ b/src/main/java/com/floralquafloral/registries/states/action/baseactions/grounded/PRun.java @@ -27,7 +27,7 @@ public class PRun extends GroundedActionDefinition { public static final CharaStat P_REDIRECTION = new CharaStat(6.0, P_RUNNING, FORWARD, REDIRECTION); @Override - public void groundedSelfTick(MarioClientData data) { + public void groundedTravel(MarioClientData data) { boolean sprinting = data.getMario().isSprinting(); groundAccel(data, sprinting ? ActionBasic.OVERRUN_ACCEL : ActionBasic.OVERWALK_ACCEL, @@ -38,7 +38,7 @@ public void groundedSelfTick(MarioClientData data) { ); } - @Override public void otherClientsTick(MarioPlayerData data) {} + @Override public void clientTick(MarioPlayerData data, boolean isSelf) {} @Override public void serverTick(MarioPlayerData data) {} @@ -58,7 +58,9 @@ public List getPreTickTransitions() { GroundedTransitions.FALL, GroundedTransitions.DUCK_WADDLE, new ActionTransitionDefinition("qua_mario:basic", - (data) -> data.getForwardVel() < ActionBasic.RUN_SPEED.getAsThreshold(data)) + (data) -> data.getForwardVel() < ActionBasic.RUN_SPEED.getAsThreshold(data) + ), + Skid.SKID_TRANSITION ); } diff --git a/src/main/java/com/floralquafloral/registries/states/action/baseactions/grounded/Skid.java b/src/main/java/com/floralquafloral/registries/states/action/baseactions/grounded/Skid.java new file mode 100644 index 0000000..3aaf470 --- /dev/null +++ b/src/main/java/com/floralquafloral/registries/states/action/baseactions/grounded/Skid.java @@ -0,0 +1,91 @@ +package com.floralquafloral.registries.states.action.baseactions.grounded; + +import com.floralquafloral.MarioQuaMario; +import com.floralquafloral.mariodata.MarioPlayerData; +import com.floralquafloral.mariodata.client.Input; +import com.floralquafloral.mariodata.client.MarioClientData; +import com.floralquafloral.registries.states.action.GroundedActionDefinition; +import com.floralquafloral.stats.CharaStat; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.MathHelper; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +import static com.floralquafloral.stats.StatCategory.*; + +public class Skid extends GroundedActionDefinition { + @Override public @NotNull Identifier getID() { + return Identifier.of(MarioQuaMario.MOD_ID, "skid"); + } + @Override public @Nullable String getAnimationName() { + return "skid"; + } + + public static final CharaStat SKID_THRESHOLD = new CharaStat(0.285, RUNNING, THRESHOLD); + + public static final CharaStat SKID_DRAG = new CharaStat(0.185, RUNNING, DRAG); + public static final CharaStat SKID_DRAG_MIN = new CharaStat(0.02, RUNNING, DRAG); + public static final CharaStat SKID_REDIRECTION = new CharaStat(4.5, RUNNING, REDIRECTION); + + public static final ActionTransitionDefinition SKID_TRANSITION = new ActionTransitionDefinition( + "qua_mario:skid", + data -> Input.getForwardInput() < -0.65 && data.getForwardVel() > SKID_THRESHOLD.get(data) + ); + + @Override + public void groundedTravel(MarioClientData data) { + applyDrag(data, + SKID_DRAG, + SKID_DRAG_MIN, + -Input.getForwardInput(), + Input.getStrafeInput(), + SKID_REDIRECTION + ); + if(MathHelper.approximatelyEquals(data.getForwardVel(), 0.0)) data.actionTimer++; + } + + @Override public void clientTick(MarioPlayerData data, boolean isSelf) {} + + @Override public void serverTick(MarioPlayerData data) {} + + @Override public SneakLegalityRule getSneakLegalityRule() { + return SneakLegalityRule.ALLOW; + } + @Override public SlidingStatus getConstantSlidingStatus() { + return SlidingStatus.SKIDDING; + } + @Override public @Nullable Identifier getStompType() { + return null; + } + + @Override + public List getPreTickTransitions() { + return List.of( + GroundedTransitions.FALL, + GroundedTransitions.DUCK_WADDLE, + new ActionTransitionDefinition("qua_mario:basic", + data -> (data.actionTimer > 0 || Input.getForwardInput() >= 0 || data.getForwardVel() < -0.05) + ) + ); + } + + @Override + public List getPostTickTransitions() { + return List.of( + // Sideflip!!! + GroundedTransitions.JUMP + ); + } + + @Override + public List getPostMoveTransitions() { + return List.of(); + } + + @Override + public List getTransitionInjections() { + return List.of(); + } +} diff --git a/src/main/java/com/floralquafloral/registries/states/character/basecharacters/Luigi.java b/src/main/java/com/floralquafloral/registries/states/character/basecharacters/Luigi.java index b84b3c5..9b7a6c9 100644 --- a/src/main/java/com/floralquafloral/registries/states/character/basecharacters/Luigi.java +++ b/src/main/java/com/floralquafloral/registries/states/character/basecharacters/Luigi.java @@ -47,12 +47,7 @@ public float getHeightFactor() { } @Override - public void selfTick(MarioClientData data) { - - } - - @Override - public void otherClientsTick(MarioPlayerData data) { + public void clientTick(MarioPlayerData data, boolean isSelf) { } diff --git a/src/main/java/com/floralquafloral/registries/states/character/basecharacters/Mario.java b/src/main/java/com/floralquafloral/registries/states/character/basecharacters/Mario.java index eaa05ed..34981a3 100644 --- a/src/main/java/com/floralquafloral/registries/states/character/basecharacters/Mario.java +++ b/src/main/java/com/floralquafloral/registries/states/character/basecharacters/Mario.java @@ -33,12 +33,7 @@ public float getHeightFactor() { } @Override - public void selfTick(MarioClientData data) { - - } - - @Override - public void otherClientsTick(MarioPlayerData data) { + public void clientTick(MarioPlayerData data, boolean isSelf) { } diff --git a/src/main/java/com/floralquafloral/registries/states/character/basecharacters/Toadette.java b/src/main/java/com/floralquafloral/registries/states/character/basecharacters/Toadette.java index 968a1b1..39afa41 100644 --- a/src/main/java/com/floralquafloral/registries/states/character/basecharacters/Toadette.java +++ b/src/main/java/com/floralquafloral/registries/states/character/basecharacters/Toadette.java @@ -33,12 +33,7 @@ public float getHeightFactor() { } @Override - public void selfTick(MarioClientData data) { - - } - - @Override - public void otherClientsTick(MarioPlayerData data) { + public void clientTick(MarioPlayerData data, boolean isSelf) { } diff --git a/src/main/java/com/floralquafloral/registries/states/powerup/ParsedPowerUp.java b/src/main/java/com/floralquafloral/registries/states/powerup/ParsedPowerUp.java index dd0cdeb..cad0a36 100644 --- a/src/main/java/com/floralquafloral/registries/states/powerup/ParsedPowerUp.java +++ b/src/main/java/com/floralquafloral/registries/states/powerup/ParsedPowerUp.java @@ -11,6 +11,7 @@ public class ParsedPowerUp extends ParsedMajorMarioState { public final int VALUE; + public final float VOICE_PITCH; public final SoundEvent ACQUISITION_SOUND; public final Identifier REVERT_TARGET; @@ -23,6 +24,7 @@ public ParsedPowerUp(PowerUpDefinition definition) { super(definition); this.VALUE = definition.getValue(); + this.VOICE_PITCH = definition.getVoicePitch(); SoundEvent acquisitionSound = definition.getAcquisitionSound(); this.ACQUISITION_SOUND = acquisitionSound == null ? MarioSFX.NORMAL_POWER : acquisitionSound; this.REVERT_TARGET = definition.getRevertTarget(); diff --git a/src/main/java/com/floralquafloral/registries/states/powerup/PowerUpDefinition.java b/src/main/java/com/floralquafloral/registries/states/powerup/PowerUpDefinition.java index e6659a0..edc75bf 100644 --- a/src/main/java/com/floralquafloral/registries/states/powerup/PowerUpDefinition.java +++ b/src/main/java/com/floralquafloral/registries/states/powerup/PowerUpDefinition.java @@ -13,6 +13,8 @@ public interface PowerUpDefinition extends MarioMajorStateDefinition { int getValue(); + float getVoicePitch(); + @Nullable SoundEvent getAcquisitionSound(); @Nullable Identifier getRevertTarget(); diff --git a/src/main/java/com/floralquafloral/registries/states/powerup/basepowerups/SmallForm.java b/src/main/java/com/floralquafloral/registries/states/powerup/basepowerups/SmallForm.java index 6e0642e..251ead2 100644 --- a/src/main/java/com/floralquafloral/registries/states/powerup/basepowerups/SmallForm.java +++ b/src/main/java/com/floralquafloral/registries/states/powerup/basepowerups/SmallForm.java @@ -20,12 +20,7 @@ public class SmallForm implements PowerUpDefinition { } @Override - public void selfTick(MarioClientData data) { - - } - - @Override - public void otherClientsTick(MarioPlayerData data) { + public void clientTick(MarioPlayerData data, boolean isSelf) { } @@ -61,6 +56,11 @@ public int getValue() { return 0; } + @Override + public float getVoicePitch() { + return 1.075F; + } + @Override public @Nullable SoundEvent getAcquisitionSound() { return null; diff --git a/src/main/java/com/floralquafloral/registries/states/powerup/basepowerups/SuperForm.java b/src/main/java/com/floralquafloral/registries/states/powerup/basepowerups/SuperForm.java index dcf9ba2..98414b9 100644 --- a/src/main/java/com/floralquafloral/registries/states/powerup/basepowerups/SuperForm.java +++ b/src/main/java/com/floralquafloral/registries/states/powerup/basepowerups/SuperForm.java @@ -20,12 +20,7 @@ public class SuperForm implements PowerUpDefinition { } @Override - public void selfTick(MarioClientData data) { - - } - - @Override - public void otherClientsTick(MarioPlayerData data) { + public void clientTick(MarioPlayerData data, boolean isSelf) { } @@ -61,6 +56,11 @@ public int getValue() { return 1; } + @Override + public float getVoicePitch() { + return 1.0F; + } + @Override public @Nullable SoundEvent getAcquisitionSound() { return null; diff --git a/src/main/java/com/floralquafloral/registries/stomp/ParsedStomp.java b/src/main/java/com/floralquafloral/registries/stomp/ParsedStomp.java index 242d346..9458f2e 100644 --- a/src/main/java/com/floralquafloral/registries/stomp/ParsedStomp.java +++ b/src/main/java/com/floralquafloral/registries/stomp/ParsedStomp.java @@ -91,14 +91,15 @@ public void executeClient(MarioPlayerData data, boolean isSelf, Entity target, b data.applyModifiedVelocity(); } - public void attempt(MarioData data, Vec3d movement) { + public boolean attempt(MarioData data, Vec3d movement) { ServerPlayerEntity mario = (ServerPlayerEntity) data.getMario(); List targets = mario.getWorld().getOtherEntities(mario, mario.getBoundingBox().stretch(movement)); long seed = RandomSeed.getSeed(); for(Entity target : targets) { - if(attemptOnTarget(mario, data, target, seed)) break; + if(attemptOnTarget(mario, data, target, seed)) return true; } + return false; } private boolean attemptOnTarget(ServerPlayerEntity mario, MarioData data, Entity target, long seed) { @@ -109,7 +110,7 @@ private boolean attemptOnTarget(ServerPlayerEntity mario, MarioData data, Entity if(this.SHOULD_ATTEMPT_MOUNTING) { if((target instanceof Saddleable saddleableTarget && saddleableTarget.isSaddled()) || target instanceof VehicleEntity) { - if(mario.startRiding(target)) return false; + if(mario.startRiding(target)) return true; } } @@ -118,13 +119,6 @@ private boolean attemptOnTarget(ServerPlayerEntity mario, MarioData data, Entity livingTarget.isDead(); boolean targetHurtsToStomp = target.getType().isIn(StompHandler.HURTS_TO_STOMP_TAG); - MarioQuaMario.LOGGER.info("hurts:" - + "\ntarget type: " + target.getType() - + "\ntag: " + StompHandler.HURTS_TO_STOMP_TAG - + "\ninTag: " + target.getType().isIn(StompHandler.HURTS_TO_STOMP_TAG) - + "\ninVanillaTag: " + target.getType().isIn(EntityTypeTags.AQUATIC) - + "\nresponse: " + this.PAINFUL_STOMP_RESPONSE - ); if(this.PAINFUL_STOMP_RESPONSE == StompDefinition.PainfulStompResponse.INJURY && targetHurtsToStomp) { // Hurt Mario mario.damage(makeDamageSource(mario.getServerWorld(), DamageTypes.THORNS, target), 2.8F); diff --git a/src/main/java/com/floralquafloral/registries/stomp/StompHandler.java b/src/main/java/com/floralquafloral/registries/stomp/StompHandler.java index cfb73f4..a48fb14 100644 --- a/src/main/java/com/floralquafloral/registries/stomp/StompHandler.java +++ b/src/main/java/com/floralquafloral/registries/stomp/StompHandler.java @@ -67,13 +67,6 @@ public static void registerReceiver() { MarioQuaMario.LOGGER.error("Target: {}", target); return; } - MarioQuaMario.LOGGER.info("receiver:" - + "\ncontextPlayerWorld: " + context.player().getWorld() - + "\nmarioWorld: " + mario.getWorld() - + "\nareEqual: " + (context.player().getWorld() == mario.getWorld()) - + "\nareEqual2: " + (context.player().getWorld().equals(mario.getWorld())) - + "\nmarioDataMarioWorld: " + getMarioData(mario).getMario().getWorld() - ); stompType.executeClient((MarioPlayerData) getMarioData(mario), mario.isMainPlayer(), target, payload.harmless, payload.seed); }); } diff --git a/src/main/java/com/floralquafloral/stats/CharaStat.java b/src/main/java/com/floralquafloral/stats/CharaStat.java index 656c629..17547bb 100644 --- a/src/main/java/com/floralquafloral/stats/CharaStat.java +++ b/src/main/java/com/floralquafloral/stats/CharaStat.java @@ -1,8 +1,11 @@ package com.floralquafloral.stats; +import com.floralquafloral.MarioQuaMario; import com.floralquafloral.mariodata.MarioData; import com.floralquafloral.mariodata.MarioDataManager; import com.floralquafloral.registries.states.ParsedMajorMarioState; +import net.minecraft.entity.attribute.EntityAttributes; +import net.minecraft.entity.effect.StatusEffects; import java.util.*; @@ -21,7 +24,12 @@ public CharaStat(double base, StatCategory... categories) { this.CATEGORIES = Set.of(categories); } + private static final double MOVEMENT_SPEED_MULTIPLIER = 1.0 / 0.10000000149011612; + private static final double MOVEMENT_SPEED_MULTIPLIER_SPRINTING = 1.0 / 0.13000000312924387; + public double get(MarioData data) { + double modifiedBase; + if(data.getMario().isMainPlayer()) { // Only cache stat values for the client-side player Double value = CACHE.get(this); if(value == null) { @@ -29,9 +37,28 @@ public double get(MarioData data) { CACHE.put(this, value); } - return value; + modifiedBase = value; + } + else modifiedBase = this.BASE * this.getMultiplier(data); + + double attributeFactor = 1.0; + double attributeAddend = 0.0; + + if(this.CATEGORIES.contains(StatCategory.SPEED) && ( + this.CATEGORIES.contains(StatCategory.WALKING) + || this.CATEGORIES.contains(StatCategory.RUNNING) + || this.CATEGORIES.contains(StatCategory.P_RUNNING) + || this.CATEGORIES.contains(StatCategory.DUCKING) + )) { + attributeFactor = data.getMario().getAttributes().getValue(EntityAttributes.GENERIC_MOVEMENT_SPEED) + * (data.getMario().isSprinting() ? MOVEMENT_SPEED_MULTIPLIER_SPRINTING : MOVEMENT_SPEED_MULTIPLIER); + } + + if(this.CATEGORIES.contains(StatCategory.JUMP_VELOCITY)) { + attributeAddend = data.getMario().getJumpBoostVelocityModifier(); } - else return this.BASE * this.getMultiplier(data); + + return attributeFactor * modifiedBase + attributeAddend; } public double getAsThreshold(MarioData data) { return this.get(data) * 0.99; diff --git a/src/main/java/com/floralquafloral/util/JumpSoundPlayer.java b/src/main/java/com/floralquafloral/util/JumpSoundPlayer.java index 78ef801..c6377a4 100644 --- a/src/main/java/com/floralquafloral/util/JumpSoundPlayer.java +++ b/src/main/java/com/floralquafloral/util/JumpSoundPlayer.java @@ -76,10 +76,7 @@ private record FadeJumpSoundC2SPayload() implements CustomPayload { public static final PacketCodec CODEC = PacketCodec.unit(new FadeJumpSoundC2SPayload()); public static void registerReceiver() { ServerPlayNetworking.registerGlobalReceiver(ID, (payload, context) -> - { - MarioPackets.sendPacketToTrackersExclusive(context.player(), new FadeJumpSoundS2CPayload(context.player())); - MarioQuaMario.LOGGER.info("Received C2S packet to fade the jump sound!"); - } + MarioPackets.sendPacketToTrackersExclusive(context.player(), new FadeJumpSoundS2CPayload(context.player())) ); } diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index f67f065..c4b6c17 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -26,6 +26,7 @@ "mario-actions-grounded": [ "com.floralquafloral.registries.states.action.baseactions.grounded.ActionBasic", "com.floralquafloral.registries.states.action.baseactions.grounded.PRun", + "com.floralquafloral.registries.states.action.baseactions.grounded.Skid", "com.floralquafloral.registries.states.action.baseactions.grounded.DuckWaddle", "com.floralquafloral.registries.states.action.baseactions.grounded.DuckSlide" ], @@ -34,7 +35,8 @@ "com.floralquafloral.registries.states.action.baseactions.airborne.Jump", "com.floralquafloral.registries.states.action.baseactions.airborne.PJump", "com.floralquafloral.registries.states.action.baseactions.airborne.DuckFall", - "com.floralquafloral.registries.states.action.baseactions.airborne.DuckJump" + "com.floralquafloral.registries.states.action.baseactions.airborne.DuckJump", + "com.floralquafloral.registries.states.action.baseactions.airborne.LongJump" ], "mario-actions-aquatic": [ diff --git a/src/main/resources/qua_mario.mixins.json b/src/main/resources/qua_mario.mixins.json index 44c01f4..e1b8080 100644 --- a/src/main/resources/qua_mario.mixins.json +++ b/src/main/resources/qua_mario.mixins.json @@ -3,6 +3,7 @@ "package": "com.floralquafloral.mixin", "compatibilityLevel": "JAVA_21", "mixins": [ + "DamageSourceMixin", "EntityMixin", "JumpMixin", "PlayerEntityMixin"