#endif
#include "log.h"
#include "settings.h"
+#include "nameidmapping.h"
/*
NodeBox
ContentFeatures::~ContentFeatures()
{
- delete initial_metadata;
#ifndef SERVER
for(u16 j=0; j<CF_SPECIAL_COUNT; j++){
delete special_materials[j];
used_texturenames.clear();
/*
Actual data
+
+ NOTE: Most of this is always overridden by the default values given
+ in builtin.lua
*/
name = "";
drawtype = NDT_NORMAL;
climbable = false;
buildable_to = false;
wall_mounted = false;
- air_equivalent = false;
often_contains_mineral = false;
dug_item = "";
extra_dug_item = "";
extra_dug_item_rarity = 2;
- initial_metadata = NULL;
+ metadata_name = "";
liquid_type = LIQUID_NONE;
- liquid_alternative_flowing = CONTENT_IGNORE;
- liquid_alternative_source = CONTENT_IGNORE;
+ liquid_alternative_flowing = "";
+ liquid_alternative_source = "";
liquid_viscosity = 0;
light_source = 0;
damage_per_second = 0;
writeU8(os, climbable);
writeU8(os, buildable_to);
writeU8(os, wall_mounted);
- writeU8(os, air_equivalent);
writeU8(os, often_contains_mineral);
os<<serializeString(dug_item);
os<<serializeString(extra_dug_item);
writeS32(os, extra_dug_item_rarity);
- if(initial_metadata){
- writeU8(os, true);
- initial_metadata->serialize(os);
- } else {
- writeU8(os, false);
- }
+ os<<serializeString(metadata_name);
writeU8(os, liquid_type);
- writeU16(os, liquid_alternative_flowing);
- writeU16(os, liquid_alternative_source);
+ os<<serializeString(liquid_alternative_flowing);
+ os<<serializeString(liquid_alternative_source);
writeU8(os, liquid_viscosity);
writeU8(os, light_source);
writeU32(os, damage_per_second);
climbable = readU8(is);
buildable_to = readU8(is);
wall_mounted = readU8(is);
- air_equivalent = readU8(is);
often_contains_mineral = readU8(is);
dug_item = deSerializeString(is);
extra_dug_item = deSerializeString(is);
extra_dug_item_rarity = readS32(is);
- if(readU8(is)){
- initial_metadata = NodeMetadata::deSerialize(is, gamedef);
- } else {
- initial_metadata = NULL;
- }
+ metadata_name = deSerializeString(is);
liquid_type = (enum LiquidType)readU8(is);
- liquid_alternative_flowing = readU16(is);
- liquid_alternative_source = readU16(is);
+ liquid_alternative_flowing = deSerializeString(is);
+ liquid_alternative_source = deSerializeString(is);
liquid_viscosity = readU8(is);
light_source = readU8(is);
damage_per_second = readU32(is);
public:
void clear()
{
+ m_name_id_mapping.clear();
for(u16 i=0; i<=MAX_CONTENT; i++)
{
- ContentFeatures *f = &m_content_features[i];
- f->reset(); // Reset to defaults
- if(i == CONTENT_IGNORE || i == CONTENT_AIR){
- f->drawtype = NDT_AIRLIKE;
- continue;
+ ContentFeatures &f = m_content_features[i];
+ f.reset(); // Reset to defaults
+ f.setAllTextures("unknown_block.png");
+ }
+
+ // Set CONTENT_AIR
+ {
+ ContentFeatures f;
+ f.name = "air";
+ f.drawtype = NDT_AIRLIKE;
+ f.param_type = CPT_LIGHT;
+ f.light_propagates = true;
+ f.sunlight_propagates = true;
+ f.walkable = false;
+ f.pointable = false;
+ f.diggable = false;
+ f.buildable_to = true;
+ // Insert directly into containers
+ content_t c = CONTENT_AIR;
+ m_content_features[c] = f;
+ m_name_id_mapping.set(c, f.name);
+ }
+ // Set CONTENT_IGNORE
+ {
+ ContentFeatures f;
+ f.name = "ignore";
+ f.drawtype = NDT_AIRLIKE;
+ f.param_type = CPT_NONE;
+ f.light_propagates = false;
+ f.sunlight_propagates = false;
+ f.walkable = false;
+ f.pointable = false;
+ f.diggable = false;
+ // A way to remove accidental CONTENT_IGNOREs
+ f.buildable_to = true;
+ // Insert directly into containers
+ content_t c = CONTENT_IGNORE;
+ m_content_features[c] = f;
+ m_name_id_mapping.set(c, f.name);
+ }
+ }
+ // CONTENT_IGNORE = not found
+ content_t getFreeId(bool require_full_param2)
+ {
+ // If allowed, first search in the large 4-byte-param2 pool
+ if(!require_full_param2){
+ for(u16 i=0x800; i<=0xfff; i++){
+ const ContentFeatures &f = m_content_features[i];
+ if(f.name == "")
+ return i;
}
- f->setAllTextures("unknown_block.png");
}
-#ifndef SERVER
- // Make CONTENT_IGNORE to not block the view when occlusion culling
- m_content_features[CONTENT_IGNORE].solidness = 0;
-#endif
+ // Then search from the small 8-byte-param2 pool
+ for(u16 i=0; i<=125; i++){
+ const ContentFeatures &f = m_content_features[i];
+ if(f.name == "")
+ return i;
+ }
+ return CONTENT_IGNORE;
}
CNodeDefManager()
{
{
return get(n.getContent());
}
- // Writable
+ virtual bool getId(const std::string &name, content_t &result) const
+ {
+ return m_name_id_mapping.getId(name, result);
+ }
+ virtual content_t getId(const std::string &name) const
+ {
+ content_t id = CONTENT_IGNORE;
+ getId(name, id);
+ return id;
+ }
+ virtual const ContentFeatures& get(const std::string &name) const
+ {
+ content_t id = CONTENT_IGNORE;
+ getId(name, id);
+ return get(id);
+ }
+ // IWritableNodeDefManager
virtual void set(content_t c, const ContentFeatures &def)
{
infostream<<"registerNode: registering content id \""<<c
<<"\": name=\""<<def.name<<"\""<<std::endl;
assert(c <= MAX_CONTENT);
+ // Don't allow redefining CONTENT_IGNORE (but allow air)
+ if(def.name == "ignore" || c == CONTENT_IGNORE){
+ infostream<<"registerNode: WARNING: Ignoring "
+ <<"CONTENT_IGNORE redefinition"<<std::endl;
+ return;
+ }
+ // Check that the special contents are not redefined as different id
+ // because it would mess up everything
+ if((def.name == "ignore" && c != CONTENT_IGNORE) ||
+ (def.name == "air" && c != CONTENT_AIR)){
+ errorstream<<"registerNode: IGNORING ERROR: "
+ <<"trying to register built-in type \""
+ <<def.name<<"\" as different id"<<std::endl;
+ return;
+ }
m_content_features[c] = def;
+ if(def.name != "")
+ m_name_id_mapping.set(c, def.name);
}
- virtual ContentFeatures* getModifiable(content_t c)
+ virtual content_t set(const std::string &name,
+ const ContentFeatures &def)
{
- assert(c <= MAX_CONTENT);
- return &m_content_features[c];
+ assert(name == def.name);
+ u16 id = CONTENT_IGNORE;
+ bool found = m_name_id_mapping.getId(name, id);
+ if(!found){
+ // Determine if full param2 is required
+ bool require_full_param2 = (
+ def.liquid_type == LIQUID_FLOWING
+ ||
+ def.drawtype == NDT_FLOWINGLIQUID
+ ||
+ def.drawtype == NDT_TORCHLIKE
+ ||
+ def.drawtype == NDT_SIGNLIKE
+ );
+ // Get some id
+ id = getFreeId(require_full_param2);
+ if(id == CONTENT_IGNORE)
+ return CONTENT_IGNORE;
+ if(name != "")
+ m_name_id_mapping.set(id, name);
+ }
+ set(id, def);
+ return id;
+ }
+ virtual content_t allocateDummy(const std::string &name)
+ {
+ assert(name != "");
+ ContentFeatures f;
+ f.name = name;
+ f.setAllTextures("unknown_block.png");
+ return set(name, f);
}
virtual void updateTextures(ITextureSource *tsrc)
{
f->solidness = 1;
if(f->alpha == 255)
f->solidness = 2;
+ f->backface_culling = false;
}
break;
case NDT_FLOWINGLIQUID:
f->drawtype = NDT_NORMAL;
f->solidness = 1;
for(u32 i=0; i<6; i++){
- f->tname_tiles[i] = std::string("[noalpha:")
- + f->tname_tiles[i];
+ f->tname_tiles[i] = f->tname_tiles[i]
+ + std::string("^[noalpha");
}
}
break;
std::ostringstream tmp_os(std::ios::binary);
for(u16 i=0; i<=MAX_CONTENT; i++)
{
+ if(i == CONTENT_IGNORE || i == CONTENT_AIR)
+ continue;
ContentFeatures *f = &m_content_features[i];
if(f->name == "")
continue;
<<"Too large content id: "<<i<<std::endl;
continue;
}
+ /*// Do not deserialize special types
+ if(i == CONTENT_IGNORE || i == CONTENT_AIR)
+ continue;*/
ContentFeatures *f = &m_content_features[i];
f->deSerialize(tmp_is, gamedef);
+ if(f->name != "")
+ m_name_id_mapping.set(i, f->name);
}
}
private:
ContentFeatures m_content_features[MAX_CONTENT+1];
+ NameIdMapping m_name_id_mapping;
};
IWritableNodeDefManager* createNodeDefManager()