Пример #1
0
    def __init__(self, world, seed):
        super(TerrainGeneratorSimple, self).__init__(seed)
        self.world = world
        self.seed = G.SEED  #seed
        self.rand = random.Random(seed)
        perm = range(255)
        self.rand.shuffle(perm)
        self.noise = SimplexNoise(permutation_table=perm).noise2
        #self.noise = PerlinNoise(seed).noise
        self.PERSISTENCE = 2.1379201  #AKA lacunarity
        self.H = 0.836281

        self.biome_generator = BiomeGenerator(seed)

        #Fun things to adjust
        self.OCTAVES = 9  #Higher linearly increases calc time; increases apparent 'randomness'
        self.height_range = 32  #If you raise this, you should shrink zoom_level equally
        self.height_base = 32  #The lowest point the perlin terrain will generate (below is "underground")
        self.island_shore = 38  #below this is sand, above is grass .. island only
        self.water_level = 36  # have water 2 block higher than base, allowing for some rivers...
        self.zoom_level = 0.002  #Smaller will create gentler, softer transitions. Larger is more mountainy

        # ores avaliable on the lowest level, closet to bedrock
        self.lowlevel_ores = ((B.stone_block, ) * 75 +
                              (B.diamondore_block, ) * 2 +
                              (B.sapphireore_block, ) * 2)
        #  ores in the 'mid-level' .. also, the common ore blocks
        self.midlevel_ores = ((B.stone_block, ) * 80 +
                              (B.rubyore_block, ) * 2 +
                              (B.coalore_block, ) * 4 +
                              (B.gravel_block, ) * 5 +
                              (B.ironore_block, ) * 5 +
                              (B.lapisore_block, ) * 2)
        # ores closest to the top level dirt and ground
        self.highlevel_ores = ((B.stone_block, ) * 85 +
                               (B.gravel_block, ) * 5 +
                               (B.coalore_block, ) * 3 +
                               (B.quartz_block, ) * 5)
        self.underwater_blocks = ((B.sand_block, ) * 70 +
                                  (B.gravel_block, ) * 20 +
                                  (B.clay_block, ) * 10)
        #self.world_type_trees = (N.oak_tree, N.birch_tree, N.water_melon, N.pumpkin, N.y_flowers, N.potato, N.carrot, N.rose)
        self.world_type_trees = (N.oak_tree, N.birch_tree, N.jungle_tree)
        self.world_type_plants = (N.pumpkin, N.potato, N.carrot, N.water_melon)
        self.world_type_grass = (N.y_flowers, N.tall_grass, N.rose,
                                 N.tall_grass0, N.tall_grass1, N.cactus,
                                 N.tall_grass2, N.tall_cactus, N.tall_grass3,
                                 N.tall_grass4, N.tall_grass5, N.tall_grass6,
                                 N.tall_grass7, N.dead_bush, N.desert_grass)
        #This is a list of blocks that may leak over from adjacent sectors and whose presence doesn't mean the sector is generated
        self.autogenerated_blocks = N.VEGETATION_BLOCKS
        self.nether = (B.nether_block, B.soulsand_block, B.netherore_block,
                       B.air_block)
        #self.nether = ((B.nether_block,) * 80 + (B.soulsand_block,) * 15 + (B.netherore_block,) * 5 + (B.air_block,) * 10)

        self.weights = [
            self.PERSISTENCE**(-self.H * n) for n in xrange(self.OCTAVES)
        ]
Пример #2
0
    def show_map(self):
        print("map called...")
        # taken from Nebual's biome_explorer, this is ment to be a full screen map that uses mini tiles to make a full 2d map.
        with open(os.path.join(G.game_dir, "world", "seed"), "rb") as f:
            SEED = f.read()
        b = BiomeGenerator(SEED)
        x, y, z = self.player.position
        curx = x
        cury = y
        xsize = 79
        ysize = 28
        pbatch = pyglet.graphics.Batch()
        pgroup = pyglet.graphics.OrderedGroup(1)
        DESERT, PLAINS, MOUNTAINS, SNOW, FOREST = range(5)
        letters = ["D", "P", "M", "S", "F"]

        #  temp background pic...
        image = load_image('resources', 'textures', 'main_menu_background.png')

        #map_frame = image_sprite(image, pbatch, 0, y=G.WINDOW_WIDTH, height=G.WINDOW_HEIGHT)
        #sprite = pyglet.sprite.Sprite(image)
        #sprite.image(image)
        #sprite.visible = True
        # map_frame.draw()
        # map_frame.visible = True
        for y in range(int(cury), int(cury + ysize)):
            for x in range(int(curx), int(curx + xsize)):
                #string += letters[b.get_biome_type(x,y)]
                tmap = letters[b.get_biome_type(x, y)]
                tile_map = load_image('resources', 'textures', tmap + '.png')
                tile_map.anchor_x = x * 8
                tile_map.anchor_Y = y * 8
                sprite = pyglet.sprite.Sprite(tile_map,
                                              x=x * 8,
                                              y=y * 8,
                                              batch=pbatch)
                game_map = image_sprite(tile_map, pbatch, pgroup, x * 8, y * 8,
                                        8, 8)
                game_map = pyglet.sprite.Sprite(image,
                                                x=G.WINDOW_WIDTH,
                                                y=G.WINDOW_HEIGHT,
                                                batch=pbatch,
                                                group=pgroup)
                game_map = pyglet.sprite.Sprite(tile_map,
                                                x=x * 8,
                                                y=y * 8,
                                                batch=pbatch,
                                                group=pgroup)

                tile_map.blit(x * 8, y * 8)

                #tile_map.draw()
                #map.append(tmap)
                game_map.draw()
                pbatch.draw()
Пример #3
0
 def __init__(self, seed):
     super(TerrainGenerator, self).__init__(seed)
     self.base_gen = PerlinNoise(seed)
     self.base_gen.octave = 8
     self.ocean_gen = PerlinNoise(seed + 11)
     self.ocean_gen.octave = 8
     self.river_gen = PerlinNoise(seed + 31)
     self.river_gen.octave = 8
     self.mount_gen = PerlinNoise(seed + 41)
     self.hill_gen = PerlinNoise(seed + 71)
     self.cave_gen = PerlinNoise(seed + 141)
     self.biome_gen = BiomeGenerator(seed)
Пример #4
0
 def set_seed(self, seed):
     self.base_gen = PerlinNoise(seed)
     self.base_gen.octave = 8
     self.ocean_gen = PerlinNoise(seed + 11)
     self.ocean_gen.octave = 8
     self.river_gen = PerlinNoise(seed + 31)
     self.river_gen.octave = 8
     self.mount_gen = PerlinNoise(seed + 41)
     self.hill_gen = PerlinNoise(seed + 71)
     self.cave_gen = PerlinNoise(seed + 141)
     self.biome_gen = BiomeGenerator(seed)
     self.seed = seed
Пример #5
0
    def show_map(self):
        print("map called...")
         # taken from Nebual's biome_explorer, this is ment to be a full screen map that uses mini tiles to make a full 2d map.
        with open(os.path.join(G.game_dir, "world", "seed"), "rb") as f:
            SEED = f.read()
        b = BiomeGenerator(SEED)
        x, y, z = self.player.position
        curx =  x
        cury = y
        xsize = 79
        ysize = 28
        pbatch = pyglet.graphics.Batch()
        pgroup = pyglet.graphics.OrderedGroup(1)
        DESERT, PLAINS, MOUNTAINS, SNOW, FOREST = range(5)
        letters = ["D","P","M","S","F"]

        #  temp background pic...
        image = load_image('resources', 'textures', 'main_menu_background.png')

        #map_frame = image_sprite(image, pbatch, 0, y=G.WINDOW_WIDTH, height=G.WINDOW_HEIGHT)
        #sprite = pyglet.sprite.Sprite(image)
        #sprite.image(image)
        #sprite.visible = True
       # map_frame.draw()
       # map_frame.visible = True
        for y in range(int(cury),int(cury+ysize)):
         for x in range(int(curx),int(curx+xsize)):
             #string += letters[b.get_biome_type(x,y)]
            tmap = letters[b.get_biome_type(x,y)]
            tile_map = load_image('resources', 'textures', tmap +'.png')
            tile_map.anchor_x = x * 8
            tile_map.anchor_Y = y * 8
            sprite = pyglet.sprite.Sprite(tile_map, x=x * 8, y=y * 8, batch=pbatch)
            game_map = image_sprite(tile_map, pbatch, pgroup, x * 8, y * 8, 8, 8)
            game_map = pyglet.sprite.Sprite(image,x=G.WINDOW_WIDTH, y=G.WINDOW_HEIGHT,batch=pbatch, group=pgroup)
            game_map = pyglet.sprite.Sprite(tile_map,x=x*8, y=y*8,batch=pbatch, group=pgroup)

            tile_map.blit(x *8, y * 8)

            #tile_map.draw()
            #map.append(tmap)
            game_map.draw()
            pbatch.draw()
Пример #6
0
 def set_seed(self, seed):
     self.base_gen = PerlinNoise(seed)
     self.base_gen.octave = 8
     self.ocean_gen = PerlinNoise(seed + 11)
     self.ocean_gen.octave = 8
     self.river_gen = PerlinNoise(seed + 31)
     self.river_gen.octave = 8
     self.mount_gen = PerlinNoise(seed + 41)
     self.hill_gen = PerlinNoise(seed + 71)
     self.cave_gen = PerlinNoise(seed + 141)
     self.biome_gen = BiomeGenerator(seed) 
     self.seed = seed
Пример #7
0
 def __init__(self, seed):
     super(TerrainGenerator, self).__init__(seed)
     self.base_gen = PerlinNoise(seed)
     self.base_gen.octave = 8
     self.ocean_gen = PerlinNoise(seed + 11)
     self.ocean_gen.octave = 8
     self.river_gen = PerlinNoise(seed + 31)
     self.river_gen.octave = 8
     self.mount_gen = PerlinNoise(seed + 41)
     self.hill_gen = PerlinNoise(seed + 71)
     self.cave_gen = PerlinNoise(seed + 141)
     self.biome_gen = BiomeGenerator(seed) 
Пример #8
0
    def __init__(self, world, seed):
        super(TerrainGeneratorSimple, self).__init__(seed)
        self.world = world
        self.seed = G.SEED  #seed
        self.rand = random.Random(seed)
        perm = range(255)
        self.rand.shuffle(perm)
        self.noise = SimplexNoise(permutation_table=perm).noise2
        #self.noise = PerlinNoise(seed).noise
        self.PERSISTENCE = 2.1379201 #AKA lacunarity
        self.H = 0.836281

        self.biome_generator = BiomeGenerator(seed)

        #Fun things to adjust
        self.OCTAVES = 9        #Higher linearly increases calc time; increases apparent 'randomness'
        self.height_range = 32  #If you raise this, you should shrink zoom_level equally
        self.height_base = 32   #The lowest point the perlin terrain will generate (below is "underground")
        self.island_shore = 38  #below this is sand, above is grass .. island only
        self.water_level = 36 # have water 2 block higher than base, allowing for some rivers...
        self.zoom_level = 0.002 #Smaller will create gentler, softer transitions. Larger is more mountainy


        # ores avaliable on the lowest level, closet to bedrock
        self.lowlevel_ores = ((B.stone_block,) * 75 + (B.diamondore_block,) * 2 + (B.sapphireore_block,) * 2)
        #  ores in the 'mid-level' .. also, the common ore blocks
        self.midlevel_ores = ((B.stone_block,) * 80 + (B.rubyore_block,) * 2 +
                              (B.coalore_block,) * 4 + (B.gravel_block,) * 5 +
                              (B.ironore_block,) * 5 + (B.lapisore_block,) * 2)
        # ores closest to the top level dirt and ground
        self.highlevel_ores = ((B.stone_block,) * 85 + (B.gravel_block,) * 5 + (B.coalore_block,) * 3 + (B.quartz_block,) * 5)
        self.underwater_blocks = ((B.sand_block,) * 70 + (B.gravel_block,) * 20 + ( B.clay_block,) * 10)
        #self.world_type_trees = (N.oak_tree, N.birch_tree, N.water_melon, N.pumpkin, N.y_flowers, N.potato, N.carrot, N.rose)
        self.world_type_trees = (N.oak_tree, N.birch_tree, N.jungle_tree)
        self.world_type_plants = (N.pumpkin, N.potato, N.carrot, N.water_melon)
        self.world_type_grass = (N.y_flowers, N.tall_grass, N.rose, N.tall_grass0, N.tall_grass1, N.cactus, N.tall_grass2, N.tall_cactus, N.tall_grass3, N.tall_grass4, N.tall_grass5, N.tall_grass6, N.tall_grass7, N.dead_bush, N.desert_grass)
        #This is a list of blocks that may leak over from adjacent sectors and whose presence doesn't mean the sector is generated
        self.autogenerated_blocks = N.VEGETATION_BLOCKS
        self.nether = (B.nether_block, B.soulsand_block, B.netherore_block, B.air_block)
        #self.nether = ((B.nether_block,) * 80 + (B.soulsand_block,) * 15 + (B.netherore_block,) * 5 + (B.air_block,) * 10)

        self.weights = [self.PERSISTENCE ** (-self.H * n) for n in xrange(self.OCTAVES)]
Пример #9
0
 def dequeue_packet(self):
     with self.lock:
         packetid, packet = self.world.sector_packets.popleft()
     if packetid == 1:  # Entire Sector
         blocks, sectors = self.world, self.world.sectors
         secpos = struct.unpack("iii", packet[:12])
         sector = sectors[secpos]
         cx, cy, cz = sector_to_blockpos(secpos)
         fpos = 12
         exposed_pos = fpos + 1024
         for x in range(cx, cx + 8):
             for y in range(cy, cy + 8):
                 for z in range(cz, cz + 8):
                     read = packet[fpos:fpos + 2]
                     fpos += 2
                     unpacked = structuchar2.unpack(read)
                     if read != null2 and unpacked in BLOCKS_DIR:
                         position = x, y, z
                         try:
                             blocks[position] = BLOCKS_DIR[unpacked]
                             if blocks[position].sub_id_as_metadata:
                                 blocks[position] = type(
                                     BLOCKS_DIR[unpacked])()
                                 blocks[position].set_metadata(0)
                         except KeyError:
                             main_blk = BLOCKS_DIR[(unpacked[0], 0)]
                             if main_blk.sub_id_as_metadata:  # sub id is metadata
                                 blocks[position] = type(main_blk)()
                                 blocks[position].set_metadata(unpacked[-1])
                         sector.append(position)
                         if packet[exposed_pos:exposed_pos + 1] == b"1":
                             blocks.show_block(position)
                     exposed_pos += 1
         if secpos in self.world.sector_queue:
             del self.world.sector_queue[
                 secpos]  #Delete any hide sector orders
     elif packetid == 2:  # Blank Sector
         self.world.sectors[struct.unpack("iii", packet)] = []
     elif packetid == 3:  # Add Block
         self.world._add_block(struct.unpack("iii", packet[:12]),
                               BLOCKS_DIR[struct.unpack("BB", packet[12:])])
     elif packetid == 4:  # Remove Block
         self.world._remove_block(struct.unpack("iii", packet))
     elif packetid == 5:  # Chat Print
         self.controller.write_line(packet[:-4].decode('utf-8'),
                                    color=struct.unpack(
                                        "BBBB", packet[-4:]))
         if not self.controller.text_input.visible:
             self.controller.chat_box.visible = True
             pyglet.clock.unschedule(self.controller.hide_chat_box)
             pyglet.clock.schedule_once(self.controller.hide_chat_box,
                                        G.CHAT_FADE_TIME)
     elif packetid == 6:  # Inventory
         player = self.controller.player
         caret = 0
         for inventory in (player.quick_slots.slots, player.inventory.slots,
                           player.armor.slots):
             for i in range(len(inventory)):
                 id_main, id_sub, amount = struct.unpack(
                     "HBB", packet[caret:caret + 4])
                 caret += 4
                 if id_main == 0: continue
                 durability = -1
                 if id_main >= G.ITEM_ID_MIN and (
                         id_main, id_sub) not in G.ITEMS_DIR:
                     #The subid must be durability
                     durability = id_sub * G.ITEMS_DIR[
                         (id_main, 0)].durability // 255
                     id_sub = 0
                 inventory[i] = ItemStack(type=BlockID(id_main, id_sub),
                                          amount=amount,
                                          durability=durability)
         self.controller.item_list.update_items()
         self.controller.inventory_list.update_items()
     elif packetid == 7:  # New player connected
         plyid, name = struct.unpack(
             "H", packet[:2])[0], packet[2:].decode('utf-8')
         if plyid not in self.controller.player_ids:
             self.controller.player_ids[plyid] = Player(username=name,
                                                        local_player=False)
         elif name == '\0':
             del self.controller.player_ids[plyid]
     elif packetid == 8:  # Player Movement
         ply = self.controller.player_ids[struct.unpack("H", packet[:2])[0]]
         ply.momentum = struct.unpack("fff", packet[2:14])
         ply.position = struct.unpack("ddd", packet[14:])
     elif packetid == 9:  # Player Jump
         self.controller.player_ids[struct.unpack("H",
                                                  packet)[0]].dy = 0.016
     elif packetid == 10:  # Update Tile Entity
         self.world[struct.unpack("iii", packet[:12])].update_tile_entity(
             packet[12:])
     elif packetid == 255:  # Spawn Position
         self.controller.player.position = struct.unpack("iii", packet[:12])
         packet = packet[12:]
         packet, seed = extract_string_packet(packet)
         self.world.biome_generator = BiomeGenerator(seed)
         #Now that we know where the player should be, we can enable .update again
         self.controller.update = self.controller.update_disabled
     else:
         warn(
             "Received unknown packetid %s, there's probably a version mismatch between client and server!"
             % packetid)
Пример #10
0
class TerrainGenerator(TerrainGeneratorBase):
    def __init__(self, seed):
        super(TerrainGenerator, self).__init__(seed)
        self.base_gen = PerlinNoise(seed)
        self.base_gen.octave = 8
        self.ocean_gen = PerlinNoise(seed + 11)
        self.ocean_gen.octave = 8
        self.river_gen = PerlinNoise(seed + 31)
        self.river_gen.octave = 8
        self.mount_gen = PerlinNoise(seed + 41)
        self.hill_gen = PerlinNoise(seed + 71)
        self.cave_gen = PerlinNoise(seed + 141)
        self.biome_gen = BiomeGenerator(seed)

    def set_seed(self, seed):
        self.base_gen = PerlinNoise(seed)
        self.base_gen.octave = 8
        self.ocean_gen = PerlinNoise(seed + 11)
        self.ocean_gen.octave = 8
        self.river_gen = PerlinNoise(seed + 31)
        self.river_gen.octave = 8
        self.mount_gen = PerlinNoise(seed + 41)
        self.hill_gen = PerlinNoise(seed + 71)
        self.cave_gen = PerlinNoise(seed + 141)
        self.biome_gen = BiomeGenerator(seed)
        self.seed = seed

    def generate_chunk(self, chunk_x, chunk_y, chunk_z):
        c = Chunk(position=(chunk_x, chunk_y, chunk_z))

        # density map
        d_map = init_3d_list(c.x_size + 1, c.y_size + 1, c.z_size + 1)

        for x in range(0, c.x_size + SAMPLE_RATE_HOR, SAMPLE_RATE_HOR):
            for z in range(0, c.z_size + SAMPLE_RATE_HOR, SAMPLE_RATE_HOR):
                for y in range(0, c.y_size + SAMPLE_RATE_VER, SAMPLE_RATE_VER):
                    d_map[x][y][z] = self.density(c.world_block_xpos(x), y,
                                                  c.world_block_zpos(z))
                    #print d_map[x][y][z]

        # interpolate the missing values
        self.tri_lerp_d_map(d_map)

        for x in range(CHUNK_X_SIZE):
            for z in range(CHUNK_Z_SIZE):
                biome_type = self.biome_gen.get_biome_type(x, z)
                first_block = -1
                for y in range(CHUNK_Y_SIZE - 1, 0, -1):
                    if y == 0:
                        c.set_block(x, y, z, bedrock_block)
                        break

                    # 32: sea level
                    if 0 < y <= 32:
                        c.set_block(x, y, z, water_block)

                    den = d_map[x][y][z]

                    if 0 <= den < 32:
                        if first_block == -1:
                            first_block = y

                        if self.cave_density(c.world_block_xpos(x), y,
                                             c.world_block_zpos(z)) > -0.7:
                            c = self.gen_outer_layer(x, y, z, first_block, c,
                                                     biome_type)
                        else:
                            c.set_block(x, y, z, air_block)

                        continue
                    elif den >= 32:

                        if first_block == -1:
                            first_block = y

                        if self.cave_density(c.world_block_xpos(x), y,
                                             c.world_block_zpos(z)) > -0.6:
                            c = self.gen_inner_layer(x, y, z, c)
                        else:
                            c.set_block(x, y, z, air_block)

                        continue

                    first_block = -1
        return c

    def gen_inner_layer(self, x, y, z, c):
        # Mineral generation should be here also
        c.set_block(x, y, z, stone_block)
        return c

    def gen_outer_layer(self, x, y, z, first_block, c, biome_type):

        depth = int(first_block - y)

        if biome_type == G.PLAINS or biome_type == G.MOUNTAINS or biome_type == G.FOREST:
            if 28 <= y <= 34:
                c.set_block(x, y, z, sand_block)
            elif depth == 0 and 32 < y < 128:
                c.set_block(x, y, z, grass_block)
            elif depth > 32:
                c.set_block(x, y, z, stone_block)
            else:
                c.set_block(x, y, z, dirt_block)
        elif biome_type == G.SNOW:
            if depth == 0 and y >= 32:
                c.set_block(x, y, z, snow_block)
            elif depth > 32:
                c.set_block(x, y, z, stone_block)
            else:
                c.set_block(x, y, z, dirt_block)
        elif biome_type == G.DESERT:
            if depth > 8:
                c.set_block(x, y, z, stone_block)
            else:
                c.set_block(x, y, z, sand_block)

        return c

    def lerp(self, x, x1, x2, v00, v01):
        return (float(x2 - x) / float(x2 - x1)) * v00 + (float(x - x1) /
                                                         float(x2 - x1)) * v01

    def tri_lerp(self, x, y, z, v000, v001, v010, v011, v100, v101, v110, v111,
                 x1, x2, y1, y2, z1, z2):
        x00 = self.lerp(x, x1, x2, v000, v100)
        x10 = self.lerp(x, x1, x2, v010, v110)
        x01 = self.lerp(x, x1, x2, v001, v101)
        x11 = self.lerp(x, x1, x2, v011, v111)
        u = self.lerp(y, y1, y2, x00, x01)
        v = self.lerp(y, y1, y2, x10, x11)
        return self.lerp(z, z1, z2, u, v)

    def tri_lerp_d_map(self, d_map):
        for x in range(CHUNK_X_SIZE):
            for y in range(CHUNK_Y_SIZE):
                for z in range(CHUNK_Z_SIZE):
                    if not (x % SAMPLE_RATE_HOR == 0 and y % SAMPLE_RATE_VER
                            == 0 and z % SAMPLE_RATE_HOR == 0):
                        offsetX = int((x / SAMPLE_RATE_HOR) * SAMPLE_RATE_HOR)
                        offsetY = int((y / SAMPLE_RATE_VER) * SAMPLE_RATE_VER)
                        offsetZ = int((z / SAMPLE_RATE_HOR) * SAMPLE_RATE_HOR)
                        d_map[x][y][z] = self.tri_lerp(
                            x, y, z, d_map[offsetX][offsetY][offsetZ],
                            d_map[offsetX][SAMPLE_RATE_VER + offsetY][offsetZ],
                            d_map[offsetX][offsetY][offsetZ + SAMPLE_RATE_HOR],
                            d_map[offsetX][offsetY +
                                           SAMPLE_RATE_VER][offsetZ +
                                                            SAMPLE_RATE_HOR],
                            d_map[SAMPLE_RATE_HOR + offsetX][offsetY][offsetZ],
                            d_map[SAMPLE_RATE_HOR +
                                  offsetX][offsetY + SAMPLE_RATE_VER][offsetZ],
                            d_map[SAMPLE_RATE_HOR +
                                  offsetX][offsetY][offsetZ + SAMPLE_RATE_HOR],
                            d_map[SAMPLE_RATE_HOR +
                                  offsetX][offsetY +
                                           SAMPLE_RATE_VER][offsetZ +
                                                            SAMPLE_RATE_HOR],
                            offsetX, SAMPLE_RATE_HOR + offsetX, offsetY,
                            SAMPLE_RATE_VER + offsetY, offsetZ,
                            offsetZ + SAMPLE_RATE_HOR)

    def _clamp(self, a):
        if a > 1:
            return 1
        elif a < 0:
            return 0
        else:
            return a

    def density(self, x, y, z):
        height = self.base_terrain(x, z)
        ocean = self.ocean_terrain(x, z)
        river = self.rive_terrain(x, z)

        mountains = self.mount_density(x, y, z)
        hills = self.hill_density(x, y, z)

        flatten = self._clamp(
            ((CHUNK_Y_SIZE - 16) - y) / int(CHUNK_Y_SIZE * 0.10))

        return -y + (((32.0 + height * 32.0) * self._clamp(river + 0.25) *
                      self._clamp(ocean + 0.25)) + mountains * 1024.0 +
                     hills * 128.0) * flatten

    def base_terrain(self, x, z):
        return self._clamp(
            (self.base_gen.fBm(0.004 * x, 0, 0.004 * z) + 1.0) / 2.0)

    def ocean_terrain(self, x, z):
        return self._clamp(self.ocean_gen.fBm(0.0009 * x, 0, 0.0009 * z) * 8.0)

    def rive_terrain(self, x, z):
        return self._clamp(
            (sqrt(abs(self.river_gen.fBm(0.0008 * x, 0, 0.0008 * z))) - 0.1) *
            7.0)

    def mount_density(self, x, y, z):
        ret = self.mount_gen.fBm(x * 0.002, y * 0.001, z * 0.002)
        return ret if ret > 0 else 0

    def hill_density(self, x, y, z):
        ret = self.hill_gen.fBm(x * 0.008, y * 0.006, z * 0.008) - 0.1
        return ret if ret > 0 else 0

    def cave_density(self, x, y, z):
        return self.cave_gen.fBm(x * 0.02, y * 0.02, z * 0.02)
Пример #11
0
class TerrainGeneratorSimple(TerrainGeneratorBase):
    """
    A simple and fast use of (Simplex) Perlin Noise to generate a heightmap
    Based on Jimx's work on the above TerrainGenerator class
    See http://code.google.com/p/fractalterraingeneration/wiki/Fractional_Brownian_Motion for more info
    """
    def __init__(self, world, seed):
        super(TerrainGeneratorSimple, self).__init__(seed)
        self.world = world
        self.seed = G.SEED  #seed
        self.rand = random.Random(seed)
        perm = list(range(255))
        self.rand.shuffle(perm)
        self.noise = SimplexNoise(permutation_table=perm).noise2
        #self.noise = PerlinNoise(seed).noise
        self.PERSISTENCE = 2.1379201  #AKA lacunarity
        self.H = 0.836281

        self.biome_generator = BiomeGenerator(seed)

        #Fun things to adjust
        self.OCTAVES = 9  #Higher linearly increases calc time; increases apparent 'randomness'
        self.height_range = 32  #If you raise this, you should shrink zoom_level equally
        self.height_base = 32  #The lowest point the perlin terrain will generate (below is "underground")
        self.island_shore = 38  #below this is sand, above is grass .. island only
        self.water_level = 36  # have water 2 block higher than base, allowing for some rivers...
        self.zoom_level = 0.002  #Smaller will create gentler, softer transitions. Larger is more mountainy

        # ores avaliable on the lowest level, closet to bedrock
        self.lowlevel_ores = ((stone_block, ) * 75 + (diamondore_block, ) * 2 +
                              (sapphireore_block, ) * 2)
        #  ores in the 'mid-level' .. also, the common ore blocks
        self.midlevel_ores = ((stone_block, ) * 80 + (rubyore_block, ) * 2 +
                              (coalore_block, ) * 4 + (gravel_block, ) * 5 +
                              (ironore_block, ) * 5 + (lapisore_block, ) * 2)
        # ores closest to the top level dirt and ground
        self.highlevel_ores = ((stone_block, ) * 85 + (gravel_block, ) * 5 +
                               (coalore_block, ) * 3 + (quartz_block, ) * 5)
        self.underwater_blocks = ((sand_block, ) * 70 + (gravel_block, ) * 20 +
                                  (clay_block, ) * 10)
        #self.world_type_trees = (OakTree, BirchTree, WaterMelon, Pumpkin, YFlowers, Potato, Carrot, Rose)
        self.world_type_trees = (OakTree, BirchTree, JungleTree)
        self.world_type_plants = (Pumpkin, Potato, Carrot, WaterMelon)
        self.world_type_grass = (YFlowers, TallGrass, Rose, TallGrass0,
                                 TallGrass1, Cactus, TallGrass2, TallCactus,
                                 TallGrass3, TallGrass4, TallGrass5,
                                 TallGrass6, TallGrass7, DeadBush, DesertGrass)
        #This is a list of blocks that may leak over from adjacent sectors and whose presence doesn't mean the sector is generated
        self.autogenerated_blocks = VEGETATION_BLOCKS
        self.nether = (nether_block, soulsand_block, netherore_block,
                       air_block)
        #self.nether = ((nether_block,) * 80 + (soulsand_block,) * 15 + (netherore_block,) * 5 + (air_block,) * 10)

        self.weights = [
            self.PERSISTENCE**(-self.H * n) for n in xrange(self.OCTAVES)
        ]

    def _clamp(self, a):
        if a > 1:
            return 0.9999  #So int rounds down properly and keeps it within the right sector
        elif a < 0:
            return 0
        else:
            return a

    def get_height(self, x, z):
        """ Given block coordinates, returns a block coordinate height """
        x *= self.zoom_level
        z *= self.zoom_level
        y = 0
        for weight in self.weights:
            y += self.noise(x, z) * weight

            x *= self.PERSISTENCE
            z *= self.PERSISTENCE

        return int(self.height_base +
                   self._clamp((y + 1.0) / 2.0) * self.height_range)

    def generate_sector(self, sector):
        world = self.world
        if sector in world.sectors:
            #This sector is already loaded? Does it just have leaf blocks or something?
            for pos in world.sectors[sector]:
                if world[pos] not in self.autogenerated_blocks:
                    return

        #if G.TERRAIN_CHOICE != 'nether':
        TERRAIN_CHOICE = self.biome_generator.get_biome_type(
            sector[0], sector[2])

        TREE_CHANCE = G.TREE_CHANCE
        WILDFOOD_CHANCE = G.WILDFOOD_CHANCE
        GRASS_CHANCE = G.GRASS_CHANCE

        #TODO: This is very untidy, should be converted to a dict or something clever
        if TERRAIN_CHOICE == G.FOREST:
            main_block = grass_block
            self.height_range = 32
            self.height_base = 32
            self.island_shore = 0
            self.water_level = 0
            self.zoom_level = 0.002
            TREE_CHANCE = 0.012
        elif TERRAIN_CHOICE == G.PLAINS:
            main_block = grass_block
            self.height_range = 32
            self.height_base = 32
            self.island_shore = 0
            self.water_level = 0
            self.zoom_level = 0.002
            TREE_CHANCE = 0.004
        elif TERRAIN_CHOICE == G.SNOW:
            main_block = snowgrass_block
            self.height_range = 32
            self.height_base = 32
            self.island_shore = 34
            self.water_level = 33
            self.zoom_level = 0.002
        elif TERRAIN_CHOICE == G.DESERT:
            main_block = sand_block
            self.height_range = 32
            self.height_base = 32
            self.island_shore = 32
            self.water_level = 0
            self.zoom_level = 0.002
            TREE_CHANCE = 0
        elif TERRAIN_CHOICE == G.ISLAND:  #Does not naturally occur
            # Some grass that cant be on sand, for a clean beach
            self.world_type_grass = (YFlowers, Rose, TallGrass)
            main_block = grass_block
            self.height_range = 32
            self.height_base = 32
            self.island_shore = 38
            self.water_level = 36
            self.zoom_level = 0.002
        elif TERRAIN_CHOICE == G.MOUNTAINS:
            main_block = stone_block
            self.height_range = 32
            self.height_base = 32
            self.island_shore = 18
            self.water_level = 20
            self.zoom_level = 0.001
        elif TERRAIN_CHOICE == G.NETHER:  #Does not naturally occur
            main_block = nether_block
            self.height_range = 32
            self.height_base = 32
            #no water in the nether
            self.island_shore = -1
            self.water_level = -2
            self.zoom_level = 0.01

        world.sectors[sector] = [
        ]  # Precache it incase it ends up being solid air, so it doesn't get regenerated indefinitely
        bx, by, bz = world.savingsystem.sector_to_blockpos(sector)

        if 0 <= by < (self.height_base + self.height_range):
            self.rand.seed(self.seed + "(%d,%d,%d)" % (bx, by, bz))

            bytop = by + 8

            # We pass these as local variables for performance and readability.
            # Functions:
            init_block = world.init_block
            get_height = self.get_height
            choose = self.rand.choice
            rand_random = self.rand.random
            # Variables (that are static during what follows)
            height_base = self.height_base
            island_shore = self.island_shore
            water_level = self.water_level
            underwater_blocks = self.underwater_blocks
            world_type_trees = self.world_type_trees
            world_type_plants = self.world_type_plants
            world_type_grass = self.world_type_grass
            if TERRAIN_CHOICE == G.NETHER:
                highlevel_ores = ((nether_block, ) * 60 +
                                  (soulsand_block, ) * 35 +
                                  (netherore_block, ) * 5 + (air_block, ) * 10)
                midlevel_ores = highlevel_ores
                lowlevel_ores = highlevel_ores
            else:
                highlevel_ores = self.highlevel_ores
                midlevel_ores = self.midlevel_ores
                lowlevel_ores = self.lowlevel_ores

            for x in xrange(bx, bx + 8):
                for z in xrange(bz, bz + 8):
                    if by < height_base:
                        # For sectors outside of the height_range, no point checking the heightmap
                        y = height_base
                    else:
                        # The heightmap falls within our sector, generate surface stuff
                        y = get_height(x, z)
                        if y > bytop:
                            y = bytop

                        if TERRAIN_CHOICE == G.MOUNTAINS:
                            if 0 <= y <= 35:  # bottom level = grass
                                main_block = grass_block
                            if 36 <= y <= 54:  # mid level = rock
                                main_block = stone_block
                            if y >= 55:  # top level = snow
                                main_block = snow_block

                        if y <= water_level:
                            if TERRAIN_CHOICE != G.DESERT:  # was y == self.height_base -- you can have water!
                                if TERRAIN_CHOICE == G.SNOW:  # top block is ice
                                    init_block((x, water_level, z), ice_block)
                                else:
                                    init_block((x, water_level, z),
                                               water_block)
                                # init_block((x, y -1, z), water_block)
                                init_block((x, water_level - 2, z),
                                           choose(underwater_blocks))
                                init_block((x, water_level - 3, z), dirt_block)
                            else:  # no water for you!
                                init_block((x, y + 1, z), sand_block)
                                init_block((x, y, z), sand_block)
                                init_block((x, y - 1, z), sand_block)
                                init_block((x, y - 2, z), sandstone_block)
                                init_block((x, y - 3, z), sandstone_block)
                            y -= 3
                        elif y < bytop:
                            if TERRAIN_CHOICE == G.ISLAND:  # always sand by the water, grass above
                                if y > island_shore:
                                    main_block = grass_block
                                else:
                                    main_block = sand_block
                            init_block((x, y, z), main_block)

                            veget_choice = rand_random()
                            veget_blocks = None
                            if veget_choice < TREE_CHANCE:
                                veget_blocks = world_type_trees
                            elif veget_choice < WILDFOOD_CHANCE:
                                veget_blocks = world_type_plants
                            elif veget_choice < GRASS_CHANCE:
                                veget_blocks = world_type_grass
                            if veget_blocks is not None:
                                world.generate_vegetation((x, y + 1, z),
                                                          choose(veget_blocks))

                            if main_block == sand_block:
                                underground_blocks = (sand_block, sand_block,
                                                      sandstone_block)
                            elif main_block == stone_block:
                                underground_blocks = (stone_block, ) * 3
                            elif main_block == nether_block:
                                underground_blocks = self.nether
                            else:
                                underground_blocks = (dirt_block, ) * 3

                            for d, block in enumerate(underground_blocks,
                                                      start=1):
                                init_block((x, y - d, z), block)

                            y -= 3

                    for yy in xrange(by, y):
                        # ores and filler...
                        if yy >= 32:
                            blockset = highlevel_ores
                        elif yy > 9:
                            blockset = midlevel_ores
                        elif yy > 2:
                            blockset = lowlevel_ores
                        elif yy <= 1:
                            blockset = (bedrock_block, )

                        init_block((x, yy, z), choose(blockset))
Пример #12
0
    def dequeue_packet(self):
        with self.lock:
            packetid, packet = self.world.sector_packets.popleft()
        # print(f"CLIENTPACKET_ID: ", packetid) if packetid != 1 else None
        # print(f"CLIENTPACKET_PAK:", packet) if packetid != 1 else None
        if packetid == 1:  # Entire Sector
            blocks, sectors = self.world, self.world.sectors
            # secpos = struct.unpack("iii", packet[:12])
            secpos = packet["sector"]
            # print(packet)
            sector = sectors[secpos]
            cx, cy, cz = sector_to_blockpos(secpos)
            fpos = 0  # 12
            exposed_pos = 0  # fpos + 1024
            for x in range(cx, cx + 8):
                for y in range(cy, cy + 8):
                    for z in range(cz, cz + 8):
                        sector_data = packet["sectorData"][
                            fpos:fpos + 2]  # .encode("ascii")
                        # print(read)
                        fpos += 2
                        unpacked = structuchar2.unpack(sector_data)
                        # unpacked = read
                        # print("UNPACKED:", unpacked)
                        if sector_data != null2 and unpacked in BLOCKS_DIR:
                            position = x, y, z
                            try:
                                blocks[position] = BLOCKS_DIR[unpacked]
                                if blocks[position].sub_id_as_metadata:
                                    blocks[position] = type(
                                        BLOCKS_DIR[unpacked])()
                                    blocks[position].set_metadata(0)
                            except KeyError:
                                main_blk = BLOCKS_DIR[(unpacked[0], 0)]
                                if main_blk.sub_id_as_metadata:  # sub id is metadata
                                    blocks[position] = type(main_blk)()
                                    blocks[position].set_metadata(unpacked[-1])
                            sector.append(position)
                            if packet["exposedSector"][exposed_pos] is "1":
                                blocks.show_block(position)
                        exposed_pos += 1
            if secpos in self.world.sector_queue:
                del self.world.sector_queue[
                    secpos]  # Delete any hide sector orders
        elif packetid == 2:  # Blank Sector
            self.world.sectors[packet["sector"]] = []
        elif packetid == 3:  # Add Block
            self.world._add_block(packet["position"],
                                  BLOCKS_DIR[packet["block"]])
        elif packetid == 4:  # Remove Block
            self.world._remove_block(packet["position"])
        elif packetid == 5:  # Chat Print
            self.controller.write_line(packet["message"].decode('utf-8'),
                                       color=packet["color"])
            if not self.controller.text_input.visible:
                self.controller.chat_box.visible = True
                pyglet.clock.unschedule(self.controller.hide_chat_box)
                pyglet.clock.schedule_once(self.controller.hide_chat_box,
                                           G.CHAT_FADE_TIME)
        elif packetid == 6:  # Inventory
            player = self.controller.player
            caret = 0
            print("CLIENT_PACKET06:", packet)
            for i in range(len(player.quick_slots.slots)):
                id_main, id_sub, amount = packet["items"]["quickSlots"][i]

                # print(id_main, id_sub, amount)
                # caret += 4
                if id_main == 0: continue
                durability = -1
                if id_main >= G.ITEM_ID_MIN and (id_main,
                                                 id_sub) not in G.ITEMS_DIR:
                    # The subid must be durability
                    durability = id_sub * G.ITEMS_DIR[BlockID(
                        id_main, 0)].durability / 255
                    id_sub = 0
                player.quick_slots.slots[i] = ItemStack(type=BlockID(
                    id_main, id_sub),
                                                        amount=amount,
                                                        durability=durability)

            for i in range(len(player.inventory.slots)):
                id_main, id_sub, amount = packet["items"]["inventory"][i]

                # print(id_main, id_sub, amount)
                # caret += 4
                if id_main == 0: continue
                durability = -1
                if id_main >= G.ITEM_ID_MIN and (id_main,
                                                 id_sub) not in G.ITEMS_DIR:
                    # The subid must be durability
                    durability = id_sub * G.ITEMS_DIR[BlockID(
                        id_main, 0)].durability / 255
                    id_sub = 0
                player.quick_slots.slots[i] = ItemStack(type=BlockID(
                    id_main, id_sub),
                                                        amount=amount,
                                                        durability=durability)

            for i in range(len(player.armor.slots)):
                id_main, id_sub, amount = packet["items"]["armor"][i]

                # print(id_main, id_sub, amount)
                # caret += 4
                if id_main == 0: continue
                durability = -1
                if id_main >= G.ITEM_ID_MIN and (id_main,
                                                 id_sub) not in G.ITEMS_DIR:
                    # The subid must be durability
                    durability = id_sub * G.ITEMS_DIR[BlockID(
                        id_main, 0)].durability / 255
                    id_sub = 0
                player.quick_slots.slots[i] = ItemStack(type=BlockID(
                    id_main, id_sub),
                                                        amount=amount,
                                                        durability=durability)

            # for inventory in (player.quick_slots.slots, player.inventory.slots, player.armor.slots):
            #     # for item in (player.quick_slots.slots + player.inventory.slots + player.armor.slots)
            #     for i in range(len(inventory)):
            #         # print(packet)
            #
            #         # print("PACKET_0x06:", packet.decode())
            #
            #         # packet = eval(packet.decode()[:-1]) if packet.decode().startswith(
            #         #     "b'") and packet.decode().endswith("'" + chr(packet[-1])) else packet
            #         id_main, id_sub, amount = packet[]
            #
            #         # print(id_main, id_sub, amount)
            #         caret += 4
            #         if id_main == 0: continue
            #         durability = -1
            #         if id_main >= G.ITEM_ID_MIN and (id_main, id_sub) not in G.ITEMS_DIR:
            #             # The subid must be durability
            #             durability = id_sub * G.ITEMS_DIR[BlockID(id_main, 0)].durability / 255
            #             id_sub = 0
            #         inventory[i] = ItemStack(type=BlockID(id_main, id_sub), amount=amount, durability=durability)
            self.controller.item_list.update_items()
            self.controller.inventory_list.update_items()
        elif packetid == 7:  # New player connected
            # plyid, name = struct.unpack("H", packet[:2])[0], packet[2:].decode('utf-8')
            plyid = packet["playerID"]
            name = packet["username"]
            if plyid not in self.controller.player_ids:
                self.controller.player_ids[plyid] = Player(username=name,
                                                           local_player=False)
            elif name == '\0':
                del self.controller.player_ids[plyid]
        elif packetid == 8:  # Player Movement
            ply = self.controller.player_ids[
                packet["playerID"]]  # struct.unpack("H", packet[:2])[0]]
            ply.momentum = packet[
                "momentum"]  # struct.unpack("fff", packet[2:14])
            ply.position = packet[
                "position"]  # struct.unpack("ddd", packet[14:])
        elif packetid == 9:  # Player Jump
            self.controller.player_ids[packet["playerID"]].dy = 0.016
        elif packetid == 10:  # Update Tile Entity
            self.world[packet["position"]].update_tile_entity(packet["value"])
        elif packetid == 255:  # Spawn Position
            self.controller.player.position = packet[
                "position"]  # struct.unpack("iii", packet[:12])
            # print(packet)
            # packet = packet[12:]  # TODO: Get the packet data from dictionary. PACKETID: 255 | CLIENT
            # packet, seed = extract_string_packet(packet)
            seed = packet["seed"]
            self.world.biome_generator = BiomeGenerator(seed)
            # Now that we know where the player should be, we can enable .update again
            self.controller.update = self.controller.update_disabled
        else:
            warn(
                "Received unknown packetid %s, there's probably a version mismatch between client and server!"
                % packetid)
Пример #13
0
class TerrainGenerator(TerrainGeneratorBase):
    def __init__(self, seed):
        super(TerrainGenerator, self).__init__(seed)
        self.base_gen = PerlinNoise(seed)
        self.base_gen.octave = 8
        self.ocean_gen = PerlinNoise(seed + 11)
        self.ocean_gen.octave = 8
        self.river_gen = PerlinNoise(seed + 31)
        self.river_gen.octave = 8
        self.mount_gen = PerlinNoise(seed + 41)
        self.hill_gen = PerlinNoise(seed + 71)
        self.cave_gen = PerlinNoise(seed + 141)
        self.biome_gen = BiomeGenerator(seed) 

    def set_seed(self, seed):
        self.base_gen = PerlinNoise(seed)
        self.base_gen.octave = 8
        self.ocean_gen = PerlinNoise(seed + 11)
        self.ocean_gen.octave = 8
        self.river_gen = PerlinNoise(seed + 31)
        self.river_gen.octave = 8
        self.mount_gen = PerlinNoise(seed + 41)
        self.hill_gen = PerlinNoise(seed + 71)
        self.cave_gen = PerlinNoise(seed + 141)
        self.biome_gen = BiomeGenerator(seed) 
        self.seed = seed

    def generate_chunk(self, chunk_x, chunk_y, chunk_z):
        c = Chunk(position=(chunk_x, chunk_y, chunk_z))

        # density map
        d_map = init_3d_list(c.x_size + 1, c.y_size + 1, c.z_size + 1)

        for x in range(0, c.x_size + SAMPLE_RATE_HOR, SAMPLE_RATE_HOR):
            for z in range(0, c.z_size + SAMPLE_RATE_HOR, SAMPLE_RATE_HOR):
                for y in range(0, c.y_size + SAMPLE_RATE_VER, SAMPLE_RATE_VER):
                    d_map[x][y][z] = self.density(c.world_block_xpos(x), y, c.world_block_zpos(z))
                    #print d_map[x][y][z]

        # interpolate the missing values
        self.tri_lerp_d_map(d_map)

        for x in range(CHUNK_X_SIZE):
            for z in range(CHUNK_Z_SIZE):
                biome_type = self.biome_gen.get_biome_type(x, z)
                first_block = -1
                for y in range(CHUNK_Y_SIZE - 1, 0, -1):
                    if y == 0:
                        c.set_block(x, y, z, B.bed_block)
                        break

                    # 32: sea level
                    if 0 < y <= 32:
                        c.set_block(x, y, z, B.water_block)

                    den = d_map[x][y][z]

                    if 0 <= den < 32:
                        if first_block == -1:
                            first_block = y

                        if self.cave_density(c.world_block_xpos(x), y, c.world_block_zpos(z)) > -0.7:
                            c = self.gen_outer_layer(x, y, z, first_block, c, biome_type)
                        else:
                            c.set_block(x, y, z, B.air_block)

                        continue
                    elif den >= 32:

                        if first_block == -1:
                            first_block = y

                        if self.cave_density(c.world_block_xpos(x), y, c.world_block_zpos(z)) > -0.6:
                            c = self.gen_inner_layer(x, y, z, c)
                        else:
                            c.set_block(x, y, z, B.air_block)

                        continue

                    first_block = -1
        return c

    def gen_inner_layer(self, x, y, z, c):
        # Mineral generation should be here also
        c.set_block(x, y, z, B.stone_block)
        return c

    def gen_outer_layer(self, x, y, z, first_block, c, biome_type):

        depth = int(first_block - y)

        if biome_type == G.PLAINS or biome_type == G.MOUNTAINS or biome_type == G.FOREST:
            if 28 <= y <= 34:
                c.set_block(x, y, z, B.sand_block)
            elif depth == 0 and 32 < y < 128:
                c.set_block(x, y, z, B.grass_block)
            elif depth > 32: 
                c.set_block(x, y, z, B.stone_block)
            else:
                c.set_block(x, y, z, B.dirt_block)
        elif biome_type == G.SNOW:
            if depth == 0 and y >= 32:
                    c.set_block(x, y, z, B.snow_block)
            elif depth > 32:
                c.set_block(x, y, z, B.stone_block)
            else:
                c.set_block(x, y, z, B.dirt_block)
        elif biome_type == G.DESERT:
            if depth > 8: 
                c.set_block(x, y, z, B.stone_block)
            else:
                c.set_block(x, y, z, B.sand_block)

        return c

    def lerp(self, x, x1, x2, v00, v01):
        return (float(x2 - x) / float(x2 - x1)) * v00 + (float(x - x1) / float(x2 - x1)) * v01

    def tri_lerp(self,x, y, z, v000, v001, v010, v011, v100, v101, v110, v111, x1, x2, y1, y2, z1, z2):
        x00 = self.lerp(x, x1, x2, v000, v100)
        x10 = self.lerp(x, x1, x2, v010, v110)
        x01 = self.lerp(x, x1, x2, v001, v101)
        x11 = self.lerp(x, x1, x2, v011, v111)
        u = self.lerp(y, y1, y2, x00, x01)
        v = self.lerp(y, y1, y2, x10, x11)
        return self.lerp(z, z1, z2, u, v)

    def tri_lerp_d_map(self, d_map):
        for x in range(CHUNK_X_SIZE):
            for y in range(CHUNK_Y_SIZE):
                for z in range(CHUNK_Z_SIZE):
                    if not (x % SAMPLE_RATE_HOR == 0 and y % SAMPLE_RATE_VER == 0 and z % SAMPLE_RATE_HOR == 0):
                        offsetX = int((x / SAMPLE_RATE_HOR) * SAMPLE_RATE_HOR)
                        offsetY = int((y / SAMPLE_RATE_VER) * SAMPLE_RATE_VER)
                        offsetZ = int((z / SAMPLE_RATE_HOR) * SAMPLE_RATE_HOR)
                        d_map[x][y][z] = self.tri_lerp(x, y, z, d_map[offsetX][offsetY][offsetZ], d_map[offsetX][SAMPLE_RATE_VER + offsetY][offsetZ], d_map[offsetX][offsetY][offsetZ + SAMPLE_RATE_HOR],
                                                                d_map[offsetX][offsetY + SAMPLE_RATE_VER][offsetZ + SAMPLE_RATE_HOR], d_map[SAMPLE_RATE_HOR + offsetX][offsetY][offsetZ], d_map[SAMPLE_RATE_HOR + offsetX][offsetY + SAMPLE_RATE_VER][offsetZ],
                                                                d_map[SAMPLE_RATE_HOR + offsetX][offsetY][offsetZ + SAMPLE_RATE_HOR], d_map[SAMPLE_RATE_HOR + offsetX][offsetY + SAMPLE_RATE_VER][offsetZ + SAMPLE_RATE_HOR], offsetX, SAMPLE_RATE_HOR + offsetX, offsetY,
                                                                SAMPLE_RATE_VER + offsetY, offsetZ, offsetZ + SAMPLE_RATE_HOR)

    def _clamp(self, a):
        if a > 1:
            return 1
        elif a < 0:
            return 0
        else:
            return a

    def density(self, x, y, z):
        height = self.base_terrain(x, z)
        ocean = self.ocean_terrain(x, z)
        river = self.rive_terrain(x, z)

        mountains = self.mount_density(x, y, z)
        hills = self.hill_density(x, y, z)

        flatten = self._clamp(((CHUNK_Y_SIZE - 16) - y) / int(CHUNK_Y_SIZE * 0.10))

        return -y + (((32.0 + height * 32.0) * self._clamp(river + 0.25) * self._clamp(ocean + 0.25)) + mountains * 1024.0 + hills * 128.0) * flatten

    def base_terrain(self, x, z):
        return self._clamp((self.base_gen.fBm(0.004 * x, 0, 0.004 * z) + 1.0) / 2.0)

    def ocean_terrain(self, x, z):
        return self._clamp(self.ocean_gen.fBm(0.0009 * x, 0, 0.0009 * z) * 8.0)

    def rive_terrain(self, x, z):
        return self._clamp((sqrt(abs(self.river_gen.fBm(0.0008 * x, 0, 0.0008 * z))) - 0.1) * 7.0)

    def mount_density(self, x, y, z):
        ret = self.mount_gen.fBm(x * 0.002, y * 0.001, z * 0.002)
        return ret if ret > 0 else 0

    def hill_density(self, x, y, z):
        ret = self.hill_gen.fBm(x * 0.008, y * 0.006, z * 0.008) - 0.1
        return ret if ret > 0 else 0

    def cave_density(self, x, y, z):
        return self.cave_gen.fBm(x * 0.02, y * 0.02, z * 0.02)
Пример #14
0
class TerrainGeneratorSimple(TerrainGeneratorBase):
    """
    A simple and fast use of (Simplex) Perlin Noise to generate a heightmap
    Based on Jimx's work on the above TerrainGenerator class
    See http://code.google.com/p/fractalterraingeneration/wiki/Fractional_Brownian_Motion for more info
    """
    def __init__(self, world, seed):
        super(TerrainGeneratorSimple, self).__init__(seed)
        self.world = world
        self.seed = G.SEED  #seed
        self.rand = random.Random(seed)
        perm = range(255)
        self.rand.shuffle(perm)
        self.noise = SimplexNoise(permutation_table=perm).noise2
        #self.noise = PerlinNoise(seed).noise
        self.PERSISTENCE = 2.1379201 #AKA lacunarity
        self.H = 0.836281

        self.biome_generator = BiomeGenerator(seed)

        #Fun things to adjust
        self.OCTAVES = 9        #Higher linearly increases calc time; increases apparent 'randomness'
        self.height_range = 32  #If you raise this, you should shrink zoom_level equally
        self.height_base = 32   #The lowest point the perlin terrain will generate (below is "underground")
        self.island_shore = 38  #below this is sand, above is grass .. island only
        self.water_level = 36 # have water 2 block higher than base, allowing for some rivers...
        self.zoom_level = 0.002 #Smaller will create gentler, softer transitions. Larger is more mountainy


        # ores avaliable on the lowest level, closet to bedrock
        self.lowlevel_ores = ((B.stone_block,) * 75 + (B.diamondore_block,) * 2 + (B.sapphireore_block,) * 2)
        #  ores in the 'mid-level' .. also, the common ore blocks
        self.midlevel_ores = ((B.stone_block,) * 80 + (B.rubyore_block,) * 2 +
                              (B.coalore_block,) * 4 + (B.gravel_block,) * 5 +
                              (B.ironore_block,) * 5 + (B.lapisore_block,) * 2)
        # ores closest to the top level dirt and ground
        self.highlevel_ores = ((B.stone_block,) * 85 + (B.gravel_block,) * 5 + (B.coalore_block,) * 3 + (B.quartz_block,) * 5)
        self.underwater_blocks = ((B.sand_block,) * 70 + (B.gravel_block,) * 20 + ( B.clay_block,) * 10)
        #self.world_type_trees = (N.oak_tree, N.birch_tree, N.water_melon, N.pumpkin, N.y_flowers, N.potato, N.carrot, N.rose)
        self.world_type_trees = (N.oak_tree, N.birch_tree, N.jungle_tree)
        self.world_type_plants = (N.pumpkin, N.potato, N.carrot, N.water_melon)
        self.world_type_grass = (N.y_flowers, N.tall_grass, N.rose, N.tall_grass0, N.tall_grass1, N.cactus, N.tall_grass2, N.tall_cactus, N.tall_grass3, N.tall_grass4, N.tall_grass5, N.tall_grass6, N.tall_grass7, N.dead_bush, N.desert_grass)
        #This is a list of blocks that may leak over from adjacent sectors and whose presence doesn't mean the sector is generated
        self.autogenerated_blocks = N.VEGETATION_BLOCKS
        self.nether = (B.nether_block, B.soulsand_block, B.netherore_block, B.air_block)
        #self.nether = ((B.nether_block,) * 80 + (B.soulsand_block,) * 15 + (B.netherore_block,) * 5 + (B.air_block,) * 10)

        self.weights = [self.PERSISTENCE ** (-self.H * n) for n in xrange(self.OCTAVES)]
    def _clamp(self, a):
        if a > 1:
            return 0.9999 #So int rounds down properly and keeps it within the right sector
        elif a < 0:
            return 0
        else:
            return a
    def get_height(self,x,z):
        """ Given block coordinates, returns a block coordinate height """
        x *= self.zoom_level
        z *= self.zoom_level
        y = 0
        for weight in self.weights:
            y += self.noise(x, z) * weight

            x *= self.PERSISTENCE
            z *= self.PERSISTENCE

        return int(self.height_base + self._clamp((y+1.0)/2.0)*self.height_range)

    def generate_sector(self, sector):
        world = self.world
        if sector in world.sectors:
            #This sector is already loaded? Does it just have leaf blocks or something?
            for pos in world.sectors[sector]:
                if world[pos] not in self.autogenerated_blocks:
                    return

        #if G.TERRAIN_CHOICE != 'nether':
        TERRAIN_CHOICE = self.biome_generator.get_biome_type(sector[0], sector[2])

        TREE_CHANCE = G.TREE_CHANCE
        WILDFOOD_CHANCE = G.WILDFOOD_CHANCE
        GRASS_CHANCE = G.GRASS_CHANCE

        #TODO: This is very untidy, should be converted to a dict or something clever
        if TERRAIN_CHOICE == G.FOREST:
            main_block = B.grass_block
            self.height_range = 32
            self.height_base = 32
            self.island_shore = 0
            self.water_level = 0
            self.zoom_level = 0.002
            TREE_CHANCE = 0.012
        elif TERRAIN_CHOICE == G.PLAINS:
            main_block = B.grass_block
            self.height_range = 32
            self.height_base = 32
            self.island_shore = 0
            self.water_level = 0
            self.zoom_level = 0.002
            TREE_CHANCE = 0.004
        elif TERRAIN_CHOICE == G.SNOW:
            main_block = B.snowgrass_block
            self.height_range = 32
            self.height_base = 32
            self.island_shore = 34
            self.water_level = 33
            self.zoom_level = 0.002
        elif TERRAIN_CHOICE == G.DESERT:
            main_block = B.sand_block
            self.height_range = 32
            self.height_base = 32
            self.island_shore = 32
            self.water_level = 0
            self.zoom_level = 0.002
            TREE_CHANCE = 0
        elif TERRAIN_CHOICE == G.ISLAND:  #Does not naturally occur
            # Some grass that cant be on sand, for a clean beach
            self.world_type_grass = (N.y_flowers, N.rose, N.tall_grass)
            main_block = B.grass_block
            self.height_range = 32
            self.height_base = 32
            self.island_shore = 38
            self.water_level = 36
            self.zoom_level = 0.002
        elif TERRAIN_CHOICE == G.MOUNTAINS:
            main_block = B.stone_block
            self.height_range = 32
            self.height_base = 32
            self.island_shore = 18
            self.water_level = 20
            self.zoom_level = 0.001
        elif TERRAIN_CHOICE == G.NETHER:  #Does not naturally occur
            main_block = B.nether_block
            self.height_range = 32
            self.height_base = 32
            #no water in the nether
            self.island_shore = -1
            self.water_level = -2
            self.zoom_level = 0.01

        world.sectors[sector] = []  # Precache it incase it ends up being solid air, so it doesn't get regenerated indefinitely
        bx, by, bz = world.savingsystem.sector_to_blockpos(sector)

        if 0 <= by < (self.height_base + self.height_range):
            self.rand.seed(self.seed + "(%d,%d,%d)" % (bx, by, bz))

            bytop = by + 8

            # We pass these as local variables for performance and readability.
            # Functions:
            init_block = world.init_block
            get_height = self.get_height
            choose = self.rand.choice
            rand_random = self.rand.random
            # Variables (that are static during what follows)
            height_base = self.height_base
            island_shore = self.island_shore
            water_level = self.water_level
            underwater_blocks = self.underwater_blocks
            world_type_trees = self.world_type_trees
            world_type_plants = self.world_type_plants
            world_type_grass = self.world_type_grass
            if TERRAIN_CHOICE == G.NETHER:
                highlevel_ores = ((B.nether_block,) * 60 + (B.soulsand_block,) * 35 + (B.netherore_block,) * 5 + (B.air_block,) * 10)
                midlevel_ores = highlevel_ores
                lowlevel_ores = highlevel_ores
            else:
                highlevel_ores = self.highlevel_ores
                midlevel_ores = self.midlevel_ores
                lowlevel_ores = self.lowlevel_ores

            for x in xrange(bx, bx + 8):
                for z in xrange(bz, bz + 8):
                    if by < height_base:
                        # For sectors outside of the height_range, no point checking the heightmap
                        y = height_base
                    else:
                        # The heightmap falls within our sector, generate surface stuff
                        y = get_height(x, z)
                        if y > bytop:
                            y = bytop

                        if TERRAIN_CHOICE == G.MOUNTAINS:
                            if 0 <= y <= 35:  # bottom level = grass
                                main_block = B.grass_block
                            if 36 <= y <= 54:  # mid level = rock
                                main_block = B.stone_block
                            if y >= 55:  # top level = snow
                                main_block = B.snow_block

                        if y <= water_level:
                            if TERRAIN_CHOICE != G.DESERT:  # was y == self.height_base -- you can have water!
                                if TERRAIN_CHOICE == G.SNOW:  # top block is ice
                                    init_block((x, water_level, z), B.ice_block)
                                else:
                                    init_block((x, water_level, z), B.water_block)
                                # init_block((x, y -1, z), water_block)
                                init_block((x, water_level - 2, z), choose(B.underwater_blocks))
                                init_block((x, water_level - 3, z), B.dirt_block)
                            else:  # no water for you!
                                init_block((x, y + 1, z), B.sand_block)
                                init_block((x, y, z), B.sand_block)
                                init_block((x, y - 1, z), B.sand_block)
                                init_block((x, y - 2, z), B.sandstone_block)
                                init_block((x, y - 3, z), B.sandstone_block)
                            y -= 3
                        elif y < bytop:
                            if TERRAIN_CHOICE == G.ISLAND:  # always sand by the water, grass above
                                if y > island_shore:
                                    main_block = B.grass_block
                                else:
                                    main_block = B.sand_block
                            init_block((x, y, z), main_block)

                            veget_choice = rand_random()
                            veget_blocks = None
                            if veget_choice < TREE_CHANCE:
                                veget_blocks = world_type_trees
                            elif veget_choice < WILDFOOD_CHANCE:
                                veget_blocks = world_type_plants
                            elif veget_choice < GRASS_CHANCE:
                                veget_blocks = world_type_grass
                            if veget_blocks is not None:
                                world.generate_vegetation((x, y + 1, z),
                                                    choose(veget_blocks))

                            if main_block == B.sand_block:
                                underground_blocks = (
                                    B.sand_block, B.sand_block, B.sandstone_block)
                            elif main_block == B.stone_block:
                                underground_blocks = (B.stone_block,) * 3
                            elif main_block == B.nether_block:
                                underground_blocks = self.nether
                            else:
                                underground_blocks = (B.dirt_block,) * 3

                            for d, block in enumerate(underground_blocks,
                                                      start=1):
                                init_block((x, y - d, z), block)

                            y -= 3

                    for yy in xrange(by, y):
                        # ores and filler...
                        if yy >= 32:
                            blockset = highlevel_ores
                        elif yy > 9:
                            blockset = midlevel_ores
                        elif yy > 2:
                            blockset = lowlevel_ores
                        elif yy <= 1:
                            blockset = (B.bed_block, )

                        init_block((x, yy, z), choose(blockset))