diff --git a/src/main/java/com/floralquafloral/BlockBumping.java b/src/main/java/com/floralquafloral/BlockBumping.java new file mode 100644 index 0000000..066a524 --- /dev/null +++ b/src/main/java/com/floralquafloral/BlockBumping.java @@ -0,0 +1,32 @@ +package com.floralquafloral; + +import com.floralquafloral.mariodata.MarioData; +import com.floralquafloral.mariodata.moveable.MarioMainClientData; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; + +import java.util.HashMap; +import java.util.Map; + +public abstract class BlockBumping { + public static final Map BUMPED_BLOCKS = new HashMap<>(); + + public static void registerPackets() { + + } + public static void registerPacketsClient() { + + } + + public static void attempt(MarioMainClientData data, Vec3d movement) { + + } + + public static void bumpBlock(MarioData data, BlockPos position, boolean isCeiling, int strength) { + MarioQuaMario.LOGGER.info("{} bumped block {}", data.getMario(), position); + } + + public static class BumpedBlockData { + + } +} diff --git a/src/main/java/com/floralquafloral/MarioPackets.java b/src/main/java/com/floralquafloral/MarioPackets.java index 798c654..e152fc6 100644 --- a/src/main/java/com/floralquafloral/MarioPackets.java +++ b/src/main/java/com/floralquafloral/MarioPackets.java @@ -24,8 +24,8 @@ public static void registerCommon() { SyncUseCharacterStatsS2CPayload.register(); MarioDataPackets.registerCommon(); StompHandler.registerPackets(); -// VoiceLine.registerPackets(); - JumpSoundPlayer.registerPackets(); + BlockBumping.registerPackets(); + ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> { MarioQuaMario.LOGGER.info(""); @@ -35,8 +35,7 @@ public static void registerClient() { SyncUseCharacterStatsS2CPayload.registerReceiver(); MarioDataPackets.registerClient(); StompHandler.registerPacketsClient(); -// VoiceLine.registerPacketsClient(); - JumpSoundPlayer.registerPacketsClient(); + BlockBumping.registerPacketsClient(); } public static PlayerEntity getPlayerFromInt(ClientPlayNetworking.Context context, int playerID) { diff --git a/src/main/java/com/floralquafloral/mixin/EntityMixin.java b/src/main/java/com/floralquafloral/mixin/EntityMixin.java index 6512117..092454e 100644 --- a/src/main/java/com/floralquafloral/mixin/EntityMixin.java +++ b/src/main/java/com/floralquafloral/mixin/EntityMixin.java @@ -1,12 +1,17 @@ package com.floralquafloral.mixin; +import com.floralquafloral.BlockBumping; import com.floralquafloral.MarioQuaMario; import com.floralquafloral.mariodata.MarioData; import com.floralquafloral.mariodata.MarioDataManager; import com.floralquafloral.mariodata.MarioPlayerData; +import com.floralquafloral.mariodata.moveable.MarioMainClientData; +import com.floralquafloral.mariodata.moveable.MarioMoveableData; import com.floralquafloral.mariodata.moveable.MarioServerData; import com.floralquafloral.registries.RegistryManager; import com.floralquafloral.registries.states.action.ParsedAction; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import net.minecraft.block.BlockState; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityPose; @@ -16,6 +21,7 @@ import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; @@ -68,8 +74,8 @@ private void preventStepSounds(BlockPos pos, BlockState state, CallbackInfo ci) @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); + if((Entity) (Object) this instanceof ServerPlayerEntity mario && shouldStompHook) { + MarioData data = MarioDataManager.getMarioData(mario); if(data.useMarioPhysics()) { ParsedAction action = data.getAction(); if(action.STOMP != null) { @@ -81,6 +87,13 @@ private void executeStompsOnServer(MovementType movementType, Vec3d movement, Ca } } + @WrapOperation(method = "checkBlockCollision", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/BlockState;onEntityCollision(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/entity/Entity;)V")) + private void executeBumpsOnClient(BlockState instance, World world, BlockPos blockPos, Entity entity, Operation original) { + if(entity instanceof ServerPlayerEntity mario) { +// world.breakBlock(blockPos, true, mario); + } + } + @Inject(method = "startRiding(Lnet/minecraft/entity/Entity;Z)Z", at = @At("HEAD")) private void setMountedAction(Entity entity, boolean force, CallbackInfoReturnable cir) { if((Entity) (Object) this instanceof PlayerEntity mario) { diff --git a/src/main/java/com/floralquafloral/registries/states/MarioMajorStateDefinition.java b/src/main/java/com/floralquafloral/registries/states/MarioMajorStateDefinition.java index b29c4c6..748a099 100644 --- a/src/main/java/com/floralquafloral/registries/states/MarioMajorStateDefinition.java +++ b/src/main/java/com/floralquafloral/registries/states/MarioMajorStateDefinition.java @@ -8,6 +8,7 @@ public interface MarioMajorStateDefinition extends MarioStateDefinition { void populateStatModifiers(Map, Double> modifiers); + int getBumpStrengthModifier(); float getWidthFactor(); float getHeightFactor(); } diff --git a/src/main/java/com/floralquafloral/registries/states/ParsedMajorMarioState.java b/src/main/java/com/floralquafloral/registries/states/ParsedMajorMarioState.java index ee11bff..958c01a 100644 --- a/src/main/java/com/floralquafloral/registries/states/ParsedMajorMarioState.java +++ b/src/main/java/com/floralquafloral/registries/states/ParsedMajorMarioState.java @@ -8,6 +8,7 @@ import java.util.Set; public abstract class ParsedMajorMarioState extends ParsedMarioState { + public final int BUMP_STRENGTH_MODIFIER; public final float WIDTH_FACTOR; public final float HEIGHT_FACTOR; public final Map, Double> STAT_MODIFIERS; @@ -15,6 +16,7 @@ public abstract class ParsedMajorMarioState extends ParsedMarioState { protected ParsedMajorMarioState(MarioMajorStateDefinition definition) { super(definition); + this.BUMP_STRENGTH_MODIFIER = definition.getBumpStrengthModifier(); this.WIDTH_FACTOR = definition.getWidthFactor(); this.HEIGHT_FACTOR = definition.getHeightFactor(); this.STAT_MODIFIERS = new HashMap<>(); 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 b4c82e3..3145d8f 100644 --- a/src/main/java/com/floralquafloral/registries/states/action/ActionDefinition.java +++ b/src/main/java/com/floralquafloral/registries/states/action/ActionDefinition.java @@ -120,6 +120,19 @@ public boolean doSpeedScaling() { return this.DO_FADING; } } + enum BumpType { + NONE(0, 0), + HIT_CEILINGS(2, 0), + GROUND_POUND(0, 2), + SPIN_JUMP(2, 1); + + public final int HIT_CEILING_STRENGTH; + public final int HIT_FLOOR_STRENGTH; + BumpType(int hitCeilingStrength, int hitFloorStrength) { + this.HIT_CEILING_STRENGTH = hitCeilingStrength; + this.HIT_FLOOR_STRENGTH = hitFloorStrength; + } + } class ActionTransitionDefinition { @FunctionalInterface public interface TransitionEvaluator { diff --git a/src/main/java/com/floralquafloral/registries/states/action/baseactions/airborne/Backflip.java b/src/main/java/com/floralquafloral/registries/states/action/baseactions/airborne/Backflip.java index c2c62a5..12faaf7 100644 --- a/src/main/java/com/floralquafloral/registries/states/action/baseactions/airborne/Backflip.java +++ b/src/main/java/com/floralquafloral/registries/states/action/baseactions/airborne/Backflip.java @@ -4,15 +4,13 @@ import com.floralquafloral.mariodata.moveable.MarioTravelData; import com.floralquafloral.stats.CharaStat; import com.floralquafloral.stats.StatCategory; -import com.floralquafloral.util.AsymmetricalEasing; -import com.floralquafloral.util.Easings; import net.minecraft.util.Identifier; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.List; -import static com.floralquafloral.util.AsymmetricalEasing.*; +import static com.floralquafloral.util.MixedEasing.*; public class Backflip extends Jump { @Override public @NotNull Identifier getID() { @@ -25,7 +23,7 @@ public class Backflip extends Jump { return new CameraAnimationSet( new CameraAnimation( false, 1.0F, - (progress, offsets) -> offsets[1] = asymmetricEase(progress, easeInOutSine, easeInOutCubic) * -360 + (progress, offsets) -> offsets[1] = mixedEase(progress, SINE, CUBIC) * -360 ), null, null 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 571ebf7..2002eb8 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 @@ -31,13 +31,13 @@ public void populateStatModifiers(Map, Double> modifiers) { modifiers.put(Set.of(DRAG), 0.4); } - @Override - public float getWidthFactor() { + @Override public int getBumpStrengthModifier() { + return 0; + } + @Override public float getWidthFactor() { return 1.0F; } - - @Override - public float getHeightFactor() { + @Override public float getHeightFactor() { return 1.0F; } 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 2a11eb0..1b9349f 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 @@ -17,13 +17,13 @@ public void populateStatModifiers(Map, Double> modifiers) { } - @Override - public float getWidthFactor() { + @Override public int getBumpStrengthModifier() { + return 0; + } + @Override public float getWidthFactor() { return 1.0F; } - - @Override - public float getHeightFactor() { + @Override public float getHeightFactor() { return 1.0F; } 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 c99eeb3..ab2f048 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 @@ -17,13 +17,13 @@ public void populateStatModifiers(Map, Double> modifiers) { } - @Override - public float getWidthFactor() { + @Override public int getBumpStrengthModifier() { + return 0; + } + @Override public float getWidthFactor() { return 1.0F; } - - @Override - public float getHeightFactor() { + @Override public float getHeightFactor() { return 1.0F; } 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 59c5e97..06dee7a 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 @@ -29,6 +29,9 @@ public void serverTick(MarioServerData data) { } + @Override public int getBumpStrengthModifier() { + return -1; + } @Override public float getWidthFactor() { return 1.0F; } 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 c970a22..d50a676 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 @@ -29,6 +29,9 @@ public void serverTick(MarioServerData data) { } + @Override public int getBumpStrengthModifier() { + return 0; + } @Override public float getWidthFactor() { return 1.0F; } diff --git a/src/main/java/com/floralquafloral/util/AsymmetricalEasing.java b/src/main/java/com/floralquafloral/util/AsymmetricalEasing.java deleted file mode 100644 index 84fdb7d..0000000 --- a/src/main/java/com/floralquafloral/util/AsymmetricalEasing.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.floralquafloral.util; - -import static java.lang.Math.*; - -// https://easings.net/ -// https://gist.github.com/dev-hydrogen/21a66f83f0386123e0c0acf107254843 -public enum AsymmetricalEasing { - easeInSine(x -> 1 - cos(x * PI) / 2), - easeOutSine(x -> sin(x * PI / 2)), - easeInOutSine(x -> -(cos(PI * x) - 1) / 2), - easeInQuad(x -> x * x), - easeOutQuad(x -> 1 - (1 - x) * (1 - x)), - easeInOutQuad(x -> x < 0.5 ? 2 * x * x : 1 - pow(-2 * x + 2, 2) / 2), - easeInCubic(x -> x * x * x), - easeOutCubic(x -> 1 - pow(1 - x, 3)), - easeInOutCubic(x -> x < 0.5 ? 4 * x * x * x : 1 - pow(-2 * x + 2, 3) / 2), - easeInQuart(x -> x * x * x * x), - easeOutQuart(x -> 1 - pow(1 - x, 4)), - easeInOutQuart(x -> x < 0.5 ? 8 * x * x * x * x : 1 - pow(-2 * x + 2, 4) / 2), - easeInQuint(x -> x * x * x * x * x), - easeOutQuint(x -> 1 - pow(1 - x, 5)), - easeInOutQuint(x -> x < 0.5 ? 16 * x * x * x * x * x : 1 - pow(-2 * x + 2, 5) / 2), - easeInExpo(x -> x == 0 ? 0 : pow(2, 10 * x - 10)), - easeOutExpo(x -> x == 1 ? 1 : 1 - pow(2, -10 * x)), - easeInOutExpo(x -> x == 0 ? 0 : x == 1 ? 1 : x < 0.5 ? pow(2, 20 * x - 10) / 2 : (2 - pow(2, -20 * x + 10)) / 2), - easeInCirc(x -> 1 - sqrt(1 - pow(x, 2))), - easeOutCirc(x -> sqrt(1 - pow(x - 1, 2))), - easeInOutCirc(x -> x < 0.5 ? (1 - sqrt(1 - pow(2 * x, 2))) / 2 : (sqrt(1 - pow(-2 * x + 2, 2)) + 1) / 2), - easeInBack(x -> 2.70158 * x * x * x - 1.70158 * x * x), - easeOutBack(x -> 1 + 2.70158 * pow(x - 1, 3) + 1.70158 * pow(x - 1, 2)), - easeInOutBack(x -> x < 0.5 ? (pow(2 * x, 2) * ((1.70158 * 1.525 + 1) * 2 * x - 1.70158 * 1.525)) / 2 : (pow(2 * x - 2, 2) * ((1.70158 * 1.525 + 1) * (x * 2 - 2) + 1.70158 * 1.525) + 2) / 2), - easeInElastic(x -> x == 0 ? 0 : x == 1 ? 1 : -pow(2, 10 * x - 10) * sin((x * 10 - 10.75) * ((2 * PI) / 3))), - easeOutElastic(x -> x == 0 ? 0 : x == 1 ? 1 : pow(2, -10 * x) * sin((x * 10 - 0.75) * ((2 * PI) / 3)) + 1), - easeInOutElastic(x -> x == 0 ? 0 : x == 1 ? 1 : x < 0.5 ? -(pow(2, 20 * x - 10) * sin((20 * x - 11.125) * ((2 * PI) / 4.5))) / 2 : (pow(2, -20 * x + 10) * sin((20 * x - 11.125) * ((2 * PI) / 4.5))) / 2 + 1); - - @FunctionalInterface - private interface EasingFunction { - double ease(double x); - } - - final EasingFunction FUNCTION; - AsymmetricalEasing(EasingFunction function) { - this.FUNCTION = function; - } - - public static float asymmetricEase(float x, AsymmetricalEasing first, AsymmetricalEasing second) { - return (float) (x < 0.5 ? first.FUNCTION.ease(x) : second.FUNCTION.ease(x)); - } -} \ No newline at end of file diff --git a/src/main/java/com/floralquafloral/util/ClientSoundPlayer.java b/src/main/java/com/floralquafloral/util/ClientSoundPlayer.java deleted file mode 100644 index 5e7d41c..0000000 --- a/src/main/java/com/floralquafloral/util/ClientSoundPlayer.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.floralquafloral.util; - -import com.floralquafloral.mariodata.MarioData; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.sound.PositionedSoundInstance; -import net.minecraft.client.sound.SoundManager; -import net.minecraft.entity.Entity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.sound.SoundCategory; -import net.minecraft.sound.SoundEvent; -import net.minecraft.util.math.random.Random; - -@SuppressWarnings("UnusedReturnValue") -public abstract class ClientSoundPlayer { - public static final SoundManager SOUND_MANAGER = MinecraftClient.getInstance().getSoundManager(); - - public static PositionedSoundInstance playSound(SoundEvent event, SoundCategory category, double x, double y, double z, float volume, float pitch, long seed) { - PositionedSoundInstance sound = new PositionedSoundInstance( - event, - category, - volume, - pitch, - Random.create(seed), - x, - y, - z - ); - SOUND_MANAGER.play(sound); - return sound; - } - - public static PositionedSoundInstance playSound(SoundEvent event, SoundCategory category, Entity entity, float volume, float pitch, long seed) { - return playSound(event, category, entity.getX(), entity.getY(), entity.getZ(), volume, pitch, seed); - } - - public static PositionedSoundInstance playSound(SoundEvent event, MarioData data, float volume, float pitch, long seed) { - return playSound(event, SoundCategory.PLAYERS, data.getMario(), volume, pitch, seed); - } - - public static PositionedSoundInstance playSound(SoundEvent event, MarioData data, long seed) { - return playSound(event, data, 1.0F, 1.0F, seed); - } - - public static void kill(PositionedSoundInstance sound) { - SOUND_MANAGER.stop(sound); - } -} diff --git a/src/main/java/com/floralquafloral/util/JumpSoundPlayer.java b/src/main/java/com/floralquafloral/util/JumpSoundPlayer.java index 025ab2b..4a83813 100644 --- a/src/main/java/com/floralquafloral/util/JumpSoundPlayer.java +++ b/src/main/java/com/floralquafloral/util/JumpSoundPlayer.java @@ -2,6 +2,7 @@ import com.floralquafloral.MarioPackets; import com.floralquafloral.MarioQuaMario; +import com.floralquafloral.mariodata.MarioClientSideData; import com.floralquafloral.mariodata.MarioData; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry; @@ -23,16 +24,6 @@ import static com.floralquafloral.mariodata.MarioDataManager.getMarioData; public class JumpSoundPlayer { - public static void registerPackets() { - FadeJumpSoundS2CPayload.register(); - FadeJumpSoundC2SPayload.register(); - - FadeJumpSoundC2SPayload.registerReceiver(); - } - public static void registerPacketsClient() { - FadeJumpSoundS2CPayload.registerReceiver(); - } - private static final Set FADING_JUMPS = new HashSet<>(); private static class JumpSoundInstance extends PositionedSoundInstance implements TickableSoundInstance { @@ -58,55 +49,15 @@ public void tick() { public static void playJumpSfx(SoundEvent event, MarioData data, long seed) { PlayerEntity mario = data.getMario(); - ClientSoundPlayer.SOUND_MANAGER.play(new JumpSoundInstance(event, mario, seed)); + MarioClientSideData.SOUND_MANAGER.play(new JumpSoundInstance(event, mario, seed)); } public static void playJumpSfx(MarioData data, long seed) { playJumpSfx(MarioSFX.JUMP, data, seed); } public static void fadeJumpSfx(PlayerEntity mario) { FADING_JUMPS.add(mario); -// if(mario.isMainPlayer()) ClientPlayNetworking.send(new FadeJumpSoundC2SPayload()); } public static void fadeJumpSfx(MarioData data) { fadeJumpSfx(data.getMario()); } - - private record FadeJumpSoundC2SPayload() implements CustomPayload { - public static final Id ID = new Id<>(Identifier.of(MarioQuaMario.MOD_ID, "fade_jump_c2s")); - 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())) - ); - } - - @Override public Id getId() { - return ID; - } - public static void register() { - PayloadTypeRegistry.playC2S().register(ID, CODEC); - } - } - - private record FadeJumpSoundS2CPayload(int player) implements CustomPayload { - public static final Id ID = new Id<>(Identifier.of(MarioQuaMario.MOD_ID, "fade_jump_s2c")); - public static final PacketCodec CODEC = PacketCodec.tuple( - PacketCodecs.INTEGER, FadeJumpSoundS2CPayload::player, - FadeJumpSoundS2CPayload::new - ); - public FadeJumpSoundS2CPayload(PlayerEntity player) { - this(player.getId()); - } - public static void registerReceiver() { - ClientPlayNetworking.registerGlobalReceiver(ID, (payload, context) -> - FADING_JUMPS.add(MarioPackets.getPlayerFromInt(context, payload.player))); - } - - @Override public Id getId() { - return ID; - } - public static void register() { - PayloadTypeRegistry.playS2C().register(ID, CODEC); - } - } } diff --git a/src/main/java/com/floralquafloral/util/MixedEasing.java b/src/main/java/com/floralquafloral/util/MixedEasing.java new file mode 100644 index 0000000..59ae654 --- /dev/null +++ b/src/main/java/com/floralquafloral/util/MixedEasing.java @@ -0,0 +1,31 @@ +package com.floralquafloral.util; + +import static java.lang.Math.*; + +// https://easings.net/ +// https://gist.github.com/dev-hydrogen/21a66f83f0386123e0c0acf107254843 +public enum MixedEasing { + SINE(x -> -(cos(PI * x) - 1) / 2), + QUAD(x -> x < 0.5 ? 2 * x * x : 1 - pow(-2 * x + 2, 2) / 2), + CUBIC(x -> x < 0.5 ? 4 * x * x * x : 1 - pow(-2 * x + 2, 3) / 2), + QUART(x -> x < 0.5 ? 8 * x * x * x * x : 1 - pow(-2 * x + 2, 4) / 2), + QUINT(x -> x < 0.5 ? 16 * x * x * x * x * x : 1 - pow(-2 * x + 2, 5) / 2), + EXPONENTIAL(x -> x == 0 ? 0 : x == 1 ? 1 : x < 0.5 ? pow(2, 20 * x - 10) / 2 : (2 - pow(2, -20 * x + 10)) / 2), + CIRCLE(x -> x < 0.5 ? (1 - sqrt(1 - pow(2 * x, 2))) / 2 : (sqrt(1 - pow(-2 * x + 2, 2)) + 1) / 2), + BACK(x -> x < 0.5 ? (pow(2 * x, 2) * ((1.70158 * 1.525 + 1) * 2 * x - 1.70158 * 1.525)) / 2 : (pow(2 * x - 2, 2) * ((1.70158 * 1.525 + 1) * (x * 2 - 2) + 1.70158 * 1.525) + 2) / 2), + ELASTIC(x -> x == 0 ? 0 : x == 1 ? 1 : x < 0.5 ? -(pow(2, 20 * x - 10) * sin((20 * x - 11.125) * ((2 * PI) / 4.5))) / 2 : (pow(2, -20 * x + 10) * sin((20 * x - 11.125) * ((2 * PI) / 4.5))) / 2 + 1); + + @FunctionalInterface + private interface EasingFunction { + double ease(double x); + } + + final EasingFunction FUNCTION; + MixedEasing(EasingFunction function) { + this.FUNCTION = function; + } + + public static float mixedEase(float x, MixedEasing first, MixedEasing second) { + return (float) (x < 0.5 ? first.FUNCTION.ease(x) : second.FUNCTION.ease(x)); + } +} \ No newline at end of file