diff options
Diffstat (limited to 'src/nodedef.cpp')
-rw-r--r-- | src/nodedef.cpp | 219 |
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) { |