Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: CI

# Every pull request runs the unit tests, the builder checks and the server game tests
# (`./gradlew check`), then the client GUI smoke test with and without JEI.
# Every pull request runs the unit tests and the server game tests (`./gradlew check`), then the
# client GUI smoke test with and without JEI.
on:
pull_request:
push:
Expand Down
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,14 @@ tasks.configureEach { task ->
if (task.name == 'runData') task.finalizedBy(refreshDataResources)
if (task.name == 'jar' || task.name == 'jarJar' || task.name == 'javadoc' || task.name.startsWith('verify')
|| task.name.startsWith('test')
|| task.name in ['compileTestJava', 'compileBuilderTestJava', 'compileRuntimeTestJava',
|| task.name in ['compileTestJava', 'compileRuntimeTestJava',
'writeMinecraftClasspathJunit', 'writeMinecraftClasspathClient', 'writeMinecraftClasspathServer',
'runClient', 'runServer', 'runGameTestServer']) {
task.mustRunAfter(refreshDataResources)
}
}

// Verification tasks (verify*, test source sets); run with `./gradlew check`.
// Verification tasks (verify*, tests); run with `./gradlew check`.
apply from: 'gradle/verification.gradle'

// Runtime GUI smoke tests compile optional JEI hooks without requiring JEI at runtime.
Expand Down
2 changes: 1 addition & 1 deletion docs/block-builder.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,6 @@ conflicting embedded names fail. Properties are nested under `properties`.
The paired item uses ItemTemplate.CODEC; custom shapes/state-dependent properties
and specialized block classes remain content-factory concerns.

`verifyBlockBuilder` runs with Gradle check/build, testing chain isolation,
`BlockBuilderTest` (JUnit, part of `./gradlew check`) tests chain isolation,
material/item binding, validation, and JSON/NBT round trips. The overall material
loading and object-registration pipeline remains unfinished.
2 changes: 1 addition & 1 deletion docs/definition-loading.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ runtime registrar. Machine and custom world-entity wiring still uses its dedicat
factory APIs. See [the playable vanilla example](vanilla-extensions.md). This stage does not discover enabled world datapacks or add registry IDs on
ordinary datapack reload.

`verifyDefinitionLoader` checks cross-mod module and handler references, delayed
`DefinitionLoaderTest` (JUnit) checks cross-mod module and handler references, delayed
material decoding, namespace/nested IDs, optional-mod filtering, duplicate IDs,
malformed files, immutable results, reversed source order, and mounted ZIP paths.
Lifecycle placement is checked against the pinned loader sources; an actual
Expand Down
2 changes: 1 addition & 1 deletion docs/entity-builder.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ placement rules, goals, and other relevant NeoForge registrations. Arrows/bolts
can implement this interface, including their own ammunition pickup and spawn
synchronization; no projectile-specific implementation is installed yet.

verifyEntityBuilder runs with check/build. It covers immutable material branches,
`EntityBuilderTest` (JUnit, part of `./gradlew check`) covers immutable material branches,
defensive factory data, codec round trips, factory lookup/class mismatch/errors,
and factory-specific settings validation. Actual spawning, persistence, rendering,
and type registration need verification in a running NeoForge instance.
2 changes: 1 addition & 1 deletion docs/fluid-builder.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,5 +70,5 @@ using deferred suppliers for their circular references. This builder does not
register fluids, provide runtime flow behavior, install renderers, generate tags,
or implement interaction callbacks. The startup loader now loads material plans, and RuntimeContentRegistrar applies their fluid families; see [the vanilla example](vanilla-extensions.md).

verifyFluidBuilder runs under check/build and covers material isolation, family
`FluidBuilderTest` (JUnit, part of `./gradlew check`) covers material isolation, family
IDs, validation, optional companion definitions, and JSON/NBT round trips.
2 changes: 1 addition & 1 deletion docs/item-builder.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,5 @@ No legacy numeric harvest level has been added. Future tool/block factories must
use the target Minecraft version's tag-based mining rules.

The checkout now targets Java 21 and NeoForge 21.1.247 for Minecraft 1.21.1.
`./gradlew check` runs verifyItemBuilder and verifyItemTemplate. StackContext NBT
`./gradlew check` runs the JUnit tests `ItemBuilderTest` and `ItemTemplateTest`. StackContext NBT
is stored in the CUSTOM_DATA component; it is not interpreted as legacy item NBT.
2 changes: 1 addition & 1 deletion docs/material-extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ still separate work. Planning and codec use do not instantiate game objects.
Existing direct MaterialContentPlanner calls plan standard parts; use
MaterialFactory to include registered extension types.

verifyMaterialExtensions tests dynamic type selections, excludes, optional mods,
`MaterialExtensionsTest` (JUnit) tests dynamic type selections, excludes, optional mods,
codec round trips, typed callback validation/dispatch, listener cleanup, deferred
creation boundaries, registry validation, and ID collisions. Actual game-object
registration, behaviors, and renderer effects require an in-game test.
Expand Down
2 changes: 1 addition & 1 deletion docs/material-factory.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ to execute the previous incomplete JSLT transform.
These operations create definitions, not registered Minecraft items/blocks,
fluids, or entity types. Concrete behavior factories, parent inheritance,
automatic mod-resource discovery, and the final registry/application stage remain
separate work. verifyMaterialFactory runs with check/build and covers exclusions,
separate work. `MaterialFactoryTest` (JUnit, part of `./gradlew check`) covers exclusions,
section validation, JSON/NBT round trips, material stats, optional-mod gates,
factory overrides, and identity binding.

Expand Down
2 changes: 1 addition & 1 deletion docs/method-events.md
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ A simple `registerEvent(name, Context.class)` accepts one `Context` argument by
default. Event contracts are extensible even though the initial player, weapon,
and tool contracts are bundled.

`verifyMethodEvents` checks real method resolution and invocation, caller-supplied
`MethodEventsTest` (JUnit) checks real method resolution and invocation, caller-supplied
class loaders, ID/material dispatch, multiple handlers for one type, error and
exception paths, failed-file atomicity, and JSON/NBT round trips. Built-in method
signatures are resolved without constructing a Minecraft world. In-game armor,
Expand Down
2 changes: 1 addition & 1 deletion docs/runtime-behaviors.md
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ block, and material definitions are dispatched by the runtime event bridge.
`StandardItems` by itself deliberately rejects ammunition instead of substituting
an item that cannot shoot.

verifyRuntimeBehavior checks dispatch classes without instantiating game objects,
`RuntimeBehaviorTest` (JUnit) checks dispatch classes without instantiating game objects,
material stat formulas, explicit tier tags, lazy repair resolution, and bundled tag
resources. The whole NeoForge project compiles and existing definition/codec/API
checks run alongside it. Scythe harvesting/protection, crackhammer processing and
Expand Down
2 changes: 1 addition & 1 deletion docs/vanilla-extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ asset JAR. The legacy `--minecraft-assets` argument is accepted but unused.
check all static parent/model/texture references, concrete model texture variables,
PNG headers, and animation metadata. `verifyStaticAssets` runs it during `check`.

`verifyVanillaExamples` loads the actual shipped files through `DefinitionLoader`,
`VanillaExamplesTest` (JUnit) loads the actual shipped files through `DefinitionLoader`,
checks every planned item/block has its packaged resources, verifies no unwanted
vanilla tool/armor duplicates, and round-trips the runtime references through
JSON/NBT and MaterialBuilder.
Expand Down
42 changes: 4 additions & 38 deletions gradle/verification.gradle
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
// Verification: the builderTest/runtimeTest source sets and every verify* task.
// Verification: the JUnit tests, the runtimeTest source set and every verify* task.
// All of it runs on `./gradlew check`; `build` only compiles and packages (see the end of this file).

sourceSets {
builderTest {
compileClasspath += sourceSets.main.output + sourceSets.test.compileClasspath
runtimeClasspath += sourceSets.main.output + sourceSets.test.runtimeClasspath
}
runtimeTest {
compileClasspath += sourceSets.main.output + sourceSets.test.compileClasspath
runtimeClasspath += sourceSets.main.output + sourceSets.test.runtimeClasspath
Expand Down Expand Up @@ -37,39 +33,9 @@ dependencies {
tasks.named('test', Test) {
useJUnitPlatform()
testLogging { events 'failed'; exceptionFormat 'full' }
}

// Standalone checks in src/builderTest, run as plain Java programs: task name -> main class
// (in zone.moddev.mc.lib.common.builders), plus any system properties the check reads.
def resources = file('src/main/resources').absolutePath
def builderChecks = [
verifyItemBuilder : ['ItemBuilderTest'],
verifyItemTemplate : ['ItemTemplateTest'],
verifyBlockBuilder : ['BlockBuilderTest'],
verifyEntityBuilder : ['EntityBuilderTest'],
verifyFluidBuilder : ['FluidBuilderTest'],
verifyMaterialParts : ['MaterialPartsTest'],
verifyMaterialFactory : ['MaterialFactoryTest'],
verifyMaterialExtensions: ['MaterialExtensionsTest'],
verifyRuntimeBehavior : ['RuntimeBehaviorTest', ['mmdlib.resources': resources]],
verifyDataModules : ['DataModulesTest'],
verifyLoadedParts : ['LoadedPartsTest'],
verifyBlockEntities : ['BlockEntitiesTest'],
verifyMethodEvents : ['MethodEventsTest'],
verifyDefinitionLoader : ['DefinitionLoaderTest'],
verifyScreens : ['zone.moddev.mc.lib.gui.ScreenLoaderTest'],
verifyVanillaExamples : ['VanillaExamplesTest', ['mmdlib.resources': resources,
'mmdlib.generated': file('src/generated/resources').absolutePath]],
]
builderChecks.each { name, spec ->
def check = tasks.register(name, JavaExec) {
group = 'verification'
dependsOn tasks.named('builderTestClasses')
classpath = sourceSets.builderTest.runtimeClasspath
mainClass = spec[0].contains('.') ? spec[0] : "zone.moddev.mc.lib.common.builders.${spec[0]}"
if (spec.size() > 1) systemProperties(spec[1])
}
tasks.named('check') { dependsOn check }
// VanillaExamplesTest and RuntimeBehaviorTest read the shipped definitions from disk.
systemProperty 'mmdlib.resources', file('src/main/resources').absolutePath
systemProperty 'mmdlib.generated', file('src/generated/resources').absolutePath
}

def verifyReleaseClasses = tasks.register('verifyReleaseClasses') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,14 @@
import net.minecraft.nbt.NbtOps;
import net.minecraft.resources.ResourceLocation;

import org.junit.jupiter.api.Test;

import zone.moddev.mc.lib.common.codecs.BlockTemplate;
import zone.moddev.mc.lib.common.parsers.BlockParser;

public final class BlockBuilderTest {
public static void main(String[] args) {
@Test
void buildsMaterialBlocksAndValidates() {
var root = BlockBuilder.create();
require(root == BlockBuilder.INSTANCE);
var template =
Expand Down Expand Up @@ -106,9 +109,6 @@ public static void main(String[] args) {
.parse(JsonOps.INSTANCE, JsonParser.parseString(invalid))
.error()
.isPresent());
System.out.println(
"Immutable material block builder, item binding, JSON/NBT codec, and validation checks"
+ " passed");
}

private static void require(boolean condition) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

import net.neoforged.neoforge.registries.DeferredRegister;

import org.junit.jupiter.api.Test;

import zone.moddev.mc.lib.api.MaterialExtensions;
import zone.moddev.mc.lib.common.codecs.MMDMaterialCodec;
import zone.moddev.mc.lib.common.factories.*;
Expand All @@ -36,7 +38,8 @@ static final class Other extends BlockEntity {
}
}

public static void main(String[] args) {
@Test
void plansMachineBlockEntitiesAndWorldEntities() {
var api = new MaterialExtensions(false);
var module =
DataModules.Block.CODEC
Expand Down Expand Up @@ -228,18 +231,15 @@ public Machine create(
var binding = new zone.moddev.mc.lib.api.BlockEntityBinding<>(prepared, () -> null);
require(binding.as(Machine.class) == binding && binding.blockEntityClass() == Machine.class);
expectFailure(() -> binding.as(Other.class));
standaloneMachine();
require(creations.get() == 0);
System.out.println(
"Machine block entities, block-owned world entities, selection/gating, codecs, deferred"
+ " typed factory validation, and standalone machine planning passed");
}

/**
* Plans a standalone machine. Queuing it on a runtime registrar needs a bootstrapped game, so
* that is covered by the runtime smoke test.
*/
private static void standaloneMachine() {
@Test
void standaloneMachinePlans() {
var machine =
DataModules.Block.CODEC
.parse(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,16 @@
import net.minecraft.nbt.NbtOps;
import net.minecraft.resources.ResourceLocation;

import org.junit.jupiter.api.Test;

import zone.moddev.mc.lib.api.MaterialExtensions;
import zone.moddev.mc.lib.common.factories.MaterialFactory;
import zone.moddev.mc.lib.common.modules.*;
import zone.moddev.mc.lib.common.modules.ModuleCatalog;

public final class DataModulesTest {
public static void main(String[] args) throws Exception {
@Test
void loadsBundledAndExternalModules() throws Exception {
var bundled = ModuleCatalog.bundled();
require(
bundled.items().size() == 32
Expand Down Expand Up @@ -134,9 +137,6 @@ public static void main(String[] args) throws Exception {
Files.delete(path);
}
}
System.out.println(
"Bundled and external data modules, overrides, selections, ZIP paths, and JSON/NBT codecs"
+ " passed");
}

private static ResourceLocation id(String value) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

import net.minecraft.resources.ResourceLocation;

import org.junit.jupiter.api.Test;

import zone.moddev.mc.lib.api.MaterialExtensions;
import zone.moddev.mc.lib.common.loading.DefinitionLoader;
import zone.moddev.mc.lib.common.loading.DefinitionLoader.SourceRoot;
Expand All @@ -18,7 +20,8 @@ public static void handler(String context) {
calls.incrementAndGet();
}

public static void main(String[] args) throws Exception {
@Test
void loadsDefinitionsAcrossMods() throws Exception {
Path temporary = Files.createTempDirectory("mmdlib-loading");
var loader = DefinitionLoaderTest.class.getClassLoader();
try {
Expand Down Expand Up @@ -255,10 +258,6 @@ public static void main(String[] args) throws Exception {
DefinitionLoader.load(List.of(), new MaterialExtensions(), mod -> false)
.materials()
.isEmpty());
System.out.println(
"Folder dispatch, cross-mod staging, extension handles, IDs, duplicates, optional mods,"
+ " standalone blocks with block entities, standalone items, and mounted ZIP loading"
+ " passed");
} finally {
try (var paths = Files.walk(temporary)) {
for (var path : paths.sorted(java.util.Comparator.reverseOrder()).toList())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.level.Level;

import org.junit.jupiter.api.Test;

import zone.moddev.mc.lib.common.codecs.EntityTemplate;
import zone.moddev.mc.lib.common.factories.EntityFactories;
import zone.moddev.mc.lib.common.factories.EntityFactory;
Expand All @@ -23,7 +25,8 @@
import zone.moddev.mc.lib.common.types.MMDEntity;

public final class EntityBuilderTest {
public static void main(String[] args) {
@Test
void buildsEntityTemplates() {
var root = EntityBuilder.create();
require(root == EntityBuilder.INSTANCE);
var settings = JsonParser.parseString("{\"power\":2}").getAsJsonObject();
Expand Down Expand Up @@ -134,9 +137,6 @@ public Entity create(
.forMaterial("test:copper")
.build();
expectFailure(() -> factories.prepare(badSettings, Entity.class));
System.out.println(
"Entity templates, typed factory resolution, settings validation, and JSON/NBT checks"
+ " passed");
}

private static void require(boolean condition) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@
import net.minecraft.nbt.NbtOps;
import net.minecraft.resources.ResourceLocation;

import org.junit.jupiter.api.Test;

import zone.moddev.mc.lib.common.codecs.FluidTemplate;
import zone.moddev.mc.lib.common.parsers.FluidParser;

public final class FluidBuilderTest {
public static void main(String[] args) {
@Test
void buildsFluidFamilies() {
var root = FluidBuilder.create();
require(root == FluidBuilder.INSTANCE);
var template =
Expand Down Expand Up @@ -125,9 +128,6 @@ public static void main(String[] args) {
.parse(JsonOps.INSTANCE, JsonParser.parseString(invalid))
.error()
.isPresent());
System.out.println(
"Fluid builder, family IDs, optional block/bucket binding, validation, and JSON/NBT checks"
+ " passed");
}

private static void require(boolean condition) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@
import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceLocation;

import org.junit.jupiter.api.Test;

import zone.moddev.mc.lib.util.StackContext;

public final class ItemBuilderTest {
public static void main(String[] args) {
@Test
void buildsMaterialItems() {
require(ItemBuilder.create() == ItemBuilder.INSTANCE);
var root = ItemBuilder.INSTANCE;
var template = root.setName("mmdlib:ingot");
Expand Down Expand Up @@ -85,7 +88,6 @@ public static void main(String[] args) {
expectFailure(() -> copper.setMaxStackSize(0));
expectFailure(() -> copper.setMaxDamage(-1));
expectFailure(() -> copper.setUseTime(-1));
System.out.println("Immutable material item template checks passed");
}

private static void require(boolean value) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@

import net.minecraft.resources.ResourceLocation;

import org.junit.jupiter.api.Test;

import zone.moddev.mc.lib.common.codecs.ItemTemplate;
import zone.moddev.mc.lib.common.parsers.ItemParser;

public final class ItemTemplateTest {
public static void main(String[] args) {
@Test
void templateRoundTripsAndValidates() {
var json =
JsonParser.parseString(
"""
Expand Down Expand Up @@ -66,8 +69,6 @@ public static void main(String[] args) {
.get(0)
.count()
== 2);
System.out.println(
"DFU item template round-trip, parser, attributes, and validation checks passed");
}

private static void require(boolean condition) {
Expand Down
Loading
Loading