use gdnative::prelude::*; use self::gen::GameRng; mod gen; mod tiles; pub struct World { pub xsize: usize, pub ysize: usize, pub zsize: usize, tiles: Vec>>, attributes: tiles::Attributelists, } impl World { pub fn get_tile_at(&self, x: usize, y: usize, z: usize) -> u16 { self.tiles[x][y][z] as u16 } pub fn is_tile_hidden(&self, x: usize, y: usize, z: usize) -> bool { if x == self.xsize - 1 || y == self.ysize - 1 || z == self.zsize - 1 { return false; } if !tiles::Tile::new(self.tiles[x + 1][y][z]).hide_top_left || !tiles::Tile::new(self.tiles[x][y + 1][z]).hide_top_right || !tiles::Tile::new(self.tiles[x][y][z + 1]).hide_below { return false; } true } pub fn generate(&mut self, rng: &mut GameRng) -> Vector3Array { self.tiles = get_vec3(self.xsize, self.ysize, self.zsize); let noisemap = gen::get_noise(rng, (self.xsize, self.ysize)); let mut ret: Vector3Array = Vector3Array::new(); for x in 0..self.xsize { for y in 0..self.ysize { ret.push(Vector3::new(x as f32, y as f32, 0.0)); if noisemap.get_value(x, y) > 0.4 { ret.append(&self.stack_tiles( 4, tiles::Tiletypes::Grass, tiles::Tiletypes::Dirt, (x, y), )); } else if noisemap.get_value(x, y) > 0.3 { ret.append(&self.stack_tiles( 3, tiles::Tiletypes::Grass, tiles::Tiletypes::Dirt, (x, y), )); } else if noisemap.get_value(x, y) > 0.2 { ret.append(&self.stack_tiles( 2, tiles::Tiletypes::Grass, tiles::Tiletypes::Dirt, (x, y), )); } else if noisemap.get_value(x, y) > -0.3 { self.tiles[x][y][0] = tiles::Tiletypes::Grass; } else if noisemap.get_value(x, y) > -0.4 { self.tiles[x][y][0] = tiles::Tiletypes::Sand; } else { self.tiles[x][y][0] = tiles::Tiletypes::WaterSlab; } } } ret } fn stack_tiles( &mut self, height: usize, top: tiles::Tiletypes, filler: tiles::Tiletypes, pos: (usize, usize), ) -> Vector3Array { let mut positions = Vector3Array::new(); for z in 0..height { positions.push(Vector3::new(pos.0 as f32, pos.1 as f32, z as f32)); if z == height - 1 { self.tiles[pos.0][pos.1][z] = top; } else { self.tiles[pos.0][pos.1][z] = filler; } } positions } pub fn put_tile_at(&mut self, x: usize, y: usize, z: usize, id: usize) -> Vector3Array { let mut changed = Vector3Array::new(); if !self.can_put_tile_at(x, y, z, id) { return changed; } self.tiles[x][y][z] = tiles::Tiletypes::from_repr(id as u8).unwrap(); changed.push(Vector3::new(x as f32, y as f32, z as f32)); changed } pub fn can_put_tile_at(&self, x: usize, y: usize, z: usize, id: usize) -> bool { if self.tiles[x][y][z] == tiles::Tiletypes::Air { return true; } false } pub fn new(xsize: usize, ysize: usize, zsize: usize) -> World { World { xsize, ysize, zsize, tiles: get_vec3(xsize, ysize, zsize), attributes: tiles::Attributelists::new(), } } } fn get_vec3(xsize: usize, ysize: usize, zsize: usize) -> Vec>> { let mut zvec: Vec = Vec::with_capacity(zsize); zvec.resize(zsize, tiles::Tiletypes::Air); let mut yvec: Vec> = Vec::with_capacity(ysize); yvec.resize(ysize, zvec.clone()); let mut xvec: Vec>> = Vec::with_capacity(xsize); xvec.resize(ysize, yvec.clone()); yvec.push(zvec); xvec.push(yvec); xvec }