Compare commits

...

10 Commits

Author SHA1 Message Date
bell07
245cca91d1
Update README.md 2018-04-16 17:12:47 +02:00
bell07
834164687b
Create README.md 2018-04-16 17:11:13 +02:00
Alexander Weber
0199943697 added wear to subpacewalker usage 2017-04-02 11:58:49 +02:00
Alexander Weber
cf5c61351c adjustments 2017-01-11 21:14:03 +01:00
Alexander Weber
7ceda3644c some variables renaming 2016-11-19 23:12:24 +01:00
Alexander Weber
8138efb2cc per user timer 2016-11-19 23:06:14 +01:00
Alexander Weber
5c35dc676c rewrites and optimizations, new screenshot 2016-11-19 21:31:00 +01:00
Alexander Weber
0803109e60 bugfix + restricted mode. Tool converts stone and dirt only 2016-11-19 18:53:02 +01:00
Alexander Weber
06d5c521e7 Use VoxelManip for hiding (more effective)
including bugfix in Globalstep timer
2016-11-19 12:54:46 +01:00
Alexander Weber
69235692dd second cleanup. Bugfix: do not store user object references in table, usernames only 2016-11-19 11:28:49 +01:00
3 changed files with 143 additions and 59 deletions

22
README.md Normal file
View File

@ -0,0 +1,22 @@
# minetest-subspacewalker
Go trough walls, rock or lava using Subspace Walker tool..
The mod contains a tool that allow you to go trough blocks. If the tool is active you are in a Subspace bubble, so the real blocks around you are not there and you can walk trough them.
How to use:
- You need to hold the Subspace Walker tool in the hand and use them (right-click) for activation.
- Sneaking results in a lower Subspace and you go downwards.
- Jumping bring the nodes below you back to outside Subspace so you can go upwards
- To disable the Subspace Walker Tool just try to place it (left click) or take something other in the hand
![Alt text](https://github.com/bell07/minetest-subspacewalker/raw/master/screenshot.png)
The tool can be crafted in as a vertical stick:
```
default:diamond
default:mese_crystal
group:stick
```
Mod dependencies: none
License: GPL-V3

180
init.lua
View File

@ -1,51 +1,38 @@
-- constant subspace size
local c_subspacesize = 3
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
-- transform compatible nodes only
local c_restricted_mode = true
local compatible_nodes = {
"default:stone",
"default:dirt"
}
-- Check if the subspace still enabled for user (or can be disabled)
local function ssw_is_enabled(user)
if not user then -- if user leave the game, disable them
local function ssw_get_wielded(playername)
local user = minetest.get_player_by_name(playername)
-- if user leave the game, disable them
if not user then
return false
end
-- user does not hold the walker in the hand
local item = user:get_wielded_item()
if not item or item:get_name() ~= "subspacewalker:walker" then
return false
end
return true
-- all ok, still active
return item
end
-- Hide a node
local function hide_node(pos)
local node = minetest.get_node(pos)
if node and node.name ~= "air" and node.name ~= "subspacewalker:subspace" and node.name ~= 'ignore' then
-- Save the node's original name
minetest.get_meta(pos):set_string("subspacewalker", node.name)
-- Swap in placeholder node
node.name = "subspacewalker:subspace"
minetest.swap_node(pos, node)
end
end
-- get y offset for sneaking or jumping
local function get_player_y_offset(user)
local control = user:get_player_control()
local y = 0.5
if control.jump then
y = y + 1
end
if control.sneak then
y = y - 1
end
return y
end
-- subspacewalker runtime object
-- subspacewalker runtime data
local subspacewalker = {
users_in_subspace = {},
timer = 0,
}
------------- Minetest registrations -----------------------
-- tool definition
minetest.register_tool("subspacewalker:walker", {
description = "Subspace Walker",
@ -54,7 +41,7 @@ minetest.register_tool("subspacewalker:walker", {
tool_capabilities = {},
range = 0,
on_use = function(itemstack, user, pointed_thing)
subspacewalker.users_in_subspace[user:get_player_name()] = user
subspacewalker.users_in_subspace[user:get_player_name()] = {timer = 1}
end,
on_place = function(itemstack, user, pointed_thing)
subspacewalker.users_in_subspace[user:get_player_name()] = nil
@ -66,22 +53,95 @@ minetest.register_tool("subspacewalker:walker", {
-- Globalstep check for nodes to hide
minetest.register_globalstep(function(dtime)
subspacewalker.timer = subspacewalker.timer + dtime
if subspacewalker.timer < 0.25 then
return
end
for name, user in pairs(subspacewalker.users_in_subspace) do
if not ssw_is_enabled(user) then
subspacewalker.users_in_subspace[user:get_player_name()] = nil
-- check each player with walker active
for playername, ssw in pairs(subspacewalker.users_in_subspace) do
ssw.timer = ssw.timer + dtime
local ssw_stack = ssw_get_wielded(playername)
if not ssw_stack then
subspacewalker.users_in_subspace[playername] = nil
else
local user = minetest.get_player_by_name(playername)
local control = user:get_player_control()
local userpos = user:getpos()
local ydelta = get_player_y_offset(user)
for x=userpos.x-c_subspacesize, userpos.x+c_subspacesize do
for y=userpos.y+ydelta, userpos.y+c_subspacesize*2 do -- we need the ground under the user
for z=userpos.z-c_subspacesize, userpos.z+c_subspacesize do
hide_node({x=x,y=y,z=z})
end
--regular step, once each second
if ssw.timer > 0.2 or --0.5
--sneaking but not in air
(control.sneak and userpos.y - 0.5 == math.floor(userpos.y)) then
ssw.timer = 0
-- 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")
local transform_count = 0
-- 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
transform_count = transform_count + 1
end
end
else
data[i] = ssw_id
minetest.get_meta(area:position(i)):set_string("subspacewalker", cur_name)
changed = true
transform_count = transform_count + 1
end
end
-- end
end
-- save changes if needed
if changed then
manip:set_data(data)
manip:write_to_map()
local wear = ssw_stack:get_wear()
ssw_stack:add_wear(transform_count)
user:set_wielded_item(ssw_stack)
end
end
-- 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
end
end
@ -104,8 +164,8 @@ minetest.register_node("subspacewalker:subspace", {
-- ABM on hidden blocks checks if there can be restored again
minetest.register_abm({
nodenames = { "subspacewalker:subspace" },
interval = 0.1,
chance = 1,
interval = 0.5,
chance = c_randomize_restore,
action = function(pos, node)
if node.name == 'ignore' then
return
@ -113,16 +173,18 @@ minetest.register_abm({
local can_be_restored = true
-- check if the node can be restored
for name, user in pairs(subspacewalker.users_in_subspace) do
if not ssw_is_enabled(user) then
subspacewalker.users_in_subspace[user:get_player_name()] = nil
for playername, _ in pairs(subspacewalker.users_in_subspace) do
local ssw_stack = ssw_get_wielded(playername)
if not ssw_stack then
subspacewalker.users_in_subspace[playername] = nil
else
local user = minetest.get_player_by_name(playername)
local userpos = user:getpos()
local ydelta = get_player_y_offset(user)
userpos.y = math.floor(userpos.y+0.5)
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
( pos.y >= userpos.y+ydelta and pos.y <= userpos.y+c_subspacesize*2+1 ) and
( pos.y >= userpos.y and pos.y <= userpos.y+c_subspacesize+1 ) and
( pos.z >= userpos.z-c_subspacesize-1 and pos.z <= userpos.z+c_subspacesize+1) then
can_be_restored = false --active user in range
can_be_restored = false --active user in range
end
end
end
@ -133,9 +195,9 @@ minetest.register_abm({
local meta = minetest.get_meta(pos)
local data = meta:to_table()
node.name = data.fields.subspacewalker
data.fields.subspacewalker = nil
meta:from_table(data)
minetest.swap_node(pos, node)
data.fields.subspacewalker = nil
meta:from_table(data)
minetest.swap_node(pos, node)
end
end
})

Binary file not shown.

Before

Width:  |  Height:  |  Size: 892 KiB

After

Width:  |  Height:  |  Size: 276 KiB