#include "nameidmapping.h"
#include "util/numeric.h"
#include "util/serialize.h"
+#include "util/string.h"
#include "exceptions.h"
#include "debug.h"
#include "gamedef.h"
u8 version = 6;
writeU8(os, version);
- os << serializeString16(name);
+ if (protocol_version > 39) {
+ os << serializeString16(name);
+ } else {
+ // 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.
+ // 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;
u16 flags = 0;
palette_name = "";
palette = NULL;
node_dig_prediction = "air";
+ move_resistance = 0;
+ liquid_move_physics = false;
}
void ContentFeatures::setAlphaFromLegacy(u8 legacy_alpha)
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);
writeU32(os, damage_per_second);
// liquid
- writeU8(os, liquid_type);
+ LiquidType liquid_type_bc = liquid_type;
+ if (protocol_version <= 39) {
+ // Since commit 7f25823, liquid drawtypes can be used even with LIQUID_NONE
+ // solution: force liquid type accordingly to accepted values
+ if (drawtype == NDT_LIQUID)
+ liquid_type_bc = LIQUID_SOURCE;
+ else if (drawtype == NDT_FLOWINGLIQUID)
+ liquid_type_bc = LIQUID_FLOWING;
+ }
+ writeU8(os, liquid_type_bc);
os << serializeString16(liquid_alternative_flowing);
os << serializeString16(liquid_alternative_source);
writeU8(os, liquid_viscosity);
writeU8(os, legacy_facedir_simple);
writeU8(os, legacy_wallmounted);
+ // new attributes
os << serializeString16(node_dig_prediction);
writeU8(os, leveled_max);
writeU8(os, alpha);
+ writeU8(os, move_resistance);
+ writeU8(os, liquid_move_physics);
}
void ContentFeatures::deSerialize(std::istream &is)
// liquid
liquid_type = (enum LiquidType) readU8(is);
+ liquid_move_physics = liquid_type != LIQUID_NONE;
liquid_alternative_flowing = deSerializeString16(is);
liquid_alternative_source = deSerializeString16(is);
liquid_viscosity = readU8(is);
+ move_resistance = liquid_viscosity; // set default move_resistance
liquid_renewable = readU8(is);
liquid_range = readU8(is);
drowning = readU8(is);
if (is.eof())
throw SerializationError("");
alpha = static_cast<enum AlphaMode>(tmp);
+
+ tmp = readU8(is);
+ if (is.eof())
+ throw SerializationError("");
+ move_resistance = tmp;
+
+ tmp = readU8(is);
+ if (is.eof())
+ throw SerializationError("");
+ liquid_move_physics = tmp;
} catch(SerializationError &e) {};
}
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);
// 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);
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("");
TileDef tdef[6];
for (u32 j = 0; j < 6; j++) {
tdef[j] = tiledef[j];
- if (tdef[j].name.empty())
- tdef[j].name = "unknown_node.png";
+ if (tdef[j].name.empty()) {
+ tdef[j].name = "no_texture.png";
+ tdef[j].backface_culling = false;
+ }
}
// also the overlay tiles
TileDef tdef_overlay[6];
tdef_overlay[j] = tiledef_overlay[j];
// also the special tiles
TileDef tdef_spec[6];
- for (u32 j = 0; j < CF_SPECIAL_COUNT; j++)
+ for (u32 j = 0; j < CF_SPECIAL_COUNT; j++) {
tdef_spec[j] = tiledef_special[j];
+ }
bool is_liquid = false;
{
ContentFeatures f;
f.name = "unknown";
+ TileDef unknownTile;
+ unknownTile.name = "unknown_node.png";
+ for (int t = 0; t < 6; t++)
+ f.tiledef[t] = unknownTile;
// Insert directly into containers
content_t c = CONTENT_UNKNOWN;
m_content_features[c] = f;