Use lua schematics instead of .mts files when building portals

Removes the need for the get_malleated_schematic_filename hack
This commit is contained in:
Treer 2020-02-08 17:15:33 +11:00 committed by SmallJoker
parent aa2bfe9472
commit 32e5d818e8
5 changed files with 147 additions and 59 deletions

View File

@ -113,6 +113,9 @@ metadata).
]] ]]
local __ = {name = "air", prob = 0}
local AA = {name = "air", prob = 255, force_place = true}
local OO = {name = "default:obsidian", prob = 255, force_place = true}
-- This object defines a portal's shape, segregating the shape logic code from portal behaviour code. -- This object defines a portal's shape, segregating the shape logic code from portal behaviour code.
-- You can create a new "PortalShape" definition object which implements the same -- You can create a new "PortalShape" definition object which implements the same
@ -123,7 +126,6 @@ nether.PortalShape_Traditional = {
name = "Traditional", name = "Traditional",
size = vector.new(4, 5, 1), -- size of the portal, and not necessarily the size of the schematic, size = vector.new(4, 5, 1), -- size of the portal, and not necessarily the size of the schematic,
-- which may clear area around the portal. -- which may clear area around the portal.
schematic_filename = nether.path .. "/schematics/nether_portal.mts",
is_horizontal = false, -- whether the wormhole is a vertical or horizontal surface is_horizontal = false, -- whether the wormhole is a vertical or horizontal surface
diagram_image = { diagram_image = {
image = "nether_book_diagram_traditional.png", -- The diagram to be shown in the Book of Portals image = "nether_book_diagram_traditional.png", -- The diagram to be shown in the Book of Portals
@ -267,7 +269,42 @@ nether.PortalShape_Traditional = {
-- wait in a portal long enough you teleport again. So a trap portal would have to link -- wait in a portal long enough you teleport again. So a trap portal would have to link
-- to one of two blocked-in portals which link to each other - which is possible, but -- to one of two blocked-in portals which link to each other - which is possible, but
-- quite extreme. -- quite extreme.
end end,
schematic = {
size = {x = 4, y = 5, z = 5},
data = { -- note that data is upside down
__,__,__,__,
AA,AA,AA,AA,
AA,AA,AA,AA,
AA,AA,AA,AA,
AA,AA,AA,AA,
__,__,__,__,
AA,AA,AA,AA,
AA,AA,AA,AA,
AA,AA,AA,AA,
AA,AA,AA,AA,
OO,OO,OO,OO,
OO,AA,AA,OO,
OO,AA,AA,OO,
OO,AA,AA,OO,
OO,OO,OO,OO,
__,__,__,__,
AA,AA,AA,AA,
AA,AA,AA,AA,
AA,AA,AA,AA,
AA,AA,AA,AA,
__,__,__,__,
AA,AA,AA,AA,
AA,AA,AA,AA,
AA,AA,AA,AA,
AA,AA,AA,AA,
}
}
} -- End of PortalShape_Traditional class } -- End of PortalShape_Traditional class
@ -276,7 +313,6 @@ nether.PortalShape_Circular = {
name = "Circular", name = "Circular",
size = vector.new(7, 7, 1), -- size of the portal, and not necessarily the size of the schematic, size = vector.new(7, 7, 1), -- size of the portal, and not necessarily the size of the schematic,
-- which may clear area around the portal. -- which may clear area around the portal.
schematic_filename = nether.path .. "/schematics/nether_portal_circular.mts",
is_horizontal = false, -- whether the wormhole is a vertical or horizontal surface is_horizontal = false, -- whether the wormhole is a vertical or horizontal surface
diagram_image = { diagram_image = {
image = "nether_book_diagram_circular.png", -- The diagram to be shown in the Book of Portals image = "nether_book_diagram_circular.png", -- The diagram to be shown in the Book of Portals
@ -401,7 +437,68 @@ nether.PortalShape_Circular = {
assert(orientation, "no orientation passed") assert(orientation, "no orientation passed")
-- Not implemented. -- Not implemented.
end end,
schematic = {
size = {x = 7, y = 7, z = 7},
data = { -- note that data is upside down
__,__,__,__,__,__,__,
__,__,__,__,__,__,__,
__,__,AA,AA,AA,__,__,
__,__,AA,AA,AA,__,__,
__,__,AA,AA,AA,__,__,
__,__,__,__,__,__,__,
__,__,__,__,__,__,__,
__,__,__,__,__,__,__,
__,AA,AA,AA,AA,AA,__,
__,AA,AA,AA,AA,AA,__,
__,AA,AA,AA,AA,AA,__,
__,AA,AA,AA,AA,AA,__,
__,AA,AA,AA,AA,AA,__,
__,__,__,__,__,__,__,
__,__,__,__,__,__,__,
__,AA,AA,AA,AA,AA,__,
AA,AA,AA,AA,AA,AA,AA,
AA,AA,AA,AA,AA,AA,AA,
AA,AA,AA,AA,AA,AA,AA,
__,AA,AA,AA,AA,AA,__,
__,__,AA,AA,AA,__,__,
__,__,OO,OO,OO,__,__,
__,OO,AA,AA,AA,OO,__,
OO,AA,AA,AA,AA,AA,OO,
OO,AA,AA,AA,AA,AA,OO,
OO,AA,AA,AA,AA,AA,OO,
__,OO,AA,AA,AA,OO,__,
__,__,OO,OO,OO,__,__,
__,__,__,__,__,__,__,
__,AA,AA,AA,AA,AA,__,
AA,AA,AA,AA,AA,AA,AA,
AA,AA,AA,AA,AA,AA,AA,
AA,AA,AA,AA,AA,AA,AA,
__,AA,AA,AA,AA,AA,__,
__,__,AA,AA,AA,__,__,
__,__,__,__,__,__,__,
__,AA,AA,AA,AA,AA,__,
__,AA,AA,AA,AA,AA,__,
__,AA,AA,AA,AA,AA,__,
__,AA,AA,AA,AA,AA,__,
__,AA,AA,AA,AA,AA,__,
__,__,__,__,__,__,__,
__,__,__,__,__,__,__,
__,__,__,__,__,__,__,
__,__,AA,AA,AA,__,__,
__,__,AA,AA,AA,__,__,
__,__,AA,AA,AA,__,__,
__,__,__,__,__,__,__,
__,__,__,__,__,__,__,
}
}
} -- End of PortalShape_Circular class } -- End of PortalShape_Circular class
@ -411,7 +508,6 @@ nether.PortalShape_Platform = {
name = "Platform", name = "Platform",
size = vector.new(5, 2, 5), -- size of the portal, and not necessarily the size of the schematic, size = vector.new(5, 2, 5), -- size of the portal, and not necessarily the size of the schematic,
-- which may clear area around the portal. -- which may clear area around the portal.
schematic_filename = nether.path .. "/schematics/nether_portal_platform.mts",
is_horizontal = true, -- whether the wormhole is a vertical or horizontal surface is_horizontal = true, -- whether the wormhole is a vertical or horizontal surface
diagram_image = { diagram_image = {
image = "nether_book_diagram_platform.png", -- The diagram to be shown in the Book of Portals image = "nether_book_diagram_platform.png", -- The diagram to be shown in the Book of Portals
@ -495,7 +591,42 @@ nether.PortalShape_Platform = {
disable_portal_trap = function(anchorPos, orientation) disable_portal_trap = function(anchorPos, orientation)
-- Not implemented. -- Not implemented.
end end,
schematic = {
size = {x = 5, y = 5, z = 5},
data = { -- note that data is upside down
__,__,__,__,__,
OO,OO,OO,OO,OO,
__,AA,AA,AA,__,
__,AA,AA,AA,__,
__,__,__,__,__,
__,OO,OO,OO,__,
OO,AA,AA,AA,OO,
AA,AA,AA,AA,AA,
AA,AA,AA,AA,AA,
__,AA,AA,AA,__,
__,OO,OO,OO,__,
OO,AA,AA,AA,OO,
AA,AA,AA,AA,AA,
AA,AA,AA,AA,AA,
__,AA,AA,AA,__,
__,OO,OO,OO,__,
OO,AA,AA,AA,OO,
AA,AA,AA,AA,AA,
AA,AA,AA,AA,AA,
__,AA,AA,AA,__,
__,__,__,__,__,
OO,OO,OO,OO,OO,
__,AA,AA,AA,__,
__,AA,AA,AA,__,
__,__,__,__,__,
}
}
} -- End of PortalShape_Platform class } -- End of PortalShape_Platform class
@ -512,7 +643,6 @@ nether.PortalShape_Platform = {
local ignition_item_name local ignition_item_name
local S = nether.get_translator local S = nether.get_translator
local mod_storage = minetest.get_mod_storage() local mod_storage = minetest.get_mod_storage()
local malleated_filenames = {}
local meseconsAvailable = minetest.get_modpath("mesecon") ~= nil and minetest.global_exists("mesecon") local meseconsAvailable = minetest.get_modpath("mesecon") ~= nil and minetest.global_exists("mesecon")
local book_added_as_treasure = false local book_added_as_treasure = false
@ -1011,11 +1141,10 @@ local function build_portal(portal_definition, anchorPos, orientation, destinati
minetest.place_schematic( minetest.place_schematic(
portal_definition.shape.get_schematicPos_from_anchorPos(anchorPos, orientation), portal_definition.shape.get_schematicPos_from_anchorPos(anchorPos, orientation),
portal_definition.schematic_filename, portal_definition.shape.schematic,
orientation, orientation,
{ -- node replacements { -- node replacements
["default:obsidian"] = portal_definition.frame_node_name, ["default:obsidian"] = portal_definition.frame_node_name,
["nether:portal"] = portal_definition.wormhole_node_name
}, },
true true
) )
@ -1100,7 +1229,8 @@ local function locate_or_build_portal(portal_definition, suggested_wormholePos,
local result_target_str = minetest.get_meta(result_anchorPos):get_string("target") local result_target_str = minetest.get_meta(result_anchorPos):get_string("target")
local result_target = minetest.string_to_pos(result_target_str) local result_target = minetest.string_to_pos(result_target_str)
if result_target ~= nil and vector.equals(result_target, destination_wormholePos) then if result_target ~= nil and vector.equals(result_target, destination_wormholePos) then
-- don't extinguish the portal the player is teleporting from -- It already links back to the portal the player is teleporting from, so don't
-- extinguish it or the player's portal will also extinguish.
if DEBUG then minetest.chat_send_all(" Build unnecessary: already a lit portal that links back here at " .. minetest.pos_to_string(found_anchorPos) .. ", orientation " .. result_orientation) end if DEBUG then minetest.chat_send_all(" Build unnecessary: already a lit portal that links back here at " .. minetest.pos_to_string(found_anchorPos) .. ", orientation " .. result_orientation) end
else else
if DEBUG then minetest.chat_send_all(" Build unnecessary: already a lit portal at " .. minetest.pos_to_string(found_anchorPos) .. ", orientation " .. result_orientation .. ", linking to " .. result_target_str .. ". Extinguishing...") end if DEBUG then minetest.chat_send_all(" Build unnecessary: already a lit portal at " .. minetest.pos_to_string(found_anchorPos) .. ", orientation " .. result_orientation .. ", linking to " .. result_target_str .. ". Extinguishing...") end
@ -1626,46 +1756,6 @@ local function create_book_of_portals()
end end
end end
-- This is hack to work around how place_schematic() never invalidates its cache.
-- A unique schematic filename is generated for each unique set of node replacements
function get_malleated_schematic_filename(portal_definition)
local result
if portal_definition.shape ~= nil and portal_definition.shape.schematic_filename ~= nil then
local schematicFileName = portal_definition.shape.schematic_filename
local uniqueId = portal_definition.frame_node_name .. " " .. portal_definition.wormhole_node_name
if malleated_filenames[schematicFileName] == nil then malleated_filenames[schematicFileName] = {} end
local filenamesForSchematic = malleated_filenames[schematicFileName]
-- Split the schematic's filename into the path and filename
local lastSlashPos, _ = schematicFileName:find("/[^/]+$") -- find the rightmost slash
local lastBackslashPos, _ = schematicFileName:find("\\[^\\]+$") -- find the rightmost backslash
if lastSlashPos == nil then lastSlashPos = -1 end
if lastBackslashPos ~= nil then lastSlashPos = math.max(lastSlashPos, lastBackslashPos) end
local part_path = schematicFileName:sub(0, math.max(0, lastSlashPos - 1))
local part_filename = schematicFileName:sub(lastSlashPos + 1)
if filenamesForSchematic[uniqueId] == nil then
local malleationCount = 0
for _ in pairs(filenamesForSchematic) do malleationCount = malleationCount + 1 end
local malleatedFilename = part_path .. DIR_DELIM
for i = 1, malleationCount do
malleatedFilename = malleatedFilename .. '.' .. DIR_DELIM -- should work on both Linux and Windows
end
malleatedFilename = malleatedFilename .. part_filename
filenamesForSchematic[uniqueId] = malleatedFilename
end
result = filenamesForSchematic[uniqueId]
end
return result
end
function register_frame_node(frame_node_name) function register_frame_node(frame_node_name)
@ -1916,8 +2006,6 @@ function nether.register_portal(name, portaldef)
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
setmetatable(portaldef, {__index = portaldef_default}) setmetatable(portaldef, {__index = portaldef_default})
portaldef.schematic_filename = get_malleated_schematic_filename(portaldef)
if portaldef.particle_color == nil then if portaldef.particle_color == nil then
-- default the particle colours to be the same as the wormhole colour -- default the particle colours to be the same as the wormhole colour
assert(portaldef.wormhole_node_color >= 0 and portaldef.wormhole_node_color < 8, "portaldef.wormhole_node_color must be between 0 and 7 (inclusive)") assert(portaldef.wormhole_node_color >= 0 and portaldef.wormhole_node_color < 8, "portaldef.wormhole_node_color must be between 0 and 7 (inclusive)")

View File

@ -31,11 +31,11 @@ docoration functions without triggering the node's `on_destruct` handler.
Realms Realms
------ ------
This API uses the concept of a "realm" for each type of portal. If a portal is This API uses the concept of a realm for each type of portal. If a portal is
outside its realm then it links to a portal inside the realm, if a portal is outside its realm then it links to a portal inside the realm, if a portal is
inside its realm then it links to the outside. inside its realm then it links to the outside.
You get to decide what consitutes your realm by implementing the function You get to decide what constitutes your realm by implementing the function
`is_within_realm(position)`. `is_within_realm(position)`.
For example, the Nether realm is defined as existing at a certain depth and For example, the Nether realm is defined as existing at a certain depth and
@ -91,11 +91,6 @@ Call these functions only at load time:
* Use error() to exit lua with a message explaining how two mods are * Use error() to exit lua with a message explaining how two mods are
clashing and how it can be resolved. clashing and how it can be resolved.
* Continue without a portal (the reason will be logged for the user). * Continue without a portal (the reason will be logged for the user).
* `nether.unregister_portal(name)`
* Unregisters the portal from the engine, and deletes the entry with key
`name` from `nether.registered_portals` and associated internal tables.
* Returns true on success
* You will probably never need to call this, it exists only for completeness.
* `nether.register_portal_ignition_item(name, ignition_failure_sound)` * `nether.register_portal_ignition_item(name, ignition_failure_sound)`
* ignition_failure_sound is optional, it plays any time an attempt to use * ignition_failure_sound is optional, it plays any time an attempt to use
the item occurs if a portal is not ignited. the item occurs if a portal is not ignited.
@ -108,6 +103,11 @@ Call these functions only at load time:
* After `register_wormhole_node()`, invoke `register_portal()` and include * After `register_wormhole_node()`, invoke `register_portal()` and include
`wormhole_node_name` in the portal_definition, assigning it the name of the `wormhole_node_name` in the portal_definition, assigning it the name of the
new wormhole node. new wormhole node.
* `nether.unregister_portal(name)`
* Unregisters the portal from the engine, and deletes the entry with key
`name` from `nether.registered_portals` and associated internal tables.
* Returns true on success
* You will probably never need to call this, it exists only for completeness.
Portal definition Portal definition

Binary file not shown.