feat(validation): add GlbValidationReloadListener — validates GLBs on resource reload
This commit is contained in:
@@ -118,6 +118,10 @@ public final class GltfClientSetup {
|
||||
LOGGER.info(
|
||||
"[GltfPipeline] Data-driven item reload listener registered"
|
||||
);
|
||||
|
||||
// GLB structural validation (runs after item definitions are loaded)
|
||||
event.registerReloadListener(new com.tiedup.remake.client.gltf.diagnostic.GlbValidationReloadListener());
|
||||
LOGGER.info("[GltfPipeline] GLB validation reload listener registered");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
package com.tiedup.remake.client.gltf.diagnostic;
|
||||
|
||||
import com.tiedup.remake.v2.bondage.datadriven.DataDrivenItemDefinition;
|
||||
import com.tiedup.remake.v2.bondage.datadriven.DataDrivenItemRegistry;
|
||||
import java.io.InputStream;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.packs.resources.Resource;
|
||||
import net.minecraft.server.packs.resources.ResourceManager;
|
||||
import net.minecraft.server.packs.resources.SimplePreparableReloadListener;
|
||||
import net.minecraft.util.profiling.ProfilerFiller;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
/**
|
||||
* Reload listener that validates all data-driven item GLB models on resource
|
||||
* reload (F3+T or startup).
|
||||
*
|
||||
* <p>Must be registered AFTER {@link com.tiedup.remake.v2.bondage.datadriven.DataDrivenItemReloadListener}
|
||||
* so that the item registry is populated before validation runs.</p>
|
||||
*
|
||||
* <p>On each reload:
|
||||
* <ol>
|
||||
* <li>Clears the {@link GlbDiagnosticRegistry}</li>
|
||||
* <li>Iterates all {@link DataDrivenItemDefinition}s</li>
|
||||
* <li>For each definition with a model location, attempts to open the GLB
|
||||
* resource and runs {@link GlbValidator#validate} on it</li>
|
||||
* <li>Records results into the diagnostic registry and logs a summary</li>
|
||||
* </ol>
|
||||
*/
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public class GlbValidationReloadListener
|
||||
extends SimplePreparableReloadListener<Void>
|
||||
{
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger("GltfValidation");
|
||||
|
||||
@Override
|
||||
protected Void prepare(
|
||||
ResourceManager resourceManager,
|
||||
ProfilerFiller profiler
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void apply(
|
||||
Void nothing,
|
||||
ResourceManager resourceManager,
|
||||
ProfilerFiller profiler
|
||||
) {
|
||||
GlbDiagnosticRegistry.clear();
|
||||
|
||||
Collection<DataDrivenItemDefinition> definitions =
|
||||
DataDrivenItemRegistry.getAll();
|
||||
|
||||
if (definitions.isEmpty()) {
|
||||
LOGGER.warn(
|
||||
"[GltfValidation] No data-driven item definitions found — skipping GLB validation"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
int passed = 0;
|
||||
int withWarnings = 0;
|
||||
int withErrors = 0;
|
||||
|
||||
for (DataDrivenItemDefinition def : definitions) {
|
||||
ResourceLocation modelLoc = def.modelLocation();
|
||||
if (modelLoc == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Optional<Resource> resourceOpt =
|
||||
resourceManager.getResource(modelLoc);
|
||||
|
||||
if (resourceOpt.isEmpty()) {
|
||||
// GLB file not found in any resource pack
|
||||
GlbValidationResult missingResult = GlbValidationResult.of(
|
||||
modelLoc,
|
||||
List.of(new GlbDiagnostic(
|
||||
modelLoc,
|
||||
def.id(),
|
||||
GlbDiagnostic.Severity.ERROR,
|
||||
"MISSING_GLB",
|
||||
"GLB file not found: " + modelLoc
|
||||
+ " (referenced by item " + def.id() + ")"
|
||||
))
|
||||
);
|
||||
GlbDiagnosticRegistry.addResult(missingResult);
|
||||
withErrors++;
|
||||
continue;
|
||||
}
|
||||
|
||||
try (InputStream stream = resourceOpt.get().open()) {
|
||||
GlbValidationResult result =
|
||||
GlbValidator.validate(stream, modelLoc);
|
||||
GlbDiagnosticRegistry.addResult(result);
|
||||
|
||||
if (!result.passed()) {
|
||||
withErrors++;
|
||||
} else if (hasWarnings(result)) {
|
||||
withWarnings++;
|
||||
} else {
|
||||
passed++;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
GlbValidationResult errorResult = GlbValidationResult.of(
|
||||
modelLoc,
|
||||
List.of(new GlbDiagnostic(
|
||||
modelLoc,
|
||||
def.id(),
|
||||
GlbDiagnostic.Severity.ERROR,
|
||||
"GLB_READ_ERROR",
|
||||
"Failed to read GLB file: " + e.getMessage()
|
||||
))
|
||||
);
|
||||
GlbDiagnosticRegistry.addResult(errorResult);
|
||||
withErrors++;
|
||||
}
|
||||
}
|
||||
|
||||
int total = passed + withWarnings + withErrors;
|
||||
LOGGER.info(
|
||||
"[GltfValidation] Validated {} GLBs: {} passed, {} with warnings, {} with errors",
|
||||
total, passed, withWarnings, withErrors
|
||||
);
|
||||
}
|
||||
|
||||
private static boolean hasWarnings(GlbValidationResult result) {
|
||||
return result.diagnostics().stream()
|
||||
.anyMatch(d -> d.severity() == GlbDiagnostic.Severity.WARNING);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user