first basic version

This commit is contained in:
Sokomine 2015-05-25 06:12:41 +02:00
commit c96859cf27
6 changed files with 459 additions and 0 deletions

1
README.md Normal file
View File

@ -0,0 +1 @@
This mod is a work in progress.

3
depends.txt Normal file
View File

@ -0,0 +1,3 @@
default
cottages?
tnt?

13
init.lua Normal file
View File

@ -0,0 +1,13 @@
-- the namespace
mines_with_shafts = {};
mines_with_shafts.modpath = minetest.get_modpath( "mines_with_shafts");
-- the mod comes with its own ladder and rope; both act as rails for carts
dofile(mines_with_shafts.modpath.."/nodes.lua")
dofile(mines_with_shafts.modpath.."/mines_horizontal_tunnels.lua")
dofile(mines_with_shafts.modpath.."/mines_create.lua")
-- TODO: give credits to the texture creator(s)
-- TODO: add vertical shafts

96
mines_create.lua Normal file
View File

@ -0,0 +1,96 @@
local cid_mines = {};
cid_mines.c_ignore = minetest.get_content_id('ignore');
cid_mines.c_air = minetest.get_content_id('air');
-- basic material used for the tunnels
cid_mines.c_wood = minetest.get_content_id('default:wood');
cid_mines.c_fence = minetest.get_content_id('default:fence_wood');
cid_mines.c_torch = minetest.get_content_id('default:torch');
cid_mines.c_rail = minetest.get_content_id('default:rail');
-- basic additional material used for the shafts
cid_mines.c_mineladder = minetest.get_content_id('mines_with_shafts:ladder');
cid_mines.c_rope = minetest.get_content_id('mines_with_shafts:rope');
-- node types that force mine shafts to end there (floodings are still possible)
cid_mines.c_lava = minetest.get_content_id('default:lava_source');
cid_mines.c_lava_flowing = minetest.get_content_id('default:lava_flowing');
cid_mines.c_water = minetest.get_content_id('default:water_source');
-- nodes that may be found at the side of the tunnels randomly
cid_mines.c_chest = minetest.get_content_id('default:chest');
cid_mines.c_stone = minetest.get_content_id('default:stone');
cid_mines.c_sand = minetest.get_content_id('default:sand');
cid_mines.c_gravel = minetest.get_content_id('default:gravel');
cid_mines.c_ladder = minetest.get_content_id('default:ladder');
cid_mines.c_sign_wall = minetest.get_content_id('default:sign_wall');
cid_mines.c_coalblock = minetest.get_content_id('default:coalblock');
cid_mines.c_steelblock = minetest.get_content_id('default:steelblock');
cid_mines.c_copperblock = minetest.get_content_id('default:copperblock');
cid_mines.c_barrel = minetest.get_content_id('cottages:barrel');
cid_mines.c_shelf = minetest.get_content_id('cottages:shelf');
cid_mines.c_tnt = minetest.get_content_id('tnt:tnt');
-- TODO
mines_with_shafts.create_mine = function( minp, maxp, data, param2_data, a )
local npos = {x=minp.x+40,y=minp.y+40,z=minp.z+40,bsizex=100,bsizez=1};
local backwards = false;
local extra_calls_mines = {chests={}, signs={}};
mines_with_shafts.place_minetunnel_horizontal(minp, maxp, data, param2_data, a, cid_mines, npos, 100, 1, extra_calls_mines );
mines_with_shafts.place_minetunnel_horizontal(minp, maxp, data, param2_data, a, cid_mines, npos, -100, 1, extra_calls_mines );
mines_with_shafts.place_minetunnel_horizontal(minp, maxp, data, param2_data, a, cid_mines, npos, 100, 0, extra_calls_mines );
mines_with_shafts.place_minetunnel_horizontal(minp, maxp, data, param2_data, a, cid_mines, npos, -100, 0, extra_calls_mines );
end
minetest.register_on_generated(function(minp, maxp, seed)
-- TODO: mines still float in the air
-- limit height of the mines
if( minp.y < -256 or minp.y > 64) then
return;
end
local vm;
local a;
local data;
local param2_data;
-- get the voxelmanip object
local emin;
local emax;
-- if no voxelmanip data was passed on, read the data here
if( not( vm ) or not( a) or not( data ) or not( param2_data ) ) then
vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
if( not( vm )) then
return;
end
a = VoxelArea:new{
MinEdge={x=emin.x, y=emin.y, z=emin.z},
MaxEdge={x=emax.x, y=emax.y, z=emax.z},
}
data = vm:get_data()
param2_data = vm:get_param2_data()
end
-- actually create the mine
mines_with_shafts.create_mine( emin, emax, data, param2_data, a );
-- store the voxelmanip data
vm:set_data(data)
vm:set_param2_data(param2_data)
vm:calc_lighting( tmin, tmax);
vm:write_to_map(data);
vm:update_liquids();
end)

View File

@ -0,0 +1,280 @@
-----------------------------------------------------
-- this creates the horizontal tunnels for the mines
----------------------------------------------------
-- if length is <0, the tunnel will go in the opposite direction
mines_with_shafts.place_minetunnel_horizontal = function(minp, maxp, data, param2_data, a, cid, pos, length, parallel_to_x_axis, extra_calls )
-- minetunnels are not allowed to follow the borders of mapchunks while beeing only partly contained in that chunk
-- as this would make consistent placement a lot harder and is not really needed for convincing mines
if( (pos.y-2 < minp.y and pos.y+2 > minp.y )
or (pos.y-2 < maxp.y and pos.y+2 > maxp.y )
or (pos.z-2 < minp.z and pos.z+2 > minp.z and parallel_to_x_axis == 1)
or (pos.z-2 < maxp.z and pos.z+2 > maxp.z and parallel_to_x_axis == 1)
or (pos.x-2 < minp.x and pos.x+2 > minp.x and parallel_to_x_axis == 0)
or (pos.x-2 < maxp.x and pos.x+2 > maxp.x and parallel_to_x_axis == 0)) then
return;
end
local vector = {x=0,y=0,z=0};
local vector_quer = {x=0,y=0,z=0};
-- the tunnel extends in x direction
if( parallel_to_x_axis == 1 ) then
if( length>0) then
vector.x = 1;
else
vector.x = -1;
end
vector_quer.z = 1;
elseif( parallel_to_x_axis == 0 ) then
if( length>0) then
vector.z = 1;
else
vector.z = -1;
end
vector_quer.x = 1;
else
-- wrong parameters
return;
end
-- the actual start position will be 2 nodes further in, thus creating nice crossings
local ax = pos.x+vector.x;
local az = pos.z+vector.z;
for i=1,math.abs(length) do
-- go one step further in eitzer x or z direction
ax = ax+vector.x;
az = az+vector.z;
-- make sure we do not exceed the boundaries of the mapchunk
if( ax < minp.x or ax > maxp.x
or az < minp.z or az > maxp.z ) then
return;
end
local res = mines_with_shafts.do_minetunnel_horizontal_slice( minp, maxp, data, param2_data, a, cid,
{x=ax, y=pos.y, z=az}, vector_quer, i%4, (length<0), extra_calls);
-- abort if there is anything that prevents the mine from progressing in that direction
if( res < 0 ) then
return;
end
end
end
-- internal function
-- * go one node into the direction given by vector
-- * place a support beam made from wood and fences if beam_seq_nr==0
-- * place torches and random nodes at the sides otherwise
-- * returns a value >= 0 if everything went fine
-- * returns a value <0 if the mine has to end at this place (i.e. sunlight detected, or water/lava found
mines_with_shafts.do_minetunnel_horizontal_slice = function( minp, maxp, data, param2_data, a, cid, pos, vector, beam_seq_nr, backwards, extra_calls )
local p = {x=pos.x, y=pos.y, z=pos.y};
local ax=pos.x;
local az=pos.z;
local no_daylight = true;
-- check if there are any nodes that force an end to the tunnel
for ax=pos.x+(vector.x*-2),pos.x+(vector.x*2) do
for az=pos.z+(vector.z*-2),pos.z+(vector.z*2) do
for y=-1,2 do
local old_node = data[ a:index( ax, pos.y+y, az)];
-- we have hit a vertical minetunnel
if( old_node==cid.c_mineladder or old_node==cid.c_rope ) then
-- the tunnel may still continue behind this vertical tunnel
return 0;
end
-- we do not want to build a tunnel through lava or water; though both may flow in if we digged too far
-- (the poor inhabitants will have given up the tunnel)
if( old_node==cid.c_lava or old_node==cid.c_lava_flowing or old_node==cid.c_water ) then
-- the tunnel has to end here
print('MINESHAFT abort due to water or lava at '..minetest.pos_to_string( pos));
return -1;
end
if( math.abs(ax-pos.x)<2 and math.abs(az-pos.z)<2 ) then
-- as soon as any of the 3 topmost nodes receives no daylight, we do not need to check any longer
if( y==2 and no_daylight) then
local light = minetest.get_node_light({x=ax, y=pos.y+y, z=az}, 0.5);
if( light and light==15 ) then
no_daylight = false;
end
end
-- if there is air at the bottom, place some wood to walk on (even if the tunnel will later be aborted)
if( y==-1 and old_node==cid.c_air) then
data[ a:index( ax, pos.y+y, az)] = cid.c_wood;
end
end
end
end
end
-- there will always be a rail on the ground
data[ a:index( pos.x, pos.y, pos.z )] = cid.c_rail;
-- ..and air directly above so that players can walk through
data[ a:index( pos.x, pos.y+1, pos.z )] = cid.c_air;
-- if all three topmost nodes receive daylight, then it's time to end our tunnel
if( not( no_daylight )) then
print('MINESHAFT abort due to daylight at '..minetest.pos_to_string(pos));
return -2;
end
-- every 4th tunnel has a wooden support beam
if( beam_seq_nr == 0 ) then
-- either vector.x or vector.z is 0; the other value will be 1
ax = vector.x;
az = vector.z;
-- place the four fences at the sides
data[ a:index( pos.x-ax, pos.y, pos.z-az )] = cid.c_fence;
data[ a:index( pos.x-ax, pos.y+1, pos.z-az )] = cid.c_fence;
data[ a:index( pos.x+ax, pos.y, pos.z+az )] = cid.c_fence;
data[ a:index( pos.x+ax, pos.y+1, pos.z+az )] = cid.c_fence;
-- place the three wooden planks on top of the fences
data[ a:index( pos.x, pos.y+2, pos.z )] = cid.c_wood;
data[ a:index( pos.x-ax, pos.y+2, pos.z-az )] = cid.c_wood;
data[ a:index( pos.x+ax, pos.y+2, pos.z+az )] = cid.c_wood;
-- all has been placed successfully
return 1;
end
-- create the tunnel as such
for ax=pos.x+(vector.x*-1),pos.x+(vector.x*1) do
for az=pos.z+(vector.z*-1),pos.z+(vector.z*1) do
for ay = pos.y, pos.y+2 do
if( (ax ~= pos.x or az ~= pos.z) and ( ay>pos.y or data[a:index(ax,ay,az)]~=cid.c_rail)) then
data[ a:index( ax, ay, az )] = cid.c_air;
end
end
end
end
-- attach a torch to the beam
local p2 = -1;
if( beam_seq_nr == 1 ) then
if( vector.x ~= 0 and not(backwards )) then
p2 = 5;
elseif( vector.x ~= 0 and backwards ) then
p2 = 4;
elseif( vector.z ~= 0 and not(backwards )) then
p2 = 3;
elseif( vector.z ~= 0 and backwards ) then
p2 = 2;
end
-- put air in the middle
elseif( beam_seq_nr == 2 ) then
data[ a:index( pos.x, pos.y+2, pos.z )] = cid.c_air;
-- attach a torch to the beam
elseif( beam_seq_nr == 3 ) then
if( vector.x ~= 0 and not(backwards )) then
p2 = 4;
elseif( vector.x ~= 0 and backwards ) then
p2 = 5;
elseif( vector.z ~= 0 and not(backwards )) then
p2 = 2;
elseif( vector.z ~= 0 and backwards ) then
p2 = 3;
end
end
if( p2 > -1 ) then
data[ a:index( pos.x, pos.y+2, pos.z )] = cid.c_torch;
param2_data[ a:index( pos.x, pos.y+2, pos.z )] = p2;
end
mines_with_shafts.place_random_decoration( data, param2_data, a, cid, pos, vector, extra_calls );
-- the tunnel has been created successfully
return 1;
end
-- internal function
-- * place a random decoration at one of the sides (or dig a one-node-wide hole or water source into the floor)
mines_with_shafts.place_random_decoration = function( data, param2_data, a, cid, pos, vector, extra_calls )
-- get a random object for placing in the tunnel
local new_id = cid.c_air;
local c = math.random( 1,100 );
if( c<5 ) then -- 1,2,3,4
new_id = cid.c_chest;
elseif( c<7 ) then -- 5,6
new_id = cid.c_barrel;
elseif( c<9 ) then -- 7,8
new_id = cid.c_shelf;
elseif( c<11 ) then -- 9,10
new_id = cid.c_stone;
elseif( c<13 ) then -- 11,12
new_id = cid.c_sand;
elseif( c<15 ) then -- 13,14
new_id = cid.c_gravel;
elseif( c<17 ) then -- 15,16
new_id = cid.c_ladder;
elseif( c<19 ) then -- 17,18
new_id = cid.c_coalblock;
elseif( c<20 ) then -- 20
new_id = cid.c_tnt;
elseif( c<21 ) then -- 21
new_id = cid.c_sign_wall;
elseif( c<22 ) then
new_id = cid.c_steelblock;
elseif( c<23 ) then
new_id = cid.c_copperblock;
-- small chance for a water hole at the side
elseif( c==96 ) then
data[ a:index( pos.x-vector.x, pos.y-1, pos.z-vector.z )]=cid.c_water;
elseif( c==97 ) then
data[ a:index( pos.x+vector.x, pos.y-1, pos.z+vector.z )]=cid.c_water;
-- holes at the sides may also occour
elseif( c==98 ) then
data[ a:index( pos.x-vector.x, pos.y-1, pos.z-vector.z )]=cid.c_air;
elseif( c==99 ) then
data[ a:index( pos.x+vector.x, pos.y-1, pos.z+vector.z )]=cid.c_air;
else
return;
end
if( new_id == cid.c_ignore or new_id == cid.c_air ) then
return;
end
-- only one side of the tunnel gets an object
local side = 1;
if( math.random( 1,2 )==1 ) then
side = -1;
end
ax = pos.x+vector.x*side;
ay = pos.y;
az = pos.z+vector.z*side;
-- only place something there if the place is currently empty
if( data[ a:index( ax, ay, az )]~=cid.c_air ) then
return;
end
data[ a:index( ax, ay, az )] = new_id;
-- rotate facedir nodes correctly
local p2 = 0;
if( side==-1 and vector.x~=0 ) then
p2 = 3;
elseif( side== 1 and vector.x~=0 ) then
p2 = 1;
elseif( side==-1 and vector.z~=0 ) then
p2 = 2;
elseif( side== 1 and vector.z~=0 ) then
p2 = 0;
end
param2_data[ a:index( ax, ay, az )] = p2;
if( new_id == cid.c_chest ) then
table.insert( extra_calls.chests, {x=ax, y=ay, z=az, typ=new_content, bpos_i=-1, typ_name='chest_in_mine'});
elseif( new_id == cid.c_shelf ) then
table.insert( extra_calls.chests, {x=ax, y=ay, z=az, typ=new_content, bpos_i=-1, typ_name='shelf_in_mine'});
elseif( new_id == cid.c_sign_wall ) then
table.insert( extra_calls.signs, {x=ax, y=ay, z=az, typ=new_content, bpos_i=-1, typ_name='sign_in_mine'});
end
end

66
nodes.lua Normal file
View File

@ -0,0 +1,66 @@
---------------------------------------------------------------------------------------
-- a rope that is of use to the mines
---------------------------------------------------------------------------------------
-- the rope can only be digged if there is no further rope above it;
-- Note: This rope also counts as a rail node; thus, carts can move through it
minetest.register_node("mines_with_shafts:rope", {
description = "rope for climbing",
tiles = {"mines_with_shafts_rope.png"},
groups = {snappy=3,choppy=3,oddly_breakable_by_hand=3,rail=1,connect_to_raillike=1},--connect_to_raillike=minetest.raillike_group("rail")},
walkable = false,
climbable = true,
paramtype = "light",
sunlight_propagates = true,
drawtype = "plantlike",
can_dig = function(pos, player)
local below = minetest.get_node( {x=pos.x, y=pos.y-1, z=pos.z});
if( below and below.name and below.name == "mines_with_shafts:rope" ) then
if( player ) then
minetest.chat_send_player( player:get_player_name(),
'The entire rope would be too heavy. Start digging at its lowest end!');
end
return false;
end
return true;
end
})
minetest.register_craft({
output = "mines_with_shafts:rope",
recipe = {
{"default:cotton","default:cotton","default:cotton"}
}
})
-- Note: This rope also counts as a rail node; thus, carts can move through it
minetest.register_node("mines_with_shafts:ladder", {
description = "Ladder with rail support",
drawtype = "signlike",
tiles = {"default_ladder.png^default_rail.png^mines_with_shafts_rope.png"},
inventory_image = "default_ladder.png",
wield_image = "default_ladder.png",
paramtype = "light",
paramtype2 = "wallmounted",
sunlight_propagates = true,
walkable = false,
climbable = true,
is_ground_content = false,
selection_box = {
type = "wallmounted",
},
groups = {choppy=2,oddly_breakable_by_hand=3,rail=1,connect_to_raillike=1}, --connect_to_raillike=minetest.raillike_group("rail")},
legacy_wallmounted = true,
sounds = default.node_sound_wood_defaults(),
})
minetest.register_craft({
output = "mines_with_shafts:ladder 2",
recipe = {
{"default:ladder","default:rail"}
}
})