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
|
||||
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)
|
||||
|
|
|
@ -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")
|
||||
|
|
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();
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -164,6 +164,8 @@ private:
|
|||
void drawRaillikeNode();
|
||||
void drawNodeboxNode();
|
||||
void drawMeshNode();
|
||||
void drawSunkenNode();
|
||||
void drawCoveredNode();
|
||||
|
||||
// common
|
||||
void errorUnknownDrawtype();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 ---
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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},
|
||||
};
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue