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 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()
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 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()
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 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)
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)
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))
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)
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)
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))