aboutsummaryrefslogtreecommitdiff
path: root/src/nodedef.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/nodedef.cpp')
-rw-r--r--src/nodedef.cpp219
1 files changed, 114 insertions, 105 deletions
diff --git a/src/nodedef.cpp b/src/nodedef.cpp
index 8a5542837..e9b322f1d 100644
--- a/src/nodedef.cpp
+++ b/src/nodedef.cpp
@@ -33,6 +33,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "nameidmapping.h"
#include "util/numeric.h"
#include "util/serialize.h"
+#include "util/string.h"
#include "exceptions.h"
#include "debug.h"
#include "gamedef.h"
@@ -55,27 +56,12 @@ void NodeBox::reset()
wall_bottom = aabb3f(-BS/2, -BS/2, -BS/2, BS/2, -BS/2+BS/16., BS/2);
wall_side = aabb3f(-BS/2, -BS/2, -BS/2, -BS/2+BS/16., BS/2, BS/2);
// no default for other parts
- connect_top.clear();
- connect_bottom.clear();
- connect_front.clear();
- connect_left.clear();
- connect_back.clear();
- connect_right.clear();
- disconnected_top.clear();
- disconnected_bottom.clear();
- disconnected_front.clear();
- disconnected_left.clear();
- disconnected_back.clear();
- disconnected_right.clear();
- disconnected.clear();
- disconnected_sides.clear();
+ connected.reset();
}
void NodeBox::serialize(std::ostream &os, u16 protocol_version) const
{
- // Protocol >= 36
- const u8 version = 6;
- writeU8(os, version);
+ writeU8(os, 6); // version. Protocol >= 36
switch (type) {
case NODEBOX_LEVELED:
@@ -98,7 +84,7 @@ void NodeBox::serialize(std::ostream &os, u16 protocol_version) const
writeV3F32(os, wall_side.MinEdge);
writeV3F32(os, wall_side.MaxEdge);
break;
- case NODEBOX_CONNECTED:
+ case NODEBOX_CONNECTED: {
writeU8(os, type);
#define WRITEBOX(box) \
@@ -108,22 +94,25 @@ void NodeBox::serialize(std::ostream &os, u16 protocol_version) const
writeV3F32(os, i.MaxEdge); \
};
+ const auto &c = getConnected();
+
WRITEBOX(fixed);
- WRITEBOX(connect_top);
- WRITEBOX(connect_bottom);
- WRITEBOX(connect_front);
- WRITEBOX(connect_left);
- WRITEBOX(connect_back);
- WRITEBOX(connect_right);
- WRITEBOX(disconnected_top);
- WRITEBOX(disconnected_bottom);
- WRITEBOX(disconnected_front);
- WRITEBOX(disconnected_left);
- WRITEBOX(disconnected_back);
- WRITEBOX(disconnected_right);
- WRITEBOX(disconnected);
- WRITEBOX(disconnected_sides);
+ WRITEBOX(c.connect_top);
+ WRITEBOX(c.connect_bottom);
+ WRITEBOX(c.connect_front);
+ WRITEBOX(c.connect_left);
+ WRITEBOX(c.connect_back);
+ WRITEBOX(c.connect_right);
+ WRITEBOX(c.disconnected_top);
+ WRITEBOX(c.disconnected_bottom);
+ WRITEBOX(c.disconnected_front);
+ WRITEBOX(c.disconnected_left);
+ WRITEBOX(c.disconnected_back);
+ WRITEBOX(c.disconnected_right);
+ WRITEBOX(c.disconnected);
+ WRITEBOX(c.disconnected_sides);
break;
+ }
default:
writeU8(os, type);
break;
@@ -132,8 +121,7 @@ void NodeBox::serialize(std::ostream &os, u16 protocol_version) const
void NodeBox::deSerialize(std::istream &is)
{
- int version = readU8(is);
- if (version < 6)
+ if (readU8(is) < 6)
throw SerializationError("unsupported NodeBox version");
reset();
@@ -172,21 +160,23 @@ void NodeBox::deSerialize(std::istream &is)
u16 count;
+ auto &c = getConnected();
+
READBOXES(fixed);
- READBOXES(connect_top);
- READBOXES(connect_bottom);
- READBOXES(connect_front);
- READBOXES(connect_left);
- READBOXES(connect_back);
- READBOXES(connect_right);
- READBOXES(disconnected_top);
- READBOXES(disconnected_bottom);
- READBOXES(disconnected_front);
- READBOXES(disconnected_left);
- READBOXES(disconnected_back);
- READBOXES(disconnected_right);
- READBOXES(disconnected);
- READBOXES(disconnected_sides);
+ READBOXES(c.connect_top);
+ READBOXES(c.connect_bottom);
+ READBOXES(c.connect_front);
+ READBOXES(c.connect_left);
+ READBOXES(c.connect_back);
+ READBOXES(c.connect_right);
+ READBOXES(c.disconnected_top);
+ READBOXES(c.disconnected_bottom);
+ READBOXES(c.disconnected_front);
+ READBOXES(c.disconnected_left);
+ READBOXES(c.disconnected_back);
+ READBOXES(c.disconnected_right);
+ READBOXES(c.disconnected);
+ READBOXES(c.disconnected_sides);
}
}
@@ -213,10 +203,21 @@ void TileDef::serialize(std::ostream &os, u16 protocol_version) const
// Before f018737, TextureSource::getTextureAverageColor did not handle
// missing textures. "[png" can be used as base texture, but is not known
// on older clients. Hence use "blank.png" to avoid this problem.
- if (!name.empty() && name[0] == '[')
- os << serializeString16("blank.png^" + name);
- else
+ // To be forward-compatible with future base textures/modifiers,
+ // we apply the same prefix to any texture beginning with [,
+ // except for the ones that are supported on older clients.
+ bool pass_through = true;
+
+ if (!name.empty() && name[0] == '[') {
+ pass_through = str_starts_with(name, "[combine:") ||
+ str_starts_with(name, "[inventorycube{") ||
+ str_starts_with(name, "[lowpart:");
+ }
+
+ if (pass_through)
os << serializeString16(name);
+ else
+ os << serializeString16("blank.png^" + name);
}
animation.serialize(os, version);
bool has_scale = scale > 0;
@@ -245,14 +246,13 @@ void TileDef::serialize(std::ostream &os, u16 protocol_version) const
writeU8(os, align_style);
}
-void TileDef::deSerialize(std::istream &is, u8 contentfeatures_version,
- NodeDrawType drawtype)
+void TileDef::deSerialize(std::istream &is, NodeDrawType drawtype, u16 protocol_version)
{
- int version = readU8(is);
- if (version < 6)
+ if (readU8(is) < 6)
throw SerializationError("unsupported TileDef version");
+
name = deSerializeString16(is);
- animation.deSerialize(is, version);
+ animation.deSerialize(is, protocol_version);
u16 flags = readU16(is);
backface_culling = flags & TILE_FLAG_BACKFACE_CULLING;
tileable_horizontal = flags & TILE_FLAG_TILEABLE_HORIZONTAL;
@@ -279,7 +279,7 @@ void TextureSettings::readSettings()
bool smooth_lighting = g_settings->getBool("smooth_lighting");
enable_mesh_cache = g_settings->getBool("enable_mesh_cache");
enable_minimap = g_settings->getBool("enable_minimap");
- node_texture_size = g_settings->getU16("texture_min_size");
+ node_texture_size = std::max<u16>(g_settings->getU16("texture_min_size"), 1);
std::string leaves_style_str = g_settings->get("leaves_style");
std::string world_aligned_mode_str = g_settings->get("world_aligned_mode");
std::string autoscale_mode_str = g_settings->get("autoscale_mode");
@@ -397,9 +397,9 @@ void ContentFeatures::reset()
drowning = 0;
light_source = 0;
damage_per_second = 0;
- node_box = NodeBox();
- selection_box = NodeBox();
- collision_box = NodeBox();
+ node_box.reset();
+ selection_box.reset();
+ collision_box.reset();
waving = 0;
legacy_facedir_simple = false;
legacy_wallmounted = false;
@@ -444,15 +444,19 @@ u8 ContentFeatures::getAlphaForLegacy() const
void ContentFeatures::serialize(std::ostream &os, u16 protocol_version) const
{
- const u8 version = CONTENTFEATURES_VERSION;
- writeU8(os, version);
+ writeU8(os, CONTENTFEATURES_VERSION);
// general
os << serializeString16(name);
writeU16(os, groups.size());
for (const auto &group : groups) {
os << serializeString16(group.first);
- writeS16(os, group.second);
+ if (protocol_version < 41 && group.first.compare("bouncy") == 0) {
+ // Old clients may choke on negative bouncy value
+ writeS16(os, abs(group.second));
+ } else {
+ writeS16(os, group.second);
+ }
}
writeU8(os, param_type);
writeU8(os, param_type_2);
@@ -525,9 +529,9 @@ void ContentFeatures::serialize(std::ostream &os, u16 protocol_version) const
collision_box.serialize(os, protocol_version);
// sound
- sound_footstep.serialize(os, version);
- sound_dig.serialize(os, version);
- sound_dug.serialize(os, version);
+ sound_footstep.serialize(os, protocol_version);
+ sound_dig.serialize(os, protocol_version);
+ sound_dug.serialize(os, protocol_version);
// legacy
writeU8(os, legacy_facedir_simple);
@@ -541,11 +545,9 @@ void ContentFeatures::serialize(std::ostream &os, u16 protocol_version) const
writeU8(os, liquid_move_physics);
}
-void ContentFeatures::deSerialize(std::istream &is)
+void ContentFeatures::deSerialize(std::istream &is, u16 protocol_version)
{
- // version detection
- const u8 version = readU8(is);
- if (version < CONTENTFEATURES_VERSION)
+ if (readU8(is) < CONTENTFEATURES_VERSION)
throw SerializationError("unsupported ContentFeatures version");
// general
@@ -567,13 +569,13 @@ void ContentFeatures::deSerialize(std::istream &is)
if (readU8(is) != 6)
throw SerializationError("unsupported tile count");
for (TileDef &td : tiledef)
- td.deSerialize(is, version, drawtype);
+ td.deSerialize(is, drawtype, protocol_version);
for (TileDef &td : tiledef_overlay)
- td.deSerialize(is, version, drawtype);
+ td.deSerialize(is, drawtype, protocol_version);
if (readU8(is) != CF_SPECIAL_COUNT)
throw SerializationError("unsupported CF_SPECIAL_COUNT");
for (TileDef &td : tiledef_special)
- td.deSerialize(is, version, drawtype);
+ td.deSerialize(is, drawtype, protocol_version);
setAlphaFromLegacy(readU8(is));
color.setRed(readU8(is));
color.setGreen(readU8(is));
@@ -624,9 +626,9 @@ void ContentFeatures::deSerialize(std::istream &is)
collision_box.deSerialize(is);
// sounds
- sound_footstep.deSerialize(is, version);
- sound_dig.deSerialize(is, version);
- sound_dug.deSerialize(is, version);
+ sound_footstep.deSerialize(is, protocol_version);
+ sound_dig.deSerialize(is, protocol_version);
+ sound_dug.deSerialize(is, protocol_version);
// read legacy properties
legacy_facedir_simple = readU8(is);
@@ -670,7 +672,7 @@ static void fillTileAttribs(ITextureSource *tsrc, TileLayer *layer,
bool has_scale = tiledef.scale > 0;
bool use_autoscale = tsettings.autoscale_mode == AUTOSCALE_FORCE ||
(tsettings.autoscale_mode == AUTOSCALE_ENABLE && !has_scale);
- if (use_autoscale) {
+ if (use_autoscale && layer->texture) {
auto texture_size = layer->texture->getOriginalSize();
float base_size = tsettings.node_texture_size;
float size = std::fmin(texture_size.Width, texture_size.Height);
@@ -706,6 +708,7 @@ static void fillTileAttribs(ITextureSource *tsrc, TileLayer *layer,
// Animation parameters
int frame_count = 1;
if (layer->material_flags & MATERIAL_FLAG_ANIMATION) {
+ assert(layer->texture);
int frame_length_ms;
tiledef.animation.determineParams(layer->texture->getOriginalSize(),
&frame_count, &frame_length_ms, NULL);
@@ -716,14 +719,13 @@ static void fillTileAttribs(ITextureSource *tsrc, TileLayer *layer,
if (frame_count == 1) {
layer->material_flags &= ~MATERIAL_FLAG_ANIMATION;
} else {
- std::ostringstream os(std::ios::binary);
- if (!layer->frames) {
+ assert(layer->texture);
+ if (!layer->frames)
layer->frames = new std::vector<FrameSpec>();
- }
layer->frames->resize(frame_count);
+ std::ostringstream os(std::ios::binary);
for (int i = 0; i < frame_count; i++) {
-
FrameSpec frame;
os.str("");
@@ -892,8 +894,15 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
solidness = 0;
visual_solidness = 1;
} else {
- drawtype = NDT_NORMAL;
- solidness = 2;
+ if (waving >= 1) {
+ // waving nodes must make faces so there are no gaps
+ drawtype = NDT_ALLFACES;
+ solidness = 0;
+ visual_solidness = 1;
+ } else {
+ drawtype = NDT_NORMAL;
+ solidness = 2;
+ }
for (TileDef &td : tdef)
td.name += std::string("^[noalpha");
}
@@ -1074,10 +1083,8 @@ void NodeDefManager::clear()
{
ContentFeatures f;
f.name = "unknown";
- TileDef unknownTile;
- unknownTile.name = "unknown_node.png";
for (int t = 0; t < 6; t++)
- f.tiledef[t] = unknownTile;
+ f.tiledef[t].name = "unknown_node.png";
// Insert directly into containers
content_t c = CONTENT_UNKNOWN;
m_content_features[c] = f;
@@ -1279,22 +1286,23 @@ void getNodeBoxUnion(const NodeBox &nodebox, const ContentFeatures &features,
break;
}
case NODEBOX_CONNECTED: {
+ const auto &c = nodebox.getConnected();
// Add all possible connected boxes
- boxVectorUnion(nodebox.fixed, box_union);
- boxVectorUnion(nodebox.connect_top, box_union);
- boxVectorUnion(nodebox.connect_bottom, box_union);
- boxVectorUnion(nodebox.connect_front, box_union);
- boxVectorUnion(nodebox.connect_left, box_union);
- boxVectorUnion(nodebox.connect_back, box_union);
- boxVectorUnion(nodebox.connect_right, box_union);
- boxVectorUnion(nodebox.disconnected_top, box_union);
- boxVectorUnion(nodebox.disconnected_bottom, box_union);
- boxVectorUnion(nodebox.disconnected_front, box_union);
- boxVectorUnion(nodebox.disconnected_left, box_union);
- boxVectorUnion(nodebox.disconnected_back, box_union);
- boxVectorUnion(nodebox.disconnected_right, box_union);
- boxVectorUnion(nodebox.disconnected, box_union);
- boxVectorUnion(nodebox.disconnected_sides, box_union);
+ boxVectorUnion(nodebox.fixed, box_union);
+ boxVectorUnion(c.connect_top, box_union);
+ boxVectorUnion(c.connect_bottom, box_union);
+ boxVectorUnion(c.connect_front, box_union);
+ boxVectorUnion(c.connect_left, box_union);
+ boxVectorUnion(c.connect_back, box_union);
+ boxVectorUnion(c.connect_right, box_union);
+ boxVectorUnion(c.disconnected_top, box_union);
+ boxVectorUnion(c.disconnected_bottom, box_union);
+ boxVectorUnion(c.disconnected_front, box_union);
+ boxVectorUnion(c.disconnected_left, box_union);
+ boxVectorUnion(c.disconnected_back, box_union);
+ boxVectorUnion(c.disconnected_right, box_union);
+ boxVectorUnion(c.disconnected, box_union);
+ boxVectorUnion(c.disconnected_sides, box_union);
break;
}
default: {
@@ -1531,12 +1539,13 @@ void NodeDefManager::serialize(std::ostream &os, u16 protocol_version) const
}
-void NodeDefManager::deSerialize(std::istream &is)
+void NodeDefManager::deSerialize(std::istream &is, u16 protocol_version)
{
clear();
- int version = readU8(is);
- if (version != 1)
+
+ if (readU8(is) < 1)
throw SerializationError("unsupported NodeDefinitionManager version");
+
u16 count = readU16(is);
std::istringstream is2(deSerializeString32(is), std::ios::binary);
ContentFeatures f;
@@ -1546,7 +1555,7 @@ void NodeDefManager::deSerialize(std::istream &is)
// Read it from the string wrapper
std::string wrapper = deSerializeString16(is2);
std::istringstream wrapper_is(wrapper, std::ios::binary);
- f.deSerialize(wrapper_is);
+ f.deSerialize(wrapper_is, protocol_version);
// Check error conditions
if (i == CONTENT_IGNORE || i == CONTENT_AIR || i == CONTENT_UNKNOWN) {