From b2b666ced22f631e6c102e891e4480b8d68cd055 Mon Sep 17 00:00:00 2001
From: Emily <emilia.lopezf.1999@gmail.com>
Date: Thu, 9 Feb 2023 14:30:30 -0300
Subject: [PATCH] Fix `Tick::addTo`/`::between` causing SOE (#8824)

---
 patches/api/Add-Tick-TemporalUnit.patch | 28 ++++++++++++++++++++++---
 1 file changed, 25 insertions(+), 3 deletions(-)

diff --git a/patches/api/Add-Tick-TemporalUnit.patch b/patches/api/Add-Tick-TemporalUnit.patch
index 8ee55f8f4f..e5d3ae790d 100644
--- a/patches/api/Add-Tick-TemporalUnit.patch
+++ b/patches/api/Add-Tick-TemporalUnit.patch
@@ -16,6 +16,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +import org.jetbrains.annotations.NotNull;
 +
 +import java.time.Duration;
++import java.time.temporal.ChronoUnit;
 +import java.time.temporal.Temporal;
 +import java.time.temporal.TemporalUnit;
 +import java.util.Objects;
@@ -68,7 +69,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +     */
 +    public int fromDuration(@NotNull Duration duration) {
 +        Objects.requireNonNull(duration, "duration cannot be null");
-+        return Math.toIntExact(Math.floorDiv(duration.toMillis(), INSTANCE.milliseconds));
++        return Math.toIntExact(Math.floorDiv(duration.toMillis(), this.milliseconds));
 +    }
 +
 +    @Override
@@ -96,12 +97,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    @SuppressWarnings("unchecked") // following ChronoUnit#addTo
 +    @Override
 +    public <R extends Temporal> @NotNull R addTo(@NotNull R temporal, long amount) {
-+        return (R) temporal.plus(amount, this);
++        return (R) temporal.plus(getDuration().multipliedBy(amount));
 +    }
 +
 +    @Override
 +    public long between(@NotNull Temporal start, @NotNull Temporal end) {
-+        return start.until(end, this);
++        return start.until(end, ChronoUnit.MILLIS) / this.milliseconds;
 +    }
 +}
 diff --git a/src/test/java/io/papermc/paper/util/TickTest.java b/src/test/java/io/papermc/paper/util/TickTest.java
@@ -113,6 +114,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +package io.papermc.paper.util;
 +
 +import java.time.Duration;
++import java.time.Instant;
++import java.time.temporal.ChronoUnit;
++
 +import org.junit.Test;
 +
 +import static org.junit.Assert.assertEquals;
@@ -132,4 +136,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        assertEquals(1, Tick.tick().fromDuration(Duration.ofMillis(60)));
 +        assertEquals(2, Tick.tick().fromDuration(Duration.ofMillis(100)));
 +    }
++
++    @Test
++    public void testAddTickToInstant() {
++        Instant now = Instant.now();
++        assertEquals(now, now.plus(0, Tick.tick()));
++        assertEquals(now.plus(50, ChronoUnit.MILLIS), now.plus(1, Tick.tick()));
++        assertEquals(now.plus(100, ChronoUnit.MILLIS), now.plus(2, Tick.tick()));
++        assertEquals(now.plus(150, ChronoUnit.MILLIS), now.plus(3, Tick.tick()));
++    }
++
++    @Test
++    public void testTicksBetweenInstants() {
++        Instant now = Instant.now();
++        assertEquals(0, now.until(now.plus(20, ChronoUnit.MILLIS), Tick.tick()));
++        assertEquals(1, now.until(now.plus(50, ChronoUnit.MILLIS), Tick.tick()));
++        assertEquals(1, now.until(now.plus(60, ChronoUnit.MILLIS), Tick.tick()));
++        assertEquals(2, now.until(now.plus(100, ChronoUnit.MILLIS), Tick.tick()));
++    }
 +}