From 661ef813bba57ddb29b65ea3dfc56b1d88859e75 Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Tue, 28 Jan 2025 13:28:37 -0800 Subject: [PATCH] Add further information to thread check errors The entity data is more complete, which will help debug problems on Folia. --- .../moonrise/common/util/EntityUtil.java | 44 +++++++++++++++++++ .../moonrise/common/util/TickThread.java | 34 +++++++------- 2 files changed, 63 insertions(+), 15 deletions(-) create mode 100644 src/main/java/ca/spottedleaf/moonrise/common/util/EntityUtil.java diff --git a/src/main/java/ca/spottedleaf/moonrise/common/util/EntityUtil.java b/src/main/java/ca/spottedleaf/moonrise/common/util/EntityUtil.java new file mode 100644 index 0000000..db58052 --- /dev/null +++ b/src/main/java/ca/spottedleaf/moonrise/common/util/EntityUtil.java @@ -0,0 +1,44 @@ +package ca.spottedleaf.moonrise.common.util; + +import net.minecraft.world.entity.Entity; +import net.minecraft.world.phys.Vec3; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.List; + +public final class EntityUtil { + + private static final ThreadLocal THREE_DECIMAL_PLACES = ThreadLocal.withInitial(() -> { + return new DecimalFormat("#,##0.000"); + }); + + private static String formatVec(final Vec3 vec) { + final DecimalFormat format = THREE_DECIMAL_PLACES.get(); + + return "(" + format.format(vec.x) + "," + format.format(vec.y) + "," + format.format(vec.z) + ")"; + } + + private static String dumpEntityWithoutReferences(final Entity entity) { + if (entity == null) { + return "{null}"; + } + + return "{type=" + entity.getClass().getSimpleName() + ",id=" + entity.getId() + ",uuid=" + entity.getUUID() + ",pos=" + formatVec(entity.position()) + + ",mot=" + formatVec(entity.getDeltaMovement()) + ",aabb=" + entity.getBoundingBox() + ",removed=" + entity.getRemovalReason() + ",has_vehicle=" + (entity.getVehicle() != null) + + ",passenger_count=" + entity.getPassengers().size(); + } + + public static String dumpEntity(final Entity entity) { + final List passengers = entity.getPassengers(); + final List passengerStrings = new ArrayList<>(passengers.size()); + + for (final Entity passenger : passengers) { + passengerStrings.add("(" + dumpEntityWithoutReferences(passenger) + ")"); + } + + return "{root=[" + dumpEntityWithoutReferences(entity) + "], vehicle=[" + dumpEntityWithoutReferences(entity.getVehicle()) + + "], passengers=[" + String.join(",", passengerStrings) + "]"; + } + + private EntityUtil() {} +} diff --git a/src/main/java/ca/spottedleaf/moonrise/common/util/TickThread.java b/src/main/java/ca/spottedleaf/moonrise/common/util/TickThread.java index 157e5ed..69cdd30 100644 --- a/src/main/java/ca/spottedleaf/moonrise/common/util/TickThread.java +++ b/src/main/java/ca/spottedleaf/moonrise/common/util/TickThread.java @@ -15,21 +15,25 @@ public class TickThread extends Thread { private static final Logger LOGGER = LoggerFactory.getLogger(TickThread.class); + private static String getThreadContext() { + return "thread=" + Thread.currentThread().getName(); + } + /** * @deprecated */ @Deprecated public static void ensureTickThread(final String reason) { if (!isTickThread()) { - LOGGER.error("Thread " + Thread.currentThread().getName() + " failed main thread check: " + reason, new Throwable()); + LOGGER.error("Thread failed main thread check: " + reason + ", context=" + getThreadContext(), new Throwable()); throw new IllegalStateException(reason); } } public static void ensureTickThread(final Level world, final BlockPos pos, final String reason) { if (!isTickThreadFor(world, pos)) { - final String ex = "Thread " + Thread.currentThread().getName() + " failed main thread check: " + - reason + ", world=" + WorldUtil.getWorldName(world) + ", block_pos=" + pos; + final String ex = "Thread failed main thread check: " + + reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", block_pos=" + pos; LOGGER.error(ex, new Throwable()); throw new IllegalStateException(ex); } @@ -37,8 +41,8 @@ public static void ensureTickThread(final Level world, final BlockPos pos, final public static void ensureTickThread(final Level world, final BlockPos pos, final int blockRadius, final String reason) { if (!isTickThreadFor(world, pos, blockRadius)) { - final String ex = "Thread " + Thread.currentThread().getName() + " failed main thread check: " + - reason + ", world=" + WorldUtil.getWorldName(world) + ", block_pos=" + pos + ", block_radius=" + blockRadius; + final String ex = "Thread failed main thread check: " + + reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", block_pos=" + pos + ", block_radius=" + blockRadius; LOGGER.error(ex, new Throwable()); throw new IllegalStateException(ex); } @@ -46,8 +50,8 @@ public static void ensureTickThread(final Level world, final BlockPos pos, final public static void ensureTickThread(final Level world, final ChunkPos pos, final String reason) { if (!isTickThreadFor(world, pos)) { - final String ex = "Thread " + Thread.currentThread().getName() + " failed main thread check: " + - reason + ", world=" + WorldUtil.getWorldName(world) + ", chunk_pos=" + pos; + final String ex = "Thread failed main thread check: " + + reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", chunk_pos=" + pos; LOGGER.error(ex, new Throwable()); throw new IllegalStateException(ex); } @@ -55,8 +59,8 @@ public static void ensureTickThread(final Level world, final ChunkPos pos, final public static void ensureTickThread(final Level world, final int chunkX, final int chunkZ, final String reason) { if (!isTickThreadFor(world, chunkX, chunkZ)) { - final String ex = "Thread " + Thread.currentThread().getName() + " failed main thread check: " + - reason + ", world=" + WorldUtil.getWorldName(world) + ", chunk_pos=" + new ChunkPos(chunkX, chunkZ); + final String ex = "Thread failed main thread check: " + + reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", chunk_pos=" + new ChunkPos(chunkX, chunkZ); LOGGER.error(ex, new Throwable()); throw new IllegalStateException(ex); } @@ -64,8 +68,8 @@ public static void ensureTickThread(final Level world, final int chunkX, final i public static void ensureTickThread(final Entity entity, final String reason) { if (!isTickThreadFor(entity)) { - final String ex = "Thread " + Thread.currentThread().getName() + " failed main thread check: " + - reason + ", entity=" + entity; + final String ex = "Thread failed main thread check: " + + reason + ", context=" + getThreadContext() + ", entity=" + EntityUtil.dumpEntity(entity); LOGGER.error(ex, new Throwable()); throw new IllegalStateException(ex); } @@ -73,8 +77,8 @@ public static void ensureTickThread(final Entity entity, final String reason) { public static void ensureTickThread(final Level world, final AABB aabb, final String reason) { if (!isTickThreadFor(world, aabb)) { - final String ex = "Thread " + Thread.currentThread().getName() + " failed main thread check: " + - reason + ", world=" + WorldUtil.getWorldName(world) + ", aabb=" + aabb; + final String ex = "Thread failed main thread check: " + + reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", aabb=" + aabb; LOGGER.error(ex, new Throwable()); throw new IllegalStateException(ex); } @@ -82,8 +86,8 @@ public static void ensureTickThread(final Level world, final AABB aabb, final St public static void ensureTickThread(final Level world, final double blockX, final double blockZ, final String reason) { if (!isTickThreadFor(world, blockX, blockZ)) { - final String ex = "Thread " + Thread.currentThread().getName() + " failed main thread check: " + - reason + ", world=" + WorldUtil.getWorldName(world) + ", block_pos=" + new Vec3(blockX, 0.0, blockZ); + final String ex = "Thread failed main thread check: " + + reason + ", context=" + getThreadContext() + ", world=" + WorldUtil.getWorldName(world) + ", block_pos=" + new Vec3(blockX, 0.0, blockZ); LOGGER.error(ex, new Throwable()); throw new IllegalStateException(ex); }