Adjust to the name change from Minetest to Luanti; use 'core' namespace instead of 'minetest' (#16)
Some checks failed
build / lint (push) Has been cancelled
Some checks failed
build / lint (push) Has been cancelled
This commit is contained in:
parent
b6dc83be19
commit
c8c93613cc
@ -10,7 +10,7 @@ read_globals = {
|
||||
string = {fields = {"split", "trim"}},
|
||||
table = {fields = {"copy", "getn", "indexof"}},
|
||||
|
||||
"minetest",
|
||||
"core",
|
||||
"PseudoRandom",
|
||||
"vector",
|
||||
"VoxelArea",
|
||||
|
12
README.md
12
README.md
@ -1,12 +1,12 @@
|
||||
# Meshport (Minetest Mesh Exporter)
|
||||
# Meshport (Luanti Mesh Exporter)
|
||||
|
||||
[](https://github.com/random-geek/meshport/actions)
|
||||
[](https://content.minetest.net/packages/random_geek/meshport/)
|
||||
[](https://content.luanti.org/packages/random_geek/meshport/)
|
||||
[](https://www.gnu.org/licenses/lgpl-3.0.en.html)
|
||||
|
||||

|
||||
|
||||
Meshport is a mod which allows easy exporting of scenes from Minetest to `.obj`
|
||||
Meshport is a mod which allows easy exporting of scenes from Luanti (Minetest) to `.obj`
|
||||
files, complete with materials and textures. These models can be imported
|
||||
directly into Blender or another 3D program for rendering and animation.
|
||||
|
||||
@ -85,7 +85,7 @@ The following node drawtypes are currently supported:
|
||||
- `mesh` (only `.obj` meshes are exported)
|
||||
- `plantlike` and `plantlike_rooted`
|
||||
|
||||
Meshport also supports many of Minetest's relevant features, including:
|
||||
Meshport also supports many of Luanti's relevant features, including:
|
||||
|
||||
- Most `paramtype2`s (note that color is ignored for colored types)
|
||||
- `visual_scale`
|
||||
@ -100,9 +100,9 @@ overlay textures, and node coloring.
|
||||
Drawtypes `allfaces_optional` and `glasslike_framed_optional` are output the
|
||||
same as `allfaces` and `glasslike`, respectively.
|
||||
|
||||
Due to the differences between Minetest's rendering engine and 3D programs such
|
||||
Due to the differences between Luanti's rendering engine and 3D programs such
|
||||
as Blender, it is impossible to exactly replicate how certain cubic nodes are
|
||||
rendered in Minetest. Instead, Meshport aims for a compromise between accuracy
|
||||
rendered in Luanti. Instead, Meshport aims for a compromise between accuracy
|
||||
and simplicity of geometry. In certain cases where two cubic nodes are
|
||||
touching, one face may be offset slightly to avoid duplicate faces while still
|
||||
allowing both faces to be visible.
|
||||
|
28
export.lua
28
export.lua
@ -1,6 +1,6 @@
|
||||
--[[
|
||||
Copyright (C) 2021 random-geek (https://github.com/random-geek)
|
||||
Minetest: Copyright (C) 2010-2021 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
Luanti (Minetest): Copyright (C) 2010-2021 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This file is part of Meshport.
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
along with Meshport. If not, see <https://www.gnu.org/licenses/>.
|
||||
]]
|
||||
|
||||
-- Much of the mesh generation code in this file is derived from Minetest's
|
||||
-- Much of the mesh generation code in this file is derived from Luanti's (Minetest's)
|
||||
-- MapblockMeshGenerator class. See minetest/src/client/content_mapblock.cpp.
|
||||
|
||||
local S = meshport.S
|
||||
@ -84,9 +84,9 @@ local function create_cubic_node(pos, content, param2, nodeDef, drawtype, neighb
|
||||
for i = 1, 6 do
|
||||
local drawFace
|
||||
|
||||
if neighbors[i] == minetest.CONTENT_AIR then
|
||||
if neighbors[i] == core.CONTENT_AIR then
|
||||
drawFace = true
|
||||
elseif neighbors[i] == minetest.CONTENT_IGNORE
|
||||
elseif neighbors[i] == core.CONTENT_IGNORE
|
||||
-- Don't draw faces between identical nodes
|
||||
or neighbors[i] == content
|
||||
-- Don't draw liquid faces bordering a corresponding flowing liquid
|
||||
@ -125,7 +125,7 @@ local function create_special_cubic_node(pos, content, nodeDef, drawtype, neighb
|
||||
local drawFace
|
||||
local inset = false
|
||||
|
||||
if allfacesScale ~= 1 or neighbors[i] == minetest.CONTENT_AIR or neighbors[i] == minetest.CONTENT_IGNORE then
|
||||
if allfacesScale ~= 1 or neighbors[i] == core.CONTENT_AIR or neighbors[i] == core.CONTENT_IGNORE then
|
||||
drawFace = true
|
||||
elseif neighbors[i] == content then
|
||||
drawFace = isAllfaces and i % 2 == 1
|
||||
@ -323,7 +323,7 @@ local function create_flowing_liquid_node(pos, nodeDef, area, vContent, vParam2)
|
||||
}
|
||||
local nData = neighbors[dz][dx]
|
||||
|
||||
if vContent[nIdx] ~= minetest.CONTENT_IGNORE then
|
||||
if vContent[nIdx] ~= core.CONTENT_IGNORE then
|
||||
if vContent[nIdx] == cSource then
|
||||
nData.is_same_liquid = true
|
||||
nData.level = 0.5
|
||||
@ -359,7 +359,7 @@ local function create_flowing_liquid_node(pos, nodeDef, area, vContent, vParam2)
|
||||
elseif nData.content == cFlowing then
|
||||
sum = sum + nData.level
|
||||
count = count + 1
|
||||
elseif nData.content == minetest.CONTENT_AIR then
|
||||
elseif nData.content == core.CONTENT_AIR then
|
||||
airCount = airCount + 1
|
||||
|
||||
if airCount >= 2 then
|
||||
@ -541,8 +541,8 @@ end
|
||||
|
||||
|
||||
local function create_nodebox_node(pos, content, param2, neighbors)
|
||||
local nodeName = minetest.get_name_from_content_id(content)
|
||||
local nodeDef = minetest.registered_nodes[nodeName]
|
||||
local nodeName = core.get_name_from_content_id(content)
|
||||
local nodeDef = core.registered_nodes[nodeName]
|
||||
|
||||
if not meshport.nodebox_cache[nodeName] then
|
||||
meshport.nodebox_cache[nodeName] = meshport.prepare_nodebox(nodeDef.node_box)
|
||||
@ -714,9 +714,9 @@ end
|
||||
|
||||
|
||||
local function create_node(idx, area, vContent, vParam2, playerName)
|
||||
if vContent[idx] == minetest.CONTENT_AIR
|
||||
or vContent[idx] == minetest.CONTENT_IGNORE
|
||||
or vContent[idx] == minetest.CONTENT_UNKNOWN then -- TODO: Export unknown nodes?
|
||||
if vContent[idx] == core.CONTENT_AIR
|
||||
or vContent[idx] == core.CONTENT_IGNORE
|
||||
or vContent[idx] == core.CONTENT_UNKNOWN then -- TODO: Export unknown nodes?
|
||||
return
|
||||
end
|
||||
|
||||
@ -787,7 +787,7 @@ function meshport.create_mesh(playerName, p1, p2, path)
|
||||
initialize_resources()
|
||||
|
||||
p1, p2 = vector.sort(p1, p2)
|
||||
local vm = minetest.get_voxel_manip()
|
||||
local vm = core.get_voxel_manip()
|
||||
|
||||
-- Add one node of padding to area so we can read neighbor blocks.
|
||||
local vp1, vp2 = vm:read_from_map(vector.subtract(p1, 1), vector.add(p2, 1))
|
||||
@ -813,7 +813,7 @@ function meshport.create_mesh(playerName, p1, p2, path)
|
||||
end
|
||||
end
|
||||
|
||||
minetest.mkdir(path)
|
||||
core.mkdir(path)
|
||||
mesh:write_obj(path)
|
||||
mesh:write_mtl(path, playerName)
|
||||
|
||||
|
40
init.lua
40
init.lua
@ -19,10 +19,10 @@
|
||||
|
||||
meshport = {
|
||||
player_data = {},
|
||||
S = minetest.get_translator("meshport"),
|
||||
S = core.get_translator("meshport"),
|
||||
}
|
||||
|
||||
modpath = minetest.get_modpath("meshport")
|
||||
modpath = core.get_modpath("meshport")
|
||||
dofile(modpath .. "/utils.lua")
|
||||
dofile(modpath .. "/mesh.lua")
|
||||
dofile(modpath .. "/parse_obj.lua")
|
||||
@ -32,9 +32,9 @@ dofile(modpath .. "/export.lua")
|
||||
local S = meshport.S
|
||||
local vec = vector.new
|
||||
|
||||
minetest.register_privilege("meshport", S("Can save meshes with Meshport."))
|
||||
core.register_privilege("meshport", S("Can save meshes with Meshport."))
|
||||
|
||||
minetest.register_on_leaveplayer(function(player, timed_out)
|
||||
core.register_on_leaveplayer(function(player, timed_out)
|
||||
local name = player:get_player_name()
|
||||
meshport.player_data[name] = nil
|
||||
end)
|
||||
@ -42,7 +42,7 @@ end)
|
||||
for n = 1, 2 do
|
||||
local tex = "meshport_corner_" .. n .. ".png"
|
||||
|
||||
minetest.register_entity("meshport:corner_" .. n, {
|
||||
core.register_entity("meshport:corner_" .. n, {
|
||||
initial_properties = {
|
||||
physical = false,
|
||||
visual = "cube",
|
||||
@ -50,7 +50,7 @@ for n = 1, 2 do
|
||||
selectionbox = {-0.52, -0.52, -0.52, 0.52, 0.52, 0.52},
|
||||
textures = {tex, tex, tex, tex, tex, tex},
|
||||
static_save = false,
|
||||
glow = minetest.LIGHT_MAX,
|
||||
glow = core.LIGHT_MAX,
|
||||
},
|
||||
|
||||
on_punch = function(self, hitter)
|
||||
@ -59,7 +59,7 @@ for n = 1, 2 do
|
||||
})
|
||||
end
|
||||
|
||||
minetest.register_entity("meshport:border", {
|
||||
core.register_entity("meshport:border", {
|
||||
initial_properties = {
|
||||
physical = false,
|
||||
visual = "upright_sprite",
|
||||
@ -68,7 +68,7 @@ minetest.register_entity("meshport:border", {
|
||||
"meshport_border.png^[transformFX",
|
||||
},
|
||||
static_save = false,
|
||||
glow = minetest.LIGHT_MAX,
|
||||
glow = core.LIGHT_MAX,
|
||||
},
|
||||
|
||||
on_punch = function(self, hitter)
|
||||
@ -137,7 +137,7 @@ local function mark_borders(playerData)
|
||||
}
|
||||
|
||||
for i = 1, 6 do
|
||||
local entity = minetest.add_entity(sideCenters[i], "meshport:border")
|
||||
local entity = core.add_entity(sideCenters[i], "meshport:border")
|
||||
entity:set_properties({
|
||||
visual_size = sideSizes[i],
|
||||
selectionbox = selectionBoxes[i],
|
||||
@ -164,7 +164,7 @@ local function set_position(playerName, n, pos)
|
||||
data.corners[n]:remove()
|
||||
end
|
||||
|
||||
data.corners[n] = minetest.add_entity(pos, "meshport:corner_" .. n)
|
||||
data.corners[n] = core.add_entity(pos, "meshport:corner_" .. n)
|
||||
|
||||
for i = 1, 6 do
|
||||
if data.borders[i] then
|
||||
@ -177,12 +177,12 @@ local function set_position(playerName, n, pos)
|
||||
mark_borders(data)
|
||||
end
|
||||
|
||||
meshport.log(playerName, "info", S("Position @1 set to @2.", n, minetest.pos_to_string(pos)))
|
||||
meshport.log(playerName, "info", S("Position @1 set to @2.", n, core.pos_to_string(pos)))
|
||||
end
|
||||
|
||||
|
||||
for n = 1, 2 do
|
||||
minetest.register_chatcommand("mesh" .. n, {
|
||||
core.register_chatcommand("mesh" .. n, {
|
||||
params = "[pos]",
|
||||
description = S(
|
||||
"Set position @1 for Meshport. Player's position is used if no other position is specified.", n),
|
||||
@ -192,9 +192,9 @@ for n = 1, 2 do
|
||||
local pos
|
||||
|
||||
if param == "" then
|
||||
pos = minetest.get_player_by_name(playerName):get_pos()
|
||||
pos = core.get_player_by_name(playerName):get_pos()
|
||||
else
|
||||
pos = minetest.string_to_pos(param)
|
||||
pos = core.string_to_pos(param)
|
||||
end
|
||||
|
||||
if not pos then
|
||||
@ -216,7 +216,7 @@ local function on_wand_click(itemstack, player, pointedThing, n)
|
||||
|
||||
local playerName = player:get_player_name()
|
||||
|
||||
if not minetest.check_player_privs(playerName, "meshport") then
|
||||
if not core.check_player_privs(playerName, "meshport") then
|
||||
meshport.log(playerName, "error", S("You must have the meshport privilege to use this tool."))
|
||||
return
|
||||
end
|
||||
@ -243,7 +243,7 @@ local function on_wand_click(itemstack, player, pointedThing, n)
|
||||
end
|
||||
|
||||
|
||||
minetest.register_tool("meshport:wand", {
|
||||
core.register_tool("meshport:wand", {
|
||||
description = S("Meshport Area Selector\nLeft-click to set 1st corner, right-click to set 2nd corner."),
|
||||
short_description = S("Meshport Area Selector"),
|
||||
inventory_image = "meshport_wand.png",
|
||||
@ -262,7 +262,7 @@ minetest.register_tool("meshport:wand", {
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand("meshrst", {
|
||||
core.register_chatcommand("meshrst", {
|
||||
description = S("Clear the current Meshport area."),
|
||||
privs = {meshport = true},
|
||||
|
||||
@ -289,7 +289,7 @@ minetest.register_chatcommand("meshrst", {
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand("meshport", {
|
||||
core.register_chatcommand("meshport", {
|
||||
params = "[filename]",
|
||||
description = S("Save a mesh of the selected area (filename optional)."),
|
||||
privs = {meshport = true},
|
||||
@ -311,10 +311,10 @@ minetest.register_chatcommand("meshport", {
|
||||
filename = os.date("%Y-%m-%d_%H-%M-%S")
|
||||
end
|
||||
|
||||
local mpPath = minetest.get_worldpath() .. "/" .. "meshport"
|
||||
local mpPath = core.get_worldpath() .. "/" .. "meshport"
|
||||
local folderName = playerName .. "_" .. filename
|
||||
|
||||
if table.indexof(minetest.get_dir_list(mpPath, true), folderName) > 0 then
|
||||
if table.indexof(core.get_dir_list(mpPath, true), folderName) > 0 then
|
||||
meshport.log(playerName, "error",
|
||||
S("Folder \"@1\" already exists. Try using a different name.", folderName))
|
||||
return
|
||||
|
2
mod.conf
2
mod.conf
@ -1,2 +1,2 @@
|
||||
name = meshport
|
||||
description = Easily export areas in Minetest to meshes for 3D rendering.
|
||||
description = Easily export areas in Luanti to meshes for 3D rendering.
|
||||
|
@ -49,7 +49,7 @@ local function node_connects_to(nodeName, connectsTo)
|
||||
for _, connectName in ipairs(connectsTo) do
|
||||
if connectName == nodeName
|
||||
or string.sub(connectName, 1, 6) == "group:"
|
||||
and minetest.get_item_group(nodeName, string.sub(connectName, 7)) ~= 0 then
|
||||
and core.get_item_group(nodeName, string.sub(connectName, 7)) ~= 0 then
|
||||
return true
|
||||
end
|
||||
end
|
||||
@ -58,7 +58,7 @@ local function node_connects_to(nodeName, connectsTo)
|
||||
end
|
||||
|
||||
|
||||
-- A list of node boxes, in the format used by Minetest:
|
||||
-- A list of node boxes, in the format used by Luanti:
|
||||
-- {a.x, a.y, a.z, b.x, b.y, b.z}
|
||||
-- Individual boxes inside the `boxes` array are not mutated.
|
||||
meshport.Boxes = {}
|
||||
@ -224,7 +224,7 @@ function meshport.collect_boxes(prepNodebox, nodeDef, param2, facedir, neighbors
|
||||
local neighborName
|
||||
|
||||
for i = 1, 6 do
|
||||
neighborName = minetest.get_name_from_content_id(neighbors[i])
|
||||
neighborName = core.get_name_from_content_id(neighbors[i])
|
||||
|
||||
if node_connects_to(neighborName, nodeDef.connects_to) then
|
||||
boxes:insert_all(prepNodebox.connected[i])
|
||||
|
@ -25,7 +25,7 @@ local function parse_vector_element(elementType, elementStr)
|
||||
if elementType == "v" or elementType == "vn" then
|
||||
-- Note that there may be an optional weight value after z, which is ignored.
|
||||
local xs, ys, zs = string.match(elementStr, "^([%d%.%-]+)%s+([%d%.%-]+)%s+([%d%.%-]+)")
|
||||
-- The X axis of vectors is inverted to match the Minetest coordinate system.
|
||||
-- The X axis of vectors is inverted to match the Luanti coordinate system.
|
||||
local vec = vector.new(-tonumber(xs), tonumber(ys), tonumber(zs))
|
||||
|
||||
if elementType == "v" then
|
||||
@ -70,7 +70,7 @@ end
|
||||
|
||||
|
||||
local function handle_group(groups, elementStr)
|
||||
-- Note: Minetest ignores usemtl; see `OBJ_LOADER_IGNORE_MATERIAL_FILES`.
|
||||
-- Note: Luanti ignores usemtl; see `OBJ_LOADER_IGNORE_MATERIAL_FILES`.
|
||||
-- The format allows multiple group names; get only the first one.
|
||||
local groupName = string.match(elementStr, "^(%S+)")
|
||||
if not groupName then
|
||||
|
20
utils.lua
20
utils.lua
@ -111,14 +111,14 @@ function meshport.log(name, level, s)
|
||||
local message
|
||||
|
||||
if level == "info" then
|
||||
message = minetest.colorize("#00EF00", s)
|
||||
message = core.colorize("#00EF00", s)
|
||||
elseif level == "warning" then
|
||||
message = minetest.colorize("#EFEF00", S("Warning: @1", s))
|
||||
message = core.colorize("#EFEF00", S("Warning: @1", s))
|
||||
elseif level == "error" then
|
||||
message = minetest.colorize("#EF0000", S("Error: @1", s))
|
||||
message = core.colorize("#EF0000", S("Error: @1", s))
|
||||
end
|
||||
|
||||
minetest.chat_send_player(name, "[meshport] " .. message)
|
||||
core.chat_send_player(name, "[meshport] " .. message)
|
||||
end
|
||||
|
||||
|
||||
@ -268,14 +268,14 @@ end
|
||||
|
||||
|
||||
function meshport.get_content_id_or_nil(nodeName)
|
||||
if minetest.registered_nodes[nodeName] then
|
||||
return minetest.get_content_id(nodeName)
|
||||
if core.registered_nodes[nodeName] then
|
||||
return core.get_content_id(nodeName)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function meshport.get_def_from_id(contentId)
|
||||
return minetest.registered_nodes[minetest.get_name_from_content_id(contentId)] or {}
|
||||
return core.registered_nodes[core.get_name_from_content_id(contentId)] or {}
|
||||
end
|
||||
|
||||
|
||||
@ -379,11 +379,11 @@ function meshport.get_asset_paths(assetFolderName, extension)
|
||||
local assets = {}
|
||||
|
||||
-- Iterate through each enabled mod.
|
||||
for _, modName in ipairs(minetest.get_modnames()) do
|
||||
modAssetPath = minetest.get_modpath(modName) .. "/" .. assetFolderName
|
||||
for _, modName in ipairs(core.get_modnames()) do
|
||||
modAssetPath = core.get_modpath(modName) .. "/" .. assetFolderName
|
||||
|
||||
-- Iterate through all the files in the requested folder of the mod.
|
||||
for _, fileName in ipairs(minetest.get_dir_list(modAssetPath, false)) do
|
||||
for _, fileName in ipairs(core.get_dir_list(modAssetPath, false)) do
|
||||
-- Add files to the table. If an extension is specified, only add files with that extension.
|
||||
if not extension or string.lower(string.sub(fileName, -string.len(extension))) == extension then
|
||||
assets[fileName] = modAssetPath .. "/" .. fileName
|
||||
|
Loading…
x
Reference in New Issue
Block a user