Check no other mod is already using a portal definition

This commit is contained in:
Treer 2019-07-28 13:15:51 +10:00 committed by Treer
parent d5bfb142fa
commit ceb7148ce8
5 changed files with 51 additions and 16 deletions

View File

@ -27,7 +27,7 @@ SOFTWARE.
### [Attribution 3.0 Unported (CC BY 3.0)](https://creativecommons.org/licenses/by/3.0/) ### [Attribution 3.0 Unported (CC BY 3.0)](https://creativecommons.org/licenses/by/3.0/)
* `nether_portal_ambient.ogg` & `nether_portal_ambient.0.ogg` are extractions from "Deep Cinematic Rumble Stereo" by [Patrick Lieberkind](http://www.lieberkindvisuals.dk) * `nether_portal_ambient.ogg` & `nether_portal_ambient.0.ogg` are extractions from "Deep Cinematic Rumble Stereo" by [Patrick Lieberkind](http://www.lieberkindvisuals.dk), used under CC BY 3.0
* `nether_portal_extinguish.ogg` is an extraction from "Tight Laser Weapon Hit Scifi" by damjancd (https://freesound.org/people/damjancd), used under CC BY 3.0 * `nether_portal_extinguish.ogg` is an extraction from "Tight Laser Weapon Hit Scifi" by damjancd (https://freesound.org/people/damjancd), used under CC BY 3.0
* `nether_portal_ignite.ogg` is a derivative of "Flame Ignition" by hykenfreak (https://freesound.org/people/hykenfreak), used under CC BY 3.0. "Nether Portal ignite" is licensed under CC BY 3.0 by Treer. * `nether_portal_ignite.ogg` is a derivative of "Flame Ignition" by hykenfreak (https://freesound.org/people/hykenfreak), used under CC BY 3.0. "Nether Portal ignite" is licensed under CC BY 3.0 by Treer.

View File

@ -71,7 +71,7 @@ This opens to a truly hellish place, though for small mercies the air there is s
The expedition parties have found no diamonds or gold, and after an experienced search party failed to return from the trail of a missing expedition party, I must conclude this is a dangerous place. The expedition parties have found no diamonds or gold, and after an experienced search party failed to return from the trail of a missing expedition party, I must conclude this is a dangerous place.
]], 10 * nether.FASTTRAVEL_FACTOR), ]], 10 * nether.FASTTRAVEL_FACTOR),
within_realm = function(pos) -- return true if pos is inside the Nether is_within_realm = function(pos) -- return true if pos is inside the Nether
return pos.y < nether.DEPTH return pos.y < nether.DEPTH
end, end,

View File

@ -483,7 +483,7 @@ local function list_closest_portals(portal_definition, anchorPos, distance_limit
local result = {} local result = {}
local isRealm = portal_definition.within_realm(anchorPos) local isRealm = portal_definition.is_within_realm(anchorPos)
if distance_limit == nil then distance_limit = -1 end if distance_limit == nil then distance_limit = -1 end
if y_factor == nil then y_factor = 1 end if y_factor == nil then y_factor = 1 end
@ -491,7 +491,7 @@ local function list_closest_portals(portal_definition, anchorPos, distance_limit
local closingBrace = key:find(")", 6, true) local closingBrace = key:find(")", 6, true)
if closingBrace ~= nil then if closingBrace ~= nil then
local found_anchorPos = minetest.string_to_pos(key:sub(0, closingBrace)) local found_anchorPos = minetest.string_to_pos(key:sub(0, closingBrace))
if found_anchorPos ~= nil and portal_definition.within_realm(found_anchorPos) == isRealm then if found_anchorPos ~= nil and portal_definition.is_within_realm(found_anchorPos) == isRealm then
local found_name = key:sub(closingBrace + 5) local found_name = key:sub(closingBrace + 5)
if found_name == portal_definition.name then if found_name == portal_definition.name then
local x = anchorPos.x - found_anchorPos.x local x = anchorPos.x - found_anchorPos.x
@ -915,7 +915,7 @@ local function ignite_portal(ignition_pos, ignition_node_name)
if DEBUG then minetest.chat_send_all("Found portal frame. Looked at " .. minetest.pos_to_string(ignition_pos) .. ", found at " .. minetest.pos_to_string(anchorPos) .. " orientation " .. orientation) end if DEBUG then minetest.chat_send_all("Found portal frame. Looked at " .. minetest.pos_to_string(ignition_pos) .. ", found at " .. minetest.pos_to_string(anchorPos) .. " orientation " .. orientation) end
local destination_anchorPos, destination_orientation local destination_anchorPos, destination_orientation
if portal_definition.within_realm(ignition_pos) then if portal_definition.is_within_realm(ignition_pos) then
destination_anchorPos, destination_orientation = portal_definition.find_surface_anchorPos(anchorPos) destination_anchorPos, destination_orientation = portal_definition.find_surface_anchorPos(anchorPos)
else else
destination_anchorPos, destination_orientation = portal_definition.find_realm_anchorPos(anchorPos) destination_anchorPos, destination_orientation = portal_definition.find_realm_anchorPos(anchorPos)
@ -1346,7 +1346,7 @@ function test_portaldef_is_valid(portal_definition)
local result = test_shapedef_is_valid(portal_definition.shape) local result = test_shapedef_is_valid(portal_definition.shape)
assert(portal_definition.wormhole_node_color >= 0 and portal_definition.wormhole_node_color < 8, "portaldef.wormhole_node_color must be between 0 and 7 (inclusive)") assert(portal_definition.wormhole_node_color >= 0 and portal_definition.wormhole_node_color < 8, "portaldef.wormhole_node_color must be between 0 and 7 (inclusive)")
assert(portal_definition.within_realm ~= nil, "portaldef.within_realm() must be implemented") assert(portal_definition.is_within_realm ~= nil, "portaldef.is_within_realm() must be implemented")
assert(portal_definition.find_realm_anchorPos ~= nil, "portaldef.find_realm_anchorPos() must be implemented") assert(portal_definition.find_realm_anchorPos ~= nil, "portaldef.find_realm_anchorPos() must be implemented")
-- todo -- todo
@ -1443,6 +1443,7 @@ function nether.register_portal(name, portaldef)
end end
portaldef.name = name portaldef.name = name
portaldef.mod_name = minetest.get_current_modname()
-- use portaldef_default for any values missing from portaldef or portaldef.sounds -- use portaldef_default for any values missing from portaldef or portaldef.sounds
if portaldef.sounds ~= nil then setmetatable(portaldef.sounds, {__index = portaldef_default.sounds}) end if portaldef.sounds ~= nil then setmetatable(portaldef.sounds, {__index = portaldef_default.sounds}) end
@ -1475,10 +1476,22 @@ function nether.register_portal(name, portaldef)
end end
if test_portaldef_is_valid(portaldef) then if test_portaldef_is_valid(portaldef) then
-- check whether the portal definition clashes with anyone else's portal
local p1, p2 = portaldef.shape:get_p1_and_p2_from_anchorPos(vector.new(), 0)
local existing_portaldef = get_portal_definition(portaldef.frame_node_name, p1, p2)
if existing_portaldef ~= nil then
minetest.log("error",
portaldef.mod_name .." tried to register a portal '" .. portaldef.name .. "' made of " .. portaldef.frame_node_name ..
", but it is the same material and shape as the portal '" .. existing_portaldef.name .. "' already registered by " .. existing_portaldef.mod_name ..
". Edit the values one of those mods uses in its call to nether.register_portal() if you wish to resolve this clash.")
else
-- the new portaldef is good
nether.registered_portals[portaldef.name] = portaldef nether.registered_portals[portaldef.name] = portaldef
create_book_of_portals() create_book_of_portals()
if not is_frame_node[portaldef.frame_node_name] then if not is_frame_node[portaldef.frame_node_name] then
-- add portal functions to the nodedef being used for the portal frame
register_frame_node(portaldef.frame_node_name) register_frame_node(portaldef.frame_node_name)
is_frame_node[portaldef.frame_node_name] = true is_frame_node[portaldef.frame_node_name] = true
end end
@ -1487,6 +1500,9 @@ function nether.register_portal(name, portaldef)
end end
end end
return false
end
function nether.unregister_portal(name) function nether.unregister_portal(name)
assert(name ~= nil, "Cannot unregister portal: Name is nil") assert(name ~= nil, "Cannot unregister portal: Name is nil")

View File

@ -4,6 +4,20 @@ Portal API Reference
The portal system used to get to the Nether can be used to create portals The portal system used to get to the Nether can be used to create portals
to other realms. to other realms.
Pick a node type to have your portals built from, a shape in which the
portals must be built, and provide 3 functions for portals to find their
destination with:
* `find_realm_anchorPos(surface_anchorPos)`
* `find_surface_anchorPos(realm_anchorPos)`
* `is_within_realm(pos)`
Optionally decorate by choosing portal colors, particles, media etc.
See `init.lua` and `portal_examples.lua` for examples of 3 different portals.
and perhaps a backup
node-type incase another mod is already using that node)
Portal code is more efficient when each type of portal uses a different type Portal code is more efficient when each type of portal uses a different type
of node to build its frame out of, however it is possible to register more than of node to build its frame out of, however it is possible to register more than
one kind of portal with the same frame material — such as obsidian — provided one kind of portal with the same frame material — such as obsidian — provided
@ -44,6 +58,11 @@ Call these functions only at load time:
* Returns true on success. Can return false if the portal definition * Returns true on success. Can return false if the portal definition
clashes with a portal already registered by another mod, e.g. if the size clashes with a portal already registered by another mod, e.g. if the size
and frame node is not unique. and frame node is not unique.
A false return value should be handled, you could:
* Fall back to using a secondary material for portals to be built with.
* Use error() to exit lua with a message explaining how two mods are
clashing and how it can be resolved.
* Continue without a portal (the reason will be logged for the user).
* `nether.unregister_portal(name)` * `nether.unregister_portal(name)`
* Unregisters the portal from the engine, and deletes the entry with key * Unregisters the portal from the engine, and deletes the entry with key
`name` from `nether.registered_portals` and associated internal tables. `name` from `nether.registered_portals` and associated internal tables.

View File

@ -52,7 +52,7 @@ Requiring 14 blocks of ice, but otherwise constructed the same as the portal to
]] .. "\u{25A9}"), ]] .. "\u{25A9}"),
within_realm = function(pos) -- return true if pos is inside the Nether is_within_realm = function(pos) -- return true if pos is inside the Nether
return pos.y < nether.DEPTH return pos.y < nether.DEPTH
end, end,
@ -114,7 +114,7 @@ nether.register_portal("stargate_portal", {
]] .. "\u{25A9}"), ]] .. "\u{25A9}"),
within_realm = function(pos) -- return true if pos is inside the Nether is_within_realm = function(pos) -- return true if pos is inside the Nether
return pos.y < nether.DEPTH return pos.y < nether.DEPTH
end, end,