2016-11-19 11:14:30 +01:00
-- constant subspace size
2016-11-19 21:31:00 +01:00
local c_subspacesize = 8
-- chance for node restoral per second (No worries, all nodes will be restored, but not immediately)
local c_randomize_restore = 5
2016-09-25 14:48:15 +02:00
2016-11-19 18:53:02 +01:00
-- transform compatible nodes only
local c_restricted_mode = true
local compatible_nodes = {
" default:stone " ,
" default:dirt "
}
2016-11-19 11:14:30 +01:00
-- Check if the subspace still enabled for user (or can be disabled)
2017-04-02 11:58:49 +02:00
local function ssw_get_wielded ( playername )
2016-11-19 23:12:24 +01:00
local user = minetest.get_player_by_name ( playername )
2016-11-19 11:28:49 +01:00
-- if user leave the game, disable them
if not user then
2016-09-25 14:48:15 +02:00
return false
end
2016-11-19 11:28:49 +01:00
-- user does not hold the walker in the hand
2016-09-25 14:48:15 +02:00
local item = user : get_wielded_item ( )
if not item or item : get_name ( ) ~= " subspacewalker:walker " then
2016-11-19 11:14:30 +01:00
return false
end
2016-11-19 11:28:49 +01:00
-- all ok, still active
2017-04-02 11:58:49 +02:00
return item
2016-09-25 14:48:15 +02:00
end
2016-11-19 11:28:49 +01:00
-- subspacewalker runtime data
2016-11-19 11:14:30 +01:00
local subspacewalker = {
users_in_subspace = { } ,
}
2016-09-25 14:48:15 +02:00
-- tool definition
minetest.register_tool ( " subspacewalker:walker " , {
description = " Subspace Walker " ,
2016-09-27 20:19:41 +02:00
inventory_image = " subspace_walker.png " ,
wield_image = " subspace_walker.png " ,
2016-09-25 14:48:15 +02:00
tool_capabilities = { } ,
range = 0 ,
2016-11-19 11:14:30 +01:00
on_use = function ( itemstack , user , pointed_thing )
2016-11-19 23:06:14 +01:00
subspacewalker.users_in_subspace [ user : get_player_name ( ) ] = { timer = 1 }
2016-11-19 11:14:30 +01:00
end ,
on_place = function ( itemstack , user , pointed_thing )
subspacewalker.users_in_subspace [ user : get_player_name ( ) ] = nil
end ,
on_secondary_use = function ( itemstack , user , pointed_thing )
subspacewalker.users_in_subspace [ user : get_player_name ( ) ] = nil
end
2016-09-25 14:48:15 +02:00
} )
2016-11-19 11:14:30 +01:00
-- Globalstep check for nodes to hide
minetest.register_globalstep ( function ( dtime )
2016-11-19 21:31:00 +01:00
-- check each player with walker active
2016-11-19 23:12:24 +01:00
for playername , ssw in pairs ( subspacewalker.users_in_subspace ) do
ssw.timer = ssw.timer + dtime
2017-04-02 11:58:49 +02:00
local ssw_stack = ssw_get_wielded ( playername )
if not ssw_stack then
2016-11-19 23:12:24 +01:00
subspacewalker.users_in_subspace [ playername ] = nil
2016-11-19 11:14:30 +01:00
else
2016-11-19 23:12:24 +01:00
local user = minetest.get_player_by_name ( playername )
2016-11-19 21:31:00 +01:00
local control = user : get_player_control ( )
2016-11-19 11:14:30 +01:00
local userpos = user : getpos ( )
2016-11-19 12:54:46 +01:00
2016-11-19 21:31:00 +01:00
--regular step, once each second
2017-01-11 21:14:03 +01:00
if ssw.timer > 0.2 or --0.5
2016-11-19 21:31:00 +01:00
--sneaking but not in air
( control.sneak and userpos.y - 0.5 == math.floor ( userpos.y ) ) then
2016-11-19 23:12:24 +01:00
ssw.timer = 0
2016-11-19 21:31:00 +01:00
-- set offset for jump or sneak
userpos.y = math.floor ( userpos.y + 0.5 )
if control.jump then
userpos.y = userpos.y + 1
elseif control.sneak then
userpos.y = userpos.y - 1
end
userpos = vector.round ( userpos )
--voxel_manip magic
local pos1 = { x = userpos.x - c_subspacesize , y = userpos.y , z = userpos.z - c_subspacesize }
local pos2 = { x = userpos.x + c_subspacesize , y = userpos.y + c_subspacesize , z = userpos.z + c_subspacesize }
local manip = minetest.get_voxel_manip ( )
local min_c , max_c = manip : read_from_map ( pos1 , pos2 )
local area = VoxelArea : new ( { MinEdge = min_c , MaxEdge = max_c } )
local data = manip : get_data ( )
local changed = false
local ssw_id = minetest.get_content_id ( " subspacewalker:subspace " )
local air_id = minetest.get_content_id ( " air " )
2017-04-02 11:58:49 +02:00
local transform_count = 0
2016-11-19 21:31:00 +01:00
-- check each node in the area
for i in area : iterp ( pos1 , pos2 ) do
local nodepos = area : position ( i )
-- if math.random(0, vector.distance(userpos, nodepos)) < 2 then
local cur_id = data [ i ]
if cur_id and cur_id ~= ssw_id and cur_id ~= air_id then
local cur_name = minetest.get_name_from_content_id ( cur_id )
if c_restricted_mode then
for _ , compat in ipairs ( compatible_nodes ) do
if compat == cur_name then
data [ i ] = ssw_id
minetest.get_meta ( area : position ( i ) ) : set_string ( " subspacewalker " , cur_name )
changed = true
2017-04-02 11:58:49 +02:00
transform_count = transform_count + 1
2016-11-19 21:31:00 +01:00
end
end
else
2016-11-19 18:53:02 +01:00
data [ i ] = ssw_id
minetest.get_meta ( area : position ( i ) ) : set_string ( " subspacewalker " , cur_name )
changed = true
2017-04-02 11:58:49 +02:00
transform_count = transform_count + 1
2016-11-19 18:53:02 +01:00
end
end
2016-11-19 21:31:00 +01:00
-- end
end
-- save changes if needed
if changed then
manip : set_data ( data )
manip : write_to_map ( )
2017-04-02 11:58:49 +02:00
local wear = ssw_stack : get_wear ( )
ssw_stack : add_wear ( transform_count )
user : set_wielded_item ( ssw_stack )
2016-11-19 11:14:30 +01:00
end
end
2016-11-19 12:54:46 +01:00
2016-11-19 21:31:00 +01:00
-- jump special handling. Restore node under the player
if control.jump then
local userpos = user : getpos ( )
userpos.y = math.floor ( userpos.y - 0.5 )
local node = minetest.get_node ( userpos )
local meta = minetest.get_meta ( userpos )
local data = meta : to_table ( )
if data.fields . subspacewalker then
node.name = data.fields . subspacewalker
data.fields . subspacewalker = nil
meta : from_table ( data )
minetest.swap_node ( userpos , node )
end
2016-11-19 12:54:46 +01:00
end
2016-11-19 11:14:30 +01:00
end
end
end )
2016-09-25 14:48:15 +02:00
-- node to hide the original one
minetest.register_node ( " subspacewalker:subspace " , {
2016-11-19 11:14:30 +01:00
drawtype = " airlike " ,
paramtype = " light " ,
sunlight_propagates = true ,
light_source = 5 ,
diggable = false ,
walkable = false ,
groups = { not_in_creative_inventory = 1 } ,
pointable = false ,
drop = " "
2016-09-25 14:48:15 +02:00
} )
2016-11-19 11:14:30 +01:00
-- ABM on hidden blocks checks if there can be restored again
2016-09-25 14:48:15 +02:00
minetest.register_abm ( {
2016-11-19 11:14:30 +01:00
nodenames = { " subspacewalker:subspace " } ,
2016-11-19 21:31:00 +01:00
interval = 0.5 ,
chance = c_randomize_restore ,
2016-11-19 11:14:30 +01:00
action = function ( pos , node )
if node.name == ' ignore ' then
return
end
local can_be_restored = true
-- check if the node can be restored
2016-11-19 23:12:24 +01:00
for playername , _ in pairs ( subspacewalker.users_in_subspace ) do
2017-04-02 11:58:49 +02:00
local ssw_stack = ssw_get_wielded ( playername )
if not ssw_stack then
2016-11-19 23:12:24 +01:00
subspacewalker.users_in_subspace [ playername ] = nil
2016-11-19 11:14:30 +01:00
else
2016-11-19 23:12:24 +01:00
local user = minetest.get_player_by_name ( playername )
2016-11-19 11:14:30 +01:00
local userpos = user : getpos ( )
2016-11-19 21:31:00 +01:00
userpos.y = math.floor ( userpos.y + 0.5 )
2016-11-19 11:14:30 +01:00
if ( pos.x >= userpos.x - c_subspacesize - 1 and pos.x <= userpos.x + c_subspacesize + 1 ) and -- "+1" is to avoid flickering of nodes. restoring range is higher then the effect range
2016-11-19 21:31:00 +01:00
( pos.y >= userpos.y and pos.y <= userpos.y + c_subspacesize + 1 ) and
2016-11-19 11:14:30 +01:00
( pos.z >= userpos.z - c_subspacesize - 1 and pos.z <= userpos.z + c_subspacesize + 1 ) then
2016-11-19 18:53:02 +01:00
can_be_restored = false --active user in range
2016-11-19 11:14:30 +01:00
end
end
end
--restore them
if can_be_restored then
local node = minetest.get_node ( pos )
local meta = minetest.get_meta ( pos )
local data = meta : to_table ( )
node.name = data.fields . subspacewalker
2016-11-19 18:53:02 +01:00
data.fields . subspacewalker = nil
meta : from_table ( data )
minetest.swap_node ( pos , node )
2016-11-19 11:14:30 +01:00
end
end
2016-09-25 14:48:15 +02:00
} )
2016-09-27 20:19:41 +02:00
minetest.register_craft ( {
2016-11-19 11:14:30 +01:00
output = " subspacewalker:walker " ,
width = 1 ,
recipe = {
{ " default:diamond " } ,
{ " default:mese_crystal " } ,
{ " group:stick " }
}
2016-09-27 20:19:41 +02:00
} )