initial commit; works
This commit is contained in:
commit
b6c97a7fb6
7
README.md
Normal file
7
README.md
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
Mod for MineTest
|
||||||
|
|
||||||
|
Operates in on_generated (at mapgen time).
|
||||||
|
The more flat places there are, the more houses will be spawned.
|
||||||
|
There is currently no limit on the amount of houses generated.
|
||||||
|
|
||||||
|
For now: Experimental. Use at your own risk.
|
1
depends.txt
Normal file
1
depends.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
handle_schematics
|
353
init.lua
Normal file
353
init.lua
Normal file
@ -0,0 +1,353 @@
|
|||||||
|
-- Known issues:
|
||||||
|
-- * cavegen may eat holes into the ground below the house
|
||||||
|
-- * panes (glass or bars) right next to a door look bad
|
||||||
|
-- * wall parts where glass panes might be will sometimes be colored strangely
|
||||||
|
-- (which actually looks intresting most of the time)
|
||||||
|
-- * glass windows look wrong due to their param2 not beeing 0 (they are
|
||||||
|
-- "filled" partly)
|
||||||
|
-- * trees, plants and snow inside the house are not cleared
|
||||||
|
|
||||||
|
simple_houses = {};
|
||||||
|
|
||||||
|
-- generate at max this many houses per mapchunk;
|
||||||
|
-- Note: This amount will likely only spawn if your mapgen is very flat.
|
||||||
|
-- Else you will see far less houses.
|
||||||
|
simple_houses.max_per_mapchunk = 20;
|
||||||
|
|
||||||
|
-- used for adding colored clay and coral as material for house walls
|
||||||
|
local palette = "unifieddyes_palette_extended.png";
|
||||||
|
|
||||||
|
--[[
|
||||||
|
-- trouble with that: digging clay only gives you the uncolored lumps,
|
||||||
|
-- and there is no way to craf the colored one yet; repairs to houses
|
||||||
|
-- would be impossible; additionally, the default node would get some
|
||||||
|
-- unwanted color attched and no longer be white
|
||||||
|
--
|
||||||
|
minetest.override_item( "default:clay", {
|
||||||
|
paramtype2 = "color",
|
||||||
|
palette = palette,
|
||||||
|
});
|
||||||
|
|
||||||
|
minetest.override_item( "default:coral_skeleton", {
|
||||||
|
paramtype2 = "color",
|
||||||
|
palette = palette,
|
||||||
|
});
|
||||||
|
--]]
|
||||||
|
|
||||||
|
-- these two nodes look very good when colored
|
||||||
|
minetest.register_node("simple_houses:painted_clay", {
|
||||||
|
description = "Painted clay",
|
||||||
|
tiles = {"default_clay.png"},
|
||||||
|
is_ground_content = false,
|
||||||
|
groups = {oddly_breakable_by_hand=3,cracky=3,snappy=3,sappy=3},
|
||||||
|
paramtype2 = "color",
|
||||||
|
palette = palette,
|
||||||
|
});
|
||||||
|
|
||||||
|
minetest.register_node("simple_houses:painted_wall", {
|
||||||
|
description = "Painted house wall",
|
||||||
|
tiles = {"default_coral_skeleton.png"},
|
||||||
|
is_ground_content = false,
|
||||||
|
groups = {oddly_breakable_by_hand=3,cracky=3,snappy=3,sappy=3},
|
||||||
|
paramtype2 = "color",
|
||||||
|
palette = palette,
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
-- locate a place for the "hut" and place it
|
||||||
|
simple_houses.simple_hut_find_place_and_build = function( heightmap, minp, maxp, sizex, sizez, minheight, maxheight )
|
||||||
|
|
||||||
|
local res = handle_schematics.find_flat_land_get_candidates_fast( heightmap, minp, maxp,
|
||||||
|
sizex, sizez, minheight, maxheight );
|
||||||
|
|
||||||
|
-- print( "Places found of size "..tostring( sizex ).."x"..tostring(sizez)..": "..tostring( #res.places_x )..
|
||||||
|
-- " and "..tostring( sizez ).."x"..tostring(sizex)..": "..tostring( #res.places_z )..
|
||||||
|
-- ".");
|
||||||
|
|
||||||
|
if( (#res.places_x + #res.places_z )< 1 ) then
|
||||||
|
-- print( " Aborting. No place found.");
|
||||||
|
return nil;
|
||||||
|
end
|
||||||
|
|
||||||
|
-- select a random place - either sizex x sizez or sizez x sizex
|
||||||
|
local c = math.random( 1, #res.places_x + #res.places_z );
|
||||||
|
local i = 1;
|
||||||
|
if( c > #res.places_x ) then
|
||||||
|
i = res.places_z[ c-#res.places_x ];
|
||||||
|
-- swap x and z due to rotation of 90 or 270 degree
|
||||||
|
local tmp = sizex;
|
||||||
|
sizex = sizez;
|
||||||
|
sizez = tmp;
|
||||||
|
tmp = nil;
|
||||||
|
else
|
||||||
|
i = res.places_x[ c ];
|
||||||
|
end
|
||||||
|
|
||||||
|
local chunksize = maxp.x - minp.x + 1;
|
||||||
|
-- translate index back into coordinates
|
||||||
|
local p = {x=minp.x+(i%chunksize)-1, y=heightmap[ i ], z=minp.z+math.floor(i/chunksize), i=i};
|
||||||
|
|
||||||
|
local wood_types = {"", "jungle", "acacia_", "aspen_", "pine_"};
|
||||||
|
-- wooden roof
|
||||||
|
local wood = wood_types[ math.random( #wood_types )];
|
||||||
|
local wood1 = wood_types[ math.random( #wood_types )];
|
||||||
|
local wood2 = wood_types[ math.random( #wood_types )];
|
||||||
|
-- ceiling of main room (which is also the floor of the room below the roof)
|
||||||
|
local wood3 = wood_types[ math.random( #wood_types )];
|
||||||
|
-- the walls can be wooden planks, tree trunks, painted clay or painted wall (=coral)
|
||||||
|
local walls = "default:"..wood1.."wood";
|
||||||
|
local color = nil;
|
||||||
|
local r = math.random(1,5);
|
||||||
|
if(r==1) then
|
||||||
|
walls = "default:"..wood1.."tree";
|
||||||
|
elseif(r==2) then
|
||||||
|
walls = "simple_houses:painted_clay";
|
||||||
|
color = math.random(0,255);
|
||||||
|
elseif(r==3) then
|
||||||
|
walls = "simple_houses:painted_wall";
|
||||||
|
color = math.random(0,255);
|
||||||
|
end
|
||||||
|
local gable = "default:"..wood2.."wood";
|
||||||
|
if( math.random(1,2)==1) then
|
||||||
|
gable = walls;
|
||||||
|
end
|
||||||
|
-- glass can be glass panes, iron bars or solid glass
|
||||||
|
local glass_materials = {"xpanes:pane_flat","default:glass","xpanes:bar_flat"};
|
||||||
|
local glass = glass_materials[ math.random( 1,#glass_materials )];
|
||||||
|
local materials = {
|
||||||
|
walls = walls,
|
||||||
|
floor = "default:brick",
|
||||||
|
gable = gable,
|
||||||
|
ceiling = "default:"..wood3.."wood",
|
||||||
|
roof = "stairs:stair_"..wood.."wood",
|
||||||
|
roof_middle = "stairs:slab_"..wood.."wood",
|
||||||
|
glass = glass,
|
||||||
|
"xpanes:pane_flat", --"default:glass",
|
||||||
|
color = color,
|
||||||
|
};
|
||||||
|
return simple_houses.simple_hut_place_hut( p, sizex, sizez, materials, heightmap );
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- actually build the "hut"
|
||||||
|
simple_houses.simple_hut_place_hut = function( p, sizex, sizez, materials, heightmap )
|
||||||
|
|
||||||
|
sizex = sizex-1;
|
||||||
|
sizez = sizez-1;
|
||||||
|
-- house too small or too large
|
||||||
|
if( sizex < 3 or sizez < 3 or sizex>64 or sizez>64) then
|
||||||
|
return nil;
|
||||||
|
end
|
||||||
|
|
||||||
|
local vm = minetest.get_voxel_manip();
|
||||||
|
local minp2, maxp2 = vm:read_from_map(
|
||||||
|
{x=p.x - sizex, y=p.y-1, z=p.z - sizez },
|
||||||
|
{x=p.x, y=p.y+math.max(sizex,sizez)*2, z=p.z});
|
||||||
|
|
||||||
|
-- print( " Placing house at "..minetest.pos_to_string( p ));
|
||||||
|
|
||||||
|
local window_at_height = {0,0,0,0,0};
|
||||||
|
local r = math.random(1,6);
|
||||||
|
if( r==1 or r==2) then
|
||||||
|
window_at_height = {0,1,1,1,0};
|
||||||
|
elseif( r==3 or r==4 or r==5) then
|
||||||
|
window_at_height = {0,0,1,1,0};
|
||||||
|
else
|
||||||
|
window_at_height = {0,0,1,0,0};
|
||||||
|
end
|
||||||
|
local window_at_odd_row = false;
|
||||||
|
if( math.random(1,2)==1 ) then
|
||||||
|
window_at_odd_row = true;
|
||||||
|
end
|
||||||
|
|
||||||
|
local dz = p.z;
|
||||||
|
for dx = p.x-sizex+1, p.x-1 do
|
||||||
|
local m1 = materials.walls;
|
||||||
|
local m2 = materials.walls;
|
||||||
|
if( dx>p.x-sizex+1 and dx<p.x-2 and (window_at_odd_row == (dx%2==1))) then
|
||||||
|
if( math.random(1,2)==1) then
|
||||||
|
m1 = materials.glass;
|
||||||
|
end
|
||||||
|
if( math.random(1,2)==1) then
|
||||||
|
m2 = materials.glass;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- param2 (orientation or color) for the first two walls
|
||||||
|
local w1_c = (materials.color or 12); -- wall 1 color
|
||||||
|
local w2_c = (materials.color or 18); -- wall 2 color
|
||||||
|
for dy = p.y, p.y+4 do
|
||||||
|
-- build two walls in x direction
|
||||||
|
if( window_at_height[ dy-p.y+1 ]==1 and (m1==materials.glass or m2==materials.glass)) then
|
||||||
|
vm:set_node_at( {x=dx,y=dy,z=dz-1 }, {name=m1, param2=12});
|
||||||
|
vm:set_node_at( {x=dx,y=dy,z=dz-sizez+1}, {name=m2, param2=18});
|
||||||
|
else
|
||||||
|
vm:set_node_at( {x=dx,y=dy,z=dz-1 }, {name=materials.walls, param2=w1_c});
|
||||||
|
vm:set_node_at( {x=dx,y=dy,z=dz-sizez+1}, {name=materials.walls, param2=w2_c});
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local dx = p.x;
|
||||||
|
for dz = p.z-sizez+1, p.z-1 do
|
||||||
|
local m1 = materials.walls;
|
||||||
|
local m2 = materials.walls;
|
||||||
|
if( dz>p.z-sizez+1 and dz<p.z-2 and ( window_at_odd_row == (dz%2==1))) then
|
||||||
|
if( math.random(1,2)==1) then
|
||||||
|
m1 = materials.glass;
|
||||||
|
end
|
||||||
|
if( math.random(1,2)==1) then
|
||||||
|
m2 = materials.glass;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- param2 (orientation or color) for the other two walls
|
||||||
|
local w3_c = (materials.color or 9); -- wall 3 color
|
||||||
|
local w4_c = (materials.color or 7); -- wall 4 color
|
||||||
|
for dy = p.y, p.y+4 do
|
||||||
|
-- build two walls in z direction
|
||||||
|
if( window_at_height[ dy-p.y+1 ]==1 and (m1==materials.glass or m2==materials.glass)) then
|
||||||
|
vm:set_node_at( {x=dx-1, y=dy,z=dz}, {name=m1, param2=9});
|
||||||
|
vm:set_node_at( {x=dx-sizex+1,y=dy,z=dz}, {name=m2, param2=7});
|
||||||
|
else
|
||||||
|
vm:set_node_at( {x=dx-1, y=dy,z=dz}, {name=materials.walls, param2=w3_c});
|
||||||
|
vm:set_node_at( {x=dx-sizex+1,y=dy,z=dz}, {name=materials.walls, param2=w4_c});
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local do_ceiling = ( math.min( sizex, sizez )>4 );
|
||||||
|
-- floor and ceiling
|
||||||
|
for dx = p.x-sizex+2, p.x-2 do
|
||||||
|
for dz = p.z-sizez+2, p.z-2 do
|
||||||
|
-- a brick roof
|
||||||
|
vm:set_node_at( {x=dx,y=p.y, z=dz}, {name=materials.floor});
|
||||||
|
if( do_ceiling ) then
|
||||||
|
vm:set_node_at( {x=dx,y=p.y+4,z=dz}, {name=materials.ceiling});
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- we need a door
|
||||||
|
local door_pos = {x=p.x-1, y=p.y+1, z=p.z-1};
|
||||||
|
local r = math.random(1,4);
|
||||||
|
-- door is in x wall
|
||||||
|
if( r==1 or r==2 ) then
|
||||||
|
door_pos.x = math.random( p.x-sizex+2, p.x-2 );
|
||||||
|
if( r==2 ) then
|
||||||
|
door_pos.z = p.z-sizez+1;
|
||||||
|
else
|
||||||
|
door_pos.z = p.z-1;
|
||||||
|
end
|
||||||
|
-- dor is in z wall
|
||||||
|
else
|
||||||
|
door_pos.z = math.random( p.z-sizez+2, p.z-2 );
|
||||||
|
if( r==2 ) then
|
||||||
|
door_pos.x = p.x-sizex+1;
|
||||||
|
else
|
||||||
|
door_pos.x = p.x-1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
vm:set_node_at( door_pos, {name="doors:door_wood_a", param2 = 0 });
|
||||||
|
vm:set_node_at( {x=door_pos.x, y=door_pos.y+1, z=door_pos.z}, {name="doors:hidden"});
|
||||||
|
-- light so that the door can be found
|
||||||
|
vm:set_node_at( {x=door_pos.x, y=door_pos.y+2, z=door_pos.z}, {name="default:meselamp"});
|
||||||
|
|
||||||
|
-- roof
|
||||||
|
local g_color = materials.color or 0; -- color of the gable
|
||||||
|
if( sizex <= sizez ) then
|
||||||
|
local xhalf = math.floor( sizex/2 );
|
||||||
|
local dy = p.y+5;
|
||||||
|
for dx = 0,xhalf do
|
||||||
|
for dz = p.z-sizez, p.z do
|
||||||
|
vm:set_node_at( {x=p.x-sizex+dx,y=dy,z=dz}, {name=materials.roof, param2=1});
|
||||||
|
vm:set_node_at( {x=p.x- dx,y=dy,z=dz}, {name=materials.roof, param2=3});
|
||||||
|
end
|
||||||
|
dy = dy+1;
|
||||||
|
end
|
||||||
|
|
||||||
|
-- if sizex is not even, then we need to use slabs at the heighest point
|
||||||
|
if( sizex%2==0 ) then
|
||||||
|
for dz = p.z-sizez, p.z do
|
||||||
|
vm:set_node_at( {x=p.x-xhalf,y=p.y+6+xhalf-1,z=dz}, {name=materials.roof_middle});
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Dachgiebel (=gable)
|
||||||
|
for dx = 0,xhalf do
|
||||||
|
for dy = p.y+5, p.y+4+dx do
|
||||||
|
vm:set_node_at( {x=p.x-sizex+dx,y=dy,z=p.z-sizez+1}, {name=materials.gable, param2=g_color});
|
||||||
|
vm:set_node_at( {x=p.x- dx,y=dy,z=p.z-sizez+1}, {name=materials.gable, param2=g_color});
|
||||||
|
|
||||||
|
vm:set_node_at( {x=p.x-sizex+dx,y=dy,z=p.z -1}, {name=materials.gable, param2=g_color});
|
||||||
|
vm:set_node_at( {x=p.x- dx,y=dy,z=p.z -1}, {name=materials.gable, param2=g_color});
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local zhalf = math.floor( sizez/2 );
|
||||||
|
local dy = p.y+5;
|
||||||
|
for dz = 0,zhalf do
|
||||||
|
for dx = p.x-sizex, p.x do
|
||||||
|
vm:set_node_at( {x=dx,y=dy,z=p.z-sizez+dz}, {name=materials.roof, param2=0});
|
||||||
|
vm:set_node_at( {x=dx,y=dy,z=p.z- dz}, {name=materials.roof, param2=2});
|
||||||
|
end
|
||||||
|
dy = dy+1;
|
||||||
|
end
|
||||||
|
|
||||||
|
-- if sizex is not even, then we need to use slabs at the heighest point
|
||||||
|
if( sizez%2==0 ) then
|
||||||
|
for dx = p.x-sizex, p.x do
|
||||||
|
vm:set_node_at( {x=dx,y=p.y+6+zhalf-1,z=p.z-zhalf}, {name=materials.roof_middle});
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Dachgiebel (=gable)
|
||||||
|
for dz = 0,zhalf do
|
||||||
|
for dy = p.y+5, p.y+4+dz do
|
||||||
|
vm:set_node_at( {x=p.x-sizex+1,y=dy,z=p.z-sizez+dz}, {name=materials.gable, param2=g_color});
|
||||||
|
vm:set_node_at( {x=p.x-sizex+1,y=dy,z=p.z- dz}, {name=materials.gable, param2=g_color});
|
||||||
|
|
||||||
|
vm:set_node_at( {x=p.x -1,y=dy,z=p.z-sizez+dz}, {name=materials.gable, param2=g_color});
|
||||||
|
vm:set_node_at( {x=p.x -1,y=dy,z=p.z- dz}, {name=materials.gable, param2=g_color});
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
vm:write_to_map(true);
|
||||||
|
-- return where the hut has been placed
|
||||||
|
return {p1={x=p.x - sizex, y=p.y, z=p.z - sizez }, p2=p};
|
||||||
|
end
|
||||||
|
|
||||||
|
simple_houses.simple_hut_generate = function( heightmap, minp, maxp)
|
||||||
|
if( minp.y < -64 or minp.y > 500 or not(heightmap)) then
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
-- halfway reasonable house sizes
|
||||||
|
local maxsize = 14;
|
||||||
|
if( math.random(1,5)==1) then
|
||||||
|
maxsize = 18;
|
||||||
|
end
|
||||||
|
local sizex = math.random(7,maxsize);
|
||||||
|
local sizez = math.max( 7, math.min( maxsize, math.random( math.floor(sizex/4), sizex*2 )));
|
||||||
|
-- chooses random materials and a random place without destroying the landscape
|
||||||
|
-- minheight 2: one above water level; avoid below water level and places on ice
|
||||||
|
return simple_houses.simple_hut_find_place_and_build( heightmap, minp, maxp, sizex, sizez, 2, 1000 );
|
||||||
|
end
|
||||||
|
|
||||||
|
minetest.register_on_generated(function(minp, maxp, seed)
|
||||||
|
local heightmap = minetest.get_mapgen_object('heightmap');
|
||||||
|
for i=1,simple_houses.max_per_mapchunk do
|
||||||
|
local res = simple_houses.simple_hut_generate( heightmap, minp, maxp);
|
||||||
|
if( res and res.p1 and res.p2 ) then
|
||||||
|
local offset = maxp.x - minp.x - (res.p2.x-res.p1.x);
|
||||||
|
local i = res.p2.i;
|
||||||
|
-- mark the place where the house has been spawned as unusable (occupied)
|
||||||
|
for dz = res.p1.z, res.p2.z do
|
||||||
|
for dx = res.p1.x, res.p2.x do
|
||||||
|
heightmap[ i ] = -1000;
|
||||||
|
i = i-1;
|
||||||
|
end
|
||||||
|
i = i - offset;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end);
|
Loading…
x
Reference in New Issue
Block a user