Compare commits
10 Commits
bfd3ecfdbd
...
245cca91d1
Author | SHA1 | Date | |
---|---|---|---|
|
245cca91d1 | ||
|
834164687b | ||
|
0199943697 | ||
|
cf5c61351c | ||
|
7ceda3644c | ||
|
8138efb2cc | ||
|
5c35dc676c | ||
|
0803109e60 | ||
|
06d5c521e7 | ||
|
69235692dd |
22
README.md
Normal file
22
README.md
Normal 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
|
170
init.lua
170
init.lua
@ -1,51 +1,38 @@
|
|||||||
-- constant subspace size
|
-- 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)
|
-- Check if the subspace still enabled for user (or can be disabled)
|
||||||
local function ssw_is_enabled(user)
|
local function ssw_get_wielded(playername)
|
||||||
if not user then -- if user leave the game, disable them
|
local user = minetest.get_player_by_name(playername)
|
||||||
|
-- if user leave the game, disable them
|
||||||
|
if not user then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
-- user does not hold the walker in the hand
|
||||||
local item = user:get_wielded_item()
|
local item = user:get_wielded_item()
|
||||||
if not item or item:get_name() ~= "subspacewalker:walker" then
|
if not item or item:get_name() ~= "subspacewalker:walker" then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
return true
|
-- all ok, still active
|
||||||
|
return item
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Hide a node
|
-- subspacewalker runtime data
|
||||||
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
|
|
||||||
local subspacewalker = {
|
local subspacewalker = {
|
||||||
users_in_subspace = {},
|
users_in_subspace = {},
|
||||||
timer = 0,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
------------- Minetest registrations -----------------------
|
|
||||||
-- tool definition
|
-- tool definition
|
||||||
minetest.register_tool("subspacewalker:walker", {
|
minetest.register_tool("subspacewalker:walker", {
|
||||||
description = "Subspace Walker",
|
description = "Subspace Walker",
|
||||||
@ -54,7 +41,7 @@ minetest.register_tool("subspacewalker:walker", {
|
|||||||
tool_capabilities = {},
|
tool_capabilities = {},
|
||||||
range = 0,
|
range = 0,
|
||||||
on_use = function(itemstack, user, pointed_thing)
|
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,
|
end,
|
||||||
on_place = function(itemstack, user, pointed_thing)
|
on_place = function(itemstack, user, pointed_thing)
|
||||||
subspacewalker.users_in_subspace[user:get_player_name()] = nil
|
subspacewalker.users_in_subspace[user:get_player_name()] = nil
|
||||||
@ -66,22 +53,95 @@ minetest.register_tool("subspacewalker:walker", {
|
|||||||
|
|
||||||
-- Globalstep check for nodes to hide
|
-- Globalstep check for nodes to hide
|
||||||
minetest.register_globalstep(function(dtime)
|
minetest.register_globalstep(function(dtime)
|
||||||
subspacewalker.timer = subspacewalker.timer + dtime
|
-- check each player with walker active
|
||||||
if subspacewalker.timer < 0.25 then
|
for playername, ssw in pairs(subspacewalker.users_in_subspace) do
|
||||||
return
|
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()
|
||||||
|
|
||||||
|
--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
|
end
|
||||||
|
|
||||||
for name, user in pairs(subspacewalker.users_in_subspace) do
|
-- jump special handling. Restore node under the player
|
||||||
if not ssw_is_enabled(user) then
|
if control.jump then
|
||||||
subspacewalker.users_in_subspace[user:get_player_name()] = nil
|
|
||||||
else
|
|
||||||
local userpos = user:getpos()
|
local userpos = user:getpos()
|
||||||
local ydelta = get_player_y_offset(user)
|
userpos.y = math.floor(userpos.y-0.5)
|
||||||
for x=userpos.x-c_subspacesize, userpos.x+c_subspacesize do
|
local node = minetest.get_node(userpos)
|
||||||
for y=userpos.y+ydelta, userpos.y+c_subspacesize*2 do -- we need the ground under the user
|
local meta = minetest.get_meta(userpos)
|
||||||
for z=userpos.z-c_subspacesize, userpos.z+c_subspacesize do
|
local data = meta:to_table()
|
||||||
hide_node({x=x,y=y,z=z})
|
if data.fields.subspacewalker then
|
||||||
end
|
node.name = data.fields.subspacewalker
|
||||||
|
data.fields.subspacewalker = nil
|
||||||
|
meta:from_table(data)
|
||||||
|
minetest.swap_node(userpos, node)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -104,8 +164,8 @@ minetest.register_node("subspacewalker:subspace", {
|
|||||||
-- ABM on hidden blocks checks if there can be restored again
|
-- ABM on hidden blocks checks if there can be restored again
|
||||||
minetest.register_abm({
|
minetest.register_abm({
|
||||||
nodenames = { "subspacewalker:subspace" },
|
nodenames = { "subspacewalker:subspace" },
|
||||||
interval = 0.1,
|
interval = 0.5,
|
||||||
chance = 1,
|
chance = c_randomize_restore,
|
||||||
action = function(pos, node)
|
action = function(pos, node)
|
||||||
if node.name == 'ignore' then
|
if node.name == 'ignore' then
|
||||||
return
|
return
|
||||||
@ -113,14 +173,16 @@ minetest.register_abm({
|
|||||||
|
|
||||||
local can_be_restored = true
|
local can_be_restored = true
|
||||||
-- check if the node can be restored
|
-- check if the node can be restored
|
||||||
for name, user in pairs(subspacewalker.users_in_subspace) do
|
for playername, _ in pairs(subspacewalker.users_in_subspace) do
|
||||||
if not ssw_is_enabled(user) then
|
local ssw_stack = ssw_get_wielded(playername)
|
||||||
subspacewalker.users_in_subspace[user:get_player_name()] = nil
|
if not ssw_stack then
|
||||||
|
subspacewalker.users_in_subspace[playername] = nil
|
||||||
else
|
else
|
||||||
|
local user = minetest.get_player_by_name(playername)
|
||||||
local userpos = user:getpos()
|
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
|
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
|
( 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
|
||||||
|
BIN
screenshot.png
BIN
screenshot.png
Binary file not shown.
Before Width: | Height: | Size: 892 KiB After Width: | Height: | Size: 276 KiB |
Loading…
x
Reference in New Issue
Block a user