Support serialization of protocol 13 ContentFeatures

master
Perttu Ahola 2012-11-26 23:59:03 +02:00
parent 9714612999
commit 23913f26cd
3 changed files with 195 additions and 120 deletions

View File

@ -215,8 +215,13 @@ void ContentFeatures::reset()
sound_dug = SimpleSoundSpec(); sound_dug = SimpleSoundSpec();
} }
void ContentFeatures::serialize(std::ostream &os) void ContentFeatures::serialize(std::ostream &os, u16 protocol_version)
{ {
if(protocol_version < 14){
serializeOld(os, protocol_version);
return;
}
writeU8(os, 6); // version writeU8(os, 6); // version
os<<serializeString(name); os<<serializeString(name);
writeU16(os, groups.size()); writeU16(os, groups.size());
@ -271,117 +276,65 @@ void ContentFeatures::serialize(std::ostream &os)
void ContentFeatures::deSerialize(std::istream &is) void ContentFeatures::deSerialize(std::istream &is)
{ {
int version = readU8(is); int version = readU8(is);
if(version == 6) // In PROTOCOL_VERSION 14 if(version != 6){
{ deSerializeOld(is, version);
name = deSerializeString(is); return;
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);
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);
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);
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);
// 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
}catch(SerializationError &e) {};
} }
else if(version == 5) // In PROTOCOL_VERSION 13
{ name = deSerializeString(is);
name = deSerializeString(is); groups.clear();
groups.clear(); u32 groups_size = readU16(is);
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);
std::string name = deSerializeString(is); int value = readS16(is);
int value = readS16(is); groups[name] = value;
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);
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);
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);
light_source = readU8(is);
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);
}
else
{
throw SerializationError("unsupported ContentFeatures version");
} }
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);
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);
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);
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);
// 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
}catch(SerializationError &e) {};
} }
/* /*
@ -748,7 +701,7 @@ public:
} }
#endif #endif
} }
void serialize(std::ostream &os) void serialize(std::ostream &os, u16 protocol_version)
{ {
writeU8(os, 1); // version writeU8(os, 1); // version
u16 count = 0; u16 count = 0;
@ -764,7 +717,7 @@ public:
// Wrap it in a string to allow different lengths without // Wrap it in a string to allow different lengths without
// strict version incompatibilities // strict version incompatibilities
std::ostringstream wrapper_os(std::ios::binary); std::ostringstream wrapper_os(std::ios::binary);
f->serialize(wrapper_os); f->serialize(wrapper_os, protocol_version);
os2<<serializeString(wrapper_os.str()); os2<<serializeString(wrapper_os.str());
count++; count++;
} }
@ -821,3 +774,122 @@ IWritableNodeDefManager* createNodeDefManager()
return new CNodeDefManager(); return new CNodeDefManager();
} }
/*
Serialization of old ContentFeatures formats
*/
void ContentFeatures::serializeOld(std::ostream &os, u16 protocol_version)
{
if(protocol_version == 13)
{
writeU8(os, 5); // version
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);
writeU8(os, CF_SPECIAL_COUNT);
for(u32 i=0; i<CF_SPECIAL_COUNT; i++){
tiledef_special[i].serialize(os);
}
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, 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, light_source);
writeU32(os, damage_per_second);
node_box.serialize(os);
selection_box.serialize(os);
writeU8(os, legacy_facedir_simple);
writeU8(os, legacy_wallmounted);
serializeSimpleSoundSpec(sound_footstep, os);
serializeSimpleSoundSpec(sound_dig, os);
serializeSimpleSoundSpec(sound_dug, os);
}
else
{
throw SerializationError("ContentFeatures::serialize(): Unsupported version requested");
}
}
void ContentFeatures::deSerializeOld(std::istream &is, int version)
{
if(version == 5) // In PROTOCOL_VERSION 13
{
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);
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);
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);
light_source = readU8(is);
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);
}
else
{
throw SerializationError("unsupported ContentFeatures version");
}
}

View File

@ -234,8 +234,10 @@ struct ContentFeatures
ContentFeatures(); ContentFeatures();
~ContentFeatures(); ~ContentFeatures();
void reset(); void reset();
void serialize(std::ostream &os); void serialize(std::ostream &os, u16 protocol_version);
void deSerialize(std::istream &is); void deSerialize(std::istream &is);
void serializeOld(std::ostream &os, u16 protocol_version);
void deSerializeOld(std::istream &is, int version);
/* /*
Some handy methods Some handy methods
@ -264,7 +266,7 @@ public:
const=0; const=0;
virtual const ContentFeatures& get(const std::string &name) const=0; virtual const ContentFeatures& get(const std::string &name) const=0;
virtual void serialize(std::ostream &os)=0; virtual void serialize(std::ostream &os, u16 protocol_version)=0;
}; };
class IWritableNodeDefManager : public INodeDefManager class IWritableNodeDefManager : public INodeDefManager
@ -305,7 +307,7 @@ public:
*/ */
virtual void updateTextures(ITextureSource *tsrc)=0; virtual void updateTextures(ITextureSource *tsrc)=0;
virtual void serialize(std::ostream &os)=0; virtual void serialize(std::ostream &os, u16 protocol_version)=0;
virtual void deSerialize(std::istream &is)=0; virtual void deSerialize(std::istream &is)=0;
}; };

View File

@ -2255,8 +2255,9 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
return; return;
} }
getClient(peer_id)->serialization_version RemoteClient *client = getClient(peer_id);
= getClient(peer_id)->pending_serialization_version; client->serialization_version =
getClient(peer_id)->pending_serialization_version;
/* /*
Send some initialization data Send some initialization data
@ -2269,7 +2270,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
SendItemDef(m_con, peer_id, m_itemdef); SendItemDef(m_con, peer_id, m_itemdef);
// Send node definitions // Send node definitions
SendNodeDef(m_con, peer_id, m_nodedef); SendNodeDef(m_con, peer_id, m_nodedef, client->net_proto_version);
// Send media announcement // Send media announcement
sendMediaAnnouncement(peer_id); sendMediaAnnouncement(peer_id);
@ -3521,7 +3522,7 @@ void Server::SendItemDef(con::Connection &con, u16 peer_id,
} }
void Server::SendNodeDef(con::Connection &con, u16 peer_id, void Server::SendNodeDef(con::Connection &con, u16 peer_id,
INodeDefManager *nodedef) INodeDefManager *nodedef, u16 protocol_version)
{ {
DSTACK(__FUNCTION_NAME); DSTACK(__FUNCTION_NAME);
std::ostringstream os(std::ios_base::binary); std::ostringstream os(std::ios_base::binary);
@ -3533,7 +3534,7 @@ void Server::SendNodeDef(con::Connection &con, u16 peer_id,
*/ */
writeU16(os, TOCLIENT_NODEDEF); writeU16(os, TOCLIENT_NODEDEF);
std::ostringstream tmp_os(std::ios::binary); std::ostringstream tmp_os(std::ios::binary);
nodedef->serialize(tmp_os); nodedef->serialize(tmp_os, protocol_version);
std::ostringstream tmp_os2(std::ios::binary); std::ostringstream tmp_os2(std::ios::binary);
compressZlib(tmp_os.str(), tmp_os2); compressZlib(tmp_os.str(), tmp_os2);
os<<serializeLongString(tmp_os2.str()); os<<serializeLongString(tmp_os2.str());