- Cave cave;
- defineCave(cave, ps, node_min, large_cave);
-
- v3f main_direction(0,0,0);
-
- // Allowed route area size in nodes
- v3s16 ar = central_area_size;
-
- // Area starting point in nodes
- v3s16 of = node_min;
-
- // Allow a bit more
- //(this should be more than the maximum radius of the tunnel)
- s16 insure = 10;
- s16 more = max_spread_amount - cave.max_tunnel_diameter / 2 - insure;
- ar += v3s16(1,0,1) * more * 2;
- of -= v3s16(1,0,1) * more;
-
- s16 route_y_min = 0;
- // Allow half a diameter + 7 over stone surface
- s16 route_y_max = -of.Y + max_stone_y + cave.max_tunnel_diameter/2 + 7;
-
- // Limit maximum to area
- route_y_max = rangelim(route_y_max, 0, ar.Y-1);
-
- if(large_cave)
- {
- s16 min = 0;
- if(node_min.Y < water_level && node_max.Y > water_level)
- {
- min = water_level - cave.max_tunnel_diameter/3 - of.Y;
- route_y_max = water_level + cave.max_tunnel_diameter/3 - of.Y;
- }
- route_y_min = ps.range(min, min + cave.max_tunnel_diameter);
- route_y_min = rangelim(route_y_min, 0, route_y_max);
- }
-
- s16 route_start_y_min = route_y_min;
- s16 route_start_y_max = route_y_max;
-
- route_start_y_min = rangelim(route_start_y_min, 0, ar.Y-1);
- route_start_y_max = rangelim(route_start_y_max, route_start_y_min, ar.Y-1);
-
- // Randomize starting position
- v3f orp(
- (float)(ps.next()%ar.X)+0.5,
- (float)(ps.range(route_start_y_min, route_start_y_max))+0.5,
- (float)(ps.next()%ar.Z)+0.5
- );
-
- v3s16 startp(orp.X, orp.Y, orp.Z);
- startp += of;
-
- MapNode airnode(CONTENT_AIR);
- MapNode waternode(c_water_source);
- MapNode lavanode(c_lava_source);
-
- /*
- Generate some tunnel starting from orp
- */
-
- for(u16 j=0; j<cave.tunnel_routepoints; j++)
- {
- if(j%cave.dswitchint==0 && large_cave == false)
- {
- main_direction = v3f(
- ((float)(ps.next()%20)-(float)10)/10,
- ((float)(ps.next()%20)-(float)10)/30,
- ((float)(ps.next()%20)-(float)10)/10
- );
- main_direction *= (float)ps.range(0, 10)/10;
- }
-
- // Randomize size
- s16 min_d = cave.min_tunnel_diameter;
- s16 max_d = cave.max_tunnel_diameter;
- s16 rs = ps.range(min_d, max_d);
-
- // Every second section is rough
- bool randomize_xz = (ps2.range(1,2) == 1);
-
- v3s16 maxlen;
- if(large_cave)
- {
- maxlen = v3s16(
- rs*cave.part_max_length_rs,
- rs*cave.part_max_length_rs/2,
- rs*cave.part_max_length_rs
- );
- }
- else
- {
- maxlen = v3s16(
- rs*cave.part_max_length_rs,
- ps.range(1, rs*cave.part_max_length_rs),
- rs*cave.part_max_length_rs
- );
- }
-
- v3f vec;
-
- vec = v3f(
- (float)(ps.next()%(maxlen.X*1))-(float)maxlen.X/2,
- (float)(ps.next()%(maxlen.Y*1))-(float)maxlen.Y/2,
- (float)(ps.next()%(maxlen.Z*1))-(float)maxlen.Z/2
- );
-
- // Jump downward sometimes
- if(!large_cave && ps.range(0,12) == 0)
- {
- vec = v3f(
- (float)(ps.next()%(maxlen.X*1))-(float)maxlen.X/2,
- (float)(ps.next()%(maxlen.Y*2))-(float)maxlen.Y*2/2,
- (float)(ps.next()%(maxlen.Z*1))-(float)maxlen.Z/2
- );
- }
-
- /*if(large_cave){
- v3f p = orp + vec;
- s16 h = find_ground_level_clever(vmanip,
- v2s16(p.X, p.Z), ndef);
- route_y_min = h - rs/3;
- route_y_max = h + rs;
- }*/
-
- vec += main_direction;
-
- v3f rp = orp + vec;
- if(rp.X < 0)
- rp.X = 0;
- else if(rp.X >= ar.X)
- rp.X = ar.X-1;
- if(rp.Y < route_y_min)
- rp.Y = route_y_min;
- else if(rp.Y >= route_y_max)
- rp.Y = route_y_max-1;
- if(rp.Z < 0)
- rp.Z = 0;
- else if(rp.Z >= ar.Z)
- rp.Z = ar.Z-1;
- vec = rp - orp;
-
- for(float f=0; f<1.0; f+=1.0/vec.getLength())
- {
- v3f fp = orp + vec * f;
- fp.X += 0.1*ps.range(-10,10);
- fp.Z += 0.1*ps.range(-10,10);
- v3s16 cp(fp.X, fp.Y, fp.Z);
-
- s16 d0 = -rs/2;
- s16 d1 = d0 + rs;
- if(randomize_xz){
- d0 += ps.range(-1,1);
- d1 += ps.range(-1,1);
- }
- for(s16 z0=d0; z0<=d1; z0++)
- {
- s16 si = rs/2 - MYMAX(0, abs(z0)-rs/7-1);
- for(s16 x0=-si-ps.range(0,1); x0<=si-1+ps.range(0,1); x0++)
- {
- s16 maxabsxz = MYMAX(abs(x0), abs(z0));
- s16 si2 = rs/2 - MYMAX(0, maxabsxz-rs/7-1);
- for(s16 y0=-si2; y0<=si2; y0++)
- {
- /*// Make better floors in small caves
- if(y0 <= -rs/2 && rs<=7)
- continue;*/
- if (cave.large_cave_is_flat) {
- // Make large caves not so tall
- if (rs > 7 && abs(y0) >= rs/3)
- continue;
- }
-
- s16 z = cp.Z + z0;
- s16 y = cp.Y + y0;
- s16 x = cp.X + x0;
- v3s16 p(x,y,z);
- p += of;
-
- if(vm->m_area.contains(p) == false)
- continue;
-
- u32 i = vm->m_area.index(p);
-
- if(large_cave) {
- if (cave.flooded && full_node_min.Y < water_level &&
- full_node_max.Y > water_level) {
- if (p.Y <= water_level)
- vm->m_data[i] = waternode;
- else
- vm->m_data[i] = airnode;
- } else if (cave.flooded && full_node_max.Y < water_level) {
- if (p.Y < startp.Y - 2)
- vm->m_data[i] = lavanode;
- else
- vm->m_data[i] = airnode;
- } else {
- vm->m_data[i] = airnode;
- }
- } else {
- // Don't replace air or water or lava or ignore
- if (vm->m_data[i].getContent() == CONTENT_IGNORE ||
- vm->m_data[i].getContent() == CONTENT_AIR ||
- vm->m_data[i].getContent() == c_water_source ||
- vm->m_data[i].getContent() == c_lava_source)
- continue;
-
- vm->m_data[i] = airnode;
-
- // Set tunnel flag
- vm->m_flags[i] |= VMANIP_FLAG_CAVE;
- }
- }
- }
- }
- }
- orp = rp;
- }