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 }