[WIP] [WGEN] BetterGen: The world generator that is better than you!

Discussion in 'WIP and Development Status' started by jtjj222, Sep 1, 2012.

Thread Status:
Not open for further replies.
  1. That wouldn't affect sever stability, in fact that is exactly what Craftbukkit does (Github) and you could just write a manager plugin to handle everything. I don't think that if I made a PR for that it would get accepted.
     
  2. Offline

    jtjj222

    mncat77
    You said you were using reflection. I'm assuming you would be using a dynamic proxy. What happens if they update their server, and the method names change? Especially for a section of code dealing with worlds, it seems risky to me. It could definitely work, but I think it would benefit everyone if we got a few other members of the bukkit community together to fix the api once and for all. We would have to discuss it with the bukkit team and the community first, but I think it might be the best option.
     
  3. I looked into the details and the chunkProviderServer is a public field that has a deobfuscated name (won't change) and all the protected fields I need to access via reflection to construct a new ChunkProviderServer have deobfuscated names aswell and for extra safety it would rely on safeguard so nothing can ever break. I would work on an api, but it would end up in something pretty similar to what we have now (thus just as slow, although it can be improved) because we can't use nms in api's (and every wrapper makes everything slower). I don't think any PR's for that would be accepted, but if the bukkit team agrees with a ChunkGenerator closer to a ChunkProvider I'd be willing to work on that.
     
  4. Offline

    jtjj222

    mncat77
    Fair enough. Seems like it could work that way. Care to write a computationally intensive (i.e multiple 3d simplex generators) chunk generator and nms chunk provider quickly, and run each through a profiler so we can see what kind of gains it offers?
     
  5. Alright I had a short internet outage. I tried both variants and the profiler only shows the same big chunk the noise generator takes up and the figures to compare are to small to do so, so I started up a server (exact same setup, even same seed, etc) and waited for the spawn chunks to be generated and the method without api was about 20% faster. (18s vs 22s). If you want to try it for yourself here are the sources for both:
    Show Spoiler
    Code:java
    1. package org.bettergenteam.bettergen.chunkgenerators;
    2.  
    3. import java.util.Random;
    4. import org.bukkit.World;
    5. import org.bukkit.generator.ChunkGenerator;
    6. import org.bukkit.util.noise.SimplexOctaveGenerator;
    7.  
    8. public class TestChunkGenerator extends ChunkGenerator {
    9.  
    10. public static void setBlock(int x, int y, int z, byte[][] chunk, byte b) {
    11. //if the Block section the block is in hasn't been used yet, allocate it
    12. if (chunk[y >> 4] == null) {
    13. chunk[y >> 4] = new byte[16 * 16 * 16];
    14. }
    15. if (!(y <= 256 && y >= 0 && x <= 16 && x >= 0 && z <= 16 && z >= 0)) {
    16. return;
    17. }
    18. try {
    19. chunk[y >> 4][((y & 0xF) << 8) | (z << 4) | x] = b;
    20. } catch (Exception e) {
    21. // do nothing
    22. }
    23. }
    24.  
    25. public static byte getBlock(int x, int y, int z, byte[][] chunk) {
    26. //if the Block section the block is in hasn't been used yet, allocate it
    27. if (chunk[y >> 4] == null) {
    28. return 0;
    29. } //block is air as it hasnt been allocated
    30. if (!(y <= 256 && y >= 0 && x <= 16 && x >= 0 && z <= 16 && z >= 0)) {
    31. return 0;
    32. }
    33. try {
    34. return chunk[y >> 4][((y & 0xF) << 8) | (z << 4) | x];
    35. } catch (Exception e) {
    36. e.printStackTrace();
    37. return 0;
    38. }
    39. }
    40.  
    41. @Override
    42. public byte[][] generateBlockSections(World world, Random random, int chunkX, int chunkZ, BiomeGrid biomes) {
    43. SimplexOctaveGenerator simplex = new SimplexOctaveGenerator(1337, 8);
    44.  
    45. byte[][] chunk = new byte[world.getMaxHeight() / 16][];
    46.  
    47. int realX = chunkX * 16;
    48. int realZ = chunkZ * 16;
    49.  
    50. for(int x = 0; x < 16; x++) {
    51. int rX = realX + x;
    52. for(int z = 0; z < 16; z++) {
    53. int rZ = realZ + z;
    54. for(int y = 0; y < 128; y++) {
    55. setBlock(x, y, z, chunk, (byte)(simplex.noise(rX + x, y, rZ + z, .002, .002)>0?1:0));
    56. }
    57. }
    58.  
    59. }
    60.  
    61. return chunk;
    62. }
    63.  
    64. }
    65.  


    Show Spoiler
    Code:java
    1. package org.bettergenteam.bettergen.chunkprovider;
    2.  
    3. import java.util.List;
    4. import net.minecraft.server.v1_6_R3.Chunk;
    5. import net.minecraft.server.v1_6_R3.ChunkPosition;
    6. import net.minecraft.server.v1_6_R3.EnumCreatureType;
    7. import net.minecraft.server.v1_6_R3.IChunkProvider;
    8. import net.minecraft.server.v1_6_R3.IProgressUpdate;
    9. import net.minecraft.server.v1_6_R3.World;
    10. import org.bukkit.util.noise.SimplexOctaveGenerator;
    11.  
    12. public class ChunkProviderTest implements IChunkProvider {
    13.  
    14. private final World world;
    15. private final long seed;
    16. private SimplexOctaveGenerator simplex;
    17.  
    18.  
    19. public ChunkProviderTest(World world, long seed) {
    20. this.seed = seed;
    21. this.world = world;
    22. this.simplex = new SimplexOctaveGenerator(this.seed, 8);
    23. }
    24.  
    25. public Chunk getChunkAt(int x, int z) {
    26. return this.getOrCreateChunk(x, z);
    27. }
    28.  
    29. public Chunk getOrCreateChunk(int chunkX, int chunkZ) {
    30. byte[] blocks = new byte['\u8000'];
    31.  
    32. int realX = chunkX * 16;
    33. int realZ = chunkZ * 16;
    34.  
    35. for(int x = 0; x < 16; x++) {
    36. int a = x * 2048;
    37. int rX = realX + x;
    38. for(int z = 0; z < 16; z++) {
    39. int b = z * 128;
    40. int rZ = realZ + z;
    41. for(int y = 0; y < 128; y++) {
    42. blocks[a + b + y] = (byte)(simplex.noise(rX + x, y, rZ + z, .002, .002)>0?1:0);
    43. }
    44. }
    45.  
    46. }
    47.  
    48. Chunk chunk = new Chunk(this.world, blocks, chunkX, chunkZ);
    49.  
    50. chunk.initLighting();
    51.  
    52. return chunk;
    53. }
    54.  
    55. public boolean isChunkLoaded(int x, int z) {
    56. return true;
    57. }
    58.  
    59. public void getChunkAt(IChunkProvider ichunkprovider, int x, int z) {
    60. this.getChunkAt(x, z);
    61. }
    62.  
    63. public boolean saveChunks(boolean flag, IProgressUpdate iprogressupdate) {
    64. return true;
    65. }
    66.  
    67. public void b() {}
    68.  
    69. public boolean unloadChunks() {
    70. return false;
    71. }
    72.  
    73. public boolean canSave() {
    74. return true;
    75. }
    76.  
    77. public String getName() {
    78. return "TestChunkProvider";
    79. }
    80.  
    81. public List getMobsFor(EnumCreatureType enumcreaturetype, int i, int j, int k) {
    82. return null;
    83. }
    84.  
    85. public ChunkPosition findNearestMapFeature(World world, String s, int i, int j, int k) {
    86. return null;
    87. }
    88.  
    89. public int getLoadedChunks() {
    90. return 0;
    91. }
    92.  
    93. public void recreateStructures(int i, int j) {
    94. }
    95.  
    96. }
    97.  
     
  6. Offline

    jtjj222

    mncat77
    I think 20% is too little a gain to warrant the huge technical debt it incurs. It will probably be even less of a performance gain (and a hell of a lot more technical debt) if we use reflection to make updates easier. I think the performance isn't worth it, and the structure saving could be done in an sqlite db or something. Besides, we could probably get similar performance gains with some interpolation. As for the nms reuse, I was hoping we would be doing it all diy, that way I could have some material for the tutorials. It's your call.
     
  7. I'll start on the actualy generator and look at times there and if the timespans grow and it's worth I'll convert the code to be a direct implementation of a ChunkProvider rather than one wrapped several times. Could you (or if anyone else is still active on this project ^^) work on BlockPopulators if you have some time? I'll have to revise the BiomeLayers and make the base terrain, I hope I'll manage to do all that in one week (Probably not, because I'm still doing other stuff).

    EDIT: By the way a Stronghold populator (the vanilla one) is included in every ChunkProvider that was created with the Bukkit API ChunkGenerator so you don't have to worry about that.
     
  8. Update: ChunkGenerator is done (with API, will keep it this way, time is viable), still TODO:
    • Biome layers and classes
    • BlockPopulators
    The Biome layers are really the only big thing left to do. jtjj222 : Do you have any ideas how to do that from scratch or should we use the same princeples the minecraft code does?
     
Thread Status:
Not open for further replies.

Share This Page