mirror of
https://github.com/luanti-org/luanti.git
synced 2025-06-27 16:36:03 +00:00
Add hardware node coloring. Includes:
- Increase ContentFeatures serialization version - Color property and palettes for nodes - paramtype2 = "color", "colored facedir" or "colored wallmounted"
This commit is contained in:
parent
43822de5c6
commit
d04d8aba70
27 changed files with 1207 additions and 554 deletions
513
src/nodedef.cpp
513
src/nodedef.cpp
|
@ -189,7 +189,9 @@ void NodeBox::deSerialize(std::istream &is)
|
|||
|
||||
void TileDef::serialize(std::ostream &os, u16 protocol_version) const
|
||||
{
|
||||
if (protocol_version >= 29)
|
||||
if (protocol_version >= 30)
|
||||
writeU8(os, 4);
|
||||
else if (protocol_version >= 29)
|
||||
writeU8(os, 3);
|
||||
else if (protocol_version >= 26)
|
||||
writeU8(os, 2);
|
||||
|
@ -205,6 +207,14 @@ void TileDef::serialize(std::ostream &os, u16 protocol_version) const
|
|||
writeU8(os, tileable_horizontal);
|
||||
writeU8(os, tileable_vertical);
|
||||
}
|
||||
if (protocol_version >= 30) {
|
||||
writeU8(os, has_color);
|
||||
if (has_color) {
|
||||
writeU8(os, color.getRed());
|
||||
writeU8(os, color.getGreen());
|
||||
writeU8(os, color.getBlue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TileDef::deSerialize(std::istream &is, const u8 contenfeatures_version, const NodeDrawType drawtype)
|
||||
|
@ -218,6 +228,14 @@ void TileDef::deSerialize(std::istream &is, const u8 contenfeatures_version, con
|
|||
tileable_horizontal = readU8(is);
|
||||
tileable_vertical = readU8(is);
|
||||
}
|
||||
if (version >= 4) {
|
||||
has_color = readU8(is);
|
||||
if (has_color) {
|
||||
color.setRed(readU8(is));
|
||||
color.setGreen(readU8(is));
|
||||
color.setBlue(readU8(is));
|
||||
}
|
||||
}
|
||||
|
||||
if ((contenfeatures_version < 8) &&
|
||||
((drawtype == NDT_MESH) ||
|
||||
|
@ -351,172 +369,222 @@ void ContentFeatures::reset()
|
|||
connects_to.clear();
|
||||
connects_to_ids.clear();
|
||||
connect_sides = 0;
|
||||
color = video::SColor(0xFFFFFFFF);
|
||||
palette_name = "";
|
||||
palette = NULL;
|
||||
}
|
||||
|
||||
void ContentFeatures::serialize(std::ostream &os, u16 protocol_version) const
|
||||
{
|
||||
if(protocol_version < 24){
|
||||
if (protocol_version < 30) {
|
||||
serializeOld(os, protocol_version);
|
||||
return;
|
||||
}
|
||||
|
||||
writeU8(os, protocol_version < 27 ? 7 : 8);
|
||||
// version
|
||||
writeU8(os, 9);
|
||||
|
||||
os<<serializeString(name);
|
||||
// general
|
||||
os << serializeString(name);
|
||||
writeU16(os, groups.size());
|
||||
for(ItemGroupList::const_iterator
|
||||
i = groups.begin(); i != groups.end(); ++i){
|
||||
os<<serializeString(i->first);
|
||||
for (ItemGroupList::const_iterator i = groups.begin(); i != groups.end();
|
||||
++i) {
|
||||
os << serializeString(i->first);
|
||||
writeS16(os, i->second);
|
||||
}
|
||||
writeU8(os, param_type);
|
||||
writeU8(os, param_type_2);
|
||||
|
||||
// visual
|
||||
writeU8(os, drawtype);
|
||||
os << serializeString(mesh);
|
||||
writeF1000(os, visual_scale);
|
||||
writeU8(os, 6);
|
||||
for(u32 i = 0; i < 6; i++)
|
||||
for (u32 i = 0; i < 6; i++)
|
||||
tiledef[i].serialize(os, protocol_version);
|
||||
writeU8(os, CF_SPECIAL_COUNT);
|
||||
for(u32 i = 0; i < CF_SPECIAL_COUNT; i++){
|
||||
for (u32 i = 0; i < CF_SPECIAL_COUNT; i++) {
|
||||
tiledef_special[i].serialize(os, protocol_version);
|
||||
}
|
||||
writeU8(os, alpha);
|
||||
writeU8(os, color.getRed());
|
||||
writeU8(os, color.getGreen());
|
||||
writeU8(os, color.getBlue());
|
||||
os << serializeString(palette_name);
|
||||
writeU8(os, waving);
|
||||
writeU8(os, connect_sides);
|
||||
writeU16(os, connects_to_ids.size());
|
||||
for (std::set<content_t>::const_iterator i = connects_to_ids.begin();
|
||||
i != connects_to_ids.end(); ++i)
|
||||
writeU16(os, *i);
|
||||
writeU8(os, post_effect_color.getAlpha());
|
||||
writeU8(os, post_effect_color.getRed());
|
||||
writeU8(os, post_effect_color.getGreen());
|
||||
writeU8(os, post_effect_color.getBlue());
|
||||
writeU8(os, param_type);
|
||||
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, leveled);
|
||||
|
||||
// lighting
|
||||
writeU8(os, light_propagates);
|
||||
writeU8(os, sunlight_propagates);
|
||||
writeU8(os, light_source);
|
||||
|
||||
// map generation
|
||||
writeU8(os, is_ground_content);
|
||||
|
||||
// interaction
|
||||
writeU8(os, walkable);
|
||||
writeU8(os, pointable);
|
||||
writeU8(os, diggable);
|
||||
writeU8(os, climbable);
|
||||
writeU8(os, buildable_to);
|
||||
os<<serializeString(""); // legacy: used to be metadata_name
|
||||
writeU8(os, rightclickable);
|
||||
writeU32(os, damage_per_second);
|
||||
|
||||
// liquid
|
||||
writeU8(os, liquid_type);
|
||||
os<<serializeString(liquid_alternative_flowing);
|
||||
os<<serializeString(liquid_alternative_source);
|
||||
os << serializeString(liquid_alternative_flowing);
|
||||
os << serializeString(liquid_alternative_source);
|
||||
writeU8(os, liquid_viscosity);
|
||||
writeU8(os, liquid_renewable);
|
||||
writeU8(os, light_source);
|
||||
writeU32(os, damage_per_second);
|
||||
writeU8(os, liquid_range);
|
||||
writeU8(os, drowning);
|
||||
writeU8(os, floodable);
|
||||
|
||||
// node boxes
|
||||
node_box.serialize(os, protocol_version);
|
||||
selection_box.serialize(os, protocol_version);
|
||||
writeU8(os, legacy_facedir_simple);
|
||||
writeU8(os, legacy_wallmounted);
|
||||
collision_box.serialize(os, protocol_version);
|
||||
|
||||
// sound
|
||||
serializeSimpleSoundSpec(sound_footstep, os);
|
||||
serializeSimpleSoundSpec(sound_dig, os);
|
||||
serializeSimpleSoundSpec(sound_dug, os);
|
||||
writeU8(os, rightclickable);
|
||||
writeU8(os, drowning);
|
||||
writeU8(os, leveled);
|
||||
writeU8(os, liquid_range);
|
||||
writeU8(os, waving);
|
||||
// Stuff below should be moved to correct place in a version that otherwise changes
|
||||
// the protocol version
|
||||
os<<serializeString(mesh);
|
||||
collision_box.serialize(os, protocol_version);
|
||||
writeU8(os, floodable);
|
||||
writeU16(os, connects_to_ids.size());
|
||||
for (std::set<content_t>::const_iterator i = connects_to_ids.begin();
|
||||
i != connects_to_ids.end(); ++i)
|
||||
writeU16(os, *i);
|
||||
writeU8(os, connect_sides);
|
||||
|
||||
// legacy
|
||||
writeU8(os, legacy_facedir_simple);
|
||||
writeU8(os, legacy_wallmounted);
|
||||
}
|
||||
|
||||
void ContentFeatures::correctAlpha()
|
||||
{
|
||||
if (alpha == 0 || alpha == 255)
|
||||
return;
|
||||
|
||||
for (u32 i = 0; i < 6; i++) {
|
||||
std::stringstream s;
|
||||
s << tiledef[i].name << "^[noalpha^[opacity:" << ((int)alpha);
|
||||
tiledef[i].name = s.str();
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < CF_SPECIAL_COUNT; i++) {
|
||||
std::stringstream s;
|
||||
s << tiledef_special[i].name << "^[noalpha^[opacity:" << ((int)alpha);
|
||||
tiledef_special[i].name = s.str();
|
||||
}
|
||||
}
|
||||
|
||||
void ContentFeatures::deSerialize(std::istream &is)
|
||||
{
|
||||
// version detection
|
||||
int version = readU8(is);
|
||||
if (version < 7) {
|
||||
if (version < 9) {
|
||||
deSerializeOld(is, version);
|
||||
return;
|
||||
} else if (version > 8) {
|
||||
} else if (version > 9) {
|
||||
throw SerializationError("unsupported ContentFeatures version");
|
||||
}
|
||||
|
||||
// general
|
||||
name = deSerializeString(is);
|
||||
groups.clear();
|
||||
u32 groups_size = readU16(is);
|
||||
for(u32 i = 0; i < groups_size; i++){
|
||||
for (u32 i = 0; i < groups_size; i++) {
|
||||
std::string name = deSerializeString(is);
|
||||
int value = readS16(is);
|
||||
groups[name] = value;
|
||||
}
|
||||
drawtype = (enum NodeDrawType)readU8(is);
|
||||
param_type = (enum ContentParamType) readU8(is);
|
||||
param_type_2 = (enum ContentParamType2) readU8(is);
|
||||
|
||||
// visual
|
||||
drawtype = (enum NodeDrawType) readU8(is);
|
||||
mesh = deSerializeString(is);
|
||||
visual_scale = readF1000(is);
|
||||
if(readU8(is) != 6)
|
||||
if (readU8(is) != 6)
|
||||
throw SerializationError("unsupported tile count");
|
||||
for(u32 i = 0; i < 6; i++)
|
||||
for (u32 i = 0; i < 6; i++)
|
||||
tiledef[i].deSerialize(is, version, drawtype);
|
||||
if(readU8(is) != CF_SPECIAL_COUNT)
|
||||
if (readU8(is) != CF_SPECIAL_COUNT)
|
||||
throw SerializationError("unsupported CF_SPECIAL_COUNT");
|
||||
for(u32 i = 0; i < CF_SPECIAL_COUNT; i++)
|
||||
for (u32 i = 0; i < CF_SPECIAL_COUNT; i++)
|
||||
tiledef_special[i].deSerialize(is, version, drawtype);
|
||||
alpha = readU8(is);
|
||||
color.setRed(readU8(is));
|
||||
color.setGreen(readU8(is));
|
||||
color.setBlue(readU8(is));
|
||||
palette_name = deSerializeString(is);
|
||||
waving = readU8(is);
|
||||
connect_sides = readU8(is);
|
||||
u16 connects_to_size = readU16(is);
|
||||
connects_to_ids.clear();
|
||||
for (u16 i = 0; i < connects_to_size; i++)
|
||||
connects_to_ids.insert(readU16(is));
|
||||
post_effect_color.setAlpha(readU8(is));
|
||||
post_effect_color.setRed(readU8(is));
|
||||
post_effect_color.setGreen(readU8(is));
|
||||
post_effect_color.setBlue(readU8(is));
|
||||
param_type = (enum ContentParamType)readU8(is);
|
||||
param_type_2 = (enum ContentParamType2)readU8(is);
|
||||
is_ground_content = readU8(is);
|
||||
leveled = readU8(is);
|
||||
|
||||
// lighting-related
|
||||
light_propagates = readU8(is);
|
||||
sunlight_propagates = readU8(is);
|
||||
light_source = readU8(is);
|
||||
light_source = MYMIN(light_source, LIGHT_MAX);
|
||||
|
||||
// map generation
|
||||
is_ground_content = readU8(is);
|
||||
|
||||
// interaction
|
||||
walkable = readU8(is);
|
||||
pointable = readU8(is);
|
||||
diggable = readU8(is);
|
||||
climbable = readU8(is);
|
||||
buildable_to = readU8(is);
|
||||
deSerializeString(is); // legacy: used to be metadata_name
|
||||
liquid_type = (enum LiquidType)readU8(is);
|
||||
rightclickable = readU8(is);
|
||||
damage_per_second = readU32(is);
|
||||
|
||||
// liquid
|
||||
liquid_type = (enum LiquidType) readU8(is);
|
||||
liquid_alternative_flowing = deSerializeString(is);
|
||||
liquid_alternative_source = deSerializeString(is);
|
||||
liquid_viscosity = readU8(is);
|
||||
liquid_renewable = readU8(is);
|
||||
light_source = readU8(is);
|
||||
light_source = MYMIN(light_source, LIGHT_MAX);
|
||||
damage_per_second = readU32(is);
|
||||
liquid_range = readU8(is);
|
||||
drowning = readU8(is);
|
||||
floodable = readU8(is);
|
||||
|
||||
// node boxes
|
||||
node_box.deSerialize(is);
|
||||
selection_box.deSerialize(is);
|
||||
legacy_facedir_simple = readU8(is);
|
||||
legacy_wallmounted = readU8(is);
|
||||
collision_box.deSerialize(is);
|
||||
|
||||
// sounds
|
||||
deSerializeSimpleSoundSpec(sound_footstep, is);
|
||||
deSerializeSimpleSoundSpec(sound_dig, is);
|
||||
deSerializeSimpleSoundSpec(sound_dug, is);
|
||||
rightclickable = readU8(is);
|
||||
drowning = readU8(is);
|
||||
leveled = readU8(is);
|
||||
liquid_range = readU8(is);
|
||||
waving = readU8(is);
|
||||
// If you add anything here, insert it primarily inside the try-catch
|
||||
// block to not need to increase the version.
|
||||
try{
|
||||
// Stuff below should be moved to correct place in a version that
|
||||
// otherwise changes the protocol version
|
||||
mesh = deSerializeString(is);
|
||||
collision_box.deSerialize(is);
|
||||
floodable = readU8(is);
|
||||
u16 connects_to_size = readU16(is);
|
||||
connects_to_ids.clear();
|
||||
for (u16 i = 0; i < connects_to_size; i++)
|
||||
connects_to_ids.insert(readU16(is));
|
||||
connect_sides = readU8(is);
|
||||
}catch(SerializationError &e) {};
|
||||
|
||||
// read legacy properties
|
||||
legacy_facedir_simple = readU8(is);
|
||||
legacy_wallmounted = readU8(is);
|
||||
}
|
||||
|
||||
#ifndef SERVER
|
||||
void ContentFeatures::fillTileAttribs(ITextureSource *tsrc, TileSpec *tile,
|
||||
TileDef *tiledef, u32 shader_id, bool use_normal_texture,
|
||||
bool backface_culling, u8 alpha, u8 material_type)
|
||||
bool backface_culling, u8 material_type)
|
||||
{
|
||||
tile->shader_id = shader_id;
|
||||
tile->texture = tsrc->getTextureForMesh(tiledef->name, &tile->texture_id);
|
||||
tile->alpha = alpha;
|
||||
tile->material_type = material_type;
|
||||
|
||||
// Normal texture and shader flags texture
|
||||
|
@ -536,6 +604,13 @@ void ContentFeatures::fillTileAttribs(ITextureSource *tsrc, TileSpec *tile,
|
|||
if (tiledef->tileable_vertical)
|
||||
tile->material_flags |= MATERIAL_FLAG_TILEABLE_VERTICAL;
|
||||
|
||||
// Color
|
||||
tile->has_color = tiledef->has_color;
|
||||
if (tiledef->has_color)
|
||||
tile->color = tiledef->color;
|
||||
else
|
||||
tile->color = color;
|
||||
|
||||
// Animation parameters
|
||||
int frame_count = 1;
|
||||
if (tile->material_flags & MATERIAL_FLAG_ANIMATION) {
|
||||
|
@ -681,6 +756,9 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
|
|||
is_water_surface = true;
|
||||
}
|
||||
|
||||
// Vertex alpha is no longer supported, correct if necessary.
|
||||
correctAlpha();
|
||||
|
||||
u32 tile_shader[6];
|
||||
for (u16 j = 0; j < 6; j++) {
|
||||
tile_shader[j] = shdsrc->getShader("nodes_shader",
|
||||
|
@ -696,14 +774,14 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
|
|||
for (u16 j = 0; j < 6; j++) {
|
||||
fillTileAttribs(tsrc, &tiles[j], &tdef[j], tile_shader[j],
|
||||
tsettings.use_normal_texture,
|
||||
tiledef[j].backface_culling, alpha, material_type);
|
||||
tiledef[j].backface_culling, material_type);
|
||||
}
|
||||
|
||||
// Special tiles (fill in f->special_tiles[])
|
||||
for (u16 j = 0; j < CF_SPECIAL_COUNT; j++) {
|
||||
fillTileAttribs(tsrc, &special_tiles[j], &tiledef_special[j],
|
||||
tile_shader[j], tsettings.use_normal_texture,
|
||||
tiledef_special[j].backface_culling, alpha, material_type);
|
||||
tiledef_special[j].backface_culling, material_type);
|
||||
}
|
||||
|
||||
if ((drawtype == NDT_MESH) && (mesh != "")) {
|
||||
|
@ -731,15 +809,19 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
|
|||
}
|
||||
|
||||
//Cache 6dfacedir and wallmounted rotated clones of meshes
|
||||
if (tsettings.enable_mesh_cache && mesh_ptr[0] && (param_type_2 == CPT2_FACEDIR)) {
|
||||
if (tsettings.enable_mesh_cache && mesh_ptr[0] &&
|
||||
(param_type_2 == CPT2_FACEDIR
|
||||
|| param_type_2 == CPT2_COLORED_FACEDIR)) {
|
||||
for (u16 j = 1; j < 24; 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)) {
|
||||
static const u8 wm_to_6d[6] = {20, 0, 16+1, 12+3, 8, 4+2};
|
||||
} else if (tsettings.enable_mesh_cache && mesh_ptr[0]
|
||||
&& (param_type_2 == CPT2_WALLMOUNTED ||
|
||||
param_type_2 == CPT2_COLORED_WALLMOUNTED)) {
|
||||
static const u8 wm_to_6d[6] = { 20, 0, 16 + 1, 12 + 3, 8, 4 + 2 };
|
||||
for (u16 j = 1; j < 6; j++) {
|
||||
mesh_ptr[j] = cloneMesh(mesh_ptr[0]);
|
||||
rotateMeshBy6dFacedir(mesh_ptr[j], wm_to_6d[j]);
|
||||
|
@ -775,6 +857,9 @@ public:
|
|||
virtual void removeNode(const std::string &name);
|
||||
virtual void updateAliases(IItemDefManager *idef);
|
||||
virtual void applyTextureOverrides(const std::string &override_filepath);
|
||||
//! Returns a palette or NULL if not found. Only on client.
|
||||
std::vector<video::SColor> *getPalette(const ContentFeatures &f,
|
||||
const IGameDef *gamedef);
|
||||
virtual void updateTextures(IGameDef *gamedef,
|
||||
void (*progress_cbk)(void *progress_args, u32 progress, u32 max_progress),
|
||||
void *progress_cbk_args);
|
||||
|
@ -823,6 +908,9 @@ private:
|
|||
// Next possibly free id
|
||||
content_t m_next_id;
|
||||
|
||||
// Maps image file names to loaded palettes.
|
||||
UNORDERED_MAP<std::string, std::vector<video::SColor> > m_palettes;
|
||||
|
||||
// NodeResolvers to callback once node registration has ended
|
||||
std::vector<NodeResolver *> m_pending_resolve_callbacks;
|
||||
|
||||
|
@ -1062,7 +1150,8 @@ void getNodeBoxUnion(const NodeBox &nodebox, const ContentFeatures &features,
|
|||
if (nodebox.type == NODEBOX_LEVELED) {
|
||||
half_processed.MaxEdge.Y = +BS / 2;
|
||||
}
|
||||
if (features.param_type_2 == CPT2_FACEDIR) {
|
||||
if (features.param_type_2 == CPT2_FACEDIR ||
|
||||
features.param_type_2 == CPT2_COLORED_FACEDIR) {
|
||||
// Get maximal coordinate
|
||||
f32 coords[] = {
|
||||
fabsf(half_processed.MinEdge.X),
|
||||
|
@ -1309,6 +1398,78 @@ void CNodeDefManager::applyTextureOverrides(const std::string &override_filepath
|
|||
}
|
||||
}
|
||||
|
||||
std::vector<video::SColor> *CNodeDefManager::getPalette(
|
||||
const ContentFeatures &f, const IGameDef *gamedef)
|
||||
{
|
||||
#ifndef SERVER
|
||||
// This works because colors always use the most significant bits
|
||||
// of param2. If you add a new colored type which uses param2
|
||||
// in a more advanced way, you should change this code, too.
|
||||
u32 palette_pixels = 0;
|
||||
switch (f.param_type_2) {
|
||||
case CPT2_COLOR:
|
||||
palette_pixels = 256;
|
||||
break;
|
||||
case CPT2_COLORED_FACEDIR:
|
||||
palette_pixels = 8;
|
||||
break;
|
||||
case CPT2_COLORED_WALLMOUNTED:
|
||||
palette_pixels = 32;
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
// This many param2 values will have the same color
|
||||
u32 step = 256 / palette_pixels;
|
||||
const std::string &name = f.palette_name;
|
||||
if (name == "")
|
||||
return NULL;
|
||||
Client *client = (Client *) gamedef;
|
||||
ITextureSource *tsrc = client->tsrc();
|
||||
|
||||
UNORDERED_MAP<std::string, std::vector<video::SColor> >::iterator it =
|
||||
m_palettes.find(name);
|
||||
if (it == m_palettes.end()) {
|
||||
// Create palette
|
||||
if (!tsrc->isKnownSourceImage(name)) {
|
||||
warningstream << "CNodeDefManager::getPalette(): palette \"" << name
|
||||
<< "\" could not be loaded." << std::endl;
|
||||
return NULL;
|
||||
}
|
||||
video::IImage *img = tsrc->generateImage(name);
|
||||
std::vector<video::SColor> new_palette;
|
||||
u32 w = img->getDimension().Width;
|
||||
u32 h = img->getDimension().Height;
|
||||
// Real area of the image
|
||||
u32 area = h * w;
|
||||
if (area != palette_pixels)
|
||||
warningstream << "CNodeDefManager::getPalette(): the "
|
||||
<< "specified palette image \"" << name << "\" does not "
|
||||
<< "contain exactly " << palette_pixels
|
||||
<< " pixels." << std::endl;
|
||||
if (area > palette_pixels)
|
||||
area = palette_pixels;
|
||||
// For each pixel in the image
|
||||
for (u32 i = 0; i < area; i++) {
|
||||
video::SColor c = img->getPixel(i % w, i / w);
|
||||
// Fill in palette with 'step' colors
|
||||
for (u32 j = 0; j < step; j++)
|
||||
new_palette.push_back(c);
|
||||
}
|
||||
img->drop();
|
||||
// Fill in remaining elements
|
||||
while (new_palette.size() < 256)
|
||||
new_palette.push_back(video::SColor(0xFFFFFFFF));
|
||||
m_palettes[name] = new_palette;
|
||||
it = m_palettes.find(name);
|
||||
}
|
||||
if (it != m_palettes.end())
|
||||
return &((*it).second);
|
||||
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void CNodeDefManager::updateTextures(IGameDef *gamedef,
|
||||
void (*progress_callback)(void *progress_args, u32 progress, u32 max_progress),
|
||||
void *progress_callback_args)
|
||||
|
@ -1325,10 +1486,13 @@ void CNodeDefManager::updateTextures(IGameDef *gamedef,
|
|||
TextureSettings tsettings;
|
||||
tsettings.readSettings();
|
||||
|
||||
m_palettes.clear();
|
||||
u32 size = m_content_features.size();
|
||||
|
||||
for (u32 i = 0; i < size; i++) {
|
||||
m_content_features[i].updateTextures(tsrc, shdsrc, meshmanip, client, tsettings);
|
||||
ContentFeatures *f = &(m_content_features[i]);
|
||||
f->palette = getPalette(*f, gamedef);
|
||||
f->updateTextures(tsrc, shdsrc, meshmanip, client, tsettings);
|
||||
progress_callback(progress_callback_args, i, size);
|
||||
}
|
||||
#endif
|
||||
|
@ -1429,6 +1593,19 @@ IWritableNodeDefManager *createNodeDefManager()
|
|||
//// Serialization of old ContentFeatures formats
|
||||
void ContentFeatures::serializeOld(std::ostream &os, u16 protocol_version) const
|
||||
{
|
||||
u8 compatible_param_type_2 = param_type_2;
|
||||
if ((protocol_version < 28)
|
||||
&& (compatible_param_type_2 == CPT2_MESHOPTIONS))
|
||||
compatible_param_type_2 = CPT2_NONE;
|
||||
else if (protocol_version < 30) {
|
||||
if (compatible_param_type_2 == CPT2_COLOR)
|
||||
compatible_param_type_2 = CPT2_NONE;
|
||||
else if (compatible_param_type_2 == CPT2_COLORED_FACEDIR)
|
||||
compatible_param_type_2 = CPT2_FACEDIR;
|
||||
else if (compatible_param_type_2 == CPT2_COLORED_WALLMOUNTED)
|
||||
compatible_param_type_2 = CPT2_WALLMOUNTED;
|
||||
}
|
||||
|
||||
if (protocol_version == 13)
|
||||
{
|
||||
writeU8(os, 5); // version
|
||||
|
@ -1454,7 +1631,7 @@ void ContentFeatures::serializeOld(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);
|
||||
writeU8(os, compatible_param_type_2);
|
||||
writeU8(os, is_ground_content);
|
||||
writeU8(os, light_propagates);
|
||||
writeU8(os, sunlight_propagates);
|
||||
|
@ -1483,9 +1660,9 @@ void ContentFeatures::serializeOld(std::ostream &os, u16 protocol_version) const
|
|||
os<<serializeString(name);
|
||||
writeU16(os, groups.size());
|
||||
for (ItemGroupList::const_iterator
|
||||
i = groups.begin(); i != groups.end(); ++i) {
|
||||
os<<serializeString(i->first);
|
||||
writeS16(os, i->second);
|
||||
i = groups.begin(); i != groups.end(); ++i) {
|
||||
os<<serializeString(i->first);
|
||||
writeS16(os, i->second);
|
||||
}
|
||||
writeU8(os, drawtype);
|
||||
writeF1000(os, visual_scale);
|
||||
|
@ -1502,7 +1679,7 @@ void ContentFeatures::serializeOld(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);
|
||||
writeU8(os, compatible_param_type_2);
|
||||
writeU8(os, is_ground_content);
|
||||
writeU8(os, light_propagates);
|
||||
writeU8(os, sunlight_propagates);
|
||||
|
@ -1530,6 +1707,68 @@ void ContentFeatures::serializeOld(std::ostream &os, u16 protocol_version) const
|
|||
writeU8(os, drowning);
|
||||
writeU8(os, leveled);
|
||||
writeU8(os, liquid_range);
|
||||
}
|
||||
else if(protocol_version >= 24 && protocol_version < 30) {
|
||||
writeU8(os, protocol_version < 27 ? 7 : 8);
|
||||
|
||||
os << serializeString(name);
|
||||
writeU16(os, groups.size());
|
||||
for (ItemGroupList::const_iterator i = groups.begin();
|
||||
i != groups.end(); ++i) {
|
||||
os << serializeString(i->first);
|
||||
writeS16(os, i->second);
|
||||
}
|
||||
writeU8(os, drawtype);
|
||||
writeF1000(os, visual_scale);
|
||||
writeU8(os, 6);
|
||||
for (u32 i = 0; i < 6; i++)
|
||||
tiledef[i].serialize(os, protocol_version);
|
||||
writeU8(os, CF_SPECIAL_COUNT);
|
||||
for (u32 i = 0; i < CF_SPECIAL_COUNT; i++)
|
||||
tiledef_special[i].serialize(os, protocol_version);
|
||||
writeU8(os, alpha);
|
||||
writeU8(os, post_effect_color.getAlpha());
|
||||
writeU8(os, post_effect_color.getRed());
|
||||
writeU8(os, post_effect_color.getGreen());
|
||||
writeU8(os, post_effect_color.getBlue());
|
||||
writeU8(os, param_type);
|
||||
writeU8(os, compatible_param_type_2);
|
||||
writeU8(os, is_ground_content);
|
||||
writeU8(os, light_propagates);
|
||||
writeU8(os, sunlight_propagates);
|
||||
writeU8(os, walkable);
|
||||
writeU8(os, pointable);
|
||||
writeU8(os, diggable);
|
||||
writeU8(os, climbable);
|
||||
writeU8(os, buildable_to);
|
||||
os << serializeString(""); // legacy: used to be metadata_name
|
||||
writeU8(os, liquid_type);
|
||||
os << serializeString(liquid_alternative_flowing);
|
||||
os << serializeString(liquid_alternative_source);
|
||||
writeU8(os, liquid_viscosity);
|
||||
writeU8(os, liquid_renewable);
|
||||
writeU8(os, light_source);
|
||||
writeU32(os, damage_per_second);
|
||||
node_box.serialize(os, protocol_version);
|
||||
selection_box.serialize(os, protocol_version);
|
||||
writeU8(os, legacy_facedir_simple);
|
||||
writeU8(os, legacy_wallmounted);
|
||||
serializeSimpleSoundSpec(sound_footstep, os);
|
||||
serializeSimpleSoundSpec(sound_dig, os);
|
||||
serializeSimpleSoundSpec(sound_dug, os);
|
||||
writeU8(os, rightclickable);
|
||||
writeU8(os, drowning);
|
||||
writeU8(os, leveled);
|
||||
writeU8(os, liquid_range);
|
||||
writeU8(os, waving);
|
||||
os << serializeString(mesh);
|
||||
collision_box.serialize(os, protocol_version);
|
||||
writeU8(os, floodable);
|
||||
writeU16(os, connects_to_ids.size());
|
||||
for (std::set<content_t>::const_iterator i = connects_to_ids.begin();
|
||||
i != connects_to_ids.end(); ++i)
|
||||
writeU16(os, *i);
|
||||
writeU8(os, connect_sides);
|
||||
} else
|
||||
throw SerializationError("ContentFeatures::serialize(): "
|
||||
"Unsupported version requested");
|
||||
|
@ -1642,7 +1881,73 @@ void ContentFeatures::deSerializeOld(std::istream &is, int version)
|
|||
drowning = readU8(is);
|
||||
leveled = readU8(is);
|
||||
liquid_range = readU8(is);
|
||||
} else {
|
||||
} else if (version == 7 || version == 8){
|
||||
name = deSerializeString(is);
|
||||
groups.clear();
|
||||
u32 groups_size = readU16(is);
|
||||
for (u32 i = 0; i < groups_size; i++) {
|
||||
std::string name = deSerializeString(is);
|
||||
int value = readS16(is);
|
||||
groups[name] = value;
|
||||
}
|
||||
drawtype = (enum NodeDrawType) readU8(is);
|
||||
|
||||
visual_scale = readF1000(is);
|
||||
if (readU8(is) != 6)
|
||||
throw SerializationError("unsupported tile count");
|
||||
for (u32 i = 0; i < 6; i++)
|
||||
tiledef[i].deSerialize(is, version, drawtype);
|
||||
if (readU8(is) != CF_SPECIAL_COUNT)
|
||||
throw SerializationError("unsupported CF_SPECIAL_COUNT");
|
||||
for (u32 i = 0; i < CF_SPECIAL_COUNT; i++)
|
||||
tiledef_special[i].deSerialize(is, version, drawtype);
|
||||
alpha = readU8(is);
|
||||
post_effect_color.setAlpha(readU8(is));
|
||||
post_effect_color.setRed(readU8(is));
|
||||
post_effect_color.setGreen(readU8(is));
|
||||
post_effect_color.setBlue(readU8(is));
|
||||
param_type = (enum ContentParamType) readU8(is);
|
||||
param_type_2 = (enum ContentParamType2) readU8(is);
|
||||
is_ground_content = readU8(is);
|
||||
light_propagates = readU8(is);
|
||||
sunlight_propagates = readU8(is);
|
||||
walkable = readU8(is);
|
||||
pointable = readU8(is);
|
||||
diggable = readU8(is);
|
||||
climbable = readU8(is);
|
||||
buildable_to = readU8(is);
|
||||
deSerializeString(is); // legacy: used to be metadata_name
|
||||
liquid_type = (enum LiquidType) readU8(is);
|
||||
liquid_alternative_flowing = deSerializeString(is);
|
||||
liquid_alternative_source = deSerializeString(is);
|
||||
liquid_viscosity = readU8(is);
|
||||
liquid_renewable = readU8(is);
|
||||
light_source = readU8(is);
|
||||
light_source = MYMIN(light_source, LIGHT_MAX);
|
||||
damage_per_second = readU32(is);
|
||||
node_box.deSerialize(is);
|
||||
selection_box.deSerialize(is);
|
||||
legacy_facedir_simple = readU8(is);
|
||||
legacy_wallmounted = readU8(is);
|
||||
deSerializeSimpleSoundSpec(sound_footstep, is);
|
||||
deSerializeSimpleSoundSpec(sound_dig, is);
|
||||
deSerializeSimpleSoundSpec(sound_dug, is);
|
||||
rightclickable = readU8(is);
|
||||
drowning = readU8(is);
|
||||
leveled = readU8(is);
|
||||
liquid_range = readU8(is);
|
||||
waving = readU8(is);
|
||||
try {
|
||||
mesh = deSerializeString(is);
|
||||
collision_box.deSerialize(is);
|
||||
floodable = readU8(is);
|
||||
u16 connects_to_size = readU16(is);
|
||||
connects_to_ids.clear();
|
||||
for (u16 i = 0; i < connects_to_size; i++)
|
||||
connects_to_ids.insert(readU16(is));
|
||||
connect_sides = readU8(is);
|
||||
} catch (SerializationError &e) {};
|
||||
}else{
|
||||
throw SerializationError("unsupported ContentFeatures version");
|
||||
}
|
||||
}
|
||||
|
@ -1736,19 +2041,23 @@ bool CNodeDefManager::nodeboxConnects(MapNode from, MapNode to, u8 connect_face)
|
|||
|
||||
// does to node declare usable faces?
|
||||
if (f2.connect_sides > 0) {
|
||||
if ((f2.param_type_2 == CPT2_FACEDIR) && (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, 0, // 4 - back
|
||||
8, 4, 32, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8 - right
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
16, 8, 4, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16 - front
|
||||
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, 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]);
|
||||
if ((f2.param_type_2 == CPT2_FACEDIR ||
|
||||
f2.param_type_2 == CPT2_COLORED_FACEDIR)
|
||||
&& (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,
|
||||
0, // 4 - back
|
||||
8, 4, 32, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, // 8 - right
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 8, 4, 32, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, // 16 - front
|
||||
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, 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)]);
|
||||
}
|
||||
return (f2.connect_sides & connect_face);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue