Problem with updating plugin to 1.13

Discussion in 'Spigot Plugin Development' started by relucaXIV, Jul 21, 2018.

  1. I'm trying to update that plugin to 1.13 using the spigot now released, all works up to now without a thing in this class:

    https://github.com/hoqhuuep/IslandC...uuep/islandcraft/nms/v1_12_R1/NmsHandler.java

    Here the code we need to see:
    Code (Text):

    if (!(world instanceof CraftWorld)) {
    // Wrong version?
    return false;
    }
    final CraftWorld craftWorld = (CraftWorld) world;
    final WorldProvider worldProvider = craftWorld.getHandle().worldProvider;
    try {

    Field field = getField(worldProvider.getClass(), "c");

    field.setAccessible(true);
    if (field.get(worldProvider) instanceof CustomWorldChunkManager) {
    // Already installed
    return false;
    }

    field.set(worldProvider, new CustomWorldChunkManager(biomeGenerator));

    return true;
    } catch (NoSuchFieldException e) {
    return false;
    } catch (IllegalArgumentException e) {
    return false;
    } catch (IllegalAccessException e) {
    return false;
    }
    }
    public boolean installBiomeGenerator(final World world, final BiomeGenerator biomeGenerator) {
     
    On this line whe are getting the c varible that in the class WorldProvider of 1.12 spigot jar is a WorldChunkManager type (the above type CustomWorldChunkManager extends WorldChunkManager)
    Code (Text):

    Field field = getField(worldProvider.getClass(), "c");
     
    In this line we are setting the CustomWorldChunkManager that extends WorldChunkManager
    Code (Text):

    field.set(worldProvider, new CustomWorldChunkManager(biomeGenerator));
     

    Here the code gives that error in runtime:
    Code (Text):

    [00:46:48 WARN]: java.lang.IllegalArgumentException: Can not set boolean field net.minecraft.server.v1_13_R1.WorldProvider.c to com.github.hoqhuuep.islandcraft.nms.v1_13_R1.CustomWorldChunkManager
    [00:46:48 WARN]:        at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(Unknown Source)
    [00:46:48 WARN]:        at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(Unknown Source)
    [00:46:48 WARN]:        at sun.reflect.UnsafeBooleanFieldAccessorImpl.set(Unknown Source)
    [00:46:48 WARN]:        at java.lang.reflect.Field.set(Unknown Source)
    [00:46:48 WARN]:        at com.github.hoqhuuep.islandcraft.nms.v1_13_R1.NmsHandler.installBiomeGenerator(NmsHandler.java:37)
    [00:46:48 WARN]:        at com.github.hoqhuuep.islandcraft.bukkit.BiomeGeneratorListener.onChunkLoad(BiomeGeneratorListener.java:91)
    [00:46:48 WARN]:        at sun.reflect.GeneratedMethodAccessor3.invoke(Unknown Source)
    [00:46:48 WARN]:        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    [00:46:48 WARN]:        at java.lang.reflect.Method.invoke(Unknown Source)
    [00:46:48 WARN]:        at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:304)
    [00:46:48 WARN]:        at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.java:62)
    [00:46:48 WARN]:        at org.bukkit.plugin.SimplePluginManager.fireEvent(SimplePluginManager.java:500)
    [00:46:48 WARN]:        at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.java:485)
    [00:46:48 WARN]:        at net.minecraft.server.v1_13_R1.ChunkMap.a(ChunkMap.java:41)
    [00:46:48 WARN]:        at net.minecraft.server.v1_13_R1.ChunkMap.put(ChunkMap.java:134)
    [00:46:48 WARN]:        at net.minecraft.server.v1_13_R1.ChunkMap.put(ChunkMap.java:1)
    [00:46:48 WARN]:        at org.bukkit.craftbukkit.libs.it.unimi.dsi.fastutil.longs.Long2ObjectMaps$SynchronizedMap.put(Long2ObjectMaps.java:371)
    [00:46:48 WARN]:        at net.minecraft.server.v1_13_R1.ChunkProviderServer.a(ChunkProviderServer.java:207)
    [00:46:48 WARN]:        at java.util.concurrent.CompletableFuture.uniApply(Unknown Source)
    [00:46:48 WARN]:        at java.util.concurrent.CompletableFuture.uniApplyStage(Unknown Source)
    [00:46:48 WARN]:        at java.util.concurrent.CompletableFuture.thenApply(Unknown Source)
    [00:46:48 WARN]:        at net.minecraft.server.v1_13_R1.ChunkProviderServer.generateChunk(ChunkProviderServer.java:169)
    [00:46:48 WARN]:        at net.minecraft.server.v1_13_R1.ChunkProviderServer.getChunkAt(ChunkProviderServer.java:127)
    [00:46:48 WARN]:        at net.minecraft.server.v1_13_R1.World.getChunkAt(World.java:268)
    [00:46:48 WARN]:        at net.minecraft.server.v1_13_R1.WorldProviderNormal.a(SourceFile:209)
    [00:46:48 WARN]:        at net.minecraft.server.v1_13_R1.WorldProviderNormal.a(SourceFile:186)
    [00:46:48 WARN]:        at net.minecraft.server.v1_13_R1.WorldServer.b(WorldServer.java:821)
    [00:46:48 WARN]:        at net.minecraft.server.v1_13_R1.WorldServer.a(WorldServer.java:731)
    [00:46:48 WARN]:        at org.bukkit.craftbukkit.v1_13_R1.CraftServer.createWorld(CraftServer.java:959)
    [00:46:48 WARN]:        at org.bukkit.Bukkit.createWorld(Bukkit.java:456)
    [00:46:48 WARN]:        at com.github.hoqhuuep.islandcraft.bukkit.IslandCraftPlugin.onCommand(IslandCraftPlugin.java:195)
    [00:46:48 WARN]:        at org.bukkit.command.PluginCommand.execute(PluginCommand.java:44)
    [00:46:48 WARN]:        at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:141)
    [00:46:48 WARN]:        at org.bukkit.craftbukkit.v1_13_R1.CraftServer.dispatchCommand(CraftServer.java:691)
    [00:46:48 WARN]:        at org.bukkit.craftbukkit.v1_13_R1.CraftServer.dispatchServerCommand(CraftServer.java:677)
    [00:46:48 WARN]:        at net.minecraft.server.v1_13_R1.DedicatedServer.aW(DedicatedServer.java:453)
    [00:46:48 WARN]:        at net.minecraft.server.v1_13_R1.DedicatedServer.w(DedicatedServer.java:412)
    [00:46:48 WARN]:        at net.minecraft.server.v1_13_R1.MinecraftServer.v(MinecraftServer.java:780)
    [00:46:48 WARN]:        at net.minecraft.server.v1_13_R1.MinecraftServer.run(MinecraftServer.java:678)
    [00:46:48 WARN]:        at java.lang.Thread.run(Unknown Source)
     
    I discovered the reason:

    WorldProovider class from spigot 1.12
    (net.minecraft.server.v1_12_R1.WorldProvider)
    How can you see the variable c is a WorldChunkManager type
    Code (Text):

    package net.minecraft.server.v1_12_R1;

    import javax.annotation.Nullable;

    public abstract class WorldProvider
    {
      public static final float[] a = { 1.0F, 0.75F, 0.5F, 0.25F, 0.0F, 0.25F, 0.5F, 0.75F };
      protected World b;
      private WorldType type;
      private String i;
      protected WorldChunkManager c;
      protected boolean d;
      protected boolean e;
      protected boolean f;
      protected final float[] g = new float[16];
      private final float[] j = new float[4];

      public final void a(World paramWorld)
      {
        this.b = paramWorld;
        this.type = paramWorld.getWorldData().getType();
        this.i = paramWorld.getWorldData().getGeneratorOptions();
        b();
        a();
      }

      protected void a()
      {
        float f1 = 0.0F;
        for (int k = 0; k <= 15; k++)
        {
          float f2 = 1.0F - k / 15.0F;
          this.g[k] = ((1.0F - f2) / (f2 * 3.0F + 1.0F) * 1.0F + 0.0F);
        }
      }

      protected void b()
      {
        this.f = true;
        WorldType localWorldType = this.b.getWorldData().getType();
        if (localWorldType == WorldType.FLAT)
        {
          WorldGenFlatInfo localWorldGenFlatInfo = WorldGenFlatInfo.a(this.b.getWorldData().getGeneratorOptions());
          this.c = new WorldChunkManagerHell(BiomeBase.getBiome(localWorldGenFlatInfo.a(), Biomes.b));
        }
        else if (localWorldType == WorldType.DEBUG_ALL_BLOCK_STATES)
        {
          this.c = new WorldChunkManagerHell(Biomes.c);
        }
        else
        {
          this.c = new WorldChunkManager(this.b.getWorldData());
        }
      }

      public ChunkGenerator getChunkGenerator()
      {
        if (this.type == WorldType.FLAT) {
          return new ChunkProviderFlat(this.b, this.b.getSeed(), this.b.getWorldData().shouldGenerateMapFeatures(), this.i);
        }
        if (this.type == WorldType.DEBUG_ALL_BLOCK_STATES) {
          return new ChunkProviderDebug(this.b);
        }
        if (this.type == WorldType.CUSTOMIZED) {
          return new ChunkProviderGenerate(this.b, this.b.getSeed(), this.b.getWorldData().shouldGenerateMapFeatures(), this.i);
        }
        return new ChunkProviderGenerate(this.b, this.b.getSeed(), this.b.getWorldData().shouldGenerateMapFeatures(), this.i);
      }

      public boolean canSpawn(int paramInt1, int paramInt2)
      {
        BlockPosition localBlockPosition = new BlockPosition(paramInt1, 0, paramInt2);
        if (this.b.getBiome(localBlockPosition).i()) {
          return true;
        }
        return this.b.c(localBlockPosition).getBlock() == Blocks.GRASS;
      }

      public float a(long paramLong, float paramFloat)
      {
        int k = (int)(paramLong % 24000L);
        float f1 = (k + paramFloat) / 24000.0F - 0.25F;
        if (f1 < 0.0F) {
          f1 += 1.0F;
        }
        if (f1 > 1.0F) {
          f1 -= 1.0F;
        }
        float f2 = f1;
        f1 = 1.0F - (float)((Math.cos(f1 * 3.141592653589793D) + 1.0D) / 2.0D);
        f1 = f2 + (f1 - f2) / 3.0F;
        return f1;
      }

      public int a(long paramLong)
      {
        return (int)(paramLong / 24000L % 8L + 8L) % 8;
      }

      public boolean d()
      {
        return true;
      }

      public boolean e()
      {
        return true;
      }

      @Nullable
      public BlockPosition h()
      {
        return null;
      }

      public int getSeaLevel()
      {
        if (this.type == WorldType.FLAT) {
          return 4;
        }
        return this.b.getSeaLevel() + 1;
      }

      public WorldChunkManager k()
      {
        return this.c;
      }

      public boolean l()
      {
        return this.d;
      }

      public boolean m()
      {
        return this.f;
      }

      public boolean n()
      {
        return this.e;
      }

      public float[] o()
      {
        return this.g;
      }

      public WorldBorder getWorldBorder()
      {
        return new WorldBorder();
      }

      public void a(EntityPlayer paramEntityPlayer) {}

      public void b(EntityPlayer paramEntityPlayer) {}

      public abstract DimensionManager getDimensionManager();

      public void r() {}

      public void s() {}

      public boolean c(int paramInt1, int paramInt2)
      {
        return true;
      }
    }
     
    WorldProovider class from spigot 1.13 pre7
    (net.minecraft.server.v1_13_R1.WorldProvider)
    Now the variable c is a boolean type...
    Code (Text):

    package net.minecraft.server.v1_13_R1;

    import javax.annotation.Nullable;

    public abstract class WorldProvider
    {
      public static final float[] a = { 1.0F, 0.75F, 0.5F, 0.25F, 0.0F, 0.25F, 0.5F, 0.75F };
      protected World b;
      protected boolean c;
      protected boolean d;
      protected boolean e;
      protected final float[] f = new float[16];
      private final float[] g = new float[4];

      public final void a(World paramWorld)
      {
        this.b = paramWorld;
        m();
        a();
      }

      protected void a()
      {
        float f1 = 0.0F;
        for (int i = 0; i <= 15; i++)
        {
          float f2 = 1.0F - i / 15.0F;
          this.f[i] = ((1.0F - f2) / (f2 * 3.0F + 1.0F) * 1.0F + 0.0F);
        }
      }

      public int a(long paramLong)
      {
        return (int)(paramLong / 24000L % 8L + 8L) % 8;
      }

      @Nullable
      public BlockPosition d()
      {
        return null;
      }

      public boolean isNether()
      {
        return this.c;
      }

      public boolean g()
      {
        return this.e;
      }

      public boolean h()
      {
        return this.d;
      }

      public float[] i()
      {
        return this.f;
      }

      public WorldBorder getWorldBorder()
      {
        return new WorldBorder();
      }

      public void a(EntityPlayer paramEntityPlayer) {}

      public void b(EntityPlayer paramEntityPlayer) {}

      public void k() {}

      public void l() {}

      public boolean a(int paramInt1, int paramInt2)
      {
        return true;
      }

      protected abstract void m();

      public abstract ChunkGenerator<?> getChunkGenerator();

      @Nullable
      public abstract BlockPosition a(ChunkCoordIntPair paramChunkCoordIntPair, boolean paramBoolean);

      @Nullable
      public abstract BlockPosition a(int paramInt1, int paramInt2, boolean paramBoolean);

      public abstract float a(long paramLong, float paramFloat);

      public abstract boolean o();

      public abstract boolean p();

      public abstract DimensionManager getDimensionManager();
    }
     

    Sincerally I do not now what those lines of code do, if someone is expert about worldgeneration coul explain me what that lines of code do? And how could I fix that in 1.13? Thanks very much
     
  2. You can see in the 'net.minecraft.server.v1_13_R1.WorldProvider' there is no variable of type WorldChunkManager, which means it was probably moved to another file. Now you have to find which file it was moved to. The variable name 'c' might have changed to something else but it should still be of the type WorldChunkManager and is probably only in one place.
     
  3. Yes thanks, I thought that and I searched, but
    I will try today another time in a better way.
    Do you intend about CustomWorldGeneration and if I won't be able to fix that problem, could you help me to update that plugin to 1.13?
    The plugin's sourceis this, if you would like to see it:
    https://github.com/hoqhuuep/IslandCraft?files=1
     
  4. I did get the chance to do a text search and found a WorldChunkManager c variable in net.minecraft.server.v1_13_R1.ChunkGeneratorAbstract.java, which is extended by the various ChunkProvider classes.

    If you change:
    Code (Text):
    final WorldProvider worldProvider = craftWorld.getHandle().worldProvider;
    to:
    Code (Text):
    final ChunkGenerator<?> chunkGenerator = craftWorld.getHandle().getChunkServer().chunkGenerator;
    you should be able to get it working again by using 'chunkGenerator' instead of 'worldProvider' variable.
     
  5. Thanks very much! I will try today and I will say you what happened
     
    • Like Like x 1
  6. Bad news, it gives me this error:
    Code (Text):

    [18:47:32 WARN]: java.lang.NoSuchFieldException: c
    [18:47:32 WARN]:        at java.lang.Class.getDeclaredField(Unknown Source)
    [18:47:32 WARN]:        at com.github.hoqhuuep.islandcraft.nms.v1_13_R1.NmsHandler.getField(NmsHandler.java:48)
    [18:47:32 WARN]:        at com.github.hoqhuuep.islandcraft.nms.v1_13_R1.NmsHandler.getField(NmsHandler.java:54)
    [18:47:32 WARN]:        at com.github.hoqhuuep.islandcraft.nms.v1_13_R1.NmsHandler.getField(NmsHandler.java:54)
    [18:47:32 WARN]:        at com.github.hoqhuuep.islandcraft.nms.v1_13_R1.NmsHandler.getField(NmsHandler.java:54)
    [18:47:32 WARN]:        at com.github.hoqhuuep.islandcraft.nms.v1_13_R1.NmsHandler.installBiomeGenerator(NmsHandler.java:25)
    [18:47:32 WARN]:        at com.github.hoqhuuep.islandcraft.bukkit.BiomeGeneratorListener.onChunkLoad(BiomeGeneratorListener.java:90)
    [18:47:32 WARN]:        at sun.reflect.GeneratedMethodAccessor3.invoke(Unknown Source)
    [18:47:32 WARN]:        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    [18:47:32 WARN]:        at java.lang.reflect.Method.invoke(Unknown Source)
    [18:47:32 WARN]:        at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:304)
    [18:47:32 WARN]:        at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.java:62)
    [18:47:32 WARN]:        at org.bukkit.plugin.SimplePluginManager.fireEvent(SimplePluginManager.java:500)
    [18:47:32 WARN]:        at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.java:485)
    [18:47:32 WARN]:        at net.minecraft.server.v1_13_R1.ChunkMap.a(ChunkMap.java:41)
    [18:47:32 WARN]:        at net.minecraft.server.v1_13_R1.ChunkMap.put(ChunkMap.java:134)
    [18:47:32 WARN]:        at net.minecraft.server.v1_13_R1.ChunkMap.put(ChunkMap.java:1)
    [18:47:32 WARN]:        at org.bukkit.craftbukkit.libs.it.unimi.dsi.fastutil.longs.Long2ObjectMaps$SynchronizedMap.put(Long2ObjectMaps.java:371)
    [18:47:32 WARN]:        at net.minecraft.server.v1_13_R1.ChunkProviderServer.a(ChunkProviderServer.java:207)
    [18:47:32 WARN]:        at java.util.concurrent.CompletableFuture.uniApply(Unknown Source)
    [18:47:32 WARN]:        at java.util.concurrent.CompletableFuture.uniApplyStage(Unknown Source)
    [18:47:32 WARN]:        at java.util.concurrent.CompletableFuture.thenApply(Unknown Source)
    [18:47:32 WARN]:        at net.minecraft.server.v1_13_R1.ChunkProviderServer.generateChunk(ChunkProviderServer.java:169)
    [18:47:32 WARN]:        at net.minecraft.server.v1_13_R1.ChunkProviderServer.getChunkAt(ChunkProviderServer.java:127)
    [18:47:32 WARN]:        at net.minecraft.server.v1_13_R1.World.getChunkAt(World.java:268)
    [18:47:32 WARN]:        at net.minecraft.server.v1_13_R1.WorldProviderNormal.a(SourceFile:209)
    [18:47:32 WARN]:        at net.minecraft.server.v1_13_R1.WorldProviderNormal.a(SourceFile:186)
    [18:47:32 WARN]:        at net.minecraft.server.v1_13_R1.WorldServer.b(WorldServer.java:821)
    [18:47:32 WARN]:        at net.minecraft.server.v1_13_R1.WorldServer.a(WorldServer.java:731)
    [18:47:32 WARN]:        at org.bukkit.craftbukkit.v1_13_R1.CraftServer.createWorld(CraftServer.java:959)
    [18:47:32 WARN]:        at org.bukkit.Bukkit.createWorld(Bukkit.java:456)
    [18:47:32 WARN]:        at com.github.hoqhuuep.islandcraft.bukkit.IslandCraftPlugin.onCommand(IslandCraftPlugin.java:194)
    [18:47:32 WARN]:        at org.bukkit.command.PluginCommand.execute(PluginCommand.java:44)
    [18:47:32 WARN]:        at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:141)
    [18:47:32 WARN]:        at org.bukkit.craftbukkit.v1_13_R1.CraftServer.dispatchCommand(CraftServer.java:691)
    [18:47:32 WARN]:        at org.bukkit.craftbukkit.v1_13_R1.CraftServer.dispatchServerCommand(CraftServer.java:677)
    [18:47:32 WARN]:        at net.minecraft.server.v1_13_R1.DedicatedServer.aW(DedicatedServer.java:453)
    [18:47:32 WARN]:        at net.minecraft.server.v1_13_R1.DedicatedServer.w(DedicatedServer.java:412)
    [18:47:32 WARN]:        at net.minecraft.server.v1_13_R1.MinecraftServer.v(MinecraftServer.java:780)
    [18:47:32 WARN]:        at net.minecraft.server.v1_13_R1.MinecraftServer.run(MinecraftServer.java:678)
    [18:47:32 WARN]:        at java.lang.Thread.run(Unknown Source)
     
     
    #6 relucaXIV, Jul 23, 2018
    Last edited: Jul 23, 2018
  7. Here is my code:
    Code (Text):

    package com.github.hoqhuuep.islandcraft.nms.v1_13_R1;

    import java.lang.reflect.Field;

    import org.bukkit.World;

    import org.bukkit.craftbukkit.v1_13_R1.CraftWorld;
    import net.minecraft.server.v1_13_R1.ChunkGenerator;

    import com.github.hoqhuuep.islandcraft.nms.BiomeGenerator;
    import com.github.hoqhuuep.islandcraft.nms.NmsWrapper;

    public class NmsHandler extends NmsWrapper {

        @Override
        public boolean installBiomeGenerator(final World world, final BiomeGenerator biomeGenerator) {
            if (!(world instanceof CraftWorld)) {
                // Wrong version?
                return false;
            }
            final CraftWorld craftWorld = (CraftWorld) world;
            final ChunkGenerator<?> chunkGenerator = craftWorld.getHandle().getChunkProviderServer().
    [code=Java]package com.github.hoqhuuep.islandcraft.nms.v1_13_R1;

    import java.lang.reflect.Field;

    import org.bukkit.World;

    import org.bukkit.craftbukkit.v1_13_R1.CraftWorld;
    import net.minecraft.server.v1_13_R1.ChunkGenerator;

    import com.github.hoqhuuep.islandcraft.nms.BiomeGenerator;
    import com.github.hoqhuuep.islandcraft.nms.NmsWrapper;

    public class NmsHandler extends NmsWrapper {

        @Override
        public boolean installBiomeGenerator(final World world, final BiomeGenerator biomeGenerator) {
            if (!(world instanceof CraftWorld)) {
                // Wrong version?
                return false;
            }
            final CraftWorld craftWorld = (CraftWorld) world;
            final ChunkGenerator<?> chunkGenerator = craftWorld.getHandle().getChunkProviderServer().chunkGenerator;
            try {
                Field field = getField(chunkGenerator.getClass(), "c");
                field.setAccessible(true);
                if (field.get(chunkGenerator) instanceof CustomWorldChunkManager) {
                    // Already installed
                    return false;
                }
                field.set(chunkGenerator, new CustomWorldChunkManager(biomeGenerator));
                Log.g("BiomeGenerator installed!");
                return true;
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
                return false;
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
                return false;
            } catch (IllegalAccessException e) {
                e.printStackTrace();
                return false;
            }
        }

        private static Field getField(Class<?> clazz, String fieldName) throws NoSuchFieldException {
            try {
                return clazz.getField(fieldName);
            } catch (NoSuchFieldException e) {
                Class<?> superClass = clazz.getSuperclass();
                if (superClass == null) {
                    throw e;
                } else {
                    return getField(superClass, fieldName);
                }
            }
        }
    }
     
     
  8. I tried also with:
    Code (Text):

    return clazz.getDeclearedField(fieldName);
     
     
  9. There's a typo in there. I tried it out with
    Code (Text):
    return clazz.getDeclaredField(fieldName);
    and it worked.

    When using Reflection, class.getField can only get public fields, while class.getDeclaredField can get public, protected and private fields.
     
  10. I set this code:
    Code (Text):

    package com.github.hoqhuuep.islandcraft.nms.v1_13_R1;

    import java.lang.reflect.Field;

    import org.bukkit.World;

    import org.bukkit.craftbukkit.v1_13_R1.CraftWorld;
    import net.minecraft.server.v1_13_R1.ChunkGenerator;

    import com.github.hoqhuuep.islandcraft.nms.BiomeGenerator;
    import com.github.hoqhuuep.islandcraft.nms.NmsWrapper;

    public class NmsHandler extends NmsWrapper {

        @Override
        public boolean installBiomeGenerator(final World world, final BiomeGenerator biomeGenerator) {
            if (!(world instanceof CraftWorld)) {
                // Wrong version?
                return false;
            }
            final CraftWorld craftWorld = (CraftWorld) world;
            final ChunkGenerator<?> chunkGenerator = craftWorld.getHandle().getChunkProviderServer().chunkGenerator;
            try {
                Field field = getField(chunkGenerator.getClass(), "c");
                field.setAccessible(true);
                if (field.get(chunkGenerator) instanceof CustomWorldChunkManager) {
                    // Already installed
                    return false;
                }
                field.set(chunkGenerator, new CustomWorldChunkManager(biomeGenerator));
                Log.g("BiomeGenerator installed!");
                return true;
            } catch (NoSuchFieldException e) {
               e.printStackTrace();
                return false;
            } catch (IllegalArgumentException e) {
               e.printStackTrace();
                return false;
            } catch (IllegalAccessException e) {
               e.printStackTrace();
                return false;
            }
        }

        private static Field getField(Class<?> clazz, String fieldName) throws NoSuchFieldException {
            try {
           return clazz.getDeclaredField(fieldName);
            } catch (NoSuchFieldException e) {
                Class<?> superClass = clazz.getSuperclass();
                if (superClass == null) {
                    throw e;
                } else {
                    return getField(superClass, fieldName);
                }
            }
        }
    }
     
    But it gives me still that error? What I have done wrong?
    Code (Text):

    [23:03:11 WARN]: java.lang.NoSuchFieldException: c
    [23:03:11 WARN]:        at java.lang.Class.getDeclaredField(Unknown Source)
    [23:03:11 WARN]:        at com.github.hoqhuuep.islandcraft.nms.v1_13_R1.NmsHandler.getField(NmsHandler.java:47)
    [23:03:11 WARN]:        at com.github.hoqhuuep.islandcraft.nms.v1_13_R1.NmsHandler.getField(NmsHandler.java:53)
    [23:03:11 WARN]:        at com.github.hoqhuuep.islandcraft.nms.v1_13_R1.NmsHandler.getField(NmsHandler.java:53)
    [23:03:11 WARN]:        at com.github.hoqhuuep.islandcraft.nms.v1_13_R1.NmsHandler.getField(NmsHandler.java:53)
    [23:03:11 WARN]:        at com.github.hoqhuuep.islandcraft.nms.v1_13_R1.NmsHandler.installBiomeGenerator(NmsHandler.java:24)
    [23:03:11 WARN]:        at com.github.hoqhuuep.islandcraft.bukkit.BiomeGeneratorListener.onChunkLoad(BiomeGeneratorListener.java:90)
    [23:03:11 WARN]:        at sun.reflect.GeneratedMethodAccessor3.invoke(Unknown Source)
    [23:03:11 WARN]:        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    [23:03:11 WARN]:        at java.lang.reflect.Method.invoke(Unknown Source)
    [23:03:11 WARN]:        at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:304)
    [23:03:11 WARN]:        at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.java:62)
    [23:03:11 WARN]:        at org.bukkit.plugin.SimplePluginManager.fireEvent(SimplePluginManager.java:500)
    [23:03:11 WARN]:        at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.java:485)
    [23:03:11 WARN]:        at net.minecraft.server.v1_13_R1.ChunkMap.a(ChunkMap.java:41)
    [23:03:11 WARN]:        at net.minecraft.server.v1_13_R1.ChunkMap.put(ChunkMap.java:134)
    [23:03:11 WARN]:        at net.minecraft.server.v1_13_R1.ChunkMap.put(ChunkMap.java:1)
    [23:03:11 WARN]:        at org.bukkit.craftbukkit.libs.it.unimi.dsi.fastutil.longs.Long2ObjectMaps$SynchronizedMap.put(Long2ObjectMaps.java:371)
    [23:03:11 WARN]:        at net.minecraft.server.v1_13_R1.ChunkProviderServer.a(ChunkProviderServer.java:207)
    [23:03:11 WARN]:        at java.util.concurrent.CompletableFuture.uniApply(Unknown Source)
    [23:03:11 WARN]:        at java.util.concurrent.CompletableFuture.uniApplyStage(Unknown Source)
    [23:03:11 WARN]:        at java.util.concurrent.CompletableFuture.thenApply(Unknown Source)
    [23:03:11 WARN]:        at net.minecraft.server.v1_13_R1.ChunkProviderServer.generateChunk(ChunkProviderServer.java:169)
    [23:03:11 WARN]:        at net.minecraft.server.v1_13_R1.ChunkProviderServer.getChunkAt(ChunkProviderServer.java:127)
    [23:03:11 WARN]:        at net.minecraft.server.v1_13_R1.World.getChunkAt(World.java:268)
    [23:03:11 WARN]:        at net.minecraft.server.v1_13_R1.WorldProviderNormal.a(SourceFile:209)
    [23:03:11 WARN]:        at net.minecraft.server.v1_13_R1.WorldProviderNormal.a(SourceFile:186)
    [23:03:11 WARN]:        at net.minecraft.server.v1_13_R1.WorldServer.b(WorldServer.java:821)
    [23:03:11 WARN]:        at net.minecraft.server.v1_13_R1.WorldServer.a(WorldServer.java:731)
    [23:03:11 WARN]:        at org.bukkit.craftbukkit.v1_13_R1.CraftServer.createWorld(CraftServer.java:959)
    [23:03:11 WARN]:        at org.bukkit.Bukkit.createWorld(Bukkit.java:456)
    [23:03:11 WARN]:        at com.github.hoqhuuep.islandcraft.bukkit.IslandCraftPlugin.onCommand(IslandCraftPlugin.java:194)
    [23:03:11 WARN]:        at org.bukkit.command.PluginCommand.execute(PluginCommand.java:44)
    [23:03:11 WARN]:        at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:141)
    [23:03:11 WARN]:        at org.bukkit.craftbukkit.v1_13_R1.CraftServer.dispatchCommand(CraftServer.java:691)
    [23:03:11 WARN]:        at org.bukkit.craftbukkit.v1_13_R1.CraftServer.dispatchServerCommand(CraftServer.java:677)
    [23:03:11 WARN]:        at net.minecraft.server.v1_13_R1.DedicatedServer.aW(DedicatedServer.java:453)
    [23:03:11 WARN]:        at net.minecraft.server.v1_13_R1.DedicatedServer.w(DedicatedServer.java:412)
    [23:03:11 WARN]:        at net.minecraft.server.v1_13_R1.MinecraftServer.v(MinecraftServer.java:780)
    [23:03:11 WARN]:        at net.minecraft.server.v1_13_R1.MinecraftServer.run(MinecraftServer.java:678)
    [23:03:11 WARN]:        at java.lang.Thread.run(Unknown Source)
     
     
  11. I invoked that method to see how much fields are decleared:
    Code (Text):

    Log.g(clazz.getDeclaredFields().length + "");
     
    And it resulted to 2.
    So I tried to get the first field:
    Code (Text):

    return clazz.getDeclaredFields()[0];
     
    And the second one:
    Code (Text):

    return clazz.getDeclaredFields()[1];
     
    All two were of the wrong type.
    How it is possible? I saw the source of net.minecraft.server.v1_13_R1.ChunkGenerator and contains a field named c of type WorldChunkManager
     
  12. Sorry the class net.minecraft.server.v1_13_R1.ChunkGeneratorAbstract contains that field, the class net.minecraft.server.v1_13_R1.ChunkGenerator doesn't contain that field and doesn't extend ChunkGeneratorAbstract
    Code (Text):

    package net.minecraft.server.v1_13_R1;

    import java.util.List;
    import javax.annotation.Nullable;
    import org.bukkit.craftbukkit.libs.it.unimi.dsi.fastutil.longs.Long2ObjectMap;
    import org.bukkit.craftbukkit.libs.it.unimi.dsi.fastutil.longs.LongSet;

    public abstract interface ChunkGenerator<C extends GeneratorSettings>
    {
      public abstract void createChunk(IChunkAccess paramIChunkAccess);
     
      public abstract void addFeatures(RegionLimitedWorldAccess paramRegionLimitedWorldAccess, WorldGenStage.Features paramFeatures);
     
      public abstract void addDecorations(RegionLimitedWorldAccess paramRegionLimitedWorldAccess);
     
      public abstract void addMobs(RegionLimitedWorldAccess paramRegionLimitedWorldAccess);
     
      public abstract List<BiomeBase.BiomeMeta> getMobsFor(EnumCreatureType paramEnumCreatureType, BlockPosition paramBlockPosition);
     
      @Nullable
      public abstract BlockPosition findNearestMapFeature(World paramWorld, String paramString, BlockPosition paramBlockPosition, int paramInt);
     
      public abstract C getSettings();
     
      public abstract int a(World paramWorld, boolean paramBoolean1, boolean paramBoolean2);
     
      public abstract boolean canSpawnStructure(BiomeBase paramBiomeBase, StructureGenerator<? extends WorldGenFeatureConfiguration> paramStructureGenerator);
     
      @Nullable
      public abstract WorldGenFeatureConfiguration getFeatureConfiguration(BiomeBase paramBiomeBase, StructureGenerator<? extends WorldGenFeatureConfiguration> paramStructureGenerator);
     
      public abstract Long2ObjectMap<StructureStart> getStructureStartCache(StructureGenerator<? extends WorldGenFeatureConfiguration> paramStructureGenerator);
     
      public abstract Long2ObjectMap<LongSet> getStructureCache(StructureGenerator<? extends WorldGenFeatureConfiguration> paramStructureGenerator);
     
      public abstract WorldChunkManager getWorldChunkManager();
     
      public abstract long getSeed();
     
      public abstract int getSpawnHeight();
     
      public abstract int e();
     
      public abstract World getWorld();
    }
     
     
    #12 relucaXIV, Jul 23, 2018
    Last edited: Jul 23, 2018
  13. Printing out the generator class I got org.bukkit.craftbukkit.v1_13_R1.generator.NormalChunkGenerator this time. That would explain the problems, the craftbukkit generator is structured a bit differently from the NMS one (another plugin or something may have been messing with my results). Sorry, that one was my mistake.

    Code (Text):
    final ChunkGenerator<?> chunkGenerator = craftWorld.getHandle().worldProvider.getChunkGenerator();
    When I tried that it gets me net.minecraft.server.v1_13_R1.ChunkProviderGenerate which does extend ChunkGeneratorAbstract and has the field you're looking for.
     
    • Like Like x 1
  14. Thanks very much! It worked, it executed all the method without errors. But now I have some other work for do it working and to create the islands.
     
  15. It seems to be not installed beacause in the console is spammed this message infinity times:
    Code (Text):

    [01:52:46 INFO]: LOG: Constructor->CustomWorldGenerator works!
    [01:52:46 INFO]: LOG: installBiomeGenerator finished!
    [01:52:46 INFO]: LOG: Constructor->CustomWorldGenerator works!
    [01:52:46 INFO]: LOG: installBiomeGenerator finished!
    [01:52:46 INFO]: LOG: Constructor->CustomWorldGenerator works!
    [01:52:46 INFO]: LOG: installBiomeGenerator finished!
    [01:52:46 INFO]: LOG: Constructor->CustomWorldGenerator works!
    [01:52:46 INFO]: LOG: installBiomeGenerator finished!
    [01:52:46 INFO]: LOG: Constructor->CustomWorldGenerator works!
    [01:52:46 INFO]: LOG: installBiomeGenerator finished!
    [01:52:46 INFO]: LOG: Constructor->CustomWorldGenerator works!
    [01:52:46 INFO]: LOG: installBiomeGenerator finished!
    [01:52:46 INFO]: LOG: Constructor->CustomWorldGenerator works!
    [01:52:46 INFO]: LOG: installBiomeGenerator finished!
    [01:52:46 INFO]: LOG: Constructor->CustomWorldGenerator works!
    [01:52:46 INFO]: LOG: installBiomeGenerator finished!
    [01:52:46 INFO]: LOG: Constructor->CustomWorldGenerator works!
    [01:52:46 INFO]: LOG: installBiomeGenerator finished!
    [01:52:46 INFO]: LOG: Constructor->CustomWorldGenerator works!
    [01:52:46 INFO]: LOG: installBiomeGenerator finished!
    [01:52:46 INFO]: LOG: Constructor->CustomWorldGenerator works!
    [01:52:46 INFO]: LOG: installBiomeGenerator finished!
     
    The problem is that the code doesn't detect the field we are trying to se it like an instanceof CustomWorldChunkManager. There is a problem in this code? Thanks for all the help
    Code (Text):

            final CraftWorld craftWorld = (CraftWorld) world;
            final ChunkGenerator<?> chunkGenerator = craftWorld.getHandle().worldProvider.getChunkGenerator();
            try {
                Field field = getField(chunkGenerator.getClass(), "c");
                field.setAccessible(true);
             
                if (field.get(chunkGenerator) instanceof CustomWorldChunkManager) {
                    // Already installed
                    return false;
                }
             
                field.set(chunkGenerator, new CustomWorldChunkManager(biomeGenerator));
                Log.g("installBiomeGenerator finished!");
                return true;
            }
            catch (NoSuchFieldException e) {
               e.printStackTrace();
                return false;
            }
            catch (IllegalArgumentException e) {
               e.printStackTrace();
                return false;
            }
            catch (IllegalAccessException e) {
               e.printStackTrace();
                return false;
            }
     
     
  16. Try this out:
    Code (Text):

    if (chunkManager.getWorldChunkManager() instanceof CustomWorldChunkManager) {
                    // Already installed
                    return false;
                }
     
    If that doesn't work, try comparing class names:
    Code (Text):

    String chunkManagerName = chunkGenerator.getWorldChunkManager().getClass().getSimpleName();
    if (chunkManagerName.equals(CustomWorldChunkManager.getClass().getSimpleName())) {
                    // Already installed
                    return false;
                }
     
     
  17. Yes but the fact is that the variable WorldChunkManager c I think for some reasons is not set to the new variable CustomWorldChunkManager so the new WorldGenerator is not installed, I don't konw if I good explained what I intend.
     
  18. That operation should set the variable WorldChunkManager c to my custom WorldChunkManager, is it right?
    Code (Text):

    field.set(chunkGenerator, new CustomWorldChunkManager(biomeGenerator));
     
     
  19. I tried also to compare the names and the other method you suggest me, but noone worked for the reason that, I think, the variable WorldChunkManager c is not set to the new variable CustomWorldChunkManager so the new WorldGenerator is not installed
     
  20. Yes, it should be set. If it is not set or gets changed somehow, I don't know why.
     

Share This Page