/* * Decompiled with CFR 0.152. */ package net.minecraft.util; import java.util.ArrayList; import java.util.List; import java.util.Optional; import net.minecraft.util.EasingType; import net.minecraft.util.Keyframe; import net.minecraft.util.KeyframeTrack; import net.minecraft.world.attribute.LerpFunction; public class KeyframeTrackSampler { private final Optional periodTicks; private final LerpFunction lerp; private final List> segments; KeyframeTrackSampler(KeyframeTrack track, Optional periodTicks, LerpFunction lerp) { this.periodTicks = periodTicks; this.lerp = lerp; this.segments = KeyframeTrackSampler.bakeSegments(track, periodTicks); } private static List> bakeSegments(KeyframeTrack track, Optional periodTicks) { List> keyframes = track.keyframes(); if (keyframes.size() == 1) { T value = keyframes.getFirst().value(); return List.of(new Segment(EasingType.CONSTANT, value, 0, value, 0)); } ArrayList> segments = new ArrayList>(); if (periodTicks.isPresent()) { Keyframe firstKeyframe = keyframes.getFirst(); Keyframe lastKeyframe = keyframes.getLast(); segments.add(new Segment(track, lastKeyframe, lastKeyframe.ticks() - periodTicks.get(), firstKeyframe, firstKeyframe.ticks())); KeyframeTrackSampler.addSegmentsFromKeyframes(track, keyframes, segments); segments.add(new Segment(track, lastKeyframe, lastKeyframe.ticks(), firstKeyframe, firstKeyframe.ticks() + periodTicks.get())); } else { KeyframeTrackSampler.addSegmentsFromKeyframes(track, keyframes, segments); } return List.copyOf(segments); } private static void addSegmentsFromKeyframes(KeyframeTrack track, List> keyframes, List> output) { for (int i = 0; i < keyframes.size() - 1; ++i) { Keyframe keyframe = keyframes.get(i); Keyframe nextKeyframe = keyframes.get(i + 1); output.add(new Segment(track, keyframe, keyframe.ticks(), nextKeyframe, nextKeyframe.ticks())); } } public T sample(long ticks) { long sampleTicks = this.loopTicks(ticks); Segment segment = this.getSegmentAt(sampleTicks); if (sampleTicks <= (long)segment.fromTicks) { return segment.fromValue; } if (sampleTicks >= (long)segment.toTicks) { return segment.toValue; } float alpha = (float)(sampleTicks - (long)segment.fromTicks) / (float)(segment.toTicks - segment.fromTicks); float easedAlpha = segment.easing.apply(alpha); return this.lerp.apply(easedAlpha, segment.fromValue, segment.toValue); } private Segment getSegmentAt(long currentTicks) { for (Segment segment : this.segments) { if (currentTicks >= (long)segment.toTicks) continue; return segment; } return this.segments.getLast(); } private long loopTicks(long ticks) { if (this.periodTicks.isPresent()) { return Math.floorMod(ticks, (int)this.periodTicks.get()); } return ticks; } private record Segment(EasingType easing, T fromValue, int fromTicks, T toValue, int toTicks) { public Segment(KeyframeTrack track, Keyframe from, int fromTicks, Keyframe to, int toTicks) { this(track.easingType(), from.value(), fromTicks, to.value(), toTicks); } } }