1
0
Fork 0
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:
SFENCE 2023-12-14 13:01:34 +01:00
parent aba2b6638e
commit 6ee9f927e7
11 changed files with 231 additions and 3 deletions

View file

@ -150,6 +150,14 @@ local function preprocess_node(nodedef)
if nodedef.liquidtype == "flowing" then
nodedef.paramtype2 = "flowingliquid"
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
local function preprocess_craft(itemdef)

View file

@ -10,4 +10,5 @@ dofile(path.."/liquids.lua")
dofile(path.."/light.lua")
dofile(path.."/textures.lua")
dofile(path.."/overlays.lua")
dofile(path.."/sunken_covered.lua")
dofile(path.."/commands.lua")

View 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},
})

View file

@ -1763,6 +1763,117 @@ void MapblockMeshGenerator::drawMeshNode()
}
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
void MapblockMeshGenerator::errorUnknownDrawtype()
@ -1804,6 +1915,8 @@ void MapblockMeshGenerator::drawNode()
case NDT_RAILLIKE: drawRaillikeNode(); break;
case NDT_NODEBOX: drawNodeboxNode(); break;
case NDT_MESH: drawMeshNode(); break;
case NDT_SUNKEN: drawSunkenNode(); break;
case NDT_COVERED: drawCoveredNode(); break;
default: errorUnknownDrawtype(); break;
}
}

View file

@ -164,6 +164,8 @@ private:
void drawRaillikeNode();
void drawNodeboxNode();
void drawMeshNode();
void drawSunkenNode();
void drawCoveredNode();
// common
void errorUnknownDrawtype();

View file

@ -408,6 +408,8 @@ void ContentFeatures::reset()
move_resistance = 0;
liquid_move_physics = false;
post_effect_color_shaded = false;
inner_node.clear();
inner_node_id = CONTENT_IGNORE;
}
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, liquid_move_physics);
writeU8(os, post_effect_color_shaded);
os << serializeString16(inner_node);
}
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())
throw SerializationError("");
post_effect_color_shaded = tmp;
if (is.eof())
throw SerializationError("");
inner_node = deSerializeString16(is);
} catch (SerializationError &e) {};
}
@ -883,6 +889,10 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
case NDT_PLANTLIKE_ROOTED:
solidness = 2;
break;
case NDT_SUNKEN:
case NDT_COVERED:
solidness = 0;
break;
}
if (is_liquid) {
@ -1630,6 +1640,9 @@ void NodeDefManager::resetNodeResolveState()
void NodeDefManager::resolveCrossrefs()
{
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()) {
f.liquid_alternative_flowing_id = getId(f.liquid_alternative_flowing);
f.liquid_alternative_source_id = getId(f.liquid_alternative_source);

View file

@ -227,6 +227,10 @@ enum NodeDrawType : u8
NDT_MESH,
// Combined plantlike-on-solid
NDT_PLANTLIKE_ROOTED,
// sunken node
NDT_SUNKEN,
// covered node
NDT_COVERED,
// Dummy for validity check
NodeDrawType_END
@ -368,6 +372,9 @@ struct ContentFeatures
u8 leveled;
// Maximum value for leveled nodes
u8 leveled_max;
// inner node for sunken and covered draw types
std::string inner_node;
content_t inner_node_id;
// --- LIGHTING-RELATED ---

View file

@ -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)
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;
}
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)

View file

@ -63,7 +63,8 @@ extern struct EnumString es_TouchInteractionMode[];
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_nodebox(lua_State *L, const NodeBox &box);

View file

@ -33,6 +33,8 @@ struct EnumString ScriptApiNode::es_DrawType[] =
{NDT_GLASSLIKE_FRAMED_OPTIONAL, "glasslike_framed_optional"},
{NDT_MESH, "mesh"},
{NDT_PLANTLIKE_ROOTED, "plantlike_rooted"},
{NDT_SUNKEN, "sunken"},
{NDT_COVERED, "covered"},
{0, NULL},
};

View file

@ -616,7 +616,7 @@ int ModApiItem::l_register_item_raw(lua_State *L)
// Read the node definition (content features) and register it
if (def.type == ITEM_NODE) {
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
// be done
if (f.name == "ignore")