Switch to ModDevGradle

This commit is contained in:
thedarkcolour 2025-11-30 15:39:29 -08:00
parent 1f96fdad5c
commit cf3eb26da2
No known key found for this signature in database
GPG Key ID: 86B37B3575FD5976
7 changed files with 70 additions and 446 deletions

View File

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

View File

@ -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

View File

@ -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

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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));
}
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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.<BlockState>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.<BlockState>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 <T extends Recipe<?>> void testNetwork(T recipe, RecipeSerializer<T> 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 <T extends Recipe<?>> void testNetwork(T recipe, RecipeSerializer<T> serializer, BiPredicate<T, T> 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 <T extends Recipe<?>> void testJson(T recipe, RecipeSerializer<T> serializer, Function<T, EFinishedRecipe> toJson) {
var id = recipe.getId();
var finishedRecipe = toJson.apply(recipe);
var json = new JsonObject();
finishedRecipe.serializeRecipeData(json);
assertEquals(recipe, serializer.fromJson(id, json));
}
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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()));
}
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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<Object> 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<String> equalList = WeightedList.<String>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<String> unbalanced = WeightedList.<String>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.<String>builder().add(20, "Hi").add(30, "Hello").build(),
WeightedList.<String>builder().add(20, "Hi").add(30, "Hello").build()
);
}
}