1 module dminer.core.generators;
2 
3 import dminer.core.minetypes;
4 import dminer.core.blocks;
5 import dminer.core.world;
6 import dminer.core.terrain;
7 import dminer.core.chunk;
8 
9 
10 __gshared static short[] TERRAIN_INIT_DATA = [
11     //                                      V
12     10,  10,  10,  10,  30,  30,  30,  30,  30,  30,  30,  30,  10,  10,  10,  10,  10,
13     10,  10,  20,  50,  50,  50,  50,  50,  50,  50,  50,  50,  20,  20,  20,  20,  10,
14     10,  20,  20,  50,  50, 150,  50,  50,  50,  50, 250,  50,  50,  50,  20,  20,  10,
15     10,  20,  50,  50,  50,  50,  50, 150,  50,  50,  50, 150,  50,  50,  50,  20,  10,
16     10,  50, 250,  50,  50,  50,  50,  50,  50,  50,  50,  50,  50, 150,  50,  20,  30,
17     30,  50,  50,  50,  50,  50, 150,  50,  50,  50, 250,  50,  50,  50,  50,  50,  30,
18     30,  50,  50,  50,  50,  50,  50,  50, 100,  50,  50,  50,  80,  50, 250,  50,  30,
19     30,  50,  50,  50,  50,  50,  50, 110,  80, 130,  50,  50, 250,  50,  50,  50,  30,
20     30,  50,  50,  50,  50,  50, 150, 100,  50, 140,  50,  50,  50,  50,  50,  50,  30, // <==
21     30,  50,  50,  50,  50,  50,  50, 110,  40, 120,  50,  90,  50, 250,  50,  50,  30,
22     30,  50,  50,  50,  50, 150,  50,  50, 110,  50,  50,  50,  50,  50,  50,  50,  30,
23     30,  50,  50,  50,  50,  50, 150,  50,  50,  50, 150,  50, 150,  50,  50,  50,  10,
24     30,  50,  50,  50,  50,  50,  80,  50,  50, 150,  50,  50,  50,  50,  50,  50,  10,
25     30,  50, 250,  80,  50,  50, 250,  50,  50,  50, 250,  50,  50,  50,  40,  50,  10,
26     30,  20,  50,  50,  50,  50,  50,  50,  50,  50,  50,  50,  50,  40,  20,  20,  10,
27     30,  20,  20,  50,  50,  50,  50,  50,  50,  50,  40,  20,  20,  20,  20,  20,  10,
28     30,  30,  30,  30,  30,  30,  30,  30,  30,  30,  30,  30,  10,  10,  10,  10,  10,
29     //                                      ^
30 ];
31 
32 __gshared static short[] TERRAIN_SCALE_DATA = [
33     //                                      V
34     20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,
35     20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,
36     20,  20,  20,  20, 120,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,
37     20,  20,  20,  20,  20,  20,  20,  20,  40,  60,  50,  20,  20,  30,  20,  20,  20,
38     20,  20, 120,  20,  20,  20,  20,  20,  20,  50,  20,  20,  20,  45,  20,  20,  20,
39     20,  20,  20,  20,  20,  20,  20,  20,  80,  20,  50,  20,  40,  50,  40,  20,  20,
40     20,  20,  20,  20,  20,  20,  90,  20,  80,  20,  80,  20,  20,  30,  20,  20,  20,
41     20,  20,  20,  20,  20,  90,  20,  80,  30,  20,  40,  20,  20,  20,  20,  20,  20,
42     20,  20,  20,  20,  20,  20,  90,  30,  20,  30,  50, 120,  20,  20,  20,  20,  20, // <==
43     20,  20,  20,  20,  20,  20,  50,  20,  30,  20,  20,  20,  20,  20,  20,  20,  20,
44     20,  20,  20,  20,  20,  20,  40,  70,  40,  90,  20,  40,  20,  20,  20,  20,  20,
45     20,  20,  20,  20,  20,  20,  80,  20,  80,  20,  50,  70,  50,  20,  20,  20,  20,
46     20,  20,  20,  20,  20,  20,  80,  20,  20,  20,  20,  60,  20,  20,  20,  20,  20,
47     20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,
48     20,  20,  20, 120,  20,  20,  20,  20,  20,  20,  20,  20,  20, 120,  20,  20,  20,
49     20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,
50     20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,  20,
51     //                                      ^
52 ];
53 
54 void initWorldTerrain(World world, int terrSizeBits = 10, int x0 = 0, int z0 = 0) {
55     import dminer.core.terrain;
56     int terrSize = 1 << terrSizeBits;
57     TerrainGen scaleterr = TerrainGen(terrSizeBits, terrSizeBits); // 512x512
58     scaleterr.generate(4321, TERRAIN_SCALE_DATA, terrSizeBits - 4); // init grid is 16x16 (1 << (9-7))
59     //scaleterr.filter(1);
60     //scaleterr.filter(2);
61     scaleterr.limit(0, 90);
62     TerrainGen terr = TerrainGen(terrSizeBits, terrSizeBits); // 512x512
63     terr.generateWithScale(123456, TERRAIN_INIT_DATA, terrSizeBits - 4, scaleterr); // init grid is 16x16 (1 << (9-7))
64     //terr.filter(1);
65     terr.limit(5, CHUNK_DY * 3 / 4);
66     terr.filter(1);
67     for (int x = 0; x < terrSize; x++) {
68         for (int z = 0; z < terrSize; z++) {
69             int cellx = x0 + x - terrSize / 2;
70             int cellz = z0 + z - terrSize / 2;
71             int h = terr.get(x, z);
72             int dh = terr.getHeightDiff(x, z);
73 
74 
75             cell_t cell = BlockId.bedrock;
76             //cell_t cell = BlockId.grass;
77             //cell_t cell = BlockId.face_test;
78             //if (h < CHUNK_DY / 10)
79             //    cell = 100;
80             //else if (h < CHUNK_DY / 5)
81             //    cell = 101;
82             //else if (h < CHUNK_DY / 4)
83             //    cell = 102;
84             //else if (h < CHUNK_DY / 3)
85             //    cell = 103;
86             //else if (h < CHUNK_DY / 2)
87             //    cell = 104;
88             //else
89             //    cell = 105;
90 
91             cell_t topcell = BlockId.bedrock;
92             if (dh <= 1)
93                 topcell = BlockId.grass;
94 
95             for (int y = 0; y < h; y++) {
96                 world.setCell(cellx, y, cellz, cell);
97             }
98             world.setCell(cellx, h, cellz, topcell);
99         }
100     }
101 }
102 
103 
104 void makeCastleWall(World world, Vector3d start, Vector3d direction, int height, int length, int width, cell_t material) {
105     Vector3d normal = direction.turnLeft;
106     for (int x = 0; x < length; x++) {
107         Vector3d x0 = start + direction * x;
108         for (int y = 0; y < height; y++) {
109             Vector3d y0 = x0;
110             y0.y += y;
111             for (int z = -width / 2; z <= width / 2; z++) {
112                 Vector3d z0 = y0 + normal * z;
113                 bool side = (z == -width/2 || z == width/2);
114                 cell_t cell = material;
115                 if (y >= height - 2) {
116                     if (!side)
117                         cell = BlockId.air;
118                     else if ((x & 1) && (y >= height - 1)) {
119                         cell = BlockId.air;
120                     }
121                 }
122                 if (cell != BlockId.air)
123                     world.setCell(z0.x, z0.y, z0.z, cell);
124             }
125         }
126     }
127 }
128 
129 void makeCastleWalls(World world, Vector3d start, int size, int height, int width, cell_t material) {
130     world.makeCastleWall(Vector3d(start.x - size - width/2, start.y, start.z - size), Vector3d(1, 0, 0), height, size * 2 + width, width, material);
131     world.makeCastleWall(Vector3d(start.x - size, start.y, start.z - size - width/2), Vector3d(0, 0, 1), height, size * 2 + width, width, material);
132     world.makeCastleWall(Vector3d(start.x + size, start.y, start.z - size - width/2), Vector3d(0, 0, 1), height, size * 2 + width, width, material);
133     world.makeCastleWall(Vector3d(start.x - size - width/2, start.y, start.z + size), Vector3d(1, 0, 0), height, size * 2 + width, width, material);
134 }
135 
136 void prepareCastleBase(World world, Vector3d start, int size) {
137     // basement - bedrock
138     world.setCellRange(Vector3d(start.x - size - 3, start.y - 10, start.z - size - 3), Vector3d(size*2 + 6, 10, size*2 + 6), BlockId.bedrock);
139     world.setCellRange(Vector3d(start.x - size - 4, start.y - 11, start.z - size - 4), Vector3d(size*2 + 8, 10, size*2 + 8), BlockId.bedrock);
140     // empty
141     world.setCellRange(Vector3d(start.x - size - 5, start.y, start.z - size - 5), Vector3d(size*2 + 10, 10, size*2 + 10), BlockId.air);
142     world.setCellRange(Vector3d(start.x - size - 6, start.y + 1, start.z - size - 6), Vector3d(size*2 + 12, 10, size*2 + 12), BlockId.air);
143     world.setCellRange(Vector3d(start.x - size - 7, start.y + 2, start.z - size - 7), Vector3d(size*2 + 14, 10, size*2 + 14), BlockId.air);
144     // floor
145     world.setCellRange(Vector3d(start.x - size, start.y - 10, start.z - size), Vector3d(size*2, 10, size*2), BlockId.red_sand);//cobblestone
146 }
147 
148 void makeCastle(World world, Vector3d start, int size, int height) {
149     world.prepareCastleBase(start, size);
150     // main walls
151     world.makeCastleWalls(start, size, height, 4, BlockId.brick);
152     // gates
153     world.setCellRange(Vector3d(start.x - 3, start.y - 1, start.z - size - 7), Vector3d(7, 1, 10), BlockId.cobblestone);
154     world.setCellRange(Vector3d(start.x - 3, start.y - 2, start.z - size - 8), Vector3d(7, 1, 10), BlockId.cobblestone);
155     world.setCellRange(Vector3d(start.x - 3, start.y - 3, start.z - size - 9), Vector3d(7, 1, 10), BlockId.cobblestone);
156     world.setCellRange(Vector3d(start.x - 3, start.y, start.z - size - 4), Vector3d(7, height * 7 / 10, 7), BlockId.air);
157     world.setCellRange(Vector3d(start.x - 4, start.y, start.z - size), Vector3d(9, height * 7 / 10 + 1, 1), BlockId.air);
158     // corner towers
159     world.makeCastleWalls(start + Vector3d(-size + 1, -5, -size + 1), 5, height + 2 + 5, 3, BlockId.gray_brick);
160     world.makeCastleWalls(start + Vector3d(size - 1, -5, -size + 1), 5, height + 2 + 5, 3, BlockId.gray_brick);
161     world.makeCastleWalls(start + Vector3d(-size + 1, -5, size - 1), 5, height + 2 + 5, 3, BlockId.gray_brick);
162     world.makeCastleWalls(start + Vector3d(size - 1, -5, size - 1), 5, height + 2 + 5, 3, BlockId.gray_brick);
163     // dungeon
164     world.makeCastleWalls(start, size / 3, height * 15 / 10, 2, BlockId.gray_brick);
165     world.setCellRange(Vector3d(start.x - 2, start.y, start.z - size - 4), Vector3d(5, height * 6 / 10, size), BlockId.air);
166 }