Bukkit 1.13.2 use flat world presets in WorldCreator

Discussion in 'Plugin Development' started by Colinus999, Feb 22, 2019.

Thread Status:
Not open for further replies.
  1. Offline

    Colinus999

    Hello There!

    You can see my older post below. I think that I overcomplicated my question a bit. When updating my plugin from 1.8 to 1.13, some behaviour in the WorldCreator class has changed. I would like to use flat world "seeds"/presets in the worldcreator. How do I do this in Bukkit 1.13.2?

    Old Post (open)
    I'm currently updating my plugins to Bukkit 1.13.2. When trying to update my World Managing plugin, it always throws this exception when I'm trying to create a new World using the WorldCreator class.

    (I have replaced my root package path with my.plugin and removed the time stamps)
    Code:
    [Server thread/INFO]: Colinus999 issued server command: /wcreate lobby normal -template the_void -type flat
    [Server thread/WARN]: [WorldManager] Task #16 for WorldManager v1.0 generated an exception
    com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 11 path $
        at com.google.gson.JsonParser.parse(JsonParser.java:65) ~[craftbukkit-1.13.2.jar:git-Bukkit-c24abab]
        at com.google.gson.JsonParser.parse(JsonParser.java:45) ~[craftbukkit-1.13.2.jar:git-Bukkit-c24abab]
        at org.bukkit.craftbukkit.v1_13_R2.CraftServer.createWorld(CraftServer.java:919) ~[craftbukkit-1.13.2.jar:git-Bukkit-c24abab]
        at org.bukkit.Bukkit.createWorld(Bukkit.java:471) ~[craftbukkit-1.13.2.jar:git-Bukkit-c24abab]
        at my.plugin.worldmanager.WorldManager$2.run(WorldManager.java:442) ~[?:?]
        at org.bukkit.craftbukkit.v1_13_R2.scheduler.CraftTask.run(CraftTask.java:77) ~[craftbukkit-1.13.2.jar:git-Bukkit-c24abab]
        at org.bukkit.craftbukkit.v1_13_R2.scheduler.CraftScheduler.mainThreadHeartbeat(CraftScheduler.java:391) [craftbukkit-1.13.2.jar:git-Bukkit-c24abab]
        at net.minecraft.server.v1_13_R2.MinecraftServer.b(MinecraftServer.java:833) [craftbukkit-1.13.2.jar:git-Bukkit-c24abab]
        at net.minecraft.server.v1_13_R2.DedicatedServer.b(DedicatedServer.java:382) [craftbukkit-1.13.2.jar:git-Bukkit-c24abab]
        at net.minecraft.server.v1_13_R2.MinecraftServer.a(MinecraftServer.java:792) [craftbukkit-1.13.2.jar:git-Bukkit-c24abab]
        at net.minecraft.server.v1_13_R2.MinecraftServer.run(MinecraftServer.java:695) [craftbukkit-1.13.2.jar:git-Bukkit-c24abab]
        at java.lang.Thread.run(Unknown Source) [?:1.8.0_201]
    Caused by: com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 11 path $
        at com.google.gson.stream.JsonReader.syntaxError(JsonReader.java:1559) ~[craftbukkit-1.13.2.jar:git-Bukkit-c24abab]
        at com.google.gson.stream.JsonReader.checkLenient(JsonReader.java:1401) ~[craftbukkit-1.13.2.jar:git-Bukkit-c24abab]
        at com.google.gson.stream.JsonReader.doPeek(JsonReader.java:542) ~[craftbukkit-1.13.2.jar:git-Bukkit-c24abab]
        at com.google.gson.stream.JsonReader.peek(JsonReader.java:425) ~[craftbukkit-1.13.2.jar:git-Bukkit-c24abab]
        at com.google.gson.JsonParser.parse(JsonParser.java:60) ~[craftbukkit-1.13.2.jar:git-Bukkit-c24abab]
        ... 11 more
    My code around there looks like this:
    I want to mention that this code worked in version Bukkit 1.8.8 fine.
    Code:
    @Override
    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
        /* [...] check permissions */
        switch(command.getName()) {
        /* [...] other sub-commands */
        case "wcreate": {
            final WorldCreator wc = new WorldCreator(args[0]);
         
            /* [...] Set the Environment (dimension) */
         
            wc.generateStructures(true);
         
            /*
             * [...] handle command arguments (this works fine)
             *
             * Method used to set the WorldType: (if argument "type <name>" is given)
             *  wc.type(type);
             * Note: type is never null
             *
             * Method used to set the generator settings (the preset string): (if argument "template <name>" is given)
             *  wc.generatorSettings(FLAT_WORLD_PRESETS.getOrDefault(template, template));
             * Note: this is also never null
             *
             * Method used to set the seed: (if argument "seed <seed>" is given)
             *  wc.seed(Long.parseLong(arg[0]));
             * Note: the seed is always a valid long; *never* NaN
             */
         
            new BukkitRunnable() {
                @Override
                public void run() {
                    final org.bukkit.World world = Bukkit.createWorld(wc); // This is where the error occurs
                    if(!Bukkit.getWorlds().contains(world))
                        Bukkit.getWorlds().add(world);
                    /* [...] doing stuff after creation of the world */
                }
            }.runTask(this);
            return true;
        }
    I have done some further inspection in the bukkit source code and this is what I've found on the stack trace of the error:

    Bukkit.java
    Code:
    /**
    * Creates or loads a world with the given name using the specified
    * options.
    * <p>
    * If the world is already loaded, it will just return the equivalent of
    * getWorld(creator.name()).
    *
    * @param creator the options to use when creating the world
    * @return newly created or loaded world
    */
    public static World createWorld(WorldCreator creator) {
        return server.createWorld(creator); // Exception
    }
    
    This leads to:
    CraftServer.java
    Code:
    @Override
    public World createWorld(WorldCreator creator) {
        // [...]
        IDataManager sdm = new ServerNBTManager(getWorldContainer(), name, getServer(), getHandle().getServer().dataConverterManager);
        PersistentCollection persistentcollection = new PersistentCollection(sdm);
        WorldData worlddata = sdm.getWorldData();
        WorldSettings worldSettings = null;
        if (worlddata == null) {
            worldSettings = new WorldSettings(creator.seed(), EnumGamemode.getById(getDefaultGameMode().getValue()), generateStructures, hardcore, type);
            JsonElement parsedSettings = new JsonParser().parse(creator.generatorSettings()); // Exception
            if (parsedSettings.isJsonObject()) {
                worldSettings.setGeneratorSettings(parsedSettings.getAsJsonObject());
            }
            worlddata = new WorldData(worldSettings, name);
        }
        worlddata.checkName(name);
    So my conclusion is that the normal presets that I can see when customizing a flat world are not used anymore. Instead, JSON is used as a preset format. Next, I'll have to figure out what the format actually looks like.

    EDIT: It seems that this is used for generating customized worlds, not flat worlds (layers). But how do I customize the layers of a flat world using a string like below then?
    Flat World Preset: Redstone Ready (open)
    minecraft:bedrock,3*minecraft:stone,52*minecraft:sandstone;minecraft:desert;


    EDIT by Moderator: merged posts, please use the edit button instead of double posting.


    I am currently doing a workaround by creating my own ChunkGenerator that supports this format. But it does not support generating ores (like it should in "Tunnler's Dream") and other props.
     
    Last edited: Mar 2, 2019
  2. Offline

    Chr0mosom3

    Code:
    new BukkitRunnable() {
    @Override
    public void run() {
    final org.bukkit.World world = Bukkit.createWorld(wc); // This is where the error occurs
    if(!Bukkit.getWorlds().contains(world))
    Bukkit.getWorlds().add(world);
    /* [...] doing stuff after creation of the world */
    }
    }.runTask(this);
    
    I have some ideas
    1. Why is it final?
    2. Why is it in a bukkit runnable?
    3. Try removing @Override (fixed one problem I had a long time ago)
     
  3. Offline

    Colinus999

    First, it is final because I am not reassigning a new Object to it, so why should it not be final?
    Second, it is a bukkit runnable because it has to run sync with Bukkit and commands are not always running sync.
    Third, @Override is telling the Java Compiler (javac) to force a override of the method run. So, if this method would not be defined in the interface BukkitRunnable, it would give me an error while compiling or even in the editor (Eclipse). This annotation is not compiled. It is removed while compiling it so it does not make any difference.

    Edit: When accessing the Bukkit API (Bukkit.doSomething()) tasks have to run synced with the server. (I think there might be exceptions but most of them have to run synced)
     
  4. Offline

    CraftCreeper6

    @Colinus999
    I can't find a method named createWorld that takes any arguments in 1.13.2, if you can find it online can you link me and I might be able to help further.
     
Thread Status:
Not open for further replies.

Share This Page