Compare commits
10 Commits
7117c0112c
...
78d60b3c70
Author | SHA1 | Date | |
---|---|---|---|
|
78d60b3c70 | ||
|
43b803d82d | ||
|
21ccde6deb | ||
|
4213e60d11 | ||
|
9845a89ec5 | ||
|
910d0cea29 | ||
|
c704426e9b | ||
|
37713a75ad | ||
|
629f635802 | ||
|
af8472eca0 |
36
README.md
36
README.md
@ -1,4 +1,4 @@
|
||||
# ccompass
|
||||
# ccompass
|
||||
|
||||
This minetest mod adds a calibratable compass to the minetest. Original mod [here](https://forum.minetest.net/viewtopic.php?f=11&t=3785)
|
||||
|
||||
@ -15,6 +15,8 @@ This minetest mod adds a calibratable compass to the minetest. Original mod [her
|
||||
3. Now this compass leads you allways to this location. You can give it away to allow other users to find this place.
|
||||
4. Punch a teleport compatible node (by default mese block) to teleport back to the calibrated place
|
||||
|
||||
Depending on servers many aspects can be different, see below.
|
||||
|
||||
## For server owners:
|
||||
The mod support the next settings:
|
||||
|
||||
@ -23,8 +25,15 @@ The mod support the next settings:
|
||||
ccompass_restrict_target (Disabled by default): If enabled, only specific nodes are allowed for calibration (usable with any type waypoint nodes for example)
|
||||
ccompass_restrict_target_nodes: List of technical node names allowed for compass calibration, separated by ','
|
||||
ccompass_aliasses: If enabled the compas:* items will be aliased to the ccompass:* items for compatibility
|
||||
ccompass_teleport_nodes: List of technical node names that triggers the teleport to destination, separated by ','
|
||||
|
||||
ccompass_teleport_nodes: List of technical node names that triggers the teleport to destination, separated by ','. Default is "default:mese". Set it to "none" to disable the teleporting feature.
|
||||
ccompass_nodes_over_target_allow: List of additional node names that must be above target for teleport to be executed. (separated by ',')
|
||||
ccompass_nodes_over_target_deny: List of additional node names that must NOT be above target for teleport to be executed. (separated by ',')
|
||||
ccompass_nodes_over_target_allow_drawtypes: List of drawtypes to allow to be over target. Defaults are: airlike, flowingliquid, liquid, plantlike and plantlike_rooted
|
||||
ccompass_deny_climbable_target: Disabled by default -> allows climbable nodes to be over target. Set to true to not allow them.
|
||||
ccompass_allow_damage_target: Disabled by default -> will not teleport player into or over damaging nodes.
|
||||
ccompass_stack_max: 1 by default. Sets maximum stack size, 1 to 65535
|
||||
ccompass_allow_using_stacks: Disabled by default -> calibrating and teleporting only works when single compass in hand. Setting to true, allows callibrating stacks to same location.
|
||||
ccompass_idle_interval: 1 by default. When no players have active compasses, the mod enters an idle state and only checks for compasses at this interval, measured in seconds. This setting is meant to reduce the load on the server.
|
||||
|
||||
## For developers:
|
||||
1. It is possible to change compass settings from other mods by changing values in global table ccompass. So it is possible for example to add a waypoint node to the target-nodes by
|
||||
@ -34,7 +43,21 @@ The mod support the next settings:
|
||||
ccompass.restrict_target = true
|
||||
ccompass.restrict_target_nodes["schnitzeljagd:waypoint"] = true
|
||||
ccompass.teleport_nodes["default:diamondblock"] = true
|
||||
ccompass.nodes_over_target_allow["vacuum:vacuum"] = true
|
||||
ccompass.nodes_over_target_deny["tnt:boom"] = true
|
||||
ccompass.nodes_over_target_allow_drawtypes["liquid"] = nil
|
||||
ccompass.allow_climbable_target = false
|
||||
ccompass.allow_damaging_target = true
|
||||
ccompass.allow_using_stacks = true
|
||||
ccompass.stack_max = 42
|
||||
ccompass.idle_interval = 0
|
||||
```
|
||||
Also you can override ccompass.is_safe_target(target, nodename) for more granular checks.
|
||||
By default first nodes_over_target_allow is checked, then nodes_over_target_deny
|
||||
and finally nodes are checked for damaging and airlike drawtype.
|
||||
|
||||
Similarly you can override ccompass.is_safe_target_under(target, nodename) for
|
||||
more granular checks on what is under players feet.
|
||||
|
||||
2. The pointed node metadata will be checked for "waypoint_name" attribute. It this attribute is set, the calibration screen take this string as proposal. This can be used for a game specific calibration node. To get it working working just set in node definition something like
|
||||
|
||||
@ -47,7 +70,7 @@ The mod support the next settings:
|
||||
end,
|
||||
```
|
||||
|
||||
3. It is possible to create pre-calibrated compasses trough other mods. Just write the position to the Itemstack meta:
|
||||
3. It is possible to create pre-calibrated compasses through other mods. Just write the position to the Itemstack meta:
|
||||
|
||||
```
|
||||
stack:get_meta():set_string("target_pos", minetest.pos_to_string(pos))
|
||||
@ -71,3 +94,8 @@ The mod support the next settings:
|
||||
return modified_compass_stack
|
||||
end
|
||||
```
|
||||
|
||||
5. Setting ccompass.stack_max to 1 restores behaviour prior to stackable feature.
|
||||
Or going the other way: set ccompass.stack_max to 777 and also set ccompass.allow_using_stacks to true.
|
||||
This would allow players to make a big number of copies at once.
|
||||
|
||||
|
197
init.lua
197
init.lua
@ -19,6 +19,10 @@ if nodes_setting then
|
||||
ccompass.restrict_target_nodes[z] = true
|
||||
end)
|
||||
end
|
||||
|
||||
ccompass.allow_climbable_target = not minetest.settings:get_bool("ccompass_deny_climbable_target")
|
||||
ccompass.allow_damaging_target = minetest.settings:get_bool("ccompass_allow_damage_target")
|
||||
|
||||
-- Teleport targets
|
||||
ccompass.teleport_nodes = {}
|
||||
local teleport_nodes_setting = minetest.settings:get("ccompass_teleport_nodes")
|
||||
@ -29,6 +33,44 @@ if teleport_nodes_setting then
|
||||
else
|
||||
ccompass.teleport_nodes["default:mese"] = true
|
||||
end
|
||||
-- Permited nodes above target
|
||||
ccompass.nodes_over_target_allow = {}
|
||||
nodes_setting = minetest.settings:get("ccompass_nodes_over_target_allow")
|
||||
if nodes_setting then
|
||||
nodes_setting:gsub("[^,]+", function(z)
|
||||
ccompass.nodes_over_target_allow[z] = true
|
||||
end)
|
||||
end
|
||||
-- Not permited nodes above target
|
||||
ccompass.nodes_over_target_deny = {}
|
||||
nodes_setting = minetest.settings:get("ccompass_nodes_over_target_deny")
|
||||
if nodes_setting then
|
||||
nodes_setting:gsub("[^,]+", function(z)
|
||||
ccompass.nodes_over_target_deny[z] = true
|
||||
end)
|
||||
end
|
||||
-- Permited drawtype of nodes above target
|
||||
ccompass.nodes_over_target_allow_drawtypes = {}
|
||||
nodes_setting = minetest.settings:get("ccompass_nodes_over_target_allow_drawtypes")
|
||||
if nodes_setting then
|
||||
nodes_setting:gsub("[^,]+", function(z)
|
||||
ccompass.nodes_over_target_allow_drawtypes[z] = true
|
||||
end)
|
||||
else
|
||||
ccompass.nodes_over_target_allow_drawtypes = {
|
||||
airlike = true,
|
||||
flowingliquid = true,
|
||||
liquid = true,
|
||||
plantlike = true,
|
||||
plantlike_rooted = true,
|
||||
}
|
||||
end
|
||||
|
||||
-- default to legacy behaviour
|
||||
ccompass.stack_max = tonumber(minetest.settings:get("ccompass_stack_max") or 1) or 1
|
||||
ccompass.allow_using_stacks = minetest.settings:get_bool("ccompass_allow_using_stacks")
|
||||
|
||||
ccompass.idle_interval = tonumber(minetest.settings:get("ccompass_idle_interval") or 1) or 1
|
||||
|
||||
if minetest.settings:get_bool("ccompass_aliasses") then
|
||||
minetest.register_alias("compass:0", "ccompass:0")
|
||||
@ -78,34 +120,125 @@ local function get_destination(player, stack)
|
||||
end
|
||||
end
|
||||
|
||||
function ccompass.is_safe_target(target, nodename)
|
||||
local node_def = minetest.registered_nodes[nodename]
|
||||
-- unknown node: not dangerous but probably best treated as one
|
||||
if not node_def then return false end
|
||||
-- white-list
|
||||
if ccompass.nodes_over_target_allow[nodename] then return true end
|
||||
-- black-list
|
||||
if ccompass.nodes_over_target_deny[nodename] then return false end
|
||||
-- damaging node
|
||||
if not ccompass.allow_damaging_target then
|
||||
if node_def.damage_per_second and 0 < node_def.damage_per_second then
|
||||
return false
|
||||
end
|
||||
end
|
||||
-- climbable nodes are ok depending on settings
|
||||
if ccompass.allow_climbable_target and node_def.climbable then return true end
|
||||
-- deeper checks
|
||||
local is_good_draw_type = ccompass.nodes_over_target_allow_drawtypes
|
||||
if is_good_draw_type[node_def.drawtype] then return true end
|
||||
|
||||
-- anything else is assumed dangerous
|
||||
return false
|
||||
end
|
||||
|
||||
function ccompass.is_safe_target_under(target, nodename)
|
||||
local node_def = minetest.registered_nodes[nodename]
|
||||
-- unknown node: not dangerous but probably best treated as one
|
||||
if not node_def then return false end
|
||||
-- damaging node
|
||||
if not ccompass.allow_damaging_target then
|
||||
if node_def.damage_per_second and 0 < node_def.damage_per_second then
|
||||
return false
|
||||
end
|
||||
end
|
||||
-- climbable nodes are ok depending on settings
|
||||
if ccompass.allow_climbable_target and node_def.climbable then return true end
|
||||
-- solid / walkable
|
||||
if node_def.walkable then return true end
|
||||
|
||||
-- anything else is assumed unsafe
|
||||
return false
|
||||
end
|
||||
|
||||
local function check_target(cur_target, nodenames_cache)
|
||||
--check target
|
||||
local nodename = nodenames_cache[cur_target.y] or minetest.get_node(cur_target).name
|
||||
if nodename == "ignore" then return false end
|
||||
nodenames_cache[cur_target.y] = nodename
|
||||
if ccompass.is_safe_target(cur_target, nodename) then
|
||||
|
||||
-- Check under
|
||||
cur_target.y = cur_target.y - 1
|
||||
nodename = nodenames_cache[cur_target.y] or minetest.get_node(cur_target).name
|
||||
if nodename == "ignore" then return false end
|
||||
nodenames_cache[cur_target.y] = nodename
|
||||
if ccompass.is_safe_target_under(cur_target, nodename) then
|
||||
|
||||
-- Check head
|
||||
cur_target.y = cur_target.y + 2
|
||||
nodename = nodenames_cache[cur_target.y] or minetest.get_node(cur_target).name
|
||||
if nodename == "ignore" then return false end
|
||||
nodenames_cache[cur_target.y] = nodename
|
||||
if ccompass.is_safe_target(cur_target, nodename) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function teleport_above(playername, target, counter)
|
||||
local player = minetest.get_player_by_name(playername)
|
||||
if not player then
|
||||
return
|
||||
end
|
||||
|
||||
for i = (counter or 1), 160 do
|
||||
local nodename = minetest.get_node(target).name
|
||||
if nodename == "ignore" then
|
||||
minetest.emerge_area(target, target)
|
||||
local found_place = false
|
||||
local cur_target = { x = target.x, z = target.z } -- y is handled in loop
|
||||
|
||||
local nodenames_cache = {}
|
||||
|
||||
for i = (counter or 0), 80 do
|
||||
-- Search above
|
||||
cur_target.y = target.y + i
|
||||
found_place = check_target(cur_target, nodenames_cache)
|
||||
if found_place == false then
|
||||
minetest.emerge_area(cur_target, cur_target)
|
||||
minetest.after(0.1, teleport_above, playername, target, i)
|
||||
return
|
||||
end
|
||||
|
||||
if nodename ~= 'air' then
|
||||
target.y = target.y + 1
|
||||
else
|
||||
elseif found_place == true then
|
||||
cur_target.y = target.y + i -- reset after check_target
|
||||
break
|
||||
end
|
||||
|
||||
if i > 0 then
|
||||
-- Search bellow
|
||||
cur_target.y = target.y - i
|
||||
found_place = check_target(cur_target, nodenames_cache)
|
||||
if found_place == false then
|
||||
minetest.emerge_area(cur_target, cur_target)
|
||||
minetest.after(0.1, teleport_above, playername, target, i)
|
||||
return
|
||||
elseif found_place == true then
|
||||
cur_target.y = target.y - i -- reset after check_target
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if found_place then
|
||||
player:set_pos(cur_target)
|
||||
else
|
||||
minetest.chat_send_player(playername, "Could not find suitable surrounding at target.")
|
||||
end
|
||||
player:setpos(target)
|
||||
return
|
||||
end
|
||||
|
||||
-- get right image number for players compas
|
||||
-- get right image number for players compass
|
||||
local function get_compass_stack(player, stack)
|
||||
local target = get_destination(player, stack)
|
||||
local pos = player:getpos()
|
||||
local pos = player:get_pos()
|
||||
local dir = player:get_look_horizontal()
|
||||
local angle_north = math.deg(math.atan2(target.x - pos.x, target.z - pos.z))
|
||||
if angle_north < 0 then
|
||||
@ -118,7 +251,7 @@ local function get_compass_stack(player, stack)
|
||||
-- create new stack with metadata copied
|
||||
local metadata = stack:get_meta():to_table()
|
||||
|
||||
local newstack = ItemStack("ccompass:"..compass_image)
|
||||
local newstack = ItemStack("ccompass:"..compass_image.." "..stack:get_count())
|
||||
if metadata then
|
||||
newstack:get_meta():from_table(metadata)
|
||||
end
|
||||
@ -130,6 +263,11 @@ end
|
||||
|
||||
-- Calibrate compass on pointed_thing
|
||||
local function on_use_function(itemstack, player, pointed_thing)
|
||||
-- if using with a bunch together, need to check server preference
|
||||
if 1 ~= itemstack:get_count() and not ccompass.allow_using_stacks then
|
||||
minetest.chat_send_player(player:get_player_name(), "Use a single compass.")
|
||||
return
|
||||
end
|
||||
-- possible only on nodes
|
||||
if pointed_thing.type ~= "node" then --support nodes only for destination
|
||||
minetest.chat_send_player(player:get_player_name(), "Calibration can be done on nodes only")
|
||||
@ -174,7 +312,6 @@ local function on_use_function(itemstack, player, pointed_thing)
|
||||
nodepos_string = waypoint_pos
|
||||
end
|
||||
|
||||
|
||||
if skip_namechange ~= "" then
|
||||
ccompass.set_target(itemstack, {
|
||||
target_pos_string = nodepos_string,
|
||||
@ -209,7 +346,8 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
end)
|
||||
|
||||
-- update inventory
|
||||
minetest.register_globalstep(function(dtime)
|
||||
local function do_update_loop()
|
||||
local found_compasses = false
|
||||
for i,player in ipairs(minetest.get_connected_players()) do
|
||||
if player:get_inventory() then
|
||||
for i,stack in ipairs(player:get_inventory():get_list("main")) do
|
||||
@ -217,12 +355,17 @@ minetest.register_globalstep(function(dtime)
|
||||
break
|
||||
end
|
||||
if string.sub(stack:get_name(), 0, 9) == "ccompass:" then
|
||||
found_compasses = true
|
||||
player:get_inventory():set_stack("main", i, get_compass_stack(player, stack))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
-- if no compasses were found, idle for a time before checking again
|
||||
local interval = found_compasses and 0 or ccompass.idle_interval
|
||||
minetest.after(interval, do_update_loop)
|
||||
end
|
||||
minetest.after(0, do_update_loop)
|
||||
|
||||
-- register items
|
||||
for i = 0, 15 do
|
||||
@ -231,13 +374,21 @@ for i = 0, 15 do
|
||||
if i > 0 then
|
||||
groups.not_in_creative_inventory = 1
|
||||
end
|
||||
minetest.register_tool("ccompass:"..i, {
|
||||
local itemname = "ccompass:"..i
|
||||
minetest.register_craftitem(itemname, {
|
||||
description = "Compass",
|
||||
inventory_image = image,
|
||||
wield_image = image,
|
||||
stack_max = ccompass.stack_max or 42,
|
||||
groups = groups,
|
||||
on_use = on_use_function,
|
||||
})
|
||||
-- reset recipe
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = "ccompass:0",
|
||||
recipe = { itemname }
|
||||
})
|
||||
end
|
||||
|
||||
minetest.register_craft({
|
||||
@ -248,3 +399,13 @@ minetest.register_craft({
|
||||
{'', 'default:steel_ingot', ''}
|
||||
}
|
||||
})
|
||||
-- add an alternative recipe
|
||||
minetest.register_craft({
|
||||
output = 'ccompass:0',
|
||||
recipe = {
|
||||
{'default:steel_ingot', '', 'default:steel_ingot'},
|
||||
{'', 'default:mese_crystal_fragment', ''},
|
||||
{'default:steel_ingot', '', 'default:steel_ingot'}
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -4,11 +4,40 @@ ccompass_recalibrate (Allow compass recalibration) bool true
|
||||
# If disabled (default) all nodes are allowed to be compass target
|
||||
ccompass_restrict_target (Restrict nodes usable for calibration) bool false
|
||||
|
||||
# If enabled, climbable nodes above target are considered unsafe.
|
||||
ccompass_deny_climbable_target (Deny climbable node above target) bool false
|
||||
|
||||
# List of technical node names allowed for compass calibration, separated by ','
|
||||
ccompass_restrict_target_nodes (Nodes list allowed for calibration) string
|
||||
|
||||
# Enable aliasses to replace other compass mods
|
||||
ccompass_aliasses (Enable compatibility aliasses) bool false
|
||||
|
||||
# Nodes able to teleport to destination on punch, separated by ','
|
||||
# Nodes able to teleport to destination on punch, separated by ','. Set it to "none" to disable the teleporting feature.
|
||||
ccompass_teleport_nodes (Nodes list for teleport on punch) string default:mese
|
||||
|
||||
# If one of these nodes is at target, skip other checks and allow teleporting.
|
||||
# String list of node names separated by ','
|
||||
ccompass_nodes_over_target_allow (Nodes list for additional allowed nodes) string
|
||||
|
||||
# If one of these nodes is at target, skip other checks and deny teleporting.
|
||||
# String list of node names separated by ','
|
||||
ccompass_nodes_over_target_deny (Nodes list for additional deny nodes) string
|
||||
|
||||
# Drawtype of nodes over target that are considered safe. This will only be checked
|
||||
# checked after ccompass_nodes_over_target_allow and ccompass_nodes_over_target_deny.
|
||||
# String list of node names separated by ','
|
||||
ccompass_nodes_over_target_allow_drawtypes (Drawtypes of nodes allowed over target) string airlike,flowingliquid,liquid,plantlike,plantlike_rooted
|
||||
|
||||
# By default ccompass will not teleport players into or over damaging nodes.
|
||||
# To allow this, change to true.
|
||||
ccompass_allow_damage_target (Enable to allow teleporting into damaging nodes) bool false
|
||||
|
||||
# Maximum size of compass stacks. Only identical and same direction pointing compasses can be stacked.
|
||||
# Defaults to 1
|
||||
ccompass_stack_max (Sets maximum stack size) int 1 1 65535
|
||||
# Requires stack_max greater than 1. When true, allows a whole stack to be calibrated at the same time.
|
||||
ccompass_allow_using_stacks (Enable to allow callibrating stacks) bool false
|
||||
|
||||
# When no players have active compasses, the mod enters an idle state and only checks for compasses at this interval, measured in seconds. This setting is meant to reduce the load on the server.
|
||||
ccompass_idle_interval (Time between checks when idling) float 1 0 10
|
||||
|
Loading…
x
Reference in New Issue
Block a user