Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
93c20ac
Do not store slice positions within chunk files
olls Nov 18, 2015
15de098
Dummy generation by chunk implementation
olls Nov 18, 2015
0f30126
Create save_chunk function for directly saving a whole chunk
olls Nov 18, 2015
d823489
First pass on feature caching: creates the cache, but it's not used.
olls Nov 19, 2015
02fe04d
Split features into 'per slice' and 'per chunk', store features as ma…
olls Nov 20, 2015
d43a4d0
Use the features to generate the terrain
olls Nov 20, 2015
c349355
Fix comment spelling
olls Nov 23, 2015
9a89b64
Fixed some typo bugs
olls Nov 23, 2015
d6ee7ea
Fix inconsitancies with `chunk`, `chunk_n` and `chunk_pos` variables
olls Nov 23, 2015
8c2f9de
Generate all ground heights in gen_chunk loop
olls Nov 23, 2015
c17a9c6
Merge branch 'multiplayer' into generic-terrain-gen
geraintwhite Nov 23, 2015
65d758a
Merge branch 'multiplayer' into generic-terrain-gen
olls Nov 23, 2015
ecd0390
Merge branch 'multiplayer' into generic-terrain-gen
olls Nov 23, 2015
dc80095
Merge branch 'multiplayer' into generic-terrain-gen
geraintwhite Nov 23, 2015
a288ca9
Merge branch 'generic-terrain-gen' of github.com:itsapi/pycraft into …
geraintwhite Nov 23, 2015
c0c1b31
Fix hill generation
geraintwhite Nov 23, 2015
2290e9e
Make feature cache big enough to work
olls Nov 23, 2015
ffb6ebf
Correct commented comment spelling
geraintwhite Nov 23, 2015
c905122
Merge branch 'multiplayer' into generic-terrain-gen
olls Nov 24, 2015
c17d1d7
Merge branch 'multiplayer' into generic-terrain-gen
olls Nov 24, 2015
cf03c3a
Fix hill generation to be compatible with the old version
olls Nov 24, 2015
46b0bc0
Merge branch 'multiplayer' into generic-terrain-gen
olls Nov 24, 2015
56180e9
Merge branch 'multiplayer' into generic-terrain-gen
olls Nov 24, 2015
2252545
Merge branch 'multiplayer' into generic-terrain-gen
geraintwhite Nov 25, 2015
8453503
Chunk boundary display in debug
olls Nov 25, 2015
ecb289b
Merge branch 'generic-terrain-gen' of github.com:itsapi/pycraft into …
olls Nov 25, 2015
1f6f0a4
Fix gen_tree_features loop radius
olls Dec 16, 2015
5489967
Terrain gen debugging
geraintwhite Jan 13, 2016
afce778
Comments
geraintwhite Jan 13, 2016
38517a8
Fix incorrect biome issue
geraintwhite Jan 13, 2016
a33a8ee
Fix tree generation
olls Jan 13, 2016
5546f87
Fix leaf slice height
olls Jan 13, 2016
06c83ca
Reimplement ores with multiple y-levels!
olls Jan 14, 2016
9f2d6d6
Add density attributes to ore generation
olls Jan 14, 2016
14ac704
Remove old terrain gen functions
olls Jan 14, 2016
6ab6c2e
Reimplelment tall grass
olls Jan 14, 2016
59b25dd
Extend terrain debugging
olls Jan 14, 2016
ce475ea
Moved feature drawing into functions
olls Jan 14, 2016
6af6dcd
Simplify slice_features branching
olls Jan 14, 2016
a9b7ebc
Add gaps at bottom of trees in debug mode
olls Jan 14, 2016
46d2887
Fix loop in terrain building
olls Jan 14, 2016
39c9c69
Fix debug for trees
olls Jan 14, 2016
fefd5a4
Clean up changes in get_pos_delta
olls Jan 14, 2016
955cfa3
Clean up
olls Jan 14, 2016
6874262
Initialise ground_heights, fixes #77
geraintwhite Jan 14, 2016
8f0ad9a
Move in_chunk function to top
olls Jan 14, 2016
9d13b39
Merge branch 'generic-terrain-gen' of github.com:itsapi/pycraft into …
olls Jan 14, 2016
ce6f3ed
Merge branch 'multiplayer' into generic-terrain-gen
geraintwhite Jan 14, 2016
9a1e3da
Merge branch 'multiplayer' into generic-terrain-gen
geraintwhite Jan 14, 2016
d02ed84
Rewrite biome generation to behave like trees, ref #71
olls Jan 17, 2016
b88fb93
Remove hill_range for olls
geraintwhite Jan 17, 2016
a9ba16e
Add start position debugging option
olls Jan 17, 2016
a8a14f5
Add leaf debugging
olls Jan 17, 2016
ac3bd55
Fix cache size for biomes
olls Jan 17, 2016
4392bbf
Merge branch 'generic-terrain-gen' of github.com:itsapi/pycraft into …
olls Jan 17, 2016
3af071f
Fix PYCRAFT_START_X int
geraintwhite Jan 17, 2016
488628b
Remove chunk cache
olls Jan 17, 2016
570315a
Merge branch 'generic-terrain-gen' of github.com:itsapi/pycraft into …
olls Jan 17, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 29 additions & 5 deletions data.py
Original file line number Diff line number Diff line change
Expand Up @@ -319,54 +319,78 @@
'min_grad': 5,
'ground_height': 10,
'chunk_size': 16,
'max_biome_size': 50,
'biome_tree_weights': [0]*2 + [.05]*2 + [.2],
'tall_grass_rate': .25,
'min_biome': 16,
'max_biome': 64,
'biomes': {
'plains': {
'chance': .3,
'trees': 0,
'grass': .15
},
'normal': {
'chance': .3,
'trees': .05,
'grass': .1
},
'forest': {
'chance': .3,
'trees': .2,
'grass': 0
}
},
# TODO: Densities need tuning.
'ores': {
'coal': {
'char': 'x',
'vain_size': 4,
'vain_density': .4,
'chance': 0.05,
'upper': 30,
'lower': 1
},
'iron': {
'char': '+',
'vain_size': 3,
'vain_density': .3,
'chance': 0.03,
'upper': 15,
'lower': 1
},
'redstone': {
'char': ':',
'vain_size': 4,
'vain_density': .6,
'chance': 0.03,
'upper': 7,
'lower': 1
},
'gold': {
'char': '"',
'vain_size': 2,
'vain_density': .3,
'chance': 0.02,
'upper': 10,
'lower': 1
},
'diamond': {
'char': 'o',
'vain_size': 1,
'vain_size': 2,
'vain_density': .5,
'chance': 0.01,
'upper': 5,
'lower': 1
},
'emerald': {
'char': '.',
'vain_size': 1,
'vain_density': 1,
'chance': 0.002,
'upper': 7,
'lower': 1
}
},
'trees': (
'trees': ( # TODO: Preprocessing should be done on these, to give the data
# the terrain gen needs.
((0, 1, 1),
(1, 1, 0),
(0, 1, 1)),
Expand Down
16 changes: 7 additions & 9 deletions player.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,14 @@ def get_pos_delta(char, map_, x, y, jump):
dy = 0
dx = 0

is_solid = lambda block: terrain.is_solid(block)

# Calculate change in x pos for left and right movement
for test_char, dir_, func in (('a', -1, left_slice), ('d', 1, right_slice)):
for test_char, dir_, next_slice in (('a', -1, left_slice), ('d', 1, right_slice)):
if ( char in test_char
and not is_solid( func[head_y] )):
and not terrain.is_solid( next_slice[head_y] )):

if is_solid( func[feet_y] ):
if ( not is_solid( func[above_y] )
and not is_solid( player_slice[above_y] )):
if terrain.is_solid( next_slice[feet_y] ):
if ( not terrain.is_solid( next_slice[above_y] )
and not terrain.is_solid( player_slice[above_y] )):

dy = -1
dx = dir_
Expand All @@ -42,8 +40,8 @@ def get_pos_delta(char, map_, x, y, jump):

# Jumps if up pressed, block below, no block above
if ( char in 'w' and y > 1
and not is_solid( player_slice[above_y] )
and ( is_solid( player_slice[below_y] )
and not terrain.is_solid( player_slice[above_y] )
and ( terrain.is_solid( player_slice[below_y] )
or player_slice[feet_y] == '=' )):

dy = -1
Expand Down
8 changes: 6 additions & 2 deletions render.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import terrain
from colors import *
from console import CLS, CLS_END, CLS_END_LN, REDRAW, POS_STR, supported_chars
from console import DEBUG, CLS, CLS_END, CLS_END_LN, REDRAW, POS_STR, supported_chars, log
import data
from data import world_gen

Expand Down Expand Up @@ -35,7 +35,7 @@ def render_map(map_, objects, sun, lights, time, last_frame):
# [2, '## ']]

# Separates the pos and data
map_ = tuple(zip(*map_))[1]
world_positions, map_ = tuple(zip(*map_))

# Orientates the data
map_ = zip(*map_)
Expand All @@ -49,6 +49,10 @@ def render_map(map_, objects, sun, lights, time, last_frame):
for x, pixel in enumerate(row):

pixel_out = calc_pixel(x, y, pixel, objects, sun, lights, time)

if DEBUG and y == 1 and world_positions[x] % world_gen['chunk_size'] == 0:
pixel_out = colorStr('*', bg=RED, fg=YELLOW)

this_frame[-1].append(pixel_out)

try:
Expand Down
126 changes: 57 additions & 69 deletions saves.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@
}

default_player = {
'player_x': 0,
'player_x': int(os.getenv('PYCRAFT_START_X') or 0),
'player_y': 1,
'inv': []
}

SAVES_DIR = 'saves'
CHUNK_EXT = '.chunk'
SLICE_SEP = '<sep>'
CHUNK_SIZE = world_gen['chunk_size'] * (world_gen['height'] + 1)


save_path = lambda save, filename='': os.path.join(SAVES_DIR, save, filename)
Expand Down Expand Up @@ -77,49 +77,13 @@ def load_meta(save):
return meta


def load_chunk(save, chunk):
try:
map_ = parse_slices(get_chunk(save, chunk))
except FileNotFoundError:
map_ = {}

valid_map = {}
for pos, slice_ in map_.items():
if pos in range(chunk, chunk + world_gen['chunk_size']):

if not len(slice_) == world_gen['height']:
if len(slice_) < world_gen['height']:
# Extend slice height
slice_ = [' '] * (world_gen['height'] - len(slice_)) + slice_
elif len(slice_) > world_gen['height']:
# Truncate slice height
slice_ = slice_[len(slice_) - world_gen['height']:]

valid_map[pos] = slice_

save_map(save, map_)
return map_


def get_meta(save):
with open(meta_path(save)) as f:
data = json.load(f)

return data


def get_chunk(save, chunk):
data = []

chunk_file = save_path(save, str(chunk) + CHUNK_EXT)

if os.path.isfile(chunk_file):
with open(chunk_file) as f:
data = f.readlines()

return data


def check_meta(meta):
# Create meta items if needed
for key, default in default_meta.items():
Expand All @@ -134,54 +98,78 @@ def check_meta(meta):
return meta


def parse_slices(data):
slices = {}
def save_meta(save, meta):
# Save meta file
with open(meta_path(save), 'w') as f:
json.dump(meta, f)

for line in data:
# Parses map file
key, slice_ = line.split(SLICE_SEP)
slice_ = list(slice_)

# Removes new line char if it exists
slices[key] = slice_ if not slice_[-1] == '\n' else slice_[:-1]
def chunk_file_name(save, chunk_n):
return save_path(save, str(chunk_n) + CHUNK_EXT)

return slices

def load_chunk(save, chunk_n):
map_ = {}
chunk_pos = chunk_n * world_gen['chunk_size']

def save_meta(save, meta):
# Save meta file
with open(meta_path(save), 'w') as f:
json.dump(meta, f)
try:
with open(chunk_file_name(save, chunk_n)) as data:
for d_pos, slice_ in enumerate(data):

# Truncate to correct size
slice_ = slice_[:world_gen['height']]

height_error = world_gen['height'] - len(slice_)
if not height_error == 0:
# Extend slice height
slice_ = (' ' * height_error) + slice_

map_[str(chunk_pos + d_pos)] = list(slice_)

except FileNotFoundError:
pass

return map_


def save_map(save, new_slices):
def save_chunk(save, chunk_n, chunk):
""" Updates slices within one chunk. """

filename = chunk_file_name(save, chunk_n)
if os.path.isfile(filename):
mode = 'r+'
else:
mode = 'w'

with open(filename, mode) as file_:

file_.truncate(CHUNK_SIZE)
for pos, slice_ in chunk.items():
rel_pos = int(pos) % world_gen['chunk_size']

file_.seek(int(rel_pos) * (world_gen['height'] + 1))
file_.write(''.join(slice_) + '\n')


def save_slices(save, new_slices):
""" Updates slices anywhere in the world. """

# Group slices by chunk
chunks = {}
for pos, slice_ in new_slices.items():
chunk_pos = chunk_num(pos)

try:
chunks[chunk_num(pos)].update({pos: slice_})
chunks[chunk_pos].update({pos: slice_})
except KeyError:
chunks[chunk_num(pos)] = {pos: slice_}
chunks[chunk_pos] = {pos: slice_}

log('saving slices', new_slices.keys())
log('saving chunks', chunks.keys())

# Update chunk files
for num, chunk in chunks.items():
chunk_file = save_path(save, str(num) + CHUNK_EXT)

# Update slices in chunk file with new slices
try:
with open(chunk_file) as f:
slices = parse_slices(f.readlines())
except (OSError, IOError):
slices = {}
slices.update(chunk)

# Write slices back to file
with open(chunk_file, 'w') as f:
for pos, slice_ in slices.items():
f.write(str(pos) + SLICE_SEP + ''.join(slice_) + '\n')
for chunk_pos, chunk in chunks.items():
save_chunk(save, chunk_pos, chunk)


def set_blocks(map_, blocks):
Expand Down
25 changes: 7 additions & 18 deletions server.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
from console import log


chunk_size = terrain.world_gen['chunk_size']

SUN_TICK = radians(1/32)
TPS = 10 # Ticks

Expand Down Expand Up @@ -171,35 +169,26 @@ def __init__(self, save):

def get_chunks(self, chunk_list):
new_slices = {}
gen_slices = {}

log('loading chunks', chunk_list)

# Generates new terrain
for chunk_num in chunk_list:
chunk = saves.load_chunk(self._save, chunk_num)
for i in range(chunk_size):
pos = i + chunk_num * chunk_size
if not str(pos) in chunk:
slice_ = terrain.gen_slice(pos, self._meta)
chunk[str(pos)] = slice_
gen_slices[str(pos)] = slice_
for chunk_n in chunk_list:

chunk = saves.load_chunk(self._save, chunk_n)
if not chunk:
chunk = terrain.gen_chunk(chunk_n, self._meta)
saves.save_chunk(self._save, chunk_n, chunk)
new_slices.update(chunk)

log('generated slices', gen_slices.keys())
log('new slices', new_slices.keys())

# Save generated terrain to file
if gen_slices:
log('saving slices', gen_slices.keys())
saves.save_map(self._save, gen_slices)

self._map.update(new_slices)
return new_slices

def set_blocks(self, blocks):
self._map, new_slices = saves.set_blocks(self._map, blocks)
saves.save_map(self._save, new_slices)
saves.save_slices(self._save, new_slices)
return blocks

def set_player(self, name, player):
Expand Down
Loading