Beispiel #1
0
  /** Populate a single chunk if needed. */
  private void populateChunk(int x, int z, boolean force) {
    GlowChunk chunk = getChunk(x, z);
    // cancel out if it's already populated
    if (chunk.isPopulated()) {
      return;
    }

    // cancel out if the 3x3 around it isn't available
    for (int x2 = x - 1; x2 <= x + 1; ++x2) {
      for (int z2 = z - 1; z2 <= z + 1; ++z2) {
        if (!getChunk(x2, z2).isLoaded() && (!force || !loadChunk(x2, z2, true))) {
          return;
        }
      }
    }

    // it might have loaded since before, so check again that it's not already populated
    if (chunk.isPopulated()) {
      return;
    }
    chunk.setPopulated(true);

    Random random = new Random(world.getSeed());
    long xRand = random.nextLong() / 2 * 2 + 1;
    long zRand = random.nextLong() / 2 * 2 + 1;
    random.setSeed((long) x * xRand + (long) z * zRand ^ world.getSeed());

    for (BlockPopulator p : world.getPopulators()) {
      p.populate(world, random, chunk);
    }

    EventFactory.callEvent(new ChunkPopulateEvent(chunk));
  }
Beispiel #2
0
 /**
  * Gets a list of loaded chunks.
  *
  * @return The currently loaded chunks.
  */
 public GlowChunk[] getLoadedChunks() {
   ArrayList<GlowChunk> result = new ArrayList<>();
   for (GlowChunk chunk : chunks.values()) {
     if (chunk.isLoaded()) {
       result.add(chunk);
     }
   }
   return result.toArray(new GlowChunk[result.size()]);
 }
Beispiel #3
0
  /**
   * Forces generation of the given chunk.
   *
   * @param x The X coordinate.
   * @param z The Z coordinate.
   * @return Whether the chunk was successfully regenerated.
   */
  public boolean forceRegeneration(int x, int z) {
    GlowChunk chunk = getChunk(x, z);

    if (chunk == null || !chunk.unload(false, false)) {
      return false;
    }

    chunk.setPopulated(false);
    try {
      generateChunk(chunk, x, z);
      populateChunk(x, z, false); // should this be forced?
    } catch (Throwable ex) {
      GlowServer.logger.log(
          Level.SEVERE, "Error while regenerating chunk (" + x + "," + z + ")", ex);
      return false;
    }
    return true;
  }
Beispiel #4
0
 /**
  * Performs the save for the given chunk using the storage provider.
  *
  * @param chunk The chunk to save.
  */
 public boolean performSave(GlowChunk chunk) {
   if (chunk.isLoaded()) {
     try {
       service.write(chunk);
       return true;
     } catch (IOException ex) {
       GlowServer.logger.log(Level.SEVERE, "Error while saving " + chunk, ex);
       return false;
     }
   }
   return false;
 }
Beispiel #5
0
  /**
   * Call the ChunkIoService to load a chunk, optionally generating the chunk.
   *
   * @param x The X coordinate of the chunk to load.
   * @param z The Y coordinate of the chunk to load.
   * @param generate Whether to generate the chunk if needed.
   * @return True on success, false on failure.
   */
  public boolean loadChunk(int x, int z, boolean generate) {
    GlowChunk chunk = getChunk(x, z);

    // try to load chunk
    try {
      if (service.read(chunk)) {
        EventFactory.callEvent(new ChunkLoadEvent(chunk, false));
        return true;
      }
    } catch (Exception e) {
      GlowServer.logger.log(Level.SEVERE, "Error while loading chunk (" + x + "," + z + ")", e);
      // an error in chunk reading may have left the chunk in an invalid state
      // (i.e. double initialization errors), so it's forcibly unloaded here
      chunk.unload(false, false);
    }

    // stop here if we can't generate
    if (!generate) {
      return false;
    }

    // get generating
    try {
      generateChunk(chunk, x, z);
    } catch (Throwable ex) {
      GlowServer.logger.log(Level.SEVERE, "Error while generating chunk (" + x + "," + z + ")", ex);
      return false;
    }

    EventFactory.callEvent(new ChunkLoadEvent(chunk, true));

    // right now, forcePopulate takes care of populating chunks that players actually see.
    /*for (int x2 = x - 1; x2 <= x + 1; ++x2) {
        for (int z2 = z - 1; z2 <= z + 1; ++z2) {
            populateChunk(x2, z2, false);
        }
    }*/
    return true;
  }
Beispiel #6
0
  /** Initialize a single chunk from the chunk generator. */
  private void generateChunk(GlowChunk chunk, int x, int z) {
    Random random = new Random((long) x * 341873128712L + (long) z * 132897987541L);
    BiomeGrid biomes = new BiomeGrid();

    int[] biomeValues =
        biomeGrid[0].generateValues(
            x * GlowChunk.WIDTH, z * GlowChunk.HEIGHT, GlowChunk.WIDTH, GlowChunk.HEIGHT);
    for (int i = 0; i < biomeValues.length; i++) {
      biomes.biomes[i] = (byte) biomeValues[i];
    }

    // extended sections with data
    if (generator instanceof GlowChunkGenerator) {
      short[][] extSections =
          ((GlowChunkGenerator) generator)
              .generateExtBlockSectionsWithData(world, random, x, z, biomes);
      if (extSections != null) {
        GlowChunk.ChunkSection[] sections = new GlowChunk.ChunkSection[extSections.length];
        for (int i = 0; i < extSections.length; ++i) {
          // this is sort of messy.
          if (extSections[i] != null) {
            sections[i] = new GlowChunk.ChunkSection();
            for (int j = 0; j < extSections[i].length; ++j) {
              sections[i].types[j] = (char) extSections[i][j];
            }
            sections[i].recount();
          }
        }
        chunk.initializeSections(sections);
        chunk.setBiomes(biomes.biomes);
        chunk.automaticHeightMap();
        return;
      }
    }

    // extended sections
    short[][] extSections = generator.generateExtBlockSections(world, random, x, z, biomes);
    if (extSections != null) {
      GlowChunk.ChunkSection[] sections = new GlowChunk.ChunkSection[extSections.length];
      for (int i = 0; i < extSections.length; ++i) {
        // this is sort of messy.
        if (extSections[i] != null) {
          sections[i] = new GlowChunk.ChunkSection();
          for (int j = 0; j < extSections[i].length; ++j) {
            sections[i].types[j] = (char) (extSections[i][j] << 4);
          }
          sections[i].recount();
        }
      }
      chunk.initializeSections(sections);
      chunk.setBiomes(biomes.biomes);
      chunk.automaticHeightMap();
      return;
    }

    // normal sections
    byte[][] blockSections = generator.generateBlockSections(world, random, x, z, biomes);
    if (blockSections != null) {
      GlowChunk.ChunkSection[] sections = new GlowChunk.ChunkSection[blockSections.length];
      for (int i = 0; i < blockSections.length; ++i) {
        // this is sort of messy.
        if (blockSections[i] != null) {
          sections[i] = new GlowChunk.ChunkSection();
          for (int j = 0; j < blockSections[i].length; ++j) {
            sections[i].types[j] = (char) (blockSections[i][j] << 4);
          }
          sections[i].recount();
        }
      }
      chunk.initializeSections(sections);
      chunk.setBiomes(biomes.biomes);
      chunk.automaticHeightMap();
      return;
    }

    // deprecated flat generation
    byte[] types = generator.generate(world, random, x, z);
    GlowChunk.ChunkSection[] sections = new GlowChunk.ChunkSection[8];
    for (int sy = 0; sy < sections.length; ++sy) {
      GlowChunk.ChunkSection sec = new GlowChunk.ChunkSection();
      int by = 16 * sy;
      for (int cx = 0; cx < 16; ++cx) {
        for (int cz = 0; cz < 16; ++cz) {
          for (int cy = by; cy < by + 16; ++cy) {
            char type = (char) types[(cx * 16 + cz) * 128 + cy];
            sec.types[sec.index(cx, cy, cz)] = (char) (type << 4);
          }
        }
      }
      sec.recount();
      sections[sy] = sec;
    }
    chunk.initializeSections(sections);
    chunk.setBiomes(biomes.biomes);
    chunk.automaticHeightMap();
  }