Jump to content

Recommended Posts

Posted

Hello,

I recently started implementation of Codec based serialization for my data objects and ran into some minor issues. I have some external utility class holding few parameters which is used by one data object (single parameter). The data object codecs are loaded via registry lookup and this extra parameter is mapped by extra key, which I would like to remove (even though I think that won't be possible as it could possibly cause issues when multiple objects are inlined, but in my case it's just one which would work). I have checked several documentations about codecs, but I have not found anything useful (is there any documentation by Mojang? I found only the DFU repository, which is for version 1.x, while MC is already on 5.x).

I'll share code snippets which should explain the situation better than I do..

 

So I have some common class like this for example

public class MyObj {

    public static final Codec<MyObj> CODEC = RecordCodecBuilder.create(i -> i.group(
        Codec.INT.fieldOf("i").forGetter(MyObj::i),
        Codec.INT.fieldOf("j").forGetter(MyObj::j)
    ).apply(i, MyObj::new));
}

which I want to be loaded from format like this

{
    "type": "namespace:id",
    "i": 1,
    "j": 2
}

The actual codec inside the following class is mapped via Codec#dispatch method. My current implementation has it like this:

public class DataObj {

    public static final Codec<DataObj> CODEC = MyObj.CODEC.fieldOf("key").xmap(DataObj::new, t -> t.myObj).codec();
    private final MyObj myObj;

    private DataObj(MyObj myObj) {
        this.myObj = myObj;
    }
}

which expects to be in another Map object like this

{
    "type": "namespace:id",
    "key": {
        "i": 1,
        "j": 2
    }
}

Is there any way to inline it without the key parameter?

Posted

I don't really follow what you are trying to do from that description. 🙂 

But if you want to change the codec based on a "type" field, look at Codec.partialDispatch() or one of its simplified helpers that call it.

The basic idea is you tell it the name of type field, and then some functions that tell it how to map

type -> Codec<value> and value -> type

 

Here's a "simple" example I knocked up. I obviously don't recommend using the class name in a real world example as the type discriminator. 

You can use any "primitive" type as the typeCodec, e.g. a ResourceLocation

public class TypedCodecRegistry<TYPE, VALUE> {

    // The codec for the type field
    private final Codec<TYPE> typeCodec;
    // The mapping of value -> type
    private final Function<VALUE, TYPE> typeFunction;
    // type -> real codec
    private final Map<TYPE, Codec<? extends VALUE>> CODECS = new HashMap<>();

    public TypedCodecRegistry(Codec<TYPE> typeCodec, Function<VALUE, TYPE> typeFunction) {
        this.typeCodec = typeCodec;
        this.typeFunction = typeFunction;
    }

    public Codec<VALUE> codec() {
        return this.typeCodec.partialDispatch(
                "type",  // The name of the type field
                // given a value what is its type?
                value -> DataResult.success(this.typeFunction.apply(value)),
                // look up the codec for a type or its an error
                type -> Optional.ofNullable(this.CODECS.get(type)).map(DataResult::success).orElse(DataResult.error("Unknown type " + type)));
    }

    public void register(TYPE type, Codec<? extends VALUE> codec) {
        this.CODECS.put(type, codec);
    }

    public static void main(String[] args) {
        // type is the class's simple name
        var registry = new TypedCodecRegistry<>(Codec.STRING, value -> value.getClass().getSimpleName());
        var codec = registry.codec();

        registry.register(Integer.class.getSimpleName(), Codec.INT);
        registry.register(String.class.getSimpleName(), Codec.STRING);
        registry.register(ResourceLocation.class.getSimpleName(), ResourceLocation.CODEC);
        System.out.println(encode(codec, "hello world"));
        System.out.println(encode(codec, 42));
        System.out.println(encode(codec, new ResourceLocation("minecraft:dirt")));
    }

    public static String encode(Codec<Object> codec, Object value) {
        return codec.encodeStart(JsonOps.INSTANCE, value).getOrThrow(false, System.err::println).toString();
    }
}

It outputs

  Quote

{"type":"String","value":"hello world"}

{"type":"Integer","value":42}

{"type":"ResourceLocation","value":"minecraft:dirt"}

Expand  

 

Boilerplate:

If you don't post your logs/debug.log we can't help you. For curseforge you need to enable the forge debug.log in its minecraft settings. You should also post your crash report if you have one.

If there is no error in the log file and you don't have a crash report then post the launcher_log.txt from the minecraft folder. Again for curseforge this will be in your curseforge/minecraft/Install

Large files should be posted to a file sharing site like https://gist.github.com  You should also read the support forum sticky post.

Posted (edited)

Not exactly that, I most likely worded that poorly.

I have already implemented different codec mappings using the #dispatch functions, this question is more about codec creation for one value.

I'll try to explain my current code in greater detail.

 

I currently have one registry of objects which are called RewardTransformerType and it's class looks like this

public final class RewardTransformerType<V, T extends RewardTransformer<V>> implements IdentifierHolder, Predicate<Class<?>> {

    public static final Codec<RewardTransformer<?>> CODEC = QuestingRegistries.REWARD_TRANSFORMERS.dispatch("type", RewardTransformer::getType, type -> type.codec);
    private final ResourceLocation identifier;
    private final Codec<T> codec;
    private final Class<V> type;

    public RewardTransformerType(ResourceLocation identifier, Codec<T> codec, Class<V> type) {
        this.identifier = identifier;
        this.codec = codec;
        this.type = type;
    }

    @Override
    public ResourceLocation getIdentifier() {
        return identifier;
    }

    @Override
    public boolean test(Class<?> aClass) {
        return aClass.equals(this.type);
    }
}

And one type implementation which looks like this

public class CountByAttributeTransformer implements RewardTransformer<Integer> {

    public static final Codec<CountByAttributeTransformer> CODEC = RecordCodecBuilder.create(instance -> instance.group(
            OutputModifier.CODEC.fieldOf("modifier").forGetter(t -> t.modifier)
    ).apply(instance, CountByAttributeTransformer::new));
    private final OutputModifier modifier;

    public CountByAttributeTransformer(OutputModifier modifier) {
        this.modifier = modifier;
    }

    @Override
    public Integer adjust(Integer originalValue, Player player, Quest quest) {
        return PlayerData.get(player).map(data -> {
            IAttributeProvider provider = data.getAttributes();
            return (int) Math.round(this.modifier.getModifiedValue(provider, originalValue));
        }).orElse(originalValue);
    }

    @Override
    public RewardTransformerType<?, ?> getType() {
        return QuestRegistry.COUNT_BY_ATTRIBUTE_TRANSFORMER;
    }
}

As you can see, currently the Codec for CountByAttributeTransformer class uses codec from OutputModifier class, which looks like this

public static final Codec<OutputModifier> CODEC = RecordCodecBuilder.create(instance -> instance.group(
            ResourceLocation.CODEC.flatXmap(location -> {
                IAttributeId id = Attribs.find(location);
                return id == null ? DataResult.error("Unknown attribute " + location) : DataResult.success(id);
            }, attributeId -> attributeId == null ? DataResult.error("Attribute is null") : DataResult.success(attributeId.getId()))
                    .fieldOf("attribute").forGetter(t -> t.attributeId),
            ResourceLocation.CODEC.flatXmap(location -> {
                IModifierOp op = AttributeOps.find(location);
                return op == null ? DataResult.error("Unknown operation " + location) : DataResult.success(op);
            }, operation -> operation == null ? DataResult.error("Operation is null") : DataResult.success(operation.getId()))
                    .fieldOf("operation").forGetter(t -> t.operator)
    ).apply(instance, OutputModifier::new));

 

My problem with this is that when I want to serialize/deserialize it, result looks like this

{
    "type": "namespace:id",
    "modifier": {
        "attribute": "namespace:id",
        "operation": "namespace:id"
    }
}

and I would like to get this result instead

{
    "type": "namespace:id",
    "attribute": "namespace:id",
    "operation": "namespace:id"
}

 

So my question is how to adjust the codec in CountByAttribute class so I can get the wanted result (if it is even possible). I have also tried using this codec, but that was resulting in "Not an JSON object" error, so thats wrong approach too

public static final Codec<CountByAttributeTransformer> CODEC = OutputModifier.CODEC.xmap(CountByAttributeTransformer::new, t -> t.modifier);

 

Is there a way to get to the second result (without creating duplicate codec for OutputModifier class)?

Edited by Toma™
Posted

Can you please stop posting snippets and show all the relevant code (preferably on github), so I don't have to guess what you are doing and waste my time like I did above.

e.g. (and it is only one example) what does this do:

  Quote

QuestingRegistries.REWARD_TRANSFORMERS

Expand  

Without seeing all the code, I can't tell why your xmap solution doesn't work, you don't show where/how it is referenced/used.

Boilerplate:

If you don't post your logs/debug.log we can't help you. For curseforge you need to enable the forge debug.log in its minecraft settings. You should also post your crash report if you have one.

If there is no error in the log file and you don't have a crash report then post the launcher_log.txt from the minecraft folder. Again for curseforge this will be in your curseforge/minecraft/Install

Large files should be posted to a file sharing site like https://gist.github.com  You should also read the support forum sticky post.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • Minecraft normal funciona perfectamente en cuaquier version, pero al usar "forge" no inicia y muestra en pantalla el error 1. Intente desinstalarlo varias veces, borrando todos los mods, la carpeta ".minecraft" e incluso formatear mi PC pero nada funciona. Les agradeceria si pueden ayudarme.   Minecraft works perfectly on any version, but when using "Forge," it won't start and displays error 1 on the screen. I've tried uninstalling it several times, deleting all mods, the .minecraft folder, and even formatting my PC, but nothing works. I'd appreciate it if you could help me.
    • [06Apr2025 14:20:17.918] [main/INFO] [cpw.mods.modlauncher.Launcher/MODLAUNCHER]: ModLauncher running: args [--username, {MINECRAFT_USERNAME}, --version, 1.20.1, --gameDir, C:\Users\{COMPUTER_USERNAME}\AppData\Roaming\ModrinthApp\profiles\dude whatttt, --assetsDir, C:\Users\{COMPUTER_USERNAME}\AppData\Roaming\ModrinthApp\meta\assets, --assetIndex, 5, --uuid, {MINECRAFT_UUID}, --accessToken, ????????, --clientId, c4502edb-87c6-40cb-b595-64a280cf8906, --xuid, 0, --userType, msa, --versionType, release, --width, 854, --height, 480, --launchTarget, forgeclient, --fml.forgeVersion, 47.4.0, --fml.mcVersion, 1.20.1, --fml.forgeGroup, net.minecraftforge, --fml.mcpVersion, 20230612.114412] [06Apr2025 14:20:17.923] [main/INFO] [cpw.mods.modlauncher.Launcher/MODLAUNCHER]: ModLauncher 10.0.9+10.0.9+main.dcd20f30 starting: java version 17.0.10 by Azul Systems, Inc.; OS Windows 11 arch amd64 version 10.0 [06Apr2025 14:20:19.188] [main/INFO] [net.minecraftforge.fml.loading.ImmediateWindowHandler/]: Loading ImmediateWindowProvider fmlearlywindow [06Apr2025 14:20:19.242] [main/INFO] [EARLYDISPLAY/]: Trying GL version 4.6 [06Apr2025 14:20:19.405] [main/INFO] [EARLYDISPLAY/]: Requested GL version 4.6 got version 4.6 [06Apr2025 14:20:19.434] [main/INFO] [mixin-transmog/]: Mixin Transmogrifier is definitely up to no good... [06Apr2025 14:20:19.450] [main/INFO] [mixin-transmog/]: crimes against java were committed [06Apr2025 14:20:19.463] [main/INFO] [mixin-transmog/]: Original mixin transformation service successfully crobbed by mixin-transmogrifier! [06Apr2025 14:20:19.495] [main/INFO] [mixin/]: SpongePowered MIXIN Subsystem Version=0.8.5 Source=union:/C:/Users/{COMPUTER_USERNAME}/AppData/Roaming/ModrinthApp/profiles/dude%20whatttt/mods/Connector-1.0.0-beta.46+1.20.1.jar%23361%23364!/ Service=ModLauncher Env=CLIENT [06Apr2025 14:20:19.505] [pool-2-thread-1/INFO] [EARLYDISPLAY/]: GL info: NVIDIA GeForce RTX 2060/PCIe/SSE2 GL version 4.6.0 NVIDIA 572.83, NVIDIA Corporation [06Apr2025 14:20:20.213] [main/WARN] [net.minecraftforge.fml.loading.moddiscovery.ModFileParser/LOADING]: Mod file C:\Users\{COMPUTER_USERNAME}\AppData\Roaming\ModrinthApp\meta\libraries\net\minecraftforge\fmlcore\1.20.1-47.4.0\fmlcore-1.20.1-47.4.0.jar is missing mods.toml file [06Apr2025 14:20:20.216] [main/WARN] [net.minecraftforge.fml.loading.moddiscovery.ModFileParser/LOADING]: Mod file C:\Users\{COMPUTER_USERNAME}\AppData\Roaming\ModrinthApp\meta\libraries\net\minecraftforge\javafmllanguage\1.20.1-47.4.0\javafmllanguage-1.20.1-47.4.0.jar is missing mods.toml file [06Apr2025 14:20:20.219] [main/WARN] [net.minecraftforge.fml.loading.moddiscovery.ModFileParser/LOADING]: Mod file C:\Users\{COMPUTER_USERNAME}\AppData\Roaming\ModrinthApp\meta\libraries\net\minecraftforge\lowcodelanguage\1.20.1-47.4.0\lowcodelanguage-1.20.1-47.4.0.jar is missing mods.toml file [06Apr2025 14:20:20.222] [main/WARN] [net.minecraftforge.fml.loading.moddiscovery.ModFileParser/LOADING]: Mod file C:\Users\{COMPUTER_USERNAME}\AppData\Roaming\ModrinthApp\meta\libraries\net\minecraftforge\mclanguage\1.20.1-47.4.0\mclanguage-1.20.1-47.4.0.jar is missing mods.toml file [06Apr2025 14:20:20.702] [main/WARN] [net.minecraftforge.jarjar.selection.JarSelector/]: Attempted to select two dependency jars from JarJar which have the same identification: Mod File:  and Mod File: . Using Mod File:  [06Apr2025 14:20:20.704] [main/WARN] [net.minecraftforge.jarjar.selection.JarSelector/]: Attempted to select a dependency jar for JarJar which was passed in as source: geckolib. Using Mod File: C:\Users\{COMPUTER_USERNAME}\AppData\Roaming\ModrinthApp\profiles\dude whatttt\mods\geckolib-forge-1.20.1-4.7.1.2.jar [06Apr2025 14:20:20.704] [main/WARN] [net.minecraftforge.jarjar.selection.JarSelector/]: Attempted to select a dependency jar for JarJar which was passed in as source: midnightlib. Using Mod File: C:\Users\{COMPUTER_USERNAME}\AppData\Roaming\ModrinthApp\profiles\dude whatttt\mods\midnightlib-forge-1.4.2.jar [06Apr2025 14:20:20.704] [main/WARN] [net.minecraftforge.jarjar.selection.JarSelector/]: Attempted to select a dependency jar for JarJar which was passed in as source: curios. Using Mod File: C:\Users\{COMPUTER_USERNAME}\AppData\Roaming\ModrinthApp\profiles\dude whatttt\mods\curios-forge-5.12.1+1.20.1.jar [06Apr2025 14:20:20.704] [main/WARN] [net.minecraftforge.jarjar.selection.JarSelector/]: Attempted to select a dependency jar for JarJar which was passed in as source: architectury. Using Mod File: C:\Users\{COMPUTER_USERNAME}\AppData\Roaming\ModrinthApp\profiles\dude whatttt\mods\architectury-9.2.14-forge.jar [06Apr2025 14:20:20.704] [main/INFO] [net.minecraftforge.fml.loading.moddiscovery.JarInJarDependencyLocator/]: Found 90 dependencies adding them to mods collection [06Apr2025 14:20:21.837] [main/INFO] [org.sinytra.connector.locator.DependencyResolver/]: Dependency resolution found 0 candidates to load [06Apr2025 14:20:23.246] [main/INFO] [org.sinytra.connector.service.hacks.ModuleLayerMigrator/]: Successfully made module authlib transformable  
    • [06Apr2025 14:20:17.918] [main/INFO] [cpw.mods.modlauncher.Launcher/MODLAUNCHER]: ModLauncher running: args [--username, {MINECRAFT_USERNAME}, --version, 1.20.1, --gameDir, C:\Users\{COMPUTER_USERNAME}\AppData\Roaming\ModrinthApp\profiles\dude whatttt, --assetsDir, C:\Users\{COMPUTER_USERNAME}\AppData\Roaming\ModrinthApp\meta\assets, --assetIndex, 5, --uuid, {MINECRAFT_UUID}, --accessToken, ????????, --clientId, c4502edb-87c6-40cb-b595-64a280cf8906, --xuid, 0, --userType, msa, --versionType, release, --width, 854, --height, 480, --launchTarget, forgeclient, --fml.forgeVersion, 47.4.0, --fml.mcVersion, 1.20.1, --fml.forgeGroup, net.minecraftforge, --fml.mcpVersion, 20230612.114412] [06Apr2025 14:20:17.923] [main/INFO] [cpw.mods.modlauncher.Launcher/MODLAUNCHER]: ModLauncher 10.0.9+10.0.9+main.dcd20f30 starting: java version 17.0.10 by Azul Systems, Inc.; OS Windows 11 arch amd64 version 10.0 [06Apr2025 14:20:19.188] [main/INFO] [net.minecraftforge.fml.loading.ImmediateWindowHandler/]: Loading ImmediateWindowProvider fmlearlywindow [06Apr2025 14:20:19.242] [main/INFO] [EARLYDISPLAY/]: Trying GL version 4.6 [06Apr2025 14:20:19.405] [main/INFO] [EARLYDISPLAY/]: Requested GL version 4.6 got version 4.6 [06Apr2025 14:20:19.434] [main/INFO] [mixin-transmog/]: Mixin Transmogrifier is definitely up to no good... [06Apr2025 14:20:19.450] [main/INFO] [mixin-transmog/]: crimes against java were committed [06Apr2025 14:20:19.463] [main/INFO] [mixin-transmog/]: Original mixin transformation service successfully crobbed by mixin-transmogrifier! [06Apr2025 14:20:19.495] [main/INFO] [mixin/]: SpongePowered MIXIN Subsystem Version=0.8.5 Source=union:/C:/Users/{COMPUTER_USERNAME}/AppData/Roaming/ModrinthApp/profiles/dude%20whatttt/mods/Connector-1.0.0-beta.46+1.20.1.jar%23361%23364!/ Service=ModLauncher Env=CLIENT [06Apr2025 14:20:19.505] [pool-2-thread-1/INFO] [EARLYDISPLAY/]: GL info: NVIDIA GeForce RTX 2060/PCIe/SSE2 GL version 4.6.0 NVIDIA 572.83, NVIDIA Corporation [06Apr2025 14:20:20.213] [main/WARN] [net.minecraftforge.fml.loading.moddiscovery.ModFileParser/LOADING]: Mod file C:\Users\{COMPUTER_USERNAME}\AppData\Roaming\ModrinthApp\meta\libraries\net\minecraftforge\fmlcore\1.20.1-47.4.0\fmlcore-1.20.1-47.4.0.jar is missing mods.toml file [06Apr2025 14:20:20.216] [main/WARN] [net.minecraftforge.fml.loading.moddiscovery.ModFileParser/LOADING]: Mod file C:\Users\{COMPUTER_USERNAME}\AppData\Roaming\ModrinthApp\meta\libraries\net\minecraftforge\javafmllanguage\1.20.1-47.4.0\javafmllanguage-1.20.1-47.4.0.jar is missing mods.toml file [06Apr2025 14:20:20.219] [main/WARN] [net.minecraftforge.fml.loading.moddiscovery.ModFileParser/LOADING]: Mod file C:\Users\{COMPUTER_USERNAME}\AppData\Roaming\ModrinthApp\meta\libraries\net\minecraftforge\lowcodelanguage\1.20.1-47.4.0\lowcodelanguage-1.20.1-47.4.0.jar is missing mods.toml file [06Apr2025 14:20:20.222] [main/WARN] [net.minecraftforge.fml.loading.moddiscovery.ModFileParser/LOADING]: Mod file C:\Users\{COMPUTER_USERNAME}\AppData\Roaming\ModrinthApp\meta\libraries\net\minecraftforge\mclanguage\1.20.1-47.4.0\mclanguage-1.20.1-47.4.0.jar is missing mods.toml file [06Apr2025 14:20:20.702] [main/WARN] [net.minecraftforge.jarjar.selection.JarSelector/]: Attempted to select two dependency jars from JarJar which have the same identification: Mod File:  and Mod File: . Using Mod File:  [06Apr2025 14:20:20.704] [main/WARN] [net.minecraftforge.jarjar.selection.JarSelector/]: Attempted to select a dependency jar for JarJar which was passed in as source: geckolib. Using Mod File: C:\Users\{COMPUTER_USERNAME}\AppData\Roaming\ModrinthApp\profiles\dude whatttt\mods\geckolib-forge-1.20.1-4.7.1.2.jar [06Apr2025 14:20:20.704] [main/WARN] [net.minecraftforge.jarjar.selection.JarSelector/]: Attempted to select a dependency jar for JarJar which was passed in as source: midnightlib. Using Mod File: C:\Users\{COMPUTER_USERNAME}\AppData\Roaming\ModrinthApp\profiles\dude whatttt\mods\midnightlib-forge-1.4.2.jar [06Apr2025 14:20:20.704] [main/WARN] [net.minecraftforge.jarjar.selection.JarSelector/]: Attempted to select a dependency jar for JarJar which was passed in as source: curios. Using Mod File: C:\Users\{COMPUTER_USERNAME}\AppData\Roaming\ModrinthApp\profiles\dude whatttt\mods\curios-forge-5.12.1+1.20.1.jar [06Apr2025 14:20:20.704] [main/WARN] [net.minecraftforge.jarjar.selection.JarSelector/]: Attempted to select a dependency jar for JarJar which was passed in as source: architectury. Using Mod File: C:\Users\{COMPUTER_USERNAME}\AppData\Roaming\ModrinthApp\profiles\dude whatttt\mods\architectury-9.2.14-forge.jar [06Apr2025 14:20:20.704] [main/INFO] [net.minecraftforge.fml.loading.moddiscovery.JarInJarDependencyLocator/]: Found 90 dependencies adding them to mods collection [06Apr2025 14:20:21.837] [main/INFO] [org.sinytra.connector.locator.DependencyResolver/]: Dependency resolution found 0 candidates to load [06Apr2025 14:20:23.246] [main/INFO] [org.sinytra.connector.service.hacks.ModuleLayerMigrator/]: Successfully made module authlib transformable  
    • I have been trying to be Frankenstein and mix 2 modpacks together for my wife and I to both enjoy together. I downloaded both from curseforge, made a new modpack, shoved all of the mods in, and painstakenly went through all 300+ mods taking half of them out then slowly adding them in a handfull at a time until the game launched with as many mods as possible. I knew there were going to be some compatibility issues and have successfully gotten to the main menu. I went to create a new world and got the -1 crash report. I opened the report and took out the mods it said were incompatible until it no longer said anything more than... "// You're mean."  I am trying to understand this report as from what other people have said, it sounds like fabric is needed but I don't see how that's possible when both modpacks are the same version of minecraft, using forge, and work individually. I do see in there stuff like this in the crash report: Does this mean I have to go through what looks like 2/3s of all the mods in there and take them out? Or is there something else I'm missing? Please help This is the crash report:  https://paste.ee/p/E8dz1PCC        
  • Topics

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.