1 /* 2 * Copyright (c) 2017-2019 sel-project 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a copy 5 * of this software and associated documentation files (the "Software"), to deal 6 * in the Software without restriction, including without limitation the rights 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 * copies of the Software, and to permit persons to whom the Software is 9 * furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in all 12 * copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 * SOFTWARE. 21 * 22 */ 23 /** 24 * Copyright: Copyright (c) 2017-2019 sel-project 25 * License: MIT 26 * Authors: Kripth 27 * Source: $(HTTP github.com/sel-project/selery/source/selery/world/generator.d, selery/world/generator.d) 28 */ 29 module selery.world.generator; 30 31 import std.algorithm : min; 32 import std.conv : to; 33 import std.random : uniform, uniform01; 34 35 import selery.block.block : Block; 36 import selery.block.blocks : Blocks; 37 import selery.math.vector : ChunkPosition, BlockPosition, distance; 38 import selery.world.chunk : Chunk; 39 import selery.world.world : World; 40 41 abstract class Generator { 42 43 protected World world; 44 private uint m_seed; 45 46 public @safe @nogc this(World world) { 47 this.world = world; 48 } 49 50 public abstract @property @safe BlockPosition spawn(); 51 52 public abstract Chunk generate(ChunkPosition position); 53 54 public pure nothrow @property @safe @nogc uint seed() { 55 return this.m_seed; 56 } 57 58 public pure nothrow @property @safe @nogc uint seed(uint seed) { 59 return this.m_seed = seed; 60 } 61 62 public abstract pure nothrow @property @safe string type(); 63 64 } 65 66 class Empty : Generator { 67 68 public @safe @nogc this(World world) { 69 super(world); 70 } 71 72 public override @property @safe BlockPosition spawn() { 73 return BlockPosition(0, 0, 0); 74 } 75 76 public override @safe Chunk generate(ChunkPosition position) { 77 return new Chunk(this.world, position); 78 } 79 80 public override pure nothrow @property @safe string type() { 81 return "flat"; 82 } 83 84 } 85 86 class Flat : Generator { 87 88 private ushort[] layers; 89 protected bool trees; 90 91 public @safe this(World world, ushort[] layers=[Blocks.bedrock, Blocks.dirt, Blocks.dirt, Blocks.dirt, Blocks.grass], bool trees=true) { 92 super(world); 93 this.layers = layers; 94 this.trees = trees; 95 } 96 97 public override @property @safe BlockPosition spawn() { 98 return BlockPosition(0, this.layers.length.to!int, 0); 99 } 100 101 public override Chunk generate(ChunkPosition position) { 102 Chunk chunk = new Chunk(this.world, position); 103 foreach(ubyte xx ; 0..16) { 104 foreach(ubyte zz ; 0..16) { 105 foreach(uint y ; 0..this.layers.length.to!uint) { 106 chunk[xx, y, zz] = this.layers[y]; 107 } 108 } 109 } 110 if(this.trees && uniform01!float(this.world.random) >= .75) { 111 //test a tree 112 ubyte tree = uniform(ubyte(0), ubyte(6), this.world.random); 113 ubyte height = uniform(ubyte(4), ubyte(24), this.world.random); 114 ubyte foliage = uniform(ubyte(3), min(height, ubyte(7)), this.world.random); 115 //logs 116 foreach(y ; this.layers.length..this.layers.length+height) { 117 chunk[7, cast(uint)y, 7] = Blocks.woodUpDown[tree]; 118 } 119 //leaves 120 BlockPosition center = BlockPosition(7, this.layers.length.to!int + height, 7); 121 foreach(ubyte xx ; to!ubyte(7 - foliage)..to!ubyte(7 + foliage + 1)) { 122 foreach(ubyte zz ; to!ubyte(7 - foliage)..to!ubyte(7 + foliage + 1)) { 123 foreach(uint yy ; (center.y - foliage)..(center.y + foliage + 1)) { 124 BlockPosition pos = BlockPosition(xx, yy, zz); 125 if(pos.distance(center) <= foliage) { 126 auto current = chunk[xx, yy, zz]; 127 if(current is null || *current is null) { 128 chunk[xx, yy, zz] = Blocks.leavesDecay[tree]; 129 } 130 } 131 } 132 } 133 } 134 } 135 return chunk; 136 } 137 138 public override pure nothrow @property @safe string type() { 139 return "flat"; 140 } 141 142 }