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
|
180
init.lua
180
init.lua
@ -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
|
||||
})
|
||||
|
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