aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/lua_api.txt16
-rw-r--r--src/content_mapblock.cpp152
-rw-r--r--src/network/networkprotocol.h4
-rw-r--r--src/nodedef.cpp5
-rw-r--r--src/nodedef.h2
-rw-r--r--src/script/cpp_api/s_node.cpp1
6 files changed, 167 insertions, 13 deletions
diff --git a/doc/lua_api.txt b/doc/lua_api.txt
index 38f19aadc..440edd963 100644
--- a/doc/lua_api.txt
+++ b/doc/lua_api.txt
@@ -578,6 +578,22 @@ node definition:
^ The rotation of this node is stored in param2. Plants are rotated this way.
Values range 0 - 179. The value stored in param2 is multiplied by two to
get the actual rotation of the node.
+ paramtype2 == "meshoptions"
+ ^ Only valid for "plantlike". The value of param2 becomes a bitfield which can
+ be used to change how the client draws plantlike nodes. Bits 0, 1 and 2 form
+ a mesh selector. Currently the following meshes are choosable:
+ 0 = a "x" shaped plant (ordinary plant)
+ 1 = a "+" shaped plant (just rotated 45 degrees)
+ 2 = a "*" shaped plant with 3 faces instead of 2
+ 3 = a "#" shaped plant with 4 faces instead of 2
+ 4 = a "#" shaped plant with 4 faces that lean outwards
+ 5-7 are unused and reserved for future meshes.
+ Bits 3 through 7 are optional flags that can be combined and give these
+ effects:
+ bit 3 (0x08) - Makes the plant slightly vary placement horizontally
+ bit 4 (0x10) - Makes the plant mesh 1.4x larger
+ bit 5 (0x20) - Moves each face randomly a small bit down (1/8 max)
+ bits 6-7 are reserved for future use.
collision_box = {
type = "fixed",
fixed = {
diff --git a/src/content_mapblock.cpp b/src/content_mapblock.cpp
index 6a83bd8f3..b86b97822 100644
--- a/src/content_mapblock.cpp
+++ b/src/content_mapblock.cpp
@@ -28,6 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <IMeshManipulator.h>
#include "gamedef.h"
#include "log.h"
+#include "noise.h"
// Create a cuboid.
@@ -1104,6 +1105,8 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
break;}
case NDT_PLANTLIKE:
{
+ PseudoRandom rng(x<<8 | z | y<<16);
+
TileSpec tile = getNodeTileN(n, p, 0, data);
tile.material_flags |= MATERIAL_FLAG_CRACK_OVERLAY;
@@ -1111,9 +1114,18 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
video::SColor c = MapBlock_LightColor(255, l, f.light_source);
float s = BS / 2 * f.visual_scale;
+ // add sqrt(2) visual scale
+ if ((f.param_type_2 == CPT2_MESHOPTIONS) && ((n.param2 & 0x10) != 0))
+ s *= 1.41421;
+
+ float random_offset_X = .0;
+ float random_offset_Z = .0;
+ if ((f.param_type_2 == CPT2_MESHOPTIONS) && ((n.param2 & 0x8) != 0)) {
+ random_offset_X = BS * ((rng.next() % 16 / 16.0) * 0.29 - 0.145);
+ random_offset_Z = BS * ((rng.next() % 16 / 16.0) * 0.29 - 0.145);
+ }
- for (int j = 0; j < 2; j++)
- {
+ for (int j = 0; j < 4; j++) {
video::S3DVertex vertices[4] =
{
video::S3DVertex(-s,-BS/2, 0, 0,0,0, c, 0,1),
@@ -1121,28 +1133,146 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
video::S3DVertex( s,-BS/2 + s*2,0, 0,0,0, c, 1,0),
video::S3DVertex(-s,-BS/2 + s*2,0, 0,0,0, c, 0,0),
};
+
float rotate_degree = 0;
+ u8 p2mesh = 0;
if (f.param_type_2 == CPT2_DEGROTATE)
rotate_degree = n.param2 * 2;
-
- if (j == 0) {
- for(u16 i = 0; i < 4; i++)
- vertices[i].Pos.rotateXZBy(46 + rotate_degree);
- } else if (j == 1) {
- for(u16 i = 0; i < 4; i++)
- vertices[i].Pos.rotateXZBy(-44 + rotate_degree);
+ else if (f.param_type_2 != CPT2_MESHOPTIONS) {
+ if (j == 0) {
+ for (u16 i = 0; i < 4; i++)
+ vertices[i].Pos.rotateXZBy(46 + rotate_degree);
+ } else if (j == 1) {
+ for (u16 i = 0; i < 4; i++)
+ vertices[i].Pos.rotateXZBy(-44 + rotate_degree);
+ }
+ } else {
+ p2mesh = n.param2 & 0x7;
+ switch (p2mesh) {
+ case 0:
+ // x
+ if (j == 0) {
+ for (u16 i = 0; i < 4; i++)
+ vertices[i].Pos.rotateXZBy(46);
+ } else if (j == 1) {
+ for (u16 i = 0; i < 4; i++)
+ vertices[i].Pos.rotateXZBy(-44);
+ }
+ break;
+ case 1:
+ // +
+ if (j == 0) {
+ for (u16 i = 0; i < 4; i++)
+ vertices[i].Pos.rotateXZBy(91);
+ } else if (j == 1) {
+ for (u16 i = 0; i < 4; i++)
+ vertices[i].Pos.rotateXZBy(1);
+ }
+ break;
+ case 2:
+ // *
+ if (j == 0) {
+ for (u16 i = 0; i < 4; i++)
+ vertices[i].Pos.rotateXZBy(121);
+ } else if (j == 1) {
+ for (u16 i = 0; i < 4; i++)
+ vertices[i].Pos.rotateXZBy(241);
+ } else { // (j == 2)
+ for (u16 i = 0; i < 4; i++)
+ vertices[i].Pos.rotateXZBy(1);
+ }
+ break;
+ case 3:
+ // #
+ switch (j) {
+ case 0:
+ for (u16 i = 0; i < 4; i++) {
+ vertices[i].Pos.rotateXZBy(1);
+ vertices[i].Pos.Z += BS / 4;
+ }
+ break;
+ case 1:
+ for (u16 i = 0; i < 4; i++) {
+ vertices[i].Pos.rotateXZBy(91);
+ vertices[i].Pos.X += BS / 4;
+ }
+ break;
+ case 2:
+ for (u16 i = 0; i < 4; i++) {
+ vertices[i].Pos.rotateXZBy(181);
+ vertices[i].Pos.Z -= BS / 4;
+ }
+ break;
+ case 3:
+ for (u16 i = 0; i < 4; i++) {
+ vertices[i].Pos.rotateXZBy(271);
+ vertices[i].Pos.X -= BS / 4;
+ }
+ break;
+ }
+ break;
+ case 4:
+ // outward leaning #-like
+ switch (j) {
+ case 0:
+ for (u16 i = 2; i < 4; i++)
+ vertices[i].Pos.Z -= BS / 2;
+ for (u16 i = 0; i < 4; i++)
+ vertices[i].Pos.rotateXZBy(1);
+ break;
+ case 1:
+ for (u16 i = 2; i < 4; i++)
+ vertices[i].Pos.Z -= BS / 2;
+ for (u16 i = 0; i < 4; i++)
+ vertices[i].Pos.rotateXZBy(91);
+ break;
+ case 2:
+ for (u16 i = 2; i < 4; i++)
+ vertices[i].Pos.Z -= BS / 2;
+ for (u16 i = 0; i < 4; i++)
+ vertices[i].Pos.rotateXZBy(181);
+ break;
+ case 3:
+ for (u16 i = 2; i < 4; i++)
+ vertices[i].Pos.Z -= BS / 2;
+ for (u16 i = 0; i < 4; i++)
+ vertices[i].Pos.rotateXZBy(271);
+ break;
+ }
+ break;
+ }
}
- for (int i = 0; i < 4; i++)
- {
+ for (int i = 0; i < 4; i++) {
vertices[i].Pos *= f.visual_scale;
vertices[i].Pos.Y += BS/2 * (f.visual_scale - 1);
vertices[i].Pos += intToFloat(p, BS);
+ // move to a random spot to avoid moire
+ if ((f.param_type_2 == CPT2_MESHOPTIONS) && ((n.param2 & 0x8) != 0)) {
+ vertices[i].Pos.X += random_offset_X;
+ vertices[i].Pos.Z += random_offset_Z;
+ }
+ // randomly move each face up/down
+ if ((f.param_type_2 == CPT2_MESHOPTIONS) && ((n.param2 & 0x20) != 0)) {
+ PseudoRandom yrng(j | x<<16 | z<<8 | y<<24 );
+ vertices[i].Pos.Y -= BS * ((yrng.next() % 16 / 16.0) * 0.125);
+ }
}
u16 indices[] = {0, 1, 2, 2, 3, 0};
// Add to mesh collector
collector.append(tile, vertices, 4, indices, 6);
+
+ // stop adding faces for meshes with less than 4 faces
+ if (f.param_type_2 == CPT2_MESHOPTIONS) {
+ if (((p2mesh == 0) || (p2mesh == 1)) && (j == 1))
+ break;
+ else if ((p2mesh == 2) && (j == 2))
+ break;
+ } else if (j == 1) {
+ break;
+ }
+
}
break;}
case NDT_FIRELIKE:
diff --git a/src/network/networkprotocol.h b/src/network/networkprotocol.h
index 3a9483efb..e3fcae0c6 100644
--- a/src/network/networkprotocol.h
+++ b/src/network/networkprotocol.h
@@ -136,9 +136,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
backface_culling: backwards compatibility for playing with
newer client on pre-27 servers.
Add nodedef v3 - connected nodeboxes
+ PROTOCOL_VERSION 28:
+ CPT2_MESHOPTIONS
*/
-#define LATEST_PROTOCOL_VERSION 27
+#define LATEST_PROTOCOL_VERSION 28
// Server's supported network protocol range
#define SERVER_PROTOCOL_VERSION_MIN 13
diff --git a/src/nodedef.cpp b/src/nodedef.cpp
index 764203efc..646375575 100644
--- a/src/nodedef.cpp
+++ b/src/nodedef.cpp
@@ -387,7 +387,10 @@ void ContentFeatures::serialize(std::ostream &os, u16 protocol_version) const
writeU8(os, post_effect_color.getGreen());
writeU8(os, post_effect_color.getBlue());
writeU8(os, param_type);
- writeU8(os, param_type_2);
+ if ((protocol_version < 28) && (param_type_2 == CPT2_MESHOPTIONS))
+ writeU8(os, CPT2_NONE);
+ else
+ writeU8(os, param_type_2);
writeU8(os, is_ground_content);
writeU8(os, light_propagates);
writeU8(os, sunlight_propagates);
diff --git a/src/nodedef.h b/src/nodedef.h
index 1c2f792d8..f17c53727 100644
--- a/src/nodedef.h
+++ b/src/nodedef.h
@@ -65,6 +65,8 @@ enum ContentParamType2
CPT2_LEVELED,
// 2D rotation for things like plants
CPT2_DEGROTATE,
+ // Mesh options for plants
+ CPT2_MESHOPTIONS
};
enum LiquidType
diff --git a/src/script/cpp_api/s_node.cpp b/src/script/cpp_api/s_node.cpp
index 17f0f0dac..379ed773f 100644
--- a/src/script/cpp_api/s_node.cpp
+++ b/src/script/cpp_api/s_node.cpp
@@ -58,6 +58,7 @@ struct EnumString ScriptApiNode::es_ContentParamType2[] =
{CPT2_WALLMOUNTED, "wallmounted"},
{CPT2_LEVELED, "leveled"},
{CPT2_DEGROTATE, "degrotate"},
+ {CPT2_MESHOPTIONS, "meshoptions"},
{0, NULL},
};