fix: Improve exception logging for entity widgets

This commit is contained in:
Linnea Gräf
2024-11-13 15:44:04 +01:00
parent 57cdcb21ec
commit 59566bcab8
4 changed files with 69 additions and 50 deletions

View File

@@ -10,9 +10,10 @@ import net.minecraft.client.gui.Element
import net.minecraft.client.gui.ParentElement import net.minecraft.client.gui.ParentElement
import net.minecraft.entity.LivingEntity import net.minecraft.entity.LivingEntity
import moe.nea.firmament.gui.entity.EntityRenderer import moe.nea.firmament.gui.entity.EntityRenderer
import moe.nea.firmament.util.ErrorUtil
class EntityWidget(val entity: LivingEntity, val point: Point) : WidgetWithBounds() { class EntityWidget(val entity: LivingEntity?, val point: Point) : WidgetWithBounds() {
override fun children(): List<Element> { override fun children(): List<Element> {
return emptyList() return emptyList()
} }
@@ -22,9 +23,9 @@ class EntityWidget(val entity: LivingEntity, val point: Point) : WidgetWithBound
override fun render(context: DrawContext, mouseX: Int, mouseY: Int, delta: Float) { override fun render(context: DrawContext, mouseX: Int, mouseY: Int, delta: Float) {
try { try {
if (!hasErrored) if (!hasErrored)
EntityRenderer.renderEntity(entity, context, point.x, point.y, mouseX.toFloat(), mouseY.toFloat()) EntityRenderer.renderEntity(entity!!, context, point.x, point.y, mouseX.toFloat(), mouseY.toFloat())
} catch (ex: Exception) { } catch (ex: Exception) {
EntityRenderer.logger.error("Failed to render constructed entity: $entity", ex) ErrorUtil.softError("Failed to render constructed entity: $entity", ex)
hasErrored = true hasErrored = true
} }
if (hasErrored) { if (hasErrored) {

View File

@@ -39,7 +39,6 @@ class SBMobDropRecipe(override val neuRecipe: NEUMobDropRecipe) : SBRecipe() {
} else { } else {
EntityRenderer.applyModifiers(source, listOf()) EntityRenderer.applyModifiers(source, listOf())
} }
if (entity != null) {
val level = display.neuRecipe.level val level = display.neuRecipe.level
val fullMobName = val fullMobName =
if (level > 0) Text.translatable("firmament.recipe.mobs.name", level, display.neuRecipe.name) if (level > 0) Text.translatable("firmament.recipe.mobs.name", level, display.neuRecipe.name)
@@ -76,7 +75,6 @@ class SBMobDropRecipe(override val neuRecipe: NEUMobDropRecipe) : SBRecipe() {
tt tt
) )
) )
}
add( add(
Widgets.createLabel(Point(bounds.minX + 15, bounds.minY + 5), Text.literal(display.neuRecipe.name)) Widgets.createLabel(Point(bounds.minX + 15, bounds.minY + 5), Text.literal(display.neuRecipe.name))
.leftAligned() .leftAligned()

View File

@@ -3,7 +3,6 @@ package moe.nea.firmament.gui.entity
import com.google.gson.Gson import com.google.gson.Gson
import com.google.gson.JsonArray import com.google.gson.JsonArray
import com.google.gson.JsonObject import com.google.gson.JsonObject
import org.apache.logging.log4j.LogManager
import org.joml.Quaternionf import org.joml.Quaternionf
import org.joml.Vector3f import org.joml.Vector3f
import kotlin.math.atan import kotlin.math.atan
@@ -15,8 +14,8 @@ import net.minecraft.entity.LivingEntity
import net.minecraft.entity.SpawnReason import net.minecraft.entity.SpawnReason
import net.minecraft.util.Identifier import net.minecraft.util.Identifier
import net.minecraft.world.World import net.minecraft.world.World
import moe.nea.firmament.util.ErrorUtil
import moe.nea.firmament.util.MC import moe.nea.firmament.util.MC
import moe.nea.firmament.util.assertNotNullOr
import moe.nea.firmament.util.iterate import moe.nea.firmament.util.iterate
import moe.nea.firmament.util.openFirmamentResource import moe.nea.firmament.util.openFirmamentResource
import moe.nea.firmament.util.render.enableScissorWithTranslation import moe.nea.firmament.util.render.enableScissorWithTranslation
@@ -76,18 +75,15 @@ object EntityRenderer {
"name" to ModifyName, "name" to ModifyName,
) )
val logger = LogManager.getLogger("Firmament.Entity")
fun applyModifiers(entityId: String, modifiers: List<JsonObject>): LivingEntity? { fun applyModifiers(entityId: String, modifiers: List<JsonObject>): LivingEntity? {
val entityType = assertNotNullOr(entityIds[entityId]) { val entityType = ErrorUtil.notNullOr(entityIds[entityId], "Could not create entity with id $entityId") {
logger.error("Could not create entity with id $entityId")
return null return null
} }
var entity = entityType() var entity = ErrorUtil.catch("") { entityType() }.or { return null }
for (modifierJson in modifiers) { for (modifierJson in modifiers) {
val modifier = assertNotNullOr(modifierJson["type"]?.asString?.let(entityModifiers::get)) { val modifier = ErrorUtil.notNullOr(
logger.error("Unknown modifier $modifierJson") modifierJson["type"]?.asString?.let(entityModifiers::get),
return null "Could not create entity with id $entityId. Failed to apply modifier $modifierJson") { return null }
}
entity = modifier.apply(entity, modifierJson) entity = modifier.apply(entity, modifierJson)
} }
return entity return entity
@@ -95,8 +91,7 @@ object EntityRenderer {
fun constructEntity(info: JsonObject): LivingEntity? { fun constructEntity(info: JsonObject): LivingEntity? {
val modifiers = (info["modifiers"] as JsonArray?)?.map { it.asJsonObject } ?: emptyList() val modifiers = (info["modifiers"] as JsonArray?)?.map { it.asJsonObject } ?: emptyList()
val entityType = assertNotNullOr(info["entity"]?.asString) { val entityType = ErrorUtil.notNullOr(info["entity"]?.asString, "Missing entity type on entity object") {
logger.error("Missing entity type on entity object")
return null return null
} }
return applyModifiers(entityType, modifiers) return applyModifiers(entityType, modifiers)

View File

@@ -37,6 +37,31 @@ object ErrorUtil {
else Firmament.logger.error(message) else Firmament.logger.error(message)
} }
class Catch<T> private constructor(val value: T?, val exc: Throwable?) {
inline fun or(block: (exc: Throwable) -> T): T {
contract {
callsInPlace(block, InvocationKind.AT_MOST_ONCE)
}
if (exc != null) return block(exc)
@Suppress("UNCHECKED_CAST")
return value as T
}
companion object {
fun <T> fail(exception: Throwable): Catch<T> = Catch(null, exception)
fun <T> succeed(value: T): Catch<T> = Catch(value, null)
}
}
inline fun <T> catch(message: String, block: () -> T): Catch<T> {
try {
return Catch.succeed(block())
} catch (exc: Throwable) {
softError(message, exc)
return Catch.fail(exc)
}
}
inline fun <T : Any> notNullOr(nullable: T?, message: String, orElse: () -> T): T { inline fun <T : Any> notNullOr(nullable: T?, message: String, orElse: () -> T): T {
contract { contract {
callsInPlace(orElse, InvocationKind.AT_MOST_ONCE) callsInPlace(orElse, InvocationKind.AT_MOST_ONCE)