]> git.lizzy.rs Git - minetest.git/commitdiff
Add paramtype2s for 4 horizontal rotations and 64 colors (#11431)
authorWuzzy <Wuzzy@disroot.org>
Fri, 16 Sep 2022 11:18:55 +0000 (13:18 +0200)
committerGitHub <noreply@github.com>
Fri, 16 Sep 2022 11:18:55 +0000 (13:18 +0200)
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.

15 files changed:
builtin/game/falling.lua
builtin/game/item.lua
builtin/game/item_s.lua
doc/lua_api.txt
games/devtest/mods/testnodes/meshes.lua
games/devtest/mods/testnodes/nodeboxes.lua
games/devtest/mods/testnodes/param2.lua
games/devtest/mods/testnodes/textures/testnodes_palette_4dir.png [new file with mode: 0644]
src/client/content_mapblock.cpp
src/client/game.cpp
src/mapnode.cpp
src/nodedef.cpp
src/nodedef.h
src/script/common/c_content.cpp
src/script/cpp_api/s_node.cpp

index d5727f2a78d618900ef7a98a8470292b08aff602..01a7d60b88cbc040f39bcac70a0f859d2c709437 100644 (file)
@@ -161,7 +161,16 @@ core.register_entity(":__builtin:falling_node", {
                                local fdir = node.param2 % 32 % 24
                                -- Get rotation from a precalculated lookup table
                                local euler = facedir_to_euler[fdir + 1]
-                               self.object:set_rotation(euler)
+                               if euler then
+                                       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
                                        (def.paramtype2 == "wallmounted" or def.paramtype2 == "colorwallmounted" or def.drawtype == "signlike")) then
                                local rot = node.param2 % 8
index 00601c68cd6e104bab9ff13d130cf0d186446256..af3fcb64512b8d6f15d4ac85372f239fa871af57 100644 (file)
@@ -205,7 +205,9 @@ function core.item_place_node(itemstack, placer, pointed_thing, param2,
                newnode.param2 = core.dir_to_wallmounted(dir)
        -- Calculate the direction for furnaces and chests and stuff
        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()
                if placer_pos then
                        local dir = vector.subtract(above, placer_pos)
@@ -225,6 +227,8 @@ function core.item_place_node(itemstack, placer, pointed_thing, param2,
                        color_divisor = 8
                elseif def.paramtype2 == "colorfacedir" then
                        color_divisor = 32
+               elseif def.paramtype2 == "color4dir" then
+                       color_divisor = 4
                elseif def.paramtype2 == "colordegrotate" then
                        color_divisor = 32
                end
index a51cd0a1ce73a3f6c12ed51b0e82848c9d0bb00a..ac1090d63d481040206d95a5f7a7df42ea30f50b 100644 (file)
@@ -92,6 +92,26 @@ function core.facedir_to_dir(facedir)
        return facedir_to_dir[facedir_to_dir_map[facedir % 32]]
 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)
        if math.abs(dir.y) > math.max(math.abs(dir.x), math.abs(dir.z)) then
                if dir.y < 0 then
@@ -137,7 +157,8 @@ end
 
 function core.is_colored_paramtype(ptype)
        return (ptype == "color") or (ptype == "colorfacedir") or
-               (ptype == "colorwallmounted") or (ptype == "colordegrotate")
+               (ptype == "color4dir") or (ptype == "colorwallmounted") or
+               (ptype == "colordegrotate")
 end
 
 function core.strip_param2_color(param2, paramtype2)
@@ -146,6 +167,8 @@ function core.strip_param2_color(param2, paramtype2)
        end
        if paramtype2 == "colorfacedir" then
                param2 = math.floor(param2 / 32) * 32
+       elseif paramtype2 == "color4dir" then
+               param2 = math.floor(param2 / 4) * 4
        elseif paramtype2 == "colorwallmounted" then
                param2 = math.floor(param2 / 8) * 8
        elseif paramtype2 == "colordegrotate" then
index abdad7f2c1bab9676594cae4fe2d976b42ae1b2b..5bac6d165981fadaeb9d43d220fa0d0707d65fec 100644 (file)
@@ -758,6 +758,17 @@ appropriate `paramtype2`:
       first (= 0 + 1) pixel will be picked from the palette.
     * `param2 = 35` is 1 * 32 + 3, so the rotation is 3 and the
       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 the node's paramtype2).
@@ -1058,18 +1069,36 @@ The function of `param2` is determined by `paramtype2` in node definition.
     * Supported drawtypes: "torchlike", "signlike", "plantlike",
       "plantlike_rooted", "normal", "nodebox", "mesh"
     * 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()`
     * Values range 0 - 5
     * The value denotes at which direction the node is "mounted":
       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"`
     * Supported drawtypes: "normal", "nodebox", "mesh"
-    * The rotation of the node is stored in `param2`. Furnaces and chests are
-      rotated this way. Can be made by using `minetest.dir_to_facedir()`.
+    * The rotation of the node is stored in `param2`.
+    * 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
     * facedir / 4 = axis direction:
       0 = y+,   1 = z+,   2 = z-,   3 = x+,   4 = x-,   5 = y-
     * 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"`
     * Only valid for "nodebox" with 'type = "leveled"', and "plantlike_rooted".
         * Leveled nodebox:
@@ -1112,6 +1141,10 @@ The function of `param2` is determined by `paramtype2` in node definition.
     * Same as `facedir`, but with colors.
     * The first three bits of `param2` tells which color is picked from the
       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"`
     * Same as `wallmounted`, but with colors.
     * The first five bits of `param2` tells which color is picked from the
@@ -5776,6 +5809,12 @@ Item handling
 * `minetest.facedir_to_dir(facedir)`
     * Convert a facedir back into a vector aimed directly out the "back" of a
       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)`
     * Convert a vector to a wallmounted value, used for
       `paramtype2="wallmounted"`.
@@ -5788,7 +5827,7 @@ Item handling
     * Convert yaw (angle) to a vector
 * `minetest.is_colored_paramtype(ptype)`
     * 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)`
     * Removes everything but the color information from the
       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
         -- the item stack metadata.
         -- 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 the item is colorized with. The palette overrides this.
index 900abc1801aaee1e4b4bf2fb816cba6d06112759..76c2c0027d4e1ada0784df169ada2ac6b20c5646 100644 (file)
@@ -60,6 +60,31 @@ minetest.register_node("testnodes:mesh_colorfacedir", {
        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
 minetest.register_node("testnodes:mesh_wallmounted", {
        description = S("Wallmounted Mesh Test Node"),
index 7e966fdce1f49fb151a6247366b07b5c74f7a328..e3c03b0733654146e6a5784d1dd25389618318d6 100644 (file)
@@ -60,6 +60,25 @@ minetest.register_node("testnodes:nodebox_leveled", {
        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
 minetest.register_node("testnodes:nodebox_connected", {
        description = S("Connected Nodebox Test Node"),
@@ -69,13 +88,44 @@ minetest.register_node("testnodes:nodebox_connected", {
        paramtype = "light",
        connects_to = {"group:connected_nodebox"},
        connect_sides = {"front", "back", "left", "right"},
-       node_box = {
-               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},
+       node_box = nodebox_wall,
+})
+
+minetest.register_node("testnodes:nodebox_connected_facedir", {
+       description = S("Facedir Connected Nodebox Test Node"),
+       tiles = {
+               "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,
 })
 
index 5d64376fa83fe6d9c72a5301e20f1e70b388404a..908b54bfc58150e1b7aef80cab80e85baf8f1fae 100644 (file)
@@ -17,6 +17,21 @@ minetest.register_node("testnodes:facedir", {
        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", {
        description = S("Facedir Nodebox Test Node"),
        tiles = {
@@ -38,6 +53,27 @@ minetest.register_node("testnodes:facedir_nodebox", {
        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", {
        description = S("Wallmounted Test Node"),
        paramtype2 = "wallmounted",
@@ -125,6 +161,44 @@ minetest.register_node("testnodes:colorfacedir_nodebox", {
        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", {
        description = S("Color Wallmounted Test Node"),
        paramtype2 = "colorwallmounted",
diff --git a/games/devtest/mods/testnodes/textures/testnodes_palette_4dir.png b/games/devtest/mods/testnodes/textures/testnodes_palette_4dir.png
new file mode 100644 (file)
index 0000000..bf5ebf2
Binary files /dev/null and b/games/devtest/mods/testnodes/textures/testnodes_palette_4dir.png differ
index 0bac5e827f40932b627b55dbe40a23edf44bfb0d..7fd5aefb1359248dac613335f47e239fad94fef8 100644 (file)
@@ -1510,7 +1510,9 @@ void MapblockMeshGenerator::drawMeshNode()
        int degrotate = 0;
 
        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);
        } else if (f->param_type_2 == CPT2_WALLMOUNTED ||
                        f->param_type_2 == CPT2_COLORED_WALLMOUNTED) {
index 6a4bff61afa16c3e73883d197b83535b2fbe6065..b4926d9bf6a80b1d3cd99b36f677f22e6ecba60f 100644 (file)
@@ -3462,7 +3462,9 @@ bool Game::nodePlacement(const ItemDefinition &selected_def,
                        param2 = dir.Z < 0 ? 5 : 4;
                }
        } 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);
 
                if (abs(dir.X) > abs(dir.Z)) {
@@ -3501,6 +3503,7 @@ bool Game::nodePlacement(const ItemDefinition &selected_def,
        // Apply 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_4DIR
                        || predicted_f.param_type_2 == CPT2_COLORED_WALLMOUNTED)) {
                const auto &indexstr = selected_item.metadata.
                        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) {
                                // param2 = pure palette index + other
                                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);
                        }
                }
        }
index 42f020e7106b651eeca3ad4e4d3f7630cac56429..1685dc11cfb9fa7a8266222ebb115967b4a0b663 100644 (file)
@@ -149,6 +149,9 @@ u8 MapNode::getFaceDir(const NodeDefManager *nodemgr,
        if (f.param_type_2 == CPT2_FACEDIR ||
                        f.param_type_2 == CPT2_COLORED_FACEDIR)
                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 ||
                        f.param_type_2 == CPT2_COLORED_WALLMOUNTED))
                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;
 
-       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] = {
                        // Table value = rotated facedir
                        // 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,
                        23, 22, 21, 20
                };
-               u8 facedir = (param2 & 31) % 24;
-               u8 index = facedir * 4 + rot;
-               param2 &= ~31;
-               param2 |= rotate_facedir[index];
+               if (cpt2 == CPT2_FACEDIR || cpt2 == CPT2_COLORED_FACEDIR) {
+                       u8 facedir = (param2 & 31) % 24;
+                       u8 index = facedir * 4 + rot;
+                       param2 &= ~31;
+                       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 ||
                        cpt2 == CPT2_COLORED_WALLMOUNTED) {
                u8 wmountface = (param2 & 7);
index e2a222ed35d020939c9ad945a3d7b6117ad2caa5..f42231736145325f63640f3d2da4b645684c4a9c 100644 (file)
@@ -992,6 +992,7 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
 
        if (param_type_2 == CPT2_COLOR ||
                        param_type_2 == CPT2_COLORED_FACEDIR ||
+                       param_type_2 == CPT2_COLORED_4DIR ||
                        param_type_2 == CPT2_COLORED_WALLMOUNTED ||
                        param_type_2 == CPT2_COLORED_DEGROTATE)
                palette = tsrc->getPalette(palette_name);
@@ -1018,6 +1019,15 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
                        recalculateBoundingBox(mesh_ptr[j]);
                        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]
                        && (param_type_2 == CPT2_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;
                        }
                        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
                                f32 coords[] = {
                                        fabsf(half_processed.MinEdge.X),
@@ -1705,7 +1717,9 @@ bool NodeDefManager::nodeboxConnects(MapNode from, MapNode to,
        // does to node declare usable faces?
        if (f2.connect_sides > 0) {
                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)) {
                        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,
@@ -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, 32, 16, 8, 4 // 32 - left
                                };
-                       return (f2.connect_sides
-                               & rot[(connect_face * 4) + (to.param2 & 0x1F)]);
+                       if (f2.param_type_2 == CPT2_FACEDIR ||
+                                       f2.param_type_2 == CPT2_COLORED_FACEDIR) {
+                               return (f2.connect_sides
+                                       & 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);
        }
index f4367cba9ba90c35ca31651ced2e91e955650ebc..b63748e443efea9029b98c22607ef8fa1f6dd53e 100644 (file)
@@ -58,7 +58,7 @@ enum ContentParamType2
        CPT2_FULL,
        // Flowing liquid properties
        CPT2_FLOWINGLIQUID,
-       // Direction for chests and furnaces and such
+       // Direction for chests and furnaces and such (with axis rotation)
        CPT2_FACEDIR,
        // Direction for signs, torches and such
        CPT2_WALLMOUNTED,
@@ -78,6 +78,10 @@ enum ContentParamType2
        CPT2_GLASSLIKE_LIQUID_LEVEL,
        // 3 bits of palette index, then 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
index f15d41f96671dda6dafa0a72e02e871bc97631e2..da54edb964bce678411fed6a487641152807ab1e 100644 (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_COLORED_FACEDIR ||
                        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()
                        << " has a palette, but not a suitable paramtype2." << std::endl;
 
index 029cb6308c4386cf619823f4481066e71225cda7..a9638e2393090f6c5458b468f6ba174052a50d3c 100644 (file)
@@ -66,6 +66,8 @@ struct EnumString ScriptApiNode::es_ContentParamType2[] =
                {CPT2_COLORED_WALLMOUNTED, "colorwallmounted"},
                {CPT2_GLASSLIKE_LIQUID_LEVEL, "glasslikeliquidlevel"},
                {CPT2_COLORED_DEGROTATE, "colordegrotate"},
+               {CPT2_4DIR, "4dir"},
+               {CPT2_COLORED_4DIR, "color4dir"},
                {0, NULL},
        };