Add paramtype2s for 4 horizontal rotations and 64 colors (#11431)

4dir is like facedir, but only for 4 horizontal directions: NESW. It is identical in behavior to facedir otherwise. The reason why game makers would want to use this over facedir is 1) simplicity and 2) you get 6 free bits.
It can be used for things like chests and furnaces and you don't need or want them to "flip them on the side" (like you could with facedir).

color4dir is like colorfacedir, but you get 64 colors instead of only 8.
This commit is contained in:
Wuzzy 2022-09-16 13:18:55 +02:00 committed by GitHub
parent b5e7280708
commit 1d04903c19
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 299 additions and 28 deletions

View File

@ -161,7 +161,16 @@ core.register_entity(":__builtin:falling_node", {
local fdir = node.param2 % 32 % 24 local fdir = node.param2 % 32 % 24
-- Get rotation from a precalculated lookup table -- Get rotation from a precalculated lookup table
local euler = facedir_to_euler[fdir + 1] local euler = facedir_to_euler[fdir + 1]
if euler then
self.object:set_rotation(euler) self.object:set_rotation(euler)
end
elseif (def.paramtype2 == "4dir" or def.paramtype2 == "color4dir") then
local fdir = node.param2 % 4
-- Get rotation from a precalculated lookup table
local euler = facedir_to_euler[fdir + 1]
if euler then
self.object:set_rotation(euler)
end
elseif (def.drawtype ~= "plantlike" and def.drawtype ~= "plantlike_rooted" and elseif (def.drawtype ~= "plantlike" and def.drawtype ~= "plantlike_rooted" and
(def.paramtype2 == "wallmounted" or def.paramtype2 == "colorwallmounted" or def.drawtype == "signlike")) then (def.paramtype2 == "wallmounted" or def.paramtype2 == "colorwallmounted" or def.drawtype == "signlike")) then
local rot = node.param2 % 8 local rot = node.param2 % 8

View File

@ -205,7 +205,9 @@ function core.item_place_node(itemstack, placer, pointed_thing, param2,
newnode.param2 = core.dir_to_wallmounted(dir) newnode.param2 = core.dir_to_wallmounted(dir)
-- Calculate the direction for furnaces and chests and stuff -- Calculate the direction for furnaces and chests and stuff
elseif (def.paramtype2 == "facedir" or elseif (def.paramtype2 == "facedir" or
def.paramtype2 == "colorfacedir") and not param2 then def.paramtype2 == "colorfacedir" or
def.paramtype2 == "4dir" or
def.paramtype2 == "color4dir") and not param2 then
local placer_pos = placer and placer:get_pos() local placer_pos = placer and placer:get_pos()
if placer_pos then if placer_pos then
local dir = vector.subtract(above, placer_pos) local dir = vector.subtract(above, placer_pos)
@ -225,6 +227,8 @@ function core.item_place_node(itemstack, placer, pointed_thing, param2,
color_divisor = 8 color_divisor = 8
elseif def.paramtype2 == "colorfacedir" then elseif def.paramtype2 == "colorfacedir" then
color_divisor = 32 color_divisor = 32
elseif def.paramtype2 == "color4dir" then
color_divisor = 4
elseif def.paramtype2 == "colordegrotate" then elseif def.paramtype2 == "colordegrotate" then
color_divisor = 32 color_divisor = 32
end end

View File

@ -92,6 +92,26 @@ function core.facedir_to_dir(facedir)
return facedir_to_dir[facedir_to_dir_map[facedir % 32]] return facedir_to_dir[facedir_to_dir_map[facedir % 32]]
end end
function core.dir_to_fourdir(dir)
if math.abs(dir.x) > math.abs(dir.z) then
if dir.x < 0 then
return 3
else
return 1
end
else
if dir.z < 0 then
return 2
else
return 0
end
end
end
function core.fourdir_to_dir(fourdir)
return facedir_to_dir[facedir_to_dir_map[fourdir % 4]]
end
function core.dir_to_wallmounted(dir) function core.dir_to_wallmounted(dir)
if math.abs(dir.y) > math.max(math.abs(dir.x), math.abs(dir.z)) then if math.abs(dir.y) > math.max(math.abs(dir.x), math.abs(dir.z)) then
if dir.y < 0 then if dir.y < 0 then
@ -137,7 +157,8 @@ end
function core.is_colored_paramtype(ptype) function core.is_colored_paramtype(ptype)
return (ptype == "color") or (ptype == "colorfacedir") or return (ptype == "color") or (ptype == "colorfacedir") or
(ptype == "colorwallmounted") or (ptype == "colordegrotate") (ptype == "color4dir") or (ptype == "colorwallmounted") or
(ptype == "colordegrotate")
end end
function core.strip_param2_color(param2, paramtype2) function core.strip_param2_color(param2, paramtype2)
@ -146,6 +167,8 @@ function core.strip_param2_color(param2, paramtype2)
end end
if paramtype2 == "colorfacedir" then if paramtype2 == "colorfacedir" then
param2 = math.floor(param2 / 32) * 32 param2 = math.floor(param2 / 32) * 32
elseif paramtype2 == "color4dir" then
param2 = math.floor(param2 / 4) * 4
elseif paramtype2 == "colorwallmounted" then elseif paramtype2 == "colorwallmounted" then
param2 = math.floor(param2 / 8) * 8 param2 = math.floor(param2 / 8) * 8
elseif paramtype2 == "colordegrotate" then elseif paramtype2 == "colordegrotate" then

View File

@ -758,6 +758,17 @@ appropriate `paramtype2`:
first (= 0 + 1) pixel will be picked from the palette. first (= 0 + 1) pixel will be picked from the palette.
* `param2 = 35` is 1 * 32 + 3, so the rotation is 3 and the * `param2 = 35` is 1 * 32 + 3, so the rotation is 3 and the
second (= 1 + 1) pixel will be picked from the palette. second (= 1 + 1) pixel will be picked from the palette.
* `paramtype2 = "color4dir"` for nodes which use the first
six bits of `param2` for palette indexing. The remaining
two bits are describing rotation, as in `4dir` paramtype2.
Division by 4 yields the palette index (without stretching the
palette). These nodes can have 64 different colors, and the
palette should contain 64 pixels.
Examples:
* `param2 = 17` is 4 * 4 + 1, so the rotation is 1 and the
fifth (= 4 + 1) pixel will be picked from the palette.
* `param2 = 35` is 8 * 4 + 3, so the rotation is 3 and the
ninth (= 8 + 1) pixel will be picked from the palette.
To colorize a node on the map, set its `param2` value (according To colorize a node on the map, set its `param2` value (according
to the node's paramtype2). to the node's paramtype2).
@ -1058,18 +1069,36 @@ The function of `param2` is determined by `paramtype2` in node definition.
* Supported drawtypes: "torchlike", "signlike", "plantlike", * Supported drawtypes: "torchlike", "signlike", "plantlike",
"plantlike_rooted", "normal", "nodebox", "mesh" "plantlike_rooted", "normal", "nodebox", "mesh"
* The rotation of the node is stored in `param2` * The rotation of the node is stored in `param2`
* Node is 'mounted'/facing towards one of 6 directions
* You can make this value by using `minetest.dir_to_wallmounted()` * You can make this value by using `minetest.dir_to_wallmounted()`
* Values range 0 - 5 * Values range 0 - 5
* The value denotes at which direction the node is "mounted": * The value denotes at which direction the node is "mounted":
0 = y+, 1 = y-, 2 = x+, 3 = x-, 4 = z+, 5 = z- 0 = y+, 1 = y-, 2 = x+, 3 = x-, 4 = z+, 5 = z-
* By default, on placement the param2 is automatically set to the
appropriate rotation, depending on which side was pointed at
* `paramtype2 = "facedir"` * `paramtype2 = "facedir"`
* Supported drawtypes: "normal", "nodebox", "mesh" * Supported drawtypes: "normal", "nodebox", "mesh"
* The rotation of the node is stored in `param2`. Furnaces and chests are * The rotation of the node is stored in `param2`.
rotated this way. Can be made by using `minetest.dir_to_facedir()`. * Node is rotated around face and axis; 24 rotations in total.
* Can be made by using `minetest.dir_to_facedir()`.
* Chests and furnaces can be rotated that way, and also 'flipped'
* Values range 0 - 23 * Values range 0 - 23
* facedir / 4 = axis direction: * facedir / 4 = axis direction:
0 = y+, 1 = z+, 2 = z-, 3 = x+, 4 = x-, 5 = y- 0 = y+, 1 = z+, 2 = z-, 3 = x+, 4 = x-, 5 = y-
* facedir modulo 4 = rotation around that axis * facedir modulo 4 = rotation around that axis
* By default, on placement the param2 is automatically set to the
horizondal direction the player was looking at (values 0-3)
* Special case: If the node is a connected nodebox, the nodebox
will NOT rotate, only the textures will.
* `paramtype2 = "4dir"`
* Supported drawtypes: "normal", "nodebox", "mesh"
* The rotation of the node is stored in `param2`.
* Allows node to be rotated horizontally, 4 rotations in total
* Can be made by using `minetest.dir_to_fourdir()`.
* Chests and furnaces can be rotated that way, but not flipped
* Values range 0 - 3
* 4dir modulo 4 = rotation
* Otherwise, behavior is identical to facedir
* `paramtype2 = "leveled"` * `paramtype2 = "leveled"`
* Only valid for "nodebox" with 'type = "leveled"', and "plantlike_rooted". * Only valid for "nodebox" with 'type = "leveled"', and "plantlike_rooted".
* Leveled nodebox: * Leveled nodebox:
@ -1112,6 +1141,10 @@ The function of `param2` is determined by `paramtype2` in node definition.
* Same as `facedir`, but with colors. * Same as `facedir`, but with colors.
* The first three bits of `param2` tells which color is picked from the * The first three bits of `param2` tells which color is picked from the
palette. The palette should have 8 pixels. palette. The palette should have 8 pixels.
* `paramtype2 = "color4dir"`
* Same as `facedir`, but with colors.
* The first six bits of `param2` tells which color is picked from the
palette. The palette should have 64 pixels.
* `paramtype2 = "colorwallmounted"` * `paramtype2 = "colorwallmounted"`
* Same as `wallmounted`, but with colors. * Same as `wallmounted`, but with colors.
* The first five bits of `param2` tells which color is picked from the * The first five bits of `param2` tells which color is picked from the
@ -5776,6 +5809,12 @@ Item handling
* `minetest.facedir_to_dir(facedir)` * `minetest.facedir_to_dir(facedir)`
* Convert a facedir back into a vector aimed directly out the "back" of a * Convert a facedir back into a vector aimed directly out the "back" of a
node. node.
* `minetest.dir_to_fourdir(dir)`
* Convert a vector to a 4dir value, used in `param2` for
`paramtype2="4dir"`.
* `minetest.fourdir_to_dir(fourdir)`
* Convert a 4dir back into a vector aimed directly out the "back" of a
node.
* `minetest.dir_to_wallmounted(dir)` * `minetest.dir_to_wallmounted(dir)`
* Convert a vector to a wallmounted value, used for * Convert a vector to a wallmounted value, used for
`paramtype2="wallmounted"`. `paramtype2="wallmounted"`.
@ -5788,7 +5827,7 @@ Item handling
* Convert yaw (angle) to a vector * Convert yaw (angle) to a vector
* `minetest.is_colored_paramtype(ptype)` * `minetest.is_colored_paramtype(ptype)`
* Returns a boolean. Returns `true` if the given `paramtype2` contains * Returns a boolean. Returns `true` if the given `paramtype2` contains
color information (`color`, `colorwallmounted` or `colorfacedir`). color information (`color`, `colorwallmounted`, `colorfacedir`, etc.).
* `minetest.strip_param2_color(param2, paramtype2)` * `minetest.strip_param2_color(param2, paramtype2)`
* Removes everything but the color information from the * Removes everything but the color information from the
given `param2` value. given `param2` value.
@ -7893,7 +7932,7 @@ Used by `minetest.register_node`, `minetest.register_craftitem`, and
-- You can set the currently used color as the "palette_index" field of -- You can set the currently used color as the "palette_index" field of
-- the item stack metadata. -- the item stack metadata.
-- The palette is always stretched to fit indices between 0 and 255, to -- The palette is always stretched to fit indices between 0 and 255, to
-- ensure compatibility with "colorfacedir" and "colorwallmounted" nodes. -- ensure compatibility with "colorfacedir" (and similar) nodes.
color = "#ffffffff", color = "#ffffffff",
-- Color the item is colorized with. The palette overrides this. -- Color the item is colorized with. The palette overrides this.

View File

@ -60,6 +60,31 @@ minetest.register_node("testnodes:mesh_colorfacedir", {
groups = {dig_immediate=3}, groups = {dig_immediate=3},
}) })
minetest.register_node("testnodes:mesh_4dir", {
description = S("4dir Mesh Test Node"),
drawtype = "mesh",
mesh = "testnodes_ocorner.obj",
tiles = {"testnodes_mesh_stripes.png"},
paramtype = "light",
paramtype2 = "4dir",
collision_box = ocorner_cbox,
groups = {dig_immediate=3},
})
minetest.register_node("testnodes:mesh_color4dir", {
description = S("Color 4dir Mesh Test Node"),
drawtype = "mesh",
mesh = "testnodes_ocorner.obj",
tiles = {"testnodes_mesh_stripes3.png"},
paramtype = "light",
paramtype2 = "color4dir",
palette = "testnodes_palette_4dir.png",
collision_box = ocorner_cbox,
groups = {dig_immediate=3},
})
-- Wallmounted mesh: pyramid -- Wallmounted mesh: pyramid
minetest.register_node("testnodes:mesh_wallmounted", { minetest.register_node("testnodes:mesh_wallmounted", {
description = S("Wallmounted Mesh Test Node"), description = S("Wallmounted Mesh Test Node"),

View File

@ -60,6 +60,25 @@ minetest.register_node("testnodes:nodebox_leveled", {
groups = {dig_immediate=3}, groups = {dig_immediate=3},
}) })
local nodebox_wall = {
type = "connected",
fixed = {-0.125, -0.500, -0.125, 0.125, 0.500, 0.125},
connect_front = {-0.125, -0.500, -0.500, 0.125, 0.400, -0.125},
connect_back = {-0.125, -0.500, 0.125, 0.125, 0.400, 0.500},
connect_left = {-0.500, -0.500, -0.125, -0.125, 0.400, 0.125},
connect_right = {0.125, -0.500, -0.125, 0.500, 0.400, 0.125},
}
local nodebox_wall_thick = {
type = "connected",
fixed = {-0.25, -0.500, -0.25, 0.25, 0.500, 0.25},
connect_front = {-0.25, -0.500, -0.500, 0.25, 0.400, -0.25},
connect_back = {-0.25, -0.500, 0.25, 0.25, 0.400, 0.500},
connect_left = {-0.500, -0.500, -0.25, -0.25, 0.400, 0.25},
connect_right = {0.25, -0.500, -0.25, 0.500, 0.400, 0.25},
}
-- Wall-like nodebox that connects to neighbors -- Wall-like nodebox that connects to neighbors
minetest.register_node("testnodes:nodebox_connected", { minetest.register_node("testnodes:nodebox_connected", {
description = S("Connected Nodebox Test Node"), description = S("Connected Nodebox Test Node"),
@ -69,13 +88,44 @@ minetest.register_node("testnodes:nodebox_connected", {
paramtype = "light", paramtype = "light",
connects_to = {"group:connected_nodebox"}, connects_to = {"group:connected_nodebox"},
connect_sides = {"front", "back", "left", "right"}, connect_sides = {"front", "back", "left", "right"},
node_box = { node_box = nodebox_wall,
type = "connected", })
fixed = {-0.125, -0.500, -0.125, 0.125, 0.500, 0.125},
connect_front = {-0.125, -0.500, -0.500, 0.125, 0.400, -0.125}, minetest.register_node("testnodes:nodebox_connected_facedir", {
connect_back = {-0.125, -0.500, 0.125, 0.125, 0.400, 0.500}, description = S("Facedir Connected Nodebox Test Node"),
connect_left = {-0.500, -0.500, -0.125, -0.125, 0.400, 0.125}, tiles = {
connect_right = {0.125, -0.500, -0.125, 0.500, 0.400, 0.125}, "testnodes_1.png",
}, "testnodes_2.png",
"testnodes_3.png",
"testnodes_4.png",
"testnodes_5.png",
"testnodes_6.png",
},
groups = {connected_nodebox=1, dig_immediate=3},
drawtype = "nodebox",
paramtype = "light",
paramtype2 = "facedir",
connects_to = {"group:connected_nodebox"},
connect_sides = {"front", "back", "left", "right"},
node_box = nodebox_wall_thick,
})
minetest.register_node("testnodes:nodebox_connected_4dir", {
description = S("4Dir Connected Nodebox Test Node"),
tiles = {
"testnodes_1.png^[colorize:#FFFF00:127",
"testnodes_2.png^[colorize:#FFFF00:127",
"testnodes_3.png^[colorize:#FFFF00:127",
"testnodes_4.png^[colorize:#FFFF00:127",
"testnodes_5.png^[colorize:#FFFF00:127",
"testnodes_6.png^[colorize:#FFFF00:127",
},
groups = {connected_nodebox=1, dig_immediate=3},
drawtype = "nodebox",
paramtype = "light",
paramtype2 = "4dir",
connects_to = {"group:connected_nodebox"},
connect_sides = {"front", "back", "left", "right"},
node_box = nodebox_wall_thick,
}) })

View File

@ -17,6 +17,21 @@ minetest.register_node("testnodes:facedir", {
groups = { dig_immediate = 3 }, groups = { dig_immediate = 3 },
}) })
minetest.register_node("testnodes:4dir", {
description = S("4dir Test Node"),
paramtype2 = "4dir",
tiles = {
"testnodes_1.png^[colorize:#FFFF00:127",
"testnodes_2.png^[colorize:#FFFF00:127",
"testnodes_3.png^[colorize:#FFFF00:127",
"testnodes_4.png^[colorize:#FFFF00:127",
"testnodes_5.png^[colorize:#FFFF00:127",
"testnodes_6.png^[colorize:#FFFF00:127",
},
groups = { dig_immediate = 3 },
})
minetest.register_node("testnodes:facedir_nodebox", { minetest.register_node("testnodes:facedir_nodebox", {
description = S("Facedir Nodebox Test Node"), description = S("Facedir Nodebox Test Node"),
tiles = { tiles = {
@ -38,6 +53,27 @@ minetest.register_node("testnodes:facedir_nodebox", {
groups = {dig_immediate=3}, groups = {dig_immediate=3},
}) })
minetest.register_node("testnodes:4dir_nodebox", {
description = S("4dir Nodebox Test Node"),
tiles = {
"testnodes_1.png^[colorize:#ffff00:127",
"testnodes_2.png^[colorize:#ffff00:127",
"testnodes_3.png^[colorize:#ffff00:127",
"testnodes_4.png^[colorize:#ffff00:127",
"testnodes_5.png^[colorize:#ffff00:127",
"testnodes_6.png^[colorize:#ffff00:127",
},
drawtype = "nodebox",
paramtype = "light",
paramtype2 = "4dir",
node_box = {
type = "fixed",
fixed = {-0.5, -0.5, -0.5, 0.2, 0.2, 0.2},
},
groups = {dig_immediate=3},
})
minetest.register_node("testnodes:wallmounted", { minetest.register_node("testnodes:wallmounted", {
description = S("Wallmounted Test Node"), description = S("Wallmounted Test Node"),
paramtype2 = "wallmounted", paramtype2 = "wallmounted",
@ -125,6 +161,44 @@ minetest.register_node("testnodes:colorfacedir_nodebox", {
groups = {dig_immediate=3}, groups = {dig_immediate=3},
}) })
minetest.register_node("testnodes:color4dir", {
description = S("Color 4dir Test Node"),
paramtype2 = "color4dir",
palette = "testnodes_palette_4dir.png",
tiles = {
"testnodes_1g.png",
"testnodes_2g.png",
"testnodes_3g.png",
"testnodes_4g.png",
"testnodes_5g.png",
"testnodes_6g.png",
},
groups = { dig_immediate = 3 },
})
minetest.register_node("testnodes:color4dir_nodebox", {
description = S("Color 4dir Nodebox Test Node"),
tiles = {
"testnodes_1g.png",
"testnodes_2g.png",
"testnodes_3g.png",
"testnodes_4g.png",
"testnodes_5g.png",
"testnodes_6g.png",
},
drawtype = "nodebox",
paramtype = "light",
paramtype2 = "color4dir",
palette = "testnodes_palette_4dir.png",
node_box = {
type = "fixed",
fixed = {-0.5, -0.5, -0.5, 0.2, 0.2, 0.2},
},
groups = {dig_immediate=3},
})
minetest.register_node("testnodes:colorwallmounted", { minetest.register_node("testnodes:colorwallmounted", {
description = S("Color Wallmounted Test Node"), description = S("Color Wallmounted Test Node"),
paramtype2 = "colorwallmounted", paramtype2 = "colorwallmounted",

Binary file not shown.

After

Width:  |  Height:  |  Size: 197 B

View File

@ -1510,7 +1510,9 @@ void MapblockMeshGenerator::drawMeshNode()
int degrotate = 0; int degrotate = 0;
if (f->param_type_2 == CPT2_FACEDIR || if (f->param_type_2 == CPT2_FACEDIR ||
f->param_type_2 == CPT2_COLORED_FACEDIR) { f->param_type_2 == CPT2_COLORED_FACEDIR ||
f->param_type_2 == CPT2_4DIR ||
f->param_type_2 == CPT2_COLORED_4DIR) {
facedir = n.getFaceDir(nodedef); facedir = n.getFaceDir(nodedef);
} else if (f->param_type_2 == CPT2_WALLMOUNTED || } else if (f->param_type_2 == CPT2_WALLMOUNTED ||
f->param_type_2 == CPT2_COLORED_WALLMOUNTED) { f->param_type_2 == CPT2_COLORED_WALLMOUNTED) {

View File

@ -3462,7 +3462,9 @@ bool Game::nodePlacement(const ItemDefinition &selected_def,
param2 = dir.Z < 0 ? 5 : 4; param2 = dir.Z < 0 ? 5 : 4;
} }
} else if (predicted_f.param_type_2 == CPT2_FACEDIR || } else if (predicted_f.param_type_2 == CPT2_FACEDIR ||
predicted_f.param_type_2 == CPT2_COLORED_FACEDIR) { predicted_f.param_type_2 == CPT2_COLORED_FACEDIR ||
predicted_f.param_type_2 == CPT2_4DIR ||
predicted_f.param_type_2 == CPT2_COLORED_4DIR) {
v3s16 dir = nodepos - floatToInt(client->getEnv().getLocalPlayer()->getPosition(), BS); v3s16 dir = nodepos - floatToInt(client->getEnv().getLocalPlayer()->getPosition(), BS);
if (abs(dir.X) > abs(dir.Z)) { if (abs(dir.X) > abs(dir.Z)) {
@ -3501,6 +3503,7 @@ bool Game::nodePlacement(const ItemDefinition &selected_def,
// Apply color // Apply color
if (!place_param2 && (predicted_f.param_type_2 == CPT2_COLOR if (!place_param2 && (predicted_f.param_type_2 == CPT2_COLOR
|| predicted_f.param_type_2 == CPT2_COLORED_FACEDIR || predicted_f.param_type_2 == CPT2_COLORED_FACEDIR
|| predicted_f.param_type_2 == CPT2_COLORED_4DIR
|| predicted_f.param_type_2 == CPT2_COLORED_WALLMOUNTED)) { || predicted_f.param_type_2 == CPT2_COLORED_WALLMOUNTED)) {
const auto &indexstr = selected_item.metadata. const auto &indexstr = selected_item.metadata.
getString("palette_index", 0); getString("palette_index", 0);
@ -3514,6 +3517,9 @@ bool Game::nodePlacement(const ItemDefinition &selected_def,
} else if (predicted_f.param_type_2 == CPT2_COLORED_FACEDIR) { } else if (predicted_f.param_type_2 == CPT2_COLORED_FACEDIR) {
// param2 = pure palette index + other // param2 = pure palette index + other
param2 = (index & 0xe0) | (param2 & 0x1f); param2 = (index & 0xe0) | (param2 & 0x1f);
} else if (predicted_f.param_type_2 == CPT2_COLORED_4DIR) {
// param2 = pure palette index + other
param2 = (index & 0xfc) | (param2 & 0x03);
} }
} }
} }

View File

@ -149,6 +149,9 @@ u8 MapNode::getFaceDir(const NodeDefManager *nodemgr,
if (f.param_type_2 == CPT2_FACEDIR || if (f.param_type_2 == CPT2_FACEDIR ||
f.param_type_2 == CPT2_COLORED_FACEDIR) f.param_type_2 == CPT2_COLORED_FACEDIR)
return (getParam2() & 0x1F) % 24; return (getParam2() & 0x1F) % 24;
if (f.param_type_2 == CPT2_4DIR ||
f.param_type_2 == CPT2_COLORED_4DIR)
return getParam2() & 0x03;
if (allow_wallmounted && (f.param_type_2 == CPT2_WALLMOUNTED || if (allow_wallmounted && (f.param_type_2 == CPT2_WALLMOUNTED ||
f.param_type_2 == CPT2_COLORED_WALLMOUNTED)) f.param_type_2 == CPT2_COLORED_WALLMOUNTED))
return wallmounted_to_facedir[getParam2() & 0x07]; return wallmounted_to_facedir[getParam2() & 0x07];
@ -196,7 +199,8 @@ void MapNode::rotateAlongYAxis(const NodeDefManager *nodemgr, Rotation rot)
{ {
ContentParamType2 cpt2 = nodemgr->get(*this).param_type_2; ContentParamType2 cpt2 = nodemgr->get(*this).param_type_2;
if (cpt2 == CPT2_FACEDIR || cpt2 == CPT2_COLORED_FACEDIR) { if (cpt2 == CPT2_FACEDIR || cpt2 == CPT2_COLORED_FACEDIR ||
cpt2 == CPT2_4DIR || cpt2 == CPT2_COLORED_4DIR) {
static const u8 rotate_facedir[24 * 4] = { static const u8 rotate_facedir[24 * 4] = {
// Table value = rotated facedir // Table value = rotated facedir
// Columns: 0, 90, 180, 270 degrees rotation around vertical axis // Columns: 0, 90, 180, 270 degrees rotation around vertical axis
@ -232,10 +236,17 @@ void MapNode::rotateAlongYAxis(const NodeDefManager *nodemgr, Rotation rot)
22, 21, 20, 23, 22, 21, 20, 23,
23, 22, 21, 20 23, 22, 21, 20
}; };
if (cpt2 == CPT2_FACEDIR || cpt2 == CPT2_COLORED_FACEDIR) {
u8 facedir = (param2 & 31) % 24; u8 facedir = (param2 & 31) % 24;
u8 index = facedir * 4 + rot; u8 index = facedir * 4 + rot;
param2 &= ~31; param2 &= ~31;
param2 |= rotate_facedir[index]; param2 |= rotate_facedir[index];
} else if (cpt2 == CPT2_4DIR || cpt2 == CPT2_COLORED_4DIR) {
u8 fourdir = param2 & 3;
u8 index = fourdir + rot;
param2 &= ~3;
param2 |= rotate_facedir[index];
}
} else if (cpt2 == CPT2_WALLMOUNTED || } else if (cpt2 == CPT2_WALLMOUNTED ||
cpt2 == CPT2_COLORED_WALLMOUNTED) { cpt2 == CPT2_COLORED_WALLMOUNTED) {
u8 wmountface = (param2 & 7); u8 wmountface = (param2 & 7);

View File

@ -992,6 +992,7 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
if (param_type_2 == CPT2_COLOR || if (param_type_2 == CPT2_COLOR ||
param_type_2 == CPT2_COLORED_FACEDIR || param_type_2 == CPT2_COLORED_FACEDIR ||
param_type_2 == CPT2_COLORED_4DIR ||
param_type_2 == CPT2_COLORED_WALLMOUNTED || param_type_2 == CPT2_COLORED_WALLMOUNTED ||
param_type_2 == CPT2_COLORED_DEGROTATE) param_type_2 == CPT2_COLORED_DEGROTATE)
palette = tsrc->getPalette(palette_name); palette = tsrc->getPalette(palette_name);
@ -1018,6 +1019,15 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
recalculateBoundingBox(mesh_ptr[j]); recalculateBoundingBox(mesh_ptr[j]);
meshmanip->recalculateNormals(mesh_ptr[j], true, false); meshmanip->recalculateNormals(mesh_ptr[j], true, false);
} }
} else if (tsettings.enable_mesh_cache && mesh_ptr[0] &&
(param_type_2 == CPT2_4DIR
|| param_type_2 == CPT2_COLORED_4DIR)) {
for (u16 j = 1; j < 4; j++) {
mesh_ptr[j] = cloneMesh(mesh_ptr[0]);
rotateMeshBy6dFacedir(mesh_ptr[j], j);
recalculateBoundingBox(mesh_ptr[j]);
meshmanip->recalculateNormals(mesh_ptr[j], true, false);
}
} else if (tsettings.enable_mesh_cache && mesh_ptr[0] } else if (tsettings.enable_mesh_cache && mesh_ptr[0]
&& (param_type_2 == CPT2_WALLMOUNTED || && (param_type_2 == CPT2_WALLMOUNTED ||
param_type_2 == CPT2_COLORED_WALLMOUNTED)) { param_type_2 == CPT2_COLORED_WALLMOUNTED)) {
@ -1241,7 +1251,9 @@ void getNodeBoxUnion(const NodeBox &nodebox, const ContentFeatures &features,
half_processed.MaxEdge.Y = +BS / 2; half_processed.MaxEdge.Y = +BS / 2;
} }
if (features.param_type_2 == CPT2_FACEDIR || if (features.param_type_2 == CPT2_FACEDIR ||
features.param_type_2 == CPT2_COLORED_FACEDIR) { features.param_type_2 == CPT2_COLORED_FACEDIR ||
features.param_type_2 == CPT2_4DIR ||
features.param_type_2 == CPT2_COLORED_4DIR) {
// Get maximal coordinate // Get maximal coordinate
f32 coords[] = { f32 coords[] = {
fabsf(half_processed.MinEdge.X), fabsf(half_processed.MinEdge.X),
@ -1705,7 +1717,9 @@ bool NodeDefManager::nodeboxConnects(MapNode from, MapNode to,
// does to node declare usable faces? // does to node declare usable faces?
if (f2.connect_sides > 0) { if (f2.connect_sides > 0) {
if ((f2.param_type_2 == CPT2_FACEDIR || if ((f2.param_type_2 == CPT2_FACEDIR ||
f2.param_type_2 == CPT2_COLORED_FACEDIR) f2.param_type_2 == CPT2_COLORED_FACEDIR ||
f2.param_type_2 == CPT2_4DIR ||
f2.param_type_2 == CPT2_COLORED_4DIR)
&& (connect_face >= 4)) { && (connect_face >= 4)) {
static const u8 rot[33 * 4] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, static const u8 rot[33 * 4] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 4, 32, 16, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 32, 16, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@ -1719,8 +1733,15 @@ bool NodeDefManager::nodeboxConnects(MapNode from, MapNode to,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 32, 16, 8, 4 // 32 - left 0, 0, 0, 0, 0, 0, 32, 16, 8, 4 // 32 - left
}; };
if (f2.param_type_2 == CPT2_FACEDIR ||
f2.param_type_2 == CPT2_COLORED_FACEDIR) {
return (f2.connect_sides return (f2.connect_sides
& rot[(connect_face * 4) + (to.param2 & 0x1F)]); & rot[(connect_face * 4) + (to.param2 & 0x1F)]);
} else if (f2.param_type_2 == CPT2_4DIR ||
f2.param_type_2 == CPT2_COLORED_4DIR) {
return (f2.connect_sides
& rot[(connect_face * 4) + (to.param2 & 0x03)]);
}
} }
return (f2.connect_sides & connect_face); return (f2.connect_sides & connect_face);
} }

View File

@ -58,7 +58,7 @@ enum ContentParamType2
CPT2_FULL, CPT2_FULL,
// Flowing liquid properties // Flowing liquid properties
CPT2_FLOWINGLIQUID, CPT2_FLOWINGLIQUID,
// Direction for chests and furnaces and such // Direction for chests and furnaces and such (with axis rotation)
CPT2_FACEDIR, CPT2_FACEDIR,
// Direction for signs, torches and such // Direction for signs, torches and such
CPT2_WALLMOUNTED, CPT2_WALLMOUNTED,
@ -78,6 +78,10 @@ enum ContentParamType2
CPT2_GLASSLIKE_LIQUID_LEVEL, CPT2_GLASSLIKE_LIQUID_LEVEL,
// 3 bits of palette index, then degrotate // 3 bits of palette index, then degrotate
CPT2_COLORED_DEGROTATE, CPT2_COLORED_DEGROTATE,
// Simplified direction for chests and furnaces and such (4 directions)
CPT2_4DIR,
// 6 bits of palette index, then 4dir
CPT2_COLORED_4DIR,
}; };
enum LiquidType enum LiquidType

View File

@ -673,7 +673,8 @@ void read_content_features(lua_State *L, ContentFeatures &f, int index)
!(f.param_type_2 == CPT2_COLOR || !(f.param_type_2 == CPT2_COLOR ||
f.param_type_2 == CPT2_COLORED_FACEDIR || f.param_type_2 == CPT2_COLORED_FACEDIR ||
f.param_type_2 == CPT2_COLORED_WALLMOUNTED || f.param_type_2 == CPT2_COLORED_WALLMOUNTED ||
f.param_type_2 == CPT2_COLORED_DEGROTATE)) f.param_type_2 == CPT2_COLORED_DEGROTATE ||
f.param_type_2 == CPT2_COLORED_4DIR))
warningstream << "Node " << f.name.c_str() warningstream << "Node " << f.name.c_str()
<< " has a palette, but not a suitable paramtype2." << std::endl; << " has a palette, but not a suitable paramtype2." << std::endl;

View File

@ -66,6 +66,8 @@ struct EnumString ScriptApiNode::es_ContentParamType2[] =
{CPT2_COLORED_WALLMOUNTED, "colorwallmounted"}, {CPT2_COLORED_WALLMOUNTED, "colorwallmounted"},
{CPT2_GLASSLIKE_LIQUID_LEVEL, "glasslikeliquidlevel"}, {CPT2_GLASSLIKE_LIQUID_LEVEL, "glasslikeliquidlevel"},
{CPT2_COLORED_DEGROTATE, "colordegrotate"}, {CPT2_COLORED_DEGROTATE, "colordegrotate"},
{CPT2_4DIR, "4dir"},
{CPT2_COLORED_4DIR, "color4dir"},
{0, NULL}, {0, NULL},
}; };