diff --git a/build.gradle b/build.gradle index b756e668..c1e19245 100644 --- a/build.gradle +++ b/build.gradle @@ -1,10 +1,9 @@ plugins { - id 'idea' - id 'net.minecraftforge.gradle' version '[6.0,6.2)' - id 'org.parchmentmc.librarian.forgegradle' version '1.+' - id 'org.spongepowered.mixin' version '0.7.+' - id("com.modrinth.minotaur") version "2.+" - id("com.matthewprenger.cursegradle") version "1.4.0" + id('idea') + id('com.modrinth.minotaur') version "2.+" + id('com.matthewprenger.cursegradle') version "1.4.0" + id('net.neoforged.moddev.legacyforge') version '2.0.80' + id('org.jetbrains.gradle.plugin.idea-ext') version "1.1.9" } version = '1.46' @@ -14,57 +13,46 @@ base.archivesName = 'exdeorum' java.toolchain.languageVersion = JavaLanguageVersion.of(17) java.withSourcesJar() -minecraft { - mappings channel: 'parchment', version: "$parchment_mappings-$mc_version" - accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') +legacyForge { + version = "${mc_version}-${forge_version}" + + accessTransformers = files('src/main/resources/META-INF/accesstransformer.cfg') + + parchment { + mappingsVersion = project.parchment_mappings + minecraftVersion = project.mc_version + } runs { - copyIdeResources = true + configureEach { + logLevel = org.slf4j.event.Level.DEBUG + jvmArgument '-XX:+AllowEnhancedClassRedefinition' + jvmArgument '-XX:+IgnoreUnrecognizedVMOptions' + } client { - workingDirectory project.file('run') - - jvmArgs.add('-XX:+AllowEnhancedClassRedefinition') - jvmArgs.add('-XX:+IgnoreUnrecognizedVMOptions') - - property 'mixin.env.remapRefMap', 'true' - property 'mixin.env.refMapRemappingFile', "${projectDir}/build/createSrgToMcp/output.srg" - property 'forge.logging.console.level', 'debug' - - mods { - exdeorum { - source sourceSets.main - } - } + client() + //property 'mixin.env.remapRefMap', 'true' + //property 'mixin.env.refMapRemappingFile', "${projectDir}/build/createSrgToMcp/output.srg" } server { - workingDirectory project.file('run/server') + server() - jvmArgs.add('-XX:+AllowEnhancedClassRedefinition') - jvmArgs.add('-XX:+IgnoreUnrecognizedVMOptions') - - property 'forge.logging.console.level', 'debug' - - mods { - exdeorum { - source sourceSets.main - } - } + gameDirectory.set(project.layout.projectDirectory.dir('run/server')) + programArgument '--nogui' } data { - workingDirectory project.file('run') + data() - property 'forge.logging.console.level', 'debug' + programArguments.addAll('--mod', 'exdeorum', '--all', '--output', file('src/generated/resources/').absolutePath, '--existing', file('src/main/resources/').absolutePath) + } + } - args '--mod', 'exdeorum', '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/') - - mods { - exdeorum { - source sourceSets.main - } - } + mods { + exdeorum { + sourceSet sourceSets.main } } } @@ -122,53 +110,51 @@ repositories { } dependencies { - minecraft("net.minecraftforge:forge:${mc_version}-${forge_version}") - // TOP OPTIONAL - compileOnly(fg.deobf("mcjty.theoneprobe:theoneprobe:1.20.1-${top_version}") { + modCompileOnly("mcjty.theoneprobe:theoneprobe:1.20.1-${top_version}") { transitive = false - }) + } // JADE OPTIONAL - implementation(fg.deobf("curse.maven:jade-324717:4986594")) + modImplementation("curse.maven:jade-324717:4986594") // JEI OPTIONAL - compileOnly(fg.deobf("mezz.jei:jei-${mc_version}-forge-api:${jei_version}")) - compileOnly(fg.deobf("mezz.jei:jei-${mc_version}-common-api:${jei_version}")) - runtimeOnly(fg.deobf("mezz.jei:jei-${mc_version}-forge:${jei_version}")) + modCompileOnly("mezz.jei:jei-${mc_version}-forge-api:${jei_version}") + modCompileOnly("mezz.jei:jei-${mc_version}-common-api:${jei_version}") + modRuntimeOnly("mezz.jei:jei-${mc_version}-forge:${jei_version}") // REI OPTIONAL - compileOnly(fg.deobf("me.shedaniel:RoughlyEnoughItems-forge:${rei_version}")) - compileOnly(fg.deobf("me.shedaniel.cloth:cloth-config-forge:${cloth_config_version}")) - compileOnly(fg.deobf("curse.maven:reipc-521393:4837449")) + modCompileOnly("me.shedaniel:RoughlyEnoughItems-forge:${rei_version}") + modCompileOnly("me.shedaniel.cloth:cloth-config-forge:${cloth_config_version}") + modCompileOnly("curse.maven:reipc-521393:4837449") // EMI OPTIONAL - compileOnly(fg.deobf("dev.emi:emi-forge:${emi_version}:api")) - //runtimeOnly(fg.deobf("dev.emi:emi-forge:${emi_version}")) + modCompileOnly("dev.emi:emi-forge:${emi_version}:api") + //modRuntimeOnly("dev.emi:emi-forge:${emi_version}") // KubeJS OPTIONAL - implementation fg.deobf("dev.architectury:architectury-forge:${architectury_version}") - implementation fg.deobf("dev.latvian.mods:rhino-forge:${rhino_version}") - implementation fg.deobf("dev.latvian.mods:kubejs-forge:${kubejs_version}") + modImplementation("dev.architectury:architectury-forge:${architectury_version}") + modImplementation("dev.latvian.mods:rhino-forge:${rhino_version}") + modImplementation("dev.latvian.mods:kubejs-forge:${kubejs_version}") // ModKit DEV ONLY - implementation fg.deobf('com.github.thedarkcolour:ModKit:78f393bfac') + modImplementation('com.github.thedarkcolour:ModKit:cc8f1c11ec') // Oculus + Embeddium OPTIONAL - compileOnly fg.deobf('maven.modrinth:oculus:1.20.1-1.6.9') - compileOnly fg.deobf('maven.modrinth:embeddium:0.2.12+mc1.20.1') + modCompileOnly('maven.modrinth:oculus:1.20.1-1.6.9') + modCompileOnly('maven.modrinth:embeddium:0.2.12+mc1.20.1') // testing - //implementation fg.deobf("curse.maven:allthecompressed-514045:4938351") - implementation fg.deobf("curse.maven:inventory-tweaks-refoxed-976858:5315928") - //implementation fg.deobf("curse.maven:inventorysorter-240633:4655091") - implementation fg.deobf("curse.maven:cyclic-239286:4994392") - implementation fg.deobf("curse.maven:flib-661261:4724762") + //modImplementation("curse.maven:allthecompressed-514045:4938351") + modImplementation("curse.maven:inventory-tweaks-refoxed-976858:5315928") + //modImplementation("curse.maven:inventorysorter-240633:4655091") + modImplementation("curse.maven:cyclic-239286:4994392") + modImplementation("curse.maven:flib-661261:4724762") - testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.2' - testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.9.2' + // DEV ONLY + compileOnly('org.jetbrains:annotations:23.0.0') } test { useJUnitPlatform() } -def replaceProperties = [ mc_version: mc_version, mod_version: version ] +def replaceProperties = [mc_version: mc_version, mod_version: version] processResources { inputs.properties replaceProperties @@ -197,13 +183,13 @@ processResources { jar { manifest { attributes([ - "Specification-Title": "exdeorum", - "Specification-Vendor": "exdeorumsareus", - "Specification-Version": "1", // We are version 1 of ourselves - "Implementation-Title": project.name, - "Implementation-Version": "${version}", - "Implementation-Vendor" :"exdeorumsareus", - "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") + "Specification-Title" : "exdeorum", + "Specification-Vendor" : "exdeorumsareus", + "Specification-Version" : "1", // We are version 1 of ourselves + "Implementation-Title" : project.name, + "Implementation-Version" : "${version}", + "Implementation-Vendor" : "exdeorumsareus", + "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") ]) } } diff --git a/gradle.properties b/gradle.properties index 8340eb7f..cdd3d518 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,12 +1,12 @@ -# Sets default memory used for gradle commands. Can be overridden by user or command line properties. -# This is required to provide enough memory for the Minecraft decompilation process. +org.gradle.daemon=true org.gradle.jvmargs=-Xmx3G -org.gradle.daemon=false -org.gradle.cache=true +org.gradle.caching=true +org.gradle.parallel=true +org.gradle.configuration-cache=true mc_version=1.20.1 forge_version=47.3.10 -parchment_mappings=1.20.1-2023.06.26 +parchment_mappings=2023.06.26 jei_version=15.20.0.104 rei_version=12.0.684 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index fae08049..0b55a3bd 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/test/java/thedarkcolour/exdeorum/recipe/BlockPredicateTest.java b/src/test/java/thedarkcolour/exdeorum/recipe/BlockPredicateTest.java deleted file mode 100644 index 51d94d4e..00000000 --- a/src/test/java/thedarkcolour/exdeorum/recipe/BlockPredicateTest.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Ex Deorum - * Copyright (c) 2024 thedarkcolour - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package thedarkcolour.exdeorum.recipe; - -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import io.netty.buffer.Unpooled; -import net.minecraft.SharedConstants; -import net.minecraft.advancements.critereon.StatePropertiesPredicate; -import net.minecraft.core.Direction; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.server.Bootstrap; -import net.minecraft.tags.BlockTags; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.util.stream.Collectors; - -import static org.junit.jupiter.api.Assertions.*; - -class BlockPredicateTest { - @BeforeEach - void setUp() { - SharedConstants.tryDetectVersion(); - Bootstrap.bootStrap(); - } - - @Test - void jsonTest() { - var testPredicate = """ - { - "block": "minecraft:oak_wood", - "state": { - "axis": "y" - } - } - """; - var json = JsonParser.parseString(testPredicate); - var expected = BlockPredicate.blockState(Blocks.OAK_WOOD, StatePropertiesPredicate.Builder.properties().hasProperty(BlockStateProperties.AXIS, Direction.Axis.Y).build()); - var actual = BlockPredicate.fromJson((JsonObject) json); - assertNotNull(actual); - assertEquals(expected.possibleStates().collect(Collectors.toSet()), actual.possibleStates().collect(Collectors.toSet())); - } - - @Test - void networkTest() { - var buffer = new FriendlyByteBuf(Unpooled.buffer()); - - var single = BlockPredicate.singleBlock(Blocks.DIAMOND_BLOCK); - single.toNetwork(buffer); - assertEquals(single, BlockPredicate.fromNetwork(buffer)); - - var states = BlockPredicate.blockState(Blocks.OAK_LOG, StatePropertiesPredicate.Builder.properties().hasProperty(BlockStateProperties.AXIS, Direction.Axis.X).build()); - states.toNetwork(buffer); - var test = BlockPredicate.fromNetwork(buffer); - assertEquals(states.toJson(), test.toJson()); - - var tag = BlockPredicate.blockTag(BlockTags.OAK_LOGS); - tag.toNetwork(buffer); - assertEquals(tag, BlockPredicate.fromNetwork(buffer)); - } -} \ No newline at end of file diff --git a/src/test/java/thedarkcolour/exdeorum/recipe/RecipeSerializationTests.java b/src/test/java/thedarkcolour/exdeorum/recipe/RecipeSerializationTests.java deleted file mode 100644 index 4b448377..00000000 --- a/src/test/java/thedarkcolour/exdeorum/recipe/RecipeSerializationTests.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Ex Deorum - * Copyright (c) 2024 thedarkcolour - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package thedarkcolour.exdeorum.recipe; - -import com.google.gson.JsonObject; -import io.netty.buffer.Unpooled; -import net.minecraft.SharedConstants; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.server.Bootstrap; -import net.minecraft.tags.BlockTags; -import net.minecraft.world.item.Items; -import net.minecraft.world.item.crafting.Ingredient; -import net.minecraft.world.item.crafting.Recipe; -import net.minecraft.world.item.crafting.RecipeSerializer; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.Fluids; -import net.minecraft.world.level.storage.loot.providers.number.UniformGenerator; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import thedarkcolour.exdeorum.recipe.barrel.FinishedFluidTransformationRecipe; -import thedarkcolour.exdeorum.recipe.barrel.FluidTransformationRecipe; -import thedarkcolour.exdeorum.recipe.crook.CrookRecipe; -import thedarkcolour.exdeorum.recipe.crucible.CrucibleHeatRecipe; -import thedarkcolour.exdeorum.recipe.crucible.FinishedCrucibleHeatRecipe; -import thedarkcolour.exdeorum.recipe.hammer.HammerRecipe; -import thedarkcolour.exdeorum.recipe.sieve.SieveRecipe; - -import java.util.function.BiPredicate; -import java.util.function.Function; - -import static org.junit.jupiter.api.Assertions.*; - -// Tests JSON and network serialization/deserialization methods of all recipes to ensure everything works -public class RecipeSerializationTests { - @BeforeEach - void setUp() { - SharedConstants.tryDetectVersion(); - Bootstrap.bootStrap(); - } - - @Test - void networkRecipes() { - CompoundTag testData = new CompoundTag(); - testData.putInt("apple", 12); - - testNetwork(new CrucibleHeatRecipe(null, BlockPredicate.blockTag(BlockTags.DIRT), 3), new CrucibleHeatRecipe.Serializer()); - testNetwork(new FluidTransformationRecipe(null, Fluids.WATER, Fluids.LAVA, 1, BlockPredicate.blockTag(BlockTags.DIRT), WeightedList.builder().build(), 1000), new FluidTransformationRecipe.Serializer()); - testNetwork(new CrookRecipe(null, BlockPredicate.blockTag(BlockTags.DIRT), Items.DIAMOND, null, 0.0025f), new CrookRecipe.Serializer()); - testNetwork(new SieveRecipe(null, Ingredient.of(Items.SOUL_SOIL), Items.IRON_AXE, Items.DIAMOND, UniformGenerator.between(1, 3), null, true), new SieveRecipe.Serializer(), SieveRecipe::areEqual); - testNetwork(new SieveRecipe(null, Ingredient.of(Items.SOUL_SOIL), Items.IRON_AXE, Items.DIAMOND, UniformGenerator.between(1, 3), testData, true), new SieveRecipe.Serializer(), SieveRecipe::areEqual); - testNetwork(new HammerRecipe(null, Ingredient.of(Items.SOUL_SOIL), Items.SOUL_SAND, UniformGenerator.between(1, 3), null), new HammerRecipe.Serializer(), HammerRecipe::areEqual); - testNetwork(new HammerRecipe(null, Ingredient.of(Items.SOUL_SOIL), Items.SOUL_SAND, UniformGenerator.between(1, 3), testData), new HammerRecipe.Serializer(), HammerRecipe::areEqual); - } - - @Test - void jsonRecipes() { - testJson(new CrucibleHeatRecipe(null, BlockPredicate.blockTag(BlockTags.DIRT), 3), new CrucibleHeatRecipe.Serializer(), recipe -> { - return new FinishedCrucibleHeatRecipe(recipe.id(), recipe.blockPredicate(), recipe.heatValue()); - }); - testJson(new FluidTransformationRecipe(null, Fluids.WATER, Fluids.LAVA, 1, BlockPredicate.blockTag(BlockTags.DIRT), WeightedList.builder().build(), 1000), new FluidTransformationRecipe.Serializer(), recipe -> { - return new FinishedFluidTransformationRecipe(recipe.getId(), recipe.baseFluid, recipe.resultFluid, recipe.resultColor, recipe.catalyst, recipe.byproducts, recipe.duration); - }); - } - - // Takes a recipe, uses its serializer to write it to a buffer, then reads it - // back and checks if the recipe it got is the same as the one originally written - private static > void testNetwork(T recipe, RecipeSerializer serializer) { - testNetwork(recipe, serializer, Recipe::equals); - } - - // Takes a recipe, uses its serializer to write it to a buffer, then reads it - // back and checks if the recipe it got is the same as the one originally written - private static > void testNetwork(T recipe, RecipeSerializer serializer, BiPredicate equalityCheck) { - var id = recipe.getId(); - var buffer = new FriendlyByteBuf(Unpooled.buffer()); - serializer.toNetwork(buffer, recipe); - assertTrue(equalityCheck.test(recipe, serializer.fromNetwork(id, buffer))); - } - - private static > void testJson(T recipe, RecipeSerializer serializer, Function toJson) { - var id = recipe.getId(); - var finishedRecipe = toJson.apply(recipe); - var json = new JsonObject(); - finishedRecipe.serializeRecipeData(json); - assertEquals(recipe, serializer.fromJson(id, json)); - } -} diff --git a/src/test/java/thedarkcolour/exdeorum/recipe/RecipeUtilTest.java b/src/test/java/thedarkcolour/exdeorum/recipe/RecipeUtilTest.java deleted file mode 100644 index fab6c275..00000000 --- a/src/test/java/thedarkcolour/exdeorum/recipe/RecipeUtilTest.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Ex Deorum - * Copyright (c) 2024 thedarkcolour - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package thedarkcolour.exdeorum.recipe; - -import com.google.gson.JsonObject; -import net.minecraft.SharedConstants; -import net.minecraft.core.Direction; -import net.minecraft.server.Bootstrap; -import net.minecraft.world.item.Items; -import net.minecraft.world.item.crafting.Ingredient; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.level.material.Fluids; -import net.minecraftforge.common.Tags; -import net.minecraftforge.fluids.FluidStack; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - -class RecipeUtilTest { - @BeforeEach - void setUp() { - SharedConstants.tryDetectVersion(); - Bootstrap.bootStrap(); - } - - @Test - void jsonFluidStack() { - var fluidStack = new FluidStack(Fluids.LAVA, 345); - var root = new JsonObject(); - root.add("test", RecipeUtil.writeFluidStackJson(fluidStack)); - var testStack = RecipeUtil.readFluidStack(root, "test"); - assertTrue( - testStack.getAmount() == fluidStack.getAmount() && - testStack.getFluid() == fluidStack.getFluid() && - testStack.getTag() == fluidStack.getTag() - ); - } - - @Test - void areIngredientsEqual() { - assertTrue(RecipeUtil.areIngredientsEqual(Ingredient.of(Items.OAK_SLAB), Ingredient.of(Items.OAK_SLAB))); - assertFalse(RecipeUtil.areIngredientsEqual(Ingredient.of(Items.BIRCH_SLAB), Ingredient.of(Items.OAK_SLAB))); - assertTrue(RecipeUtil.areIngredientsEqual(Ingredient.of(Tags.Items.GEMS_DIAMOND), Ingredient.of(Tags.Items.GEMS_DIAMOND))); - assertFalse(RecipeUtil.areIngredientsEqual(Ingredient.of(Tags.Items.INGOTS_IRON), Ingredient.of(Tags.Items.GEMS_DIAMOND))); - assertTrue(RecipeUtil.areIngredientsEqual(Ingredient.of(Items.OAK_SLAB, Items.SPRUCE_SLAB), Ingredient.of(Items.OAK_SLAB, Items.SPRUCE_SLAB))); - assertTrue(RecipeUtil.areIngredientsEqual(Ingredient.of(Items.OAK_SLAB, Items.SPRUCE_SLAB), Ingredient.of(Items.SPRUCE_SLAB, Items.OAK_SLAB))); - assertFalse(RecipeUtil.areIngredientsEqual(Ingredient.of(Items.OAK_SLAB, Items.SPRUCE_SLAB), Ingredient.of(Items.SPRUCE_SLAB, Items.OAK_SLAB, Items.OAK_SLAB))); - } - - @Test - void stringBlockState() { - var state = Blocks.ACACIA_LOG.defaultBlockState().setValue(BlockStateProperties.AXIS, Direction.Axis.Z); - assertEquals(state, RecipeUtil.parseBlockState(RecipeUtil.writeBlockState(state).getAsString())); - } -} \ No newline at end of file diff --git a/src/test/java/thedarkcolour/exdeorum/recipe/WeightedListTest.java b/src/test/java/thedarkcolour/exdeorum/recipe/WeightedListTest.java deleted file mode 100644 index 2c0d9868..00000000 --- a/src/test/java/thedarkcolour/exdeorum/recipe/WeightedListTest.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Ex Deorum - * Copyright (c) 2024 thedarkcolour - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package thedarkcolour.exdeorum.recipe; - -import net.minecraft.util.Mth; -import net.minecraft.util.RandomSource; -import net.minecraft.world.level.levelgen.XoroshiroRandomSource; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - -class WeightedListTest { - - @Test - void isEmpty() { - WeightedList.Builder list = WeightedList.builder(); - assertTrue(list.build().isEmpty()); - } - - @Test - void getRandom() { - RandomSource rand = new XoroshiroRandomSource(123, 123); - // An equal list should give all elements a roughly equal chance of appearing randomly - WeightedList equalList = WeightedList.builder() - .add(20, "Hello") - .add(20, "Hi") - .add(20, "How ya doin") - .build(); - - int hellos = 0; - int his = 0; - int howYaDoins = 0; - - for (int i = 0; i < 1_000_000; i++) { - String choice = equalList.getRandom(rand); - switch (choice) { - case "Hello" -> hellos++; - case "Hi" -> his++; - case "How ya doin" -> howYaDoins++; - default -> fail("Bad test"); - } - } - - System.out.println("Hello: " + hellos + String.format(" (%.2f)", (float) hellos / 1000000)); - System.out.println("Hi: " + his + String.format(" (%.2f)", (float) his / 1000000)); - System.out.println("How ya doin: " + howYaDoins + String.format(" (%.2f)", (float) howYaDoins / 1000000)); - - // Ensure that these two elements have roughly the same frequency - assertTrue(Mth.abs((float) hellos / 1_000_000f - (float) his / 1_000_000f) < 0.025f); - - // Test that the weights specified in the list roughly match the random results - WeightedList unbalanced = WeightedList.builder() - .add(60, "Hello") - .add(20, "Hi") - .add(20, "How ya doin") - .build(); - - hellos = 0; - his = 0; - howYaDoins = 0; - - for (int i = 0; i < 1_000_000; i++) { - String choice = unbalanced.getRandom(rand); - switch (choice) { - case "Hello" -> hellos++; - case "Hi" -> his++; - case "How ya doin" -> howYaDoins++; - default -> fail("Bad test"); - } - } - - // Ensure the dominant element has the 60% frequency, just as its 60/100 weight specifies - assertTrue(Mth.abs((float) hellos / 1_000_000f - 0.6f) < 0.025f); - } - - @Test - void testEquals() { - // regular equality - assertNotEquals( - WeightedList.builder().add(20, new Object()).add(30, new Object()).build(), - WeightedList.builder().add(20, new Object()).add(30, new Object()).build() - ); - // deep equality - assertEquals( - WeightedList.builder().add(20, "Hi").add(30, "Hello").build(), - WeightedList.builder().add(20, "Hi").add(30, "Hello").build() - ); - } -} \ No newline at end of file