DataFixerUpper icon indicating copy to clipboard operation
DataFixerUpper copied to clipboard

Datafixers.Dynamic can't convert boolean values. always 'false'

Open ch99q opened this issue 5 years ago • 2 comments

Issue from https://bugs.mojang.com/browse/MC-135413

I found a problem with the class: com.mojang.datafixers.Dynamic When I try to convert a boolean value from a JsonElement it always turns up as false.

Base a basic UnitTest to explain my scenario.

import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.mojang.datafixers.Dynamic;
import com.mojang.datafixers.types.JsonOps;
import net.minecraft.server.v1_13_R1.DynamicOpsNBT;
import net.minecraft.server.v1_13_R1.NBTTagCompound;
import org.junit.Test;

import static org.junit.Assert.*;

public class DynamicTest {
    @Test
    public void convertTest() {
        JsonObject element = new JsonObject();
        element.addProperty("string", "hello world");
        element.addProperty("boolean_true", true);
        element.addProperty("boolean_false", false);
        element.addProperty("byte_1", (byte) 1);
        element.addProperty("byte_0", (byte) 0);
        element.addProperty("double", 10.5);
        element.addProperty("int", 11);
        element.addProperty("long", 12L);
        element.addProperty("float", 13.5F);
        element.addProperty("short", (short) 100);

        JsonObject properties = new JsonParser().parse(element.toString()).getAsJsonObject();

        assertEquals("hello world", properties.get("string").getAsString());
        assertEquals(true, properties.get("boolean_true").getAsBoolean());
        assertEquals(false, properties.get("boolean_false").getAsBoolean());
        assertEquals((byte) 1, properties.get("byte_1").getAsByte());
        assertEquals((byte) 0, properties.get("byte_0").getAsByte());
        assertEquals(10.5, properties.get("double").getAsDouble(), 10.5);
        assertEquals(11, properties.get("int").getAsInt());
        assertEquals(12L, properties.get("long").getAsLong());
        assertEquals(13.5F, properties.get("float").getAsFloat(), 13.5F);
        assertEquals((short) 100, properties.get("short").getAsShort());

        NBTTagCompound dynamic = ((NBTTagCompound) Dynamic.convert(JsonOps.INSTANCE, DynamicOpsNBT.a, properties));

        assertEquals("hello world", dynamic.getString("string"));
        assertEquals(true, dynamic.getBoolean("boolean_true")); // Fails here?? Dynamic.class can't convert true to a boolean.
        assertEquals(false, dynamic.getBoolean("boolean_false"));
        assertEquals((byte) 1, dynamic.getByte("byte_1"));
        assertEquals((byte) 0, dynamic.getByte("byte_0"));
        assertEquals(10.5, dynamic.getDouble("double"), 10.5);
        assertEquals(11, dynamic.getInt("int"));
        assertEquals(12L, dynamic.getLong("long"));
        assertEquals(13.5F, dynamic.getFloat("float"), 13.5F);
        assertEquals((short) 100, dynamic.getShort("short"));
    }
}

The result when we run the UnitTest is

java.lang.AssertionError: 
Expected :true
Actual   :false
 <Click to see difference>


	at org.junit.Assert.fail(Assert.java:93)
	at org.junit.Assert.failNotEquals(Assert.java:647)
	at org.junit.Assert.assertEquals(Assert.java:128)
	at org.junit.Assert.assertEquals(Assert.java:147)
	at DynamicTest.convertTest(DynamicTest.java:43) // The line is commented in the example above.
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
...

Where will this bug be a problem?

When you set the generator-settings in the server.properties to a JSON object it will always turn up in the level.dat as:

useCaves: 0
useRavines: 0

When you set the generator-settings to {"useCaves":true,"useRavines":false}

ch99q avatar Jan 22 '20 22:01 ch99q

Looking at this Unit Test I wrote in 2018, I can conclude the issue is not with DataFixerUpper but with the NBT logic in Minecraft, sadly :/

Waiting to close this issue to a maintainer can answer how to proceed from here?

Is it time for Mojang to open-source the internal NBT library?

ch99q avatar Jan 22 '20 23:01 ch99q

As far as I can identify the problem is with NBTTagCompound, when calling getBoolean it looks for 1 or 0 as boolean, but the value is stored as a string "false" or "true".

ch99q avatar Jan 22 '20 23:01 ch99q