mirror of
https://github.com/luanti-org/luanti.git
synced 2025-06-27 16:36:03 +00:00
Undocumented version of sunken and covered drawtype of nodes.
This commit is contained in:
parent
aba2b6638e
commit
6ee9f927e7
11 changed files with 231 additions and 3 deletions
|
@ -150,6 +150,14 @@ local function preprocess_node(nodedef)
|
||||||
if nodedef.liquidtype == "flowing" then
|
if nodedef.liquidtype == "flowing" then
|
||||||
nodedef.paramtype2 = "flowingliquid"
|
nodedef.paramtype2 = "flowingliquid"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if itemdef.type == "node" and (itemdef.drawtype == "sunken" or itemdef.drawtype == "covered") then
|
||||||
|
if not core.registered_nodes[itemdef.inner_node] then
|
||||||
|
error("Unable to register item " .. name .. ": Inner node not registered: " .. itemdef.inner_node)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
itemdef.inner_node = nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function preprocess_craft(itemdef)
|
local function preprocess_craft(itemdef)
|
||||||
|
|
|
@ -10,4 +10,5 @@ dofile(path.."/liquids.lua")
|
||||||
dofile(path.."/light.lua")
|
dofile(path.."/light.lua")
|
||||||
dofile(path.."/textures.lua")
|
dofile(path.."/textures.lua")
|
||||||
dofile(path.."/overlays.lua")
|
dofile(path.."/overlays.lua")
|
||||||
|
dofile(path.."/sunken_covered.lua")
|
||||||
dofile(path.."/commands.lua")
|
dofile(path.."/commands.lua")
|
||||||
|
|
78
games/devtest/mods/testnodes/sunken_covered.lua
Normal file
78
games/devtest/mods/testnodes/sunken_covered.lua
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
local S = minetest.get_translator("testnodes")
|
||||||
|
|
||||||
|
-- Sunken node example.
|
||||||
|
minetest.register_node("testnodes:sunken_torchlike", {
|
||||||
|
description = "Sunken Torchlike Test Node in Liquid Source Range 5",
|
||||||
|
drawtype = "sunken",
|
||||||
|
tiles = {"testnodes_liquidsource_r5.png"},
|
||||||
|
special_tiles = {
|
||||||
|
{name = "testnodes_liquidsource_r5.png", backface_culling = false},
|
||||||
|
{name = "testnodes_liquidsource_r5.png", backface_culling = true},
|
||||||
|
},
|
||||||
|
use_texture_alpha = "blend",
|
||||||
|
paramtype = "light",
|
||||||
|
walkable = false,
|
||||||
|
buildable_to = true,
|
||||||
|
is_ground_content = false,
|
||||||
|
liquidtype = "source",
|
||||||
|
--liquid_alternative_flowing = "testnodes:rliquid_flowing_5",
|
||||||
|
--liquid_alternative_source = "testnodes:rliquid_5",
|
||||||
|
liquid_alternative_flowing = "testnodes:sunken_torchlike",
|
||||||
|
liquid_alternative_source = "testnodes:sunken_torchlike",
|
||||||
|
liquid_range = 0,
|
||||||
|
|
||||||
|
inner_node = "testnodes:torchlike",
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node("testnodes:sunken_nodebox", {
|
||||||
|
description = "Sunken Nodebox Test Node in Liquid Source Range 5",
|
||||||
|
drawtype = "sunken",
|
||||||
|
tiles = {"testnodes_liquidsource_r5.png"},
|
||||||
|
special_tiles = {
|
||||||
|
{name = "testnodes_liquidsource_r5.png", backface_culling = false},
|
||||||
|
{name = "testnodes_liquidsource_r5.png", backface_culling = true},
|
||||||
|
},
|
||||||
|
use_texture_alpha = "blend",
|
||||||
|
paramtype = "light",
|
||||||
|
walkable = false,
|
||||||
|
buildable_to = true,
|
||||||
|
is_ground_content = false,
|
||||||
|
liquidtype = "source",
|
||||||
|
--liquid_alternative_flowing = "testnodes:rliquid_flowing_5",
|
||||||
|
--liquid_alternative_source = "testnodes:rliquid_5",
|
||||||
|
liquid_alternative_flowing = "testnodes:sunken_nodebox",
|
||||||
|
liquid_alternative_source = "testnodes:sunken_nodebox",
|
||||||
|
liquid_range = 0,
|
||||||
|
|
||||||
|
inner_node = "testnodes:nodebox_fixed",
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
-- Covered node example.
|
||||||
|
-- An simple example nodebox with one centered box
|
||||||
|
minetest.register_node("testnodes:covered_torchlike_node", {
|
||||||
|
description = S("Covered Tochlike Test Node").."\n"..
|
||||||
|
S("Torchlike node inside"),
|
||||||
|
--tiles = {"testnodes_nodebox.png"},
|
||||||
|
tiles = { "testnodes_glasslike.png" },
|
||||||
|
drawtype = "covered",
|
||||||
|
paramtype = "light",
|
||||||
|
|
||||||
|
inner_node = "testnodes:torchlike",
|
||||||
|
|
||||||
|
groups = {dig_immediate=3},
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_node("testnodes:covered_nodebox_node", {
|
||||||
|
description = S("Covered Fixed Nodebox Test Node").."\n"..
|
||||||
|
S("Torchlike node inside"),
|
||||||
|
--tiles = {"testnodes_nodebox.png"},
|
||||||
|
tiles = { "testnodes_glasslike.png" },
|
||||||
|
drawtype = "covered",
|
||||||
|
paramtype = "light",
|
||||||
|
|
||||||
|
inner_node = "testnodes:nodebox_fixed",
|
||||||
|
|
||||||
|
groups = {dig_immediate=3},
|
||||||
|
})
|
||||||
|
|
|
@ -1763,6 +1763,117 @@ void MapblockMeshGenerator::drawMeshNode()
|
||||||
}
|
}
|
||||||
mesh->drop();
|
mesh->drop();
|
||||||
}
|
}
|
||||||
|
void MapblockMeshGenerator::drawSunkenNode()
|
||||||
|
{
|
||||||
|
MapNode store_n;
|
||||||
|
const ContentFeatures *store_f;
|
||||||
|
store_n = cur_node.n;
|
||||||
|
store_f = cur_node.f;
|
||||||
|
cur_node.n.param0 = cur_node.f->inner_node_id;
|
||||||
|
cur_node.f = &nodedef->get(cur_node.f->inner_node_id);
|
||||||
|
drawNode();
|
||||||
|
|
||||||
|
cur_node.n = store_n;
|
||||||
|
cur_node.f = store_f;
|
||||||
|
drawSolidNode();
|
||||||
|
}
|
||||||
|
void MapblockMeshGenerator::drawCoveredNode()
|
||||||
|
{
|
||||||
|
MapNode store_n;
|
||||||
|
const ContentFeatures *store_f;
|
||||||
|
store_n = cur_node.n;
|
||||||
|
store_f = cur_node.f;
|
||||||
|
cur_node.n.param0 = cur_node.f->inner_node_id;
|
||||||
|
cur_node.n.param2 &= 0x0F;
|
||||||
|
cur_node.f = &nodedef->get(cur_node.f->inner_node_id);
|
||||||
|
drawNode();
|
||||||
|
cur_node.n = store_n;
|
||||||
|
cur_node.f = store_f;
|
||||||
|
|
||||||
|
u8 faces = 0; // k-th bit will be set if k-th face is to be drawn.
|
||||||
|
static const v3s16 tile_dirs[6] = {
|
||||||
|
v3s16(0, 1, 0),
|
||||||
|
v3s16(0, -1, 0),
|
||||||
|
v3s16(1, 0, 0),
|
||||||
|
v3s16(-1, 0, 0),
|
||||||
|
v3s16(0, 0, 1),
|
||||||
|
v3s16(0, 0, -1)
|
||||||
|
};
|
||||||
|
TileSpec tiles[6];
|
||||||
|
u16 lights[6];
|
||||||
|
content_t n1 = cur_node.n.getContent();
|
||||||
|
for (int face = 0; face < 6; face++) {
|
||||||
|
v3s16 p2 = blockpos_nodes + cur_node.p + tile_dirs[face];
|
||||||
|
MapNode neighbor = data->m_vmanip.getNodeNoEx(p2);
|
||||||
|
content_t n2 = neighbor.getContent();
|
||||||
|
bool backface_culling = cur_node.f->drawtype == NDT_NORMAL;
|
||||||
|
if (n2 == n1)
|
||||||
|
continue;
|
||||||
|
if (n2 == CONTENT_IGNORE)
|
||||||
|
continue;
|
||||||
|
if (n2 != CONTENT_AIR) {
|
||||||
|
const ContentFeatures &f2 = nodedef->get(n2);
|
||||||
|
if (f2.solidness == 2)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
faces |= 1 << face;
|
||||||
|
getTile(tile_dirs[face], &tiles[face]);
|
||||||
|
for (auto &layer : tiles[face].layers) {
|
||||||
|
if (backface_culling)
|
||||||
|
layer.material_flags |= MATERIAL_FLAG_BACKFACE_CULLING;
|
||||||
|
layer.material_flags |= MATERIAL_FLAG_TILEABLE_HORIZONTAL;
|
||||||
|
layer.material_flags |= MATERIAL_FLAG_TILEABLE_VERTICAL;
|
||||||
|
}
|
||||||
|
if (!data->m_smooth_lighting) {
|
||||||
|
lights[face] = getFaceLight(cur_node.n, neighbor, nodedef);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!faces)
|
||||||
|
return;
|
||||||
|
u8 mask = faces ^ 0b0011'1111; // k-th bit is set if k-th face is to be *omitted*, as expected by cuboid drawing functions.
|
||||||
|
cur_node.origin = intToFloat(cur_node.p, BS);
|
||||||
|
auto box = aabb3f(v3f(-0.5 * BS), v3f(0.5 * BS));
|
||||||
|
f32 corr_y = ((cur_node.n.param2&0xF0)>>4)/16.0;
|
||||||
|
box.MaxEdge.Y -= corr_y * BS;
|
||||||
|
f32 texture_coord_buf[24];
|
||||||
|
box.MinEdge += cur_node.origin;
|
||||||
|
box.MaxEdge += cur_node.origin;
|
||||||
|
generateCuboidTextureCoords(box, texture_coord_buf);
|
||||||
|
if (data->m_smooth_lighting) {
|
||||||
|
LightPair lights[6][4];
|
||||||
|
for (int face = 0; face < 6; ++face) {
|
||||||
|
for (int k = 0; k < 4; k++) {
|
||||||
|
v3s16 corner = light_dirs[light_indices[face][k]];
|
||||||
|
lights[face][k] = LightPair(getSmoothLightSolid(
|
||||||
|
blockpos_nodes + cur_node.p, tile_dirs[face], corner, data));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drawCuboid(box, tiles, 6, texture_coord_buf, mask, [&] (int face, video::S3DVertex vertices[4]) {
|
||||||
|
auto final_lights = lights[face];
|
||||||
|
for (int j = 0; j < 4; j++) {
|
||||||
|
video::S3DVertex &vertex = vertices[j];
|
||||||
|
vertex.Color = encode_light(final_lights[j], cur_node.f->light_source);
|
||||||
|
if (!cur_node.f->light_source)
|
||||||
|
applyFacesShading(vertex.Color, vertex.Normal);
|
||||||
|
}
|
||||||
|
if (lightDiff(final_lights[1], final_lights[3]) < lightDiff(final_lights[0], final_lights[2]))
|
||||||
|
return QuadDiagonal::Diag13;
|
||||||
|
return QuadDiagonal::Diag02;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
drawCuboid(box, tiles, 6, texture_coord_buf, mask, [&] (int face, video::S3DVertex vertices[4]) {
|
||||||
|
video::SColor color = encode_light(lights[face], cur_node.f->light_source);
|
||||||
|
if (!cur_node.f->light_source)
|
||||||
|
applyFacesShading(color, vertices[0].Normal);
|
||||||
|
for (int j = 0; j < 4; j++) {
|
||||||
|
video::S3DVertex &vertex = vertices[j];
|
||||||
|
vertex.Color = color;
|
||||||
|
}
|
||||||
|
return QuadDiagonal::Diag02;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// also called when the drawtype is known but should have been pre-converted
|
// also called when the drawtype is known but should have been pre-converted
|
||||||
void MapblockMeshGenerator::errorUnknownDrawtype()
|
void MapblockMeshGenerator::errorUnknownDrawtype()
|
||||||
|
@ -1804,6 +1915,8 @@ void MapblockMeshGenerator::drawNode()
|
||||||
case NDT_RAILLIKE: drawRaillikeNode(); break;
|
case NDT_RAILLIKE: drawRaillikeNode(); break;
|
||||||
case NDT_NODEBOX: drawNodeboxNode(); break;
|
case NDT_NODEBOX: drawNodeboxNode(); break;
|
||||||
case NDT_MESH: drawMeshNode(); break;
|
case NDT_MESH: drawMeshNode(); break;
|
||||||
|
case NDT_SUNKEN: drawSunkenNode(); break;
|
||||||
|
case NDT_COVERED: drawCoveredNode(); break;
|
||||||
default: errorUnknownDrawtype(); break;
|
default: errorUnknownDrawtype(); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -164,6 +164,8 @@ private:
|
||||||
void drawRaillikeNode();
|
void drawRaillikeNode();
|
||||||
void drawNodeboxNode();
|
void drawNodeboxNode();
|
||||||
void drawMeshNode();
|
void drawMeshNode();
|
||||||
|
void drawSunkenNode();
|
||||||
|
void drawCoveredNode();
|
||||||
|
|
||||||
// common
|
// common
|
||||||
void errorUnknownDrawtype();
|
void errorUnknownDrawtype();
|
||||||
|
|
|
@ -408,6 +408,8 @@ void ContentFeatures::reset()
|
||||||
move_resistance = 0;
|
move_resistance = 0;
|
||||||
liquid_move_physics = false;
|
liquid_move_physics = false;
|
||||||
post_effect_color_shaded = false;
|
post_effect_color_shaded = false;
|
||||||
|
inner_node.clear();
|
||||||
|
inner_node_id = CONTENT_IGNORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContentFeatures::setAlphaFromLegacy(u8 legacy_alpha)
|
void ContentFeatures::setAlphaFromLegacy(u8 legacy_alpha)
|
||||||
|
@ -535,6 +537,7 @@ void ContentFeatures::serialize(std::ostream &os, u16 protocol_version) const
|
||||||
writeU8(os, move_resistance);
|
writeU8(os, move_resistance);
|
||||||
writeU8(os, liquid_move_physics);
|
writeU8(os, liquid_move_physics);
|
||||||
writeU8(os, post_effect_color_shaded);
|
writeU8(os, post_effect_color_shaded);
|
||||||
|
os << serializeString16(inner_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContentFeatures::deSerialize(std::istream &is, u16 protocol_version)
|
void ContentFeatures::deSerialize(std::istream &is, u16 protocol_version)
|
||||||
|
@ -665,6 +668,9 @@ void ContentFeatures::deSerialize(std::istream &is, u16 protocol_version)
|
||||||
if (is.eof())
|
if (is.eof())
|
||||||
throw SerializationError("");
|
throw SerializationError("");
|
||||||
post_effect_color_shaded = tmp;
|
post_effect_color_shaded = tmp;
|
||||||
|
if (is.eof())
|
||||||
|
throw SerializationError("");
|
||||||
|
inner_node = deSerializeString16(is);
|
||||||
} catch (SerializationError &e) {};
|
} catch (SerializationError &e) {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -883,6 +889,10 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
|
||||||
case NDT_PLANTLIKE_ROOTED:
|
case NDT_PLANTLIKE_ROOTED:
|
||||||
solidness = 2;
|
solidness = 2;
|
||||||
break;
|
break;
|
||||||
|
case NDT_SUNKEN:
|
||||||
|
case NDT_COVERED:
|
||||||
|
solidness = 0;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_liquid) {
|
if (is_liquid) {
|
||||||
|
@ -1630,6 +1640,9 @@ void NodeDefManager::resetNodeResolveState()
|
||||||
void NodeDefManager::resolveCrossrefs()
|
void NodeDefManager::resolveCrossrefs()
|
||||||
{
|
{
|
||||||
for (ContentFeatures &f : m_content_features) {
|
for (ContentFeatures &f : m_content_features) {
|
||||||
|
if (f.drawtype == NDT_SUNKEN || f.drawtype == NDT_COVERED) {
|
||||||
|
f.inner_node_id = getId(f.inner_node);
|
||||||
|
}
|
||||||
if (f.isLiquid() || f.isLiquidRender()) {
|
if (f.isLiquid() || f.isLiquidRender()) {
|
||||||
f.liquid_alternative_flowing_id = getId(f.liquid_alternative_flowing);
|
f.liquid_alternative_flowing_id = getId(f.liquid_alternative_flowing);
|
||||||
f.liquid_alternative_source_id = getId(f.liquid_alternative_source);
|
f.liquid_alternative_source_id = getId(f.liquid_alternative_source);
|
||||||
|
|
|
@ -227,6 +227,10 @@ enum NodeDrawType : u8
|
||||||
NDT_MESH,
|
NDT_MESH,
|
||||||
// Combined plantlike-on-solid
|
// Combined plantlike-on-solid
|
||||||
NDT_PLANTLIKE_ROOTED,
|
NDT_PLANTLIKE_ROOTED,
|
||||||
|
// sunken node
|
||||||
|
NDT_SUNKEN,
|
||||||
|
// covered node
|
||||||
|
NDT_COVERED,
|
||||||
|
|
||||||
// Dummy for validity check
|
// Dummy for validity check
|
||||||
NodeDrawType_END
|
NodeDrawType_END
|
||||||
|
@ -368,6 +372,9 @@ struct ContentFeatures
|
||||||
u8 leveled;
|
u8 leveled;
|
||||||
// Maximum value for leveled nodes
|
// Maximum value for leveled nodes
|
||||||
u8 leveled_max;
|
u8 leveled_max;
|
||||||
|
// inner node for sunken and covered draw types
|
||||||
|
std::string inner_node;
|
||||||
|
content_t inner_node_id;
|
||||||
|
|
||||||
// --- LIGHTING-RELATED ---
|
// --- LIGHTING-RELATED ---
|
||||||
|
|
||||||
|
|
|
@ -674,7 +674,7 @@ TileDef read_tiledef(lua_State *L, int index, u8 drawtype, bool special)
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
void read_content_features(lua_State *L, ContentFeatures &f, int index)
|
void read_content_features(lua_State *L, ContentFeatures &f, int index, NodeDefManager *ndef)
|
||||||
{
|
{
|
||||||
if(index < 0)
|
if(index < 0)
|
||||||
index = lua_gettop(L) + 1 + index;
|
index = lua_gettop(L) + 1 + index;
|
||||||
|
@ -1013,6 +1013,9 @@ void read_content_features(lua_State *L, ContentFeatures &f, int index)
|
||||||
errorstream << "Field \"liquid_move_physics\": Invalid type!" << std::endl;
|
errorstream << "Field \"liquid_move_physics\": Invalid type!" << std::endl;
|
||||||
}
|
}
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
|
|
||||||
|
// inner_node for sunken and covered drawtype
|
||||||
|
getstringfield(L, index, "inner_node", f.inner_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
void push_content_features(lua_State *L, const ContentFeatures &c)
|
void push_content_features(lua_State *L, const ContentFeatures &c)
|
||||||
|
|
|
@ -63,7 +63,8 @@ extern struct EnumString es_TouchInteractionMode[];
|
||||||
|
|
||||||
extern const std::array<const char *, 33> object_property_keys;
|
extern const std::array<const char *, 33> object_property_keys;
|
||||||
|
|
||||||
void read_content_features(lua_State *L, ContentFeatures &f, int index);
|
void read_content_features(lua_State *L, ContentFeatures &f, int index,
|
||||||
|
NodeDefManager *ndef);
|
||||||
void push_content_features(lua_State *L, const ContentFeatures &c);
|
void push_content_features(lua_State *L, const ContentFeatures &c);
|
||||||
|
|
||||||
void push_nodebox(lua_State *L, const NodeBox &box);
|
void push_nodebox(lua_State *L, const NodeBox &box);
|
||||||
|
|
|
@ -33,6 +33,8 @@ struct EnumString ScriptApiNode::es_DrawType[] =
|
||||||
{NDT_GLASSLIKE_FRAMED_OPTIONAL, "glasslike_framed_optional"},
|
{NDT_GLASSLIKE_FRAMED_OPTIONAL, "glasslike_framed_optional"},
|
||||||
{NDT_MESH, "mesh"},
|
{NDT_MESH, "mesh"},
|
||||||
{NDT_PLANTLIKE_ROOTED, "plantlike_rooted"},
|
{NDT_PLANTLIKE_ROOTED, "plantlike_rooted"},
|
||||||
|
{NDT_SUNKEN, "sunken"},
|
||||||
|
{NDT_COVERED, "covered"},
|
||||||
{0, NULL},
|
{0, NULL},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -616,7 +616,7 @@ int ModApiItem::l_register_item_raw(lua_State *L)
|
||||||
// Read the node definition (content features) and register it
|
// Read the node definition (content features) and register it
|
||||||
if (def.type == ITEM_NODE) {
|
if (def.type == ITEM_NODE) {
|
||||||
ContentFeatures f;
|
ContentFeatures f;
|
||||||
read_content_features(L, f, table);
|
read_content_features(L, f, table, ndef);
|
||||||
// when a mod reregisters ignore, only texture changes and such should
|
// when a mod reregisters ignore, only texture changes and such should
|
||||||
// be done
|
// be done
|
||||||
if (f.name == "ignore")
|
if (f.name == "ignore")
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue