feature/gltf-pipeline-v2 #18

Merged
NotEvil merged 19 commits from feature/gltf-pipeline-v2 into develop 2026-04-17 02:07:45 +00:00
2 changed files with 142 additions and 0 deletions
Showing only changes of commit ca4cbcad12 - Show all commits

View File

@@ -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");
}
}

View File

@@ -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);
}
}