Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Mods with collective as a dependency] Unable to compile #2508

Closed
GanerCodes opened this issue Jul 9, 2024 · 2 comments
Closed

[Mods with collective as a dependency] Unable to compile #2508

GanerCodes opened this issue Jul 9, 2024 · 2 comments
Assignees
Labels
Question Further information is requested

Comments

@GanerCodes
Copy link

Minecraft version: 1.21
Modloader: Fabric
Fabric loader version: 0.51.11

Hi, I'm having some trouble getting some of your mods compiled when they depend on collective. When I execute ./gradlew build, there are no failures and I have three folders for the three respective mod platforms [as well as the Common folder]. If I transfer the produced lib/….jar file from the relevant folder to my mods (using the public collective jar file alongside it), the game crashes during startup saying it cannot find DuckConfig classes.
If I compile collective locally as well, it is able to detect it. I am unsure why this is. I assume I am missing instructions for how to combine the libraries all together, which may fix the issue.
Crash Log:
image

[also, if it's of any additional encouragement once I get things running I have a pull request prepared for randommodeffects adding optional RNG dependence on number effects and effect level :)]

@GanerCodes GanerCodes added Mod Label Missing A new issue where the mod label has yet to be assigned. Question Further information is requested labels Jul 9, 2024
@ricksouth ricksouth removed the Mod Label Missing A new issue where the mod label has yet to be assigned. label Jul 20, 2024
@ricksouth
Copy link
Member

To do local testing you'll need to compile Collective similar to how you do the mod, or use one of the non-compiled Collective files from the maven: https://github.com/Serilum/.maven/tree/maven/com/natamus/collective-ml

This is due to how I merge the mod loaders into one jar, by splitting the common source. If you'd like to do a PR (thank you!), I'll build the mod correctly with the merging.

@GanerCodes
Copy link
Author

hey, thanks for your reply. I already ended up just making my own mod with my implementation, however feel free to copy paste anything from this into your mod. The important parts are the Statistics class and the last dozen or so lines which use the distribution to select the effects.

packagePKG_BASE;

import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import java.io.*;
import java.nio.*;
import java.nio.charset.*;
import java.nio.file.*;
import java.util.*;
import net.fabricmc.loader.api.*;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.event.lifecycle.v1.*;
import net.minecraft.entity.*;
import net.minecraft.entity.effect.*;
import net.minecraft.entity.mob.MobEntity;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.registry.*;
import net.minecraft.registry.entry.*;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.*;

public class ExampleMod implements ModInitializer {
	public static String fabConfDir, dirpath, blacklistFile, configFile;
	public static File modConfigDir;
	
	public static Random rand;
	
	public class Config {
		public static double effectChance = 0.5;
		public static Statistics.Distribution effectLevelDistribution = Statistics.Distribution.FUNKY;
		public static Statistics.Distribution effectCountDistribution = Statistics.Distribution.FUNKY;
		public static int maxPotionEffectLevel = 255;
		public static int maxPotionEffectCount = 1000;
		public static double effectLevelDistributionParameter = 0.5;
		public static double effectCountDistributionParameter = 0.5;
		
		public static ArrayList<StatusEffect> potionEffects = new ArrayList<StatusEffect>();
		public static ArrayList<String> blacklist = new ArrayList<String>();
		
		public static void init() {
			fabConfDir   = FabricLoader.getInstance().getConfigDir().toString();
			dirpath      = fabConfDir + File.separator + "MODID_config";
			configFile   = dirpath    + File.separator + "config.json";
			modConfigDir = new File(dirpath);
			
			if(!modConfigDir.isDirectory()) modConfigDir.mkdirs();
			updateFromJson(configFile);
			setupPotions(); }
		
		public static void updateFromJson(String fp) {
	        Gson gson = new Gson();
			var jstr = "";
			try { jstr = new String(Files.readAllBytes(Paths.get(fp))); }
			catch(IOException e) {}
            var jo = JsonParser.parseString(jstr).getAsJsonObject();
            if (jo.has("effectChance"                    )) effectChance                     =               jo.get("effectChance"                    ).getAsDouble();
            if (jo.has("effectLevelDistribution"         )) effectLevelDistribution          = gson.fromJson(jo.get("effectLevelDistribution"         ), Statistics.Distribution.class);
            if (jo.has("effectCountDistribution"         )) effectCountDistribution          = gson.fromJson(jo.get("effectCountDistribution"         ), Statistics.Distribution.class);
            if (jo.has("maxPotionEffectLevel"            )) maxPotionEffectLevel             =               jo.get("maxPotionEffectLevel"            ).getAsInt();
            if (jo.has("maxPotionEffectCount"            )) maxPotionEffectCount             =               jo.get("maxPotionEffectCount"            ).getAsInt();
            if (jo.has("effectLevelDistributionParameter")) effectLevelDistributionParameter =               jo.get("effectLevelDistributionParameter").getAsDouble();
            if (jo.has("effectCountDistributionParameter")) effectCountDistributionParameter =               jo.get("effectCountDistributionParameter").getAsDouble();
			if (jo.has("blacklist")) {
                var ja = jo.getAsJsonArray("blacklist"); blacklist.clear();
		        for(var e : ja) blacklist.add(e.getAsString()); } }
		
		public static void setupPotions() {
			for (StatusEffect effect : Registries.STATUS_EFFECT) {
				var n = effect.getName().getString();
				if (!blacklist.contains(n)) potionEffects.add(effect); } } }

	public class Statistics {
	    public enum Distribution { UNIFORM, GEOMETRIC, FUNKY }

	    public static int mapGeometric(double u, double p) {
	    	return (int) Math.min(
	    		Math.ceil(Math.log(1-u) / Math.log(1-p)),
	            Integer.MAX_VALUE); }
		public static int mapFunky(double u) {
	    	return (int) Math.min(
	    		Math.ceil(1 / (10 * Math.pow(1-u, 2))),
	            Integer.MAX_VALUE); }
	    public static int drawDistribution(Distribution t, double p, int min, int max) {
	        var u = rand.nextDouble();
	        var r = 0;
	        switch(t) {
	            case   UNIFORM: { r = (int)(min + u*(max-min)       ); } break;
	            case GEOMETRIC: { r = (int)(min + mapGeometric(u, p)); } break;
	            case     FUNKY: { r = (int)(min + mapFunky(u))       ; } break; }
	        return Math.min(r, max); }

	    // Reservoir Sampling Algorithm
	    public static <T> List<T> chooseN(List<T> l, int n) {
	        if (n >= l.size()) return l;
	        var r = new ArrayList<T>(n);
	        for (var i = 0; i < n; i++) r.add(l.get(i));
	        for (var i = n; i < l.size(); i++) {
	            int o = rand.nextInt(i + 1);
	            if (o < n) r.set(o, l.get(i)); }
	        return r; } }
	
    public void onInitialize() {
		Config.init();
		rand = new Random();
        ServerEntityEvents.ENTITY_LOAD.register(this::onMobSpawn); }

    public void onMobSpawn(Entity entity, ServerWorld world) {
		if(!(entity instanceof MobEntity)) return;
		
		var dat = entity.writeNbt(new NbtCompound());
		if (dat.contains("MODIDtag")) return;
		dat.putBoolean("MODIDtag", true); // 󰤱 this doesn't work fix it
		entity.readNbt(dat);
		
		if (rand.nextDouble() > Config.effectChance) return;
		
		var l = (LivingEntity)entity;
		var n = Statistics.drawDistribution(
			Config.effectCountDistribution,
			Config.effectCountDistributionParameter,
			1, Config.maxPotionEffectCount);
		for (var effect : Statistics.chooseN(Config.potionEffects, n)) {
			var lvl = Statistics.drawDistribution(
				Config.effectLevelDistribution,
				Config.effectLevelDistributionParameter,
				1, Config.maxPotionEffectLevel);
			var effectInst = new StatusEffectInstance(
				Registries.STATUS_EFFECT.getEntry(effect),
				Integer.MAX_VALUE, lvl-1);
			l.addStatusEffect(effectInst); } } }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants