void ToolCapabilities::deSerialize(std::istream &is) { int version = readU8(is); if(version != 1 && version != 2) throw SerializationError( "unsupported ToolCapabilities version"); full_punch_interval = readF1000(is); max_drop_level = readS16(is); groupcaps.clear(); u32 groupcaps_size = readU32(is); for(u32 i=0; i<groupcaps_size; i++){ std::string name = deSerializeString(is); ToolGroupCap cap; cap.uses = readS16(is); cap.maxlevel = readS16(is); u32 times_size = readU32(is); for(u32 i=0; i<times_size; i++){ int level = readS16(is); float time = readF1000(is); cap.times[level] = time; } groupcaps[name] = cap; } if(version == 2) { u32 damage_groups_size = readU32(is); for(u32 i=0; i<damage_groups_size; i++){ std::string name = deSerializeString(is); s16 rating = readS16(is); damageGroups[name] = rating; } } }
void ItemDefinition::deSerialize(std::istream &is) { // Reset everything reset(); // Deserialize int version = readU8(is); if(version != 1) throw SerializationError("unsupported ItemDefinition version"); type = (enum ItemType)readU8(is); name = deSerializeString(is); description = deSerializeString(is); inventory_image = deSerializeString(is); wield_image = deSerializeString(is); wield_scale = readV3F1000(is); stack_max = readS16(is); usable = readU8(is); liquids_pointable = readU8(is); eatable = readU8(is); std::string tool_capabilities_s = deSerializeString(is); if(!tool_capabilities_s.empty()) { std::istringstream tmp_is(tool_capabilities_s, std::ios::binary); tool_capabilities = new ToolCapabilities; tool_capabilities->deSerialize(tmp_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; } }
void ItemDefinition::deSerialize(std::istream &is) { // Reset everything reset(); // Deserialize int version = readU8(is); if(version < 1 || version > 3) throw SerializationError("unsupported ItemDefinition version"); type = (enum ItemType)readU8(is); name = deSerializeString(is); description = deSerializeString(is); inventory_image = deSerializeString(is); wield_image = deSerializeString(is); wield_scale = readV3F1000(is); stack_max = readS16(is); usable = readU8(is); liquids_pointable = readU8(is); std::string tool_capabilities_s = deSerializeString(is); if(!tool_capabilities_s.empty()) { std::istringstream tmp_is(tool_capabilities_s, std::ios::binary); tool_capabilities = new ToolCapabilities; tool_capabilities->deSerialize(tmp_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; } if(version == 1){ // We cant be sure that node_placement_prediction is send in version 1 try{ node_placement_prediction = deSerializeString(is); }catch(SerializationError &e) {}; // Set the old default sound sound_place.name = "default_place_node"; sound_place.gain = 0.5; } else if(version >= 2) { node_placement_prediction = deSerializeString(is); //deserializeSimpleSoundSpec(sound_place, is); sound_place.name = deSerializeString(is); sound_place.gain = readF1000(is); } if(version == 3) { range = readF1000(is); } // If you add anything here, insert it primarily inside the try-catch // block to not need to increase the version. try { sound_place_failed.name = deSerializeString(is); sound_place_failed.gain = readF1000(is); } catch(SerializationError &e) {}; }
void ItemDefinition::deSerialize(std::istream &is) { // Reset everything reset(); // Deserialize int version = readU8(is); if (version < 5) throw SerializationError("unsupported ItemDefinition version"); type = (enum ItemType)readU8(is); name = deSerializeString(is); description = deSerializeString(is); inventory_image = deSerializeString(is); wield_image = deSerializeString(is); wield_scale = readV3F1000(is); stack_max = readS16(is); usable = readU8(is); liquids_pointable = readU8(is); std::string tool_capabilities_s = deSerializeString(is); if(!tool_capabilities_s.empty()) { std::istringstream tmp_is(tool_capabilities_s, std::ios::binary); tool_capabilities = new ToolCapabilities; tool_capabilities->deSerialize(tmp_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; } node_placement_prediction = deSerializeString(is); //deserializeSimpleSoundSpec(sound_place, is); sound_place.name = deSerializeString(is); sound_place.gain = readF1000(is); range = readF1000(is); sound_place_failed.name = deSerializeString(is); sound_place_failed.gain = readF1000(is); palette_image = deSerializeString(is); color = readARGB8(is); sound_place.pitch = readF1000(is); sound_place_failed.pitch = readF1000(is); inventory_overlay = deSerializeString(is); wield_overlay = deSerializeString(is); // If you add anything here, insert it primarily inside the try-catch // block to not need to increase the version. //try { //} catch(SerializationError &e) {}; }
static void readCoefficients(void) { #if BMP085_USE_DATASHEET_VALS _bmp085_coeffs.ac1 = 408; _bmp085_coeffs.ac2 = -72; _bmp085_coeffs.ac3 = -14383; _bmp085_coeffs.ac4 = 32741; _bmp085_coeffs.ac5 = 32757; _bmp085_coeffs.ac6 = 23153; _bmp085_coeffs.b1 = 6190; _bmp085_coeffs.b2 = 4; _bmp085_coeffs.mb = -32768; _bmp085_coeffs.mc = -8711; _bmp085_coeffs.md = 2868; _bmp085Mode = 0; #else readS16(BMP085_REGISTER_CAL_AC1, &_bmp085_coeffs.ac1); readS16(BMP085_REGISTER_CAL_AC2, &_bmp085_coeffs.ac2); readS16(BMP085_REGISTER_CAL_AC3, &_bmp085_coeffs.ac3); read16(BMP085_REGISTER_CAL_AC4, &_bmp085_coeffs.ac4); read16(BMP085_REGISTER_CAL_AC5, &_bmp085_coeffs.ac5); read16(BMP085_REGISTER_CAL_AC6, &_bmp085_coeffs.ac6); readS16(BMP085_REGISTER_CAL_B1, &_bmp085_coeffs.b1); readS16(BMP085_REGISTER_CAL_B2, &_bmp085_coeffs.b2); readS16(BMP085_REGISTER_CAL_MB, &_bmp085_coeffs.mb); readS16(BMP085_REGISTER_CAL_MC, &_bmp085_coeffs.mc); readS16(BMP085_REGISTER_CAL_MD, &_bmp085_coeffs.md); #endif }
void ContentFeatures::deSerialize(std::istream &is) { int version = readU8(is); if(version != 5) throw SerializationError("unsupported ContentFeatures version"); 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); // 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 liquid_renewable = readU8(is); }catch(SerializationError &e) {}; }
ServerActiveObject* LuaEntitySAO::create(ServerEnvironment *env, v3f pos, const std::string &data) { std::string name; std::string state; s16 hp = 1; v3f velocity; float yaw = 0; if(data != ""){ std::istringstream is(data, std::ios::binary); // read version u8 version = readU8(is); // check if version is supported if(version == 0){ name = deSerializeString(is); state = deSerializeLongString(is); } else if(version == 1){ name = deSerializeString(is); state = deSerializeLongString(is); hp = readS16(is); velocity = readV3F1000(is); yaw = readF1000(is); } } // create object infostream<<"LuaEntitySAO::create(name=\""<<name<<"\" state=\"" <<state<<"\")"<<std::endl; LuaEntitySAO *sao = new LuaEntitySAO(env, pos, name, state); sao->m_hp = hp; sao->m_velocity = velocity; sao->m_yaw = yaw; return sao; }
void ObjectProperties::deSerialize(std::istream &is) { int version = readU8(is); if(version != 1) throw SerializationError( "unsupported ObjectProperties version"); hp_max = readS16(is); physical = readU8(is); weight = readF1000(is); collisionbox.MinEdge = readV3F1000(is); collisionbox.MaxEdge = readV3F1000(is); visual = deSerializeString(is); visual_size = readV2F1000(is); textures.clear(); u32 texture_count = readU16(is); for(u32 i=0; i<texture_count; i++){ textures.push_back(deSerializeString(is)); } spritediv = readV2S16(is); initial_sprite_basepos = readV2S16(is); is_visible = readU8(is); makes_footstep_sound = readU8(is); try{ automatic_rotate = readF1000(is); }catch(SerializationError &e){} }
ServerActiveObject* FallingSAO::create(ServerEnvironment *env, v3f pos, const std::string &data) { std::string name; std::string state; s16 hp = 1; v3f velocity; float yaw = 0; if(data != "") { std::istringstream is(data, std::ios::binary); // read version u8 version = readU8(is); // check if version is supported if(version == 0){ name = deSerializeString(is); state = deSerializeLongString(is); } else if(version == 1){ name = deSerializeString(is); state = deSerializeLongString(is); hp = readS16(is); velocity = readV3F1000(is); yaw = readF1000(is); } } // create object //infostream<<"FallingSAO::create(name='%s' state='%s')", name.c_str(), state.c_str(); epixel::FallingSAO *sao = new epixel::FallingSAO(env, pos, name, state); sao->m_hp = hp; sao->m_velocity = velocity; sao->m_yaw = yaw; return sao; }
void PointedThing::deSerialize(std::istream &is) { int version = readU8(is); if(version != 0) throw SerializationError( "unsupported PointedThing version"); type = (PointedThingType) readU8(is); if(type == POINTEDTHING_NOTHING) { // nothing } else if(type == POINTEDTHING_NODE) { node_undersurface = readV3S16(is); node_abovesurface = readV3S16(is); } else if(type == POINTEDTHING_OBJECT) { object_id = readS16(is); } else { throw SerializationError( "unsupported PointedThingType"); } }
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"); } }
/************************************************************************************ * * ***********************************************************************************/ bool ScopeDome::UpdatePosition() { // int counter = readS32(GetCounterExt); readS16(GetCounter, rotationCounter); // LOGF_INFO("Counters are %d - %d", counter, counter2); // We assume counter value 0 is at home sensor position double az = ((double)rotationCounter * -360.0 / stepsPerTurn) + DomeHomePositionN[0].value; az = fmod(az, 360.0); if (az < 0.0) { az += 360.0; } DomeAbsPosN[0].value = az; return true; }
void PointedThing::deSerialize(std::istream &is) { int version = readU8(is); if (version != 0) throw SerializationError( "unsupported PointedThing version"); type = (PointedThingType) readU8(is); switch (type) { case POINTEDTHING_NOTHING: break; case POINTEDTHING_NODE: node_undersurface = readV3S16(is); node_abovesurface = readV3S16(is); break; case POINTEDTHING_OBJECT: object_id = readS16(is); break; default: throw SerializationError("unsupported PointedThingType"); } }
void TestSerialization::testStreamRead() { std::string datastr( (const char *)test_serialized_data, sizeof(test_serialized_data)); std::istringstream is(datastr, std::ios_base::binary); UASSERT(readU8(is) == 0x11); UASSERT(readU16(is) == 0x2233); UASSERT(readU32(is) == 0x44556677); UASSERT(readU64(is) == 0x8899AABBCCDDEEFF); UASSERT(readS8(is) == -128); UASSERT(readS16(is) == 30000); UASSERT(readS32(is) == -6); UASSERT(readS64(is) == -43); UASSERT(readF1000(is) == 53.534f); UASSERT(readF1000(is) == -300000.32f); UASSERT(readF1000(is) == F1000_MIN); UASSERT(readF1000(is) == F1000_MAX); UASSERT(deSerializeString(is) == "foobar!"); UASSERT(readV2S16(is) == v2s16(500, 500)); UASSERT(readV3S16(is) == v3s16(4207, 604, -30)); UASSERT(readV2S32(is) == v2s32(1920, 1080)); UASSERT(readV3S32(is) == v3s32(-400, 6400054, 290549855)); UASSERT(readV2F1000(is) == v2f(500.656f, 350.345f)); UASSERT(deSerializeWideString(is) == L"\x02~woof~\x5455"); UASSERT(readV3F1000(is) == v3f(500, 10024.2f, -192.54f)); UASSERT(readARGB8(is) == video::SColor(255, 128, 50, 128)); UASSERT(deSerializeLongString(is) == "some longer string here"); UASSERT(is.rdbuf()->in_avail() == 2); UASSERT(readU16(is) == 0xF00D); UASSERT(is.rdbuf()->in_avail() == 0); }
void ObjectProperties::deSerialize(std::istream &is) { int version = readU8(is); if(version == 1) { try{ hp_max = readS16(is); physical = readU8(is); weight = readF1000(is); collisionbox.MinEdge = readV3F1000(is); collisionbox.MaxEdge = readV3F1000(is); visual = deSerializeString(is); visual_size = readV2F1000(is); textures.clear(); u32 texture_count = readU16(is); for(u32 i=0; i<texture_count; i++){ textures.push_back(deSerializeString(is)); } spritediv = readV2S16(is); initial_sprite_basepos = readV2S16(is); is_visible = readU8(is); makes_footstep_sound = readU8(is); automatic_rotate = readF1000(is); mesh = deSerializeString(is); u32 color_count = readU16(is); for(u32 i=0; i<color_count; i++){ colors.push_back(readARGB8(is)); } collideWithObjects = readU8(is); stepheight = readF1000(is); automatic_face_movement_dir = readU8(is); automatic_face_movement_dir_offset = readF1000(is); }catch(SerializationError &e){} } else { throw SerializationError("unsupported ObjectProperties version"); } }
NodeMetadata* NodeMetadata::deSerialize(std::istream &is) { // Read id u8 buf[2]; is.read((char*)buf, 2); s16 id = readS16(buf); // Read data std::string data = deSerializeString(is); // Find factory function core::map<u16, Factory>::Node *n; n = m_types.find(id); if(n == NULL) { // If factory is not found, just return. infostream<<"WARNING: NodeMetadata: No factory for typeId=" <<id<<std::endl; return NULL; } // Try to load the metadata. If it fails, just return. try { std::istringstream iss(data, std::ios_base::binary); Factory f = n->getValue(); NodeMetadata *meta = (*f)(iss); return meta; } catch(SerializationError &e) { infostream<<"WARNING: NodeMetadata: ignoring SerializationError"<<std::endl; return NULL; } }
/* sender_peer_id given to this shall be quaranteed to be a valid peer */ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) { DSTACK(__FUNCTION_NAME); // Ignore packets that don't even fit a command if(datasize < 2) { m_packetcounter.add(60000); return; } ToClientCommand command = (ToClientCommand)readU16(&data[0]); //infostream<<"Client: received command="<<command<<std::endl; m_packetcounter.add((u16)command); /* If this check is removed, be sure to change the queue system to know the ids */ if(sender_peer_id != PEER_ID_SERVER) { infostream<<"Client::ProcessData(): Discarding data not " "coming from server: peer_id="<<sender_peer_id <<std::endl; return; } u8 ser_version = m_server_ser_ver; //infostream<<"Client received command="<<(int)command<<std::endl; if(command == TOCLIENT_INIT) { if(datasize < 3) return; u8 deployed = data[2]; infostream<<"Client: TOCLIENT_INIT received with " "deployed="<<((int)deployed&0xff)<<std::endl; if(deployed < SER_FMT_VER_LOWEST || deployed > SER_FMT_VER_HIGHEST) { infostream<<"Client: TOCLIENT_INIT: Server sent " <<"unsupported ser_fmt_ver"<<std::endl; return; } m_server_ser_ver = deployed; // Get player position v3s16 playerpos_s16(0, BS*2+BS*20, 0); if(datasize >= 2+1+6) playerpos_s16 = readV3S16(&data[2+1]); v3f playerpos_f = intToFloat(playerpos_s16, BS) - v3f(0, BS/2, 0); { //envlock //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out // Set player position Player *player = m_env.getLocalPlayer(); assert(player != NULL); player->setPosition(playerpos_f); } if(datasize >= 2+1+6+8) { // Get map seed m_map_seed = readU64(&data[2+1+6]); infostream<<"Client: received map seed: "<<m_map_seed<<std::endl; } // Reply to server u32 replysize = 2; SharedBuffer<u8> reply(replysize); writeU16(&reply[0], TOSERVER_INIT2); // Send as reliable m_con.Send(PEER_ID_SERVER, 1, reply, true); return; } if(command == TOCLIENT_ACCESS_DENIED) { // The server didn't like our password. Note, this needs // to be processed even if the serialisation format has // not been agreed yet, the same as TOCLIENT_INIT. m_access_denied = true; m_access_denied_reason = L"Unknown"; if(datasize >= 4) { std::string datastring((char*)&data[2], datasize-2); std::istringstream is(datastring, std::ios_base::binary); m_access_denied_reason = deSerializeWideString(is); } return; } if(ser_version == SER_FMT_VER_INVALID) { infostream<<"Client: Server serialization" " format invalid or not initialized." " Skipping incoming command="<<command<<std::endl; return; } // Just here to avoid putting the two if's together when // making some copypasta {} if(command == TOCLIENT_REMOVENODE) { if(datasize < 8) return; v3s16 p; p.X = readS16(&data[2]); p.Y = readS16(&data[4]); p.Z = readS16(&data[6]); //TimeTaker t1("TOCLIENT_REMOVENODE"); // This will clear the cracking animation after digging ((ClientMap&)m_env.getMap()).clearTempMod(p); removeNode(p); } else if(command == TOCLIENT_ADDNODE) { if(datasize < 8 + MapNode::serializedLength(ser_version)) return; v3s16 p; p.X = readS16(&data[2]); p.Y = readS16(&data[4]); p.Z = readS16(&data[6]); //TimeTaker t1("TOCLIENT_ADDNODE"); MapNode n; n.deSerialize(&data[8], ser_version); addNode(p, n); } else if(command == TOCLIENT_BLOCKDATA) { // Ignore too small packet if(datasize < 8) return; v3s16 p; p.X = readS16(&data[2]); p.Y = readS16(&data[4]); p.Z = readS16(&data[6]); /*infostream<<"Client: Thread: BLOCKDATA for (" <<p.X<<","<<p.Y<<","<<p.Z<<")"<<std::endl;*/ /*infostream<<"Client: Thread: BLOCKDATA for (" <<p.X<<","<<p.Y<<","<<p.Z<<")"<<std::endl;*/ std::string datastring((char*)&data[8], datasize-8); std::istringstream istr(datastring, std::ios_base::binary); MapSector *sector; MapBlock *block; v2s16 p2d(p.X, p.Z); sector = m_env.getMap().emergeSector(p2d); assert(sector->getPos() == p2d); //TimeTaker timer("MapBlock deSerialize"); // 0ms block = sector->getBlockNoCreateNoEx(p.Y); if(block) { /* Update an existing block */ //infostream<<"Updating"<<std::endl; block->deSerialize(istr, ser_version); } else { /* Create a new block */ //infostream<<"Creating new"<<std::endl; block = new MapBlock(&m_env.getMap(), p); block->deSerialize(istr, ser_version); sector->insertBlock(block); //DEBUG /*NodeMod mod; mod.type = NODEMOD_CHANGECONTENT; mod.param = CONTENT_MESE; block->setTempMod(v3s16(8,10,8), mod); block->setTempMod(v3s16(8,9,8), mod); block->setTempMod(v3s16(8,8,8), mod); block->setTempMod(v3s16(8,7,8), mod); block->setTempMod(v3s16(8,6,8), mod);*/ } #if 0 /* Acknowledge block */ /* [0] u16 command [2] u8 count [3] v3s16 pos_0 [3+6] v3s16 pos_1 ... */ u32 replysize = 2+1+6; SharedBuffer<u8> reply(replysize); writeU16(&reply[0], TOSERVER_GOTBLOCKS); reply[2] = 1; writeV3S16(&reply[3], p); // Send as reliable m_con.Send(PEER_ID_SERVER, 1, reply, true); #endif /* Update Mesh of this block and blocks at x-, y- and z-. Environment should not be locked as it interlocks with the main thread, from which is will want to retrieve textures. */ //m_env.getClientMap().updateMeshes(block->getPos(), getDayNightRatio()); /* Add it to mesh update queue and set it to be acknowledged after update. */ //infostream<<"Adding mesh update task for received block"<<std::endl; addUpdateMeshTaskWithEdge(p, true); } else if(command == TOCLIENT_PLAYERPOS) { infostream<<"Received deprecated TOCLIENT_PLAYERPOS" <<std::endl; /*u16 our_peer_id; { //JMutexAutoLock lock(m_con_mutex); //bulk comment-out our_peer_id = m_con.GetPeerID(); } // Cancel if we don't have a peer id if(our_peer_id == PEER_ID_INEXISTENT){ infostream<<"TOCLIENT_PLAYERPOS cancelled: " "we have no peer id" <<std::endl; return; }*/ { //envlock //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out u32 player_size = 2+12+12+4+4; u32 player_count = (datasize-2) / player_size; u32 start = 2; for(u32 i=0; i<player_count; i++) { u16 peer_id = readU16(&data[start]); Player *player = m_env.getPlayer(peer_id); // Skip if player doesn't exist if(player == NULL) { start += player_size; continue; } // Skip if player is local player if(player->isLocal()) { start += player_size; continue; } v3s32 ps = readV3S32(&data[start+2]); v3s32 ss = readV3S32(&data[start+2+12]); s32 pitch_i = readS32(&data[start+2+12+12]); s32 yaw_i = readS32(&data[start+2+12+12+4]); /*infostream<<"Client: got " <<"pitch_i="<<pitch_i <<" yaw_i="<<yaw_i<<std::endl;*/ f32 pitch = (f32)pitch_i / 100.0; f32 yaw = (f32)yaw_i / 100.0; v3f position((f32)ps.X/100., (f32)ps.Y/100., (f32)ps.Z/100.); v3f speed((f32)ss.X/100., (f32)ss.Y/100., (f32)ss.Z/100.); player->setPosition(position); player->setSpeed(speed); player->setPitch(pitch); player->setYaw(yaw); /*infostream<<"Client: player "<<peer_id <<" pitch="<<pitch <<" yaw="<<yaw<<std::endl;*/ start += player_size; } } //envlock } else if(command == TOCLIENT_PLAYERINFO) { u16 our_peer_id; { //JMutexAutoLock lock(m_con_mutex); //bulk comment-out our_peer_id = m_con.GetPeerID(); } // Cancel if we don't have a peer id if(our_peer_id == PEER_ID_INEXISTENT){ infostream<<"TOCLIENT_PLAYERINFO cancelled: " "we have no peer id" <<std::endl; return; } //infostream<<"Client: Server reports players:"<<std::endl; { //envlock //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out u32 item_size = 2+PLAYERNAME_SIZE; u32 player_count = (datasize-2) / item_size; u32 start = 2; // peer_ids core::list<u16> players_alive; for(u32 i=0; i<player_count; i++) { // Make sure the name ends in '\0' data[start+2+20-1] = 0; u16 peer_id = readU16(&data[start]); players_alive.push_back(peer_id); /*infostream<<"peer_id="<<peer_id <<" name="<<((char*)&data[start+2])<<std::endl;*/ // Don't update the info of the local player if(peer_id == our_peer_id) { start += item_size; continue; } Player *player = m_env.getPlayer(peer_id); // Create a player if it doesn't exist if(player == NULL) { player = new RemotePlayer( m_device->getSceneManager()->getRootSceneNode(), m_device, -1); player->peer_id = peer_id; m_env.addPlayer(player); infostream<<"Client: Adding new player " <<peer_id<<std::endl; } player->updateName((char*)&data[start+2]); start += item_size; } /* Remove those players from the environment that weren't listed by the server. */ //infostream<<"Removing dead players"<<std::endl; core::list<Player*> players = m_env.getPlayers(); core::list<Player*>::Iterator ip; for(ip=players.begin(); ip!=players.end(); ip++) { // Ingore local player if((*ip)->isLocal()) continue; // Warn about a special case if((*ip)->peer_id == 0) { infostream<<"Client: Removing " "dead player with id=0"<<std::endl; } bool is_alive = false; core::list<u16>::Iterator i; for(i=players_alive.begin(); i!=players_alive.end(); i++) { if((*ip)->peer_id == *i) { is_alive = true; break; } } /*infostream<<"peer_id="<<((*ip)->peer_id) <<" is_alive="<<is_alive<<std::endl;*/ if(is_alive) continue; infostream<<"Removing dead player "<<(*ip)->peer_id <<std::endl; m_env.removePlayer((*ip)->peer_id); } } //envlock } else if(command == TOCLIENT_SECTORMETA) { infostream<<"Client received DEPRECATED TOCLIENT_SECTORMETA"<<std::endl; #if 0 /* [0] u16 command [2] u8 sector count [3...] v2s16 pos + sector metadata */ if(datasize < 3) return; //infostream<<"Client received TOCLIENT_SECTORMETA"<<std::endl; { //envlock //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out std::string datastring((char*)&data[2], datasize-2); std::istringstream is(datastring, std::ios_base::binary); u8 buf[4]; is.read((char*)buf, 1); u16 sector_count = readU8(buf); //infostream<<"sector_count="<<sector_count<<std::endl; for(u16 i=0; i<sector_count; i++) { // Read position is.read((char*)buf, 4); v2s16 pos = readV2S16(buf); /*infostream<<"Client: deserializing sector at " <<"("<<pos.X<<","<<pos.Y<<")"<<std::endl;*/ // Create sector assert(m_env.getMap().mapType() == MAPTYPE_CLIENT); ((ClientMap&)m_env.getMap()).deSerializeSector(pos, is); } } //envlock #endif } else if(command == TOCLIENT_INVENTORY) { if(datasize < 3) return; //TimeTaker t1("Parsing TOCLIENT_INVENTORY", m_device); { //envlock //TimeTaker t2("mutex locking", m_device); //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out //t2.stop(); //TimeTaker t3("istringstream init", m_device); std::string datastring((char*)&data[2], datasize-2); std::istringstream is(datastring, std::ios_base::binary); //t3.stop(); //m_env.printPlayers(infostream); //TimeTaker t4("player get", m_device); Player *player = m_env.getLocalPlayer(); assert(player != NULL); //t4.stop(); //TimeTaker t1("inventory.deSerialize()", m_device); player->inventory.deSerialize(is); //t1.stop(); m_inventory_updated = true; //infostream<<"Client got player inventory:"<<std::endl; //player->inventory.print(infostream); } } //DEBUG else if(command == TOCLIENT_OBJECTDATA) { // Strip command word and create a stringstream std::string datastring((char*)&data[2], datasize-2); std::istringstream is(datastring, std::ios_base::binary); u8 buf[12]; /* Read players */ is.read((char*)buf, 2); u16 playercount = readU16(buf); for(u16 i=0; i<playercount; i++) { is.read((char*)buf, 2); u16 peer_id = readU16(buf); is.read((char*)buf, 12); v3s32 p_i = readV3S32(buf); is.read((char*)buf, 12); v3s32 s_i = readV3S32(buf); is.read((char*)buf, 4); s32 pitch_i = readS32(buf); is.read((char*)buf, 4); s32 yaw_i = readS32(buf); Player *player = m_env.getPlayer(peer_id); // Skip if player doesn't exist if(player == NULL) { continue; } // Skip if player is local player if(player->isLocal()) { continue; } f32 pitch = (f32)pitch_i / 100.0; f32 yaw = (f32)yaw_i / 100.0; v3f position((f32)p_i.X/100., (f32)p_i.Y/100., (f32)p_i.Z/100.); v3f speed((f32)s_i.X/100., (f32)s_i.Y/100., (f32)s_i.Z/100.); player->setPosition(position); player->setSpeed(speed); player->setPitch(pitch); player->setYaw(yaw); } /* Read block objects NOTE: Deprecated stuff */ // Read active block count u16 blockcount = readU16(is); if(blockcount != 0){ infostream<<"TOCLIENT_OBJECTDATA: blockcount != 0 " "not supported"<<std::endl; return; } } else if(command == TOCLIENT_TIME_OF_DAY) { if(datasize < 4) return; u16 time_of_day = readU16(&data[2]); time_of_day = time_of_day % 24000; //infostream<<"Client: time_of_day="<<time_of_day<<std::endl; /* time_of_day: 0 = midnight 12000 = midday */ { m_env.setTimeOfDay(time_of_day); u32 dr = m_env.getDayNightRatio(); infostream<<"Client: time_of_day="<<time_of_day <<", dr="<<dr <<std::endl; } } else if(command == TOCLIENT_CHAT_MESSAGE) { /* u16 command u16 length wstring message */ u8 buf[6]; std::string datastring((char*)&data[2], datasize-2); std::istringstream is(datastring, std::ios_base::binary); // Read stuff is.read((char*)buf, 2); u16 len = readU16(buf); std::wstring message; for(u16 i=0; i<len; i++) { is.read((char*)buf, 2); message += (wchar_t)readU16(buf); } /*infostream<<"Client received chat message: " <<wide_to_narrow(message)<<std::endl;*/ m_chat_queue.push_back(message); } else if(command == TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD) { //if(g_settings->getBool("enable_experimental")) { /* u16 command u16 count of removed objects for all removed objects { u16 id } u16 count of added objects for all added objects { u16 id u8 type u32 initialization data length string initialization data } */ char buf[6]; // Get all data except the command number std::string datastring((char*)&data[2], datasize-2); // Throw them in an istringstream std::istringstream is(datastring, std::ios_base::binary); // Read stuff // Read removed objects is.read(buf, 2); u16 removed_count = readU16((u8*)buf); for(u16 i=0; i<removed_count; i++) { is.read(buf, 2); u16 id = readU16((u8*)buf); // Remove it { //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out m_env.removeActiveObject(id); } } // Read added objects is.read(buf, 2); u16 added_count = readU16((u8*)buf); for(u16 i=0; i<added_count; i++) { is.read(buf, 2); u16 id = readU16((u8*)buf); is.read(buf, 1); u8 type = readU8((u8*)buf); std::string data = deSerializeLongString(is); // Add it { //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out m_env.addActiveObject(id, type, data); } } } } else if(command == TOCLIENT_ACTIVE_OBJECT_MESSAGES) { //if(g_settings->getBool("enable_experimental")) { /* u16 command for all objects { u16 id u16 message length string message } */ char buf[6]; // Get all data except the command number std::string datastring((char*)&data[2], datasize-2); // Throw them in an istringstream std::istringstream is(datastring, std::ios_base::binary); while(is.eof() == false) { // Read stuff is.read(buf, 2); u16 id = readU16((u8*)buf); if(is.eof()) break; is.read(buf, 2); u16 message_size = readU16((u8*)buf); std::string message; message.reserve(message_size); for(u16 i=0; i<message_size; i++) { is.read(buf, 1); message.append(buf, 1); } // Pass on to the environment { //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out m_env.processActiveObjectMessage(id, message); } } } } else if(command == TOCLIENT_HP) { std::string datastring((char*)&data[2], datasize-2); std::istringstream is(datastring, std::ios_base::binary); Player *player = m_env.getLocalPlayer(); assert(player != NULL); u8 hp = readU8(is); player->hp = hp; } else if(command == TOCLIENT_MOVE_PLAYER) { std::string datastring((char*)&data[2], datasize-2); std::istringstream is(datastring, std::ios_base::binary); Player *player = m_env.getLocalPlayer(); assert(player != NULL); v3f pos = readV3F1000(is); f32 pitch = readF1000(is); f32 yaw = readF1000(is); player->setPosition(pos); /*player->setPitch(pitch); player->setYaw(yaw);*/ infostream<<"Client got TOCLIENT_MOVE_PLAYER" <<" pos=("<<pos.X<<","<<pos.Y<<","<<pos.Z<<")" <<" pitch="<<pitch <<" yaw="<<yaw <<std::endl; /* Add to ClientEvent queue. This has to be sent to the main program because otherwise it would just force the pitch and yaw values to whatever the camera points to. */ ClientEvent event; event.type = CE_PLAYER_FORCE_MOVE; event.player_force_move.pitch = pitch; event.player_force_move.yaw = yaw; m_client_event_queue.push_back(event); // Ignore damage for a few seconds, so that the player doesn't // get damage from falling on ground m_ignore_damage_timer = 3.0; } else if(command == TOCLIENT_PLAYERITEM) { std::string datastring((char*)&data[2], datasize-2); std::istringstream is(datastring, std::ios_base::binary); u16 count = readU16(is); for (u16 i = 0; i < count; ++i) { u16 peer_id = readU16(is); Player *player = m_env.getPlayer(peer_id); if (player == NULL) { infostream<<"Client: ignoring player item " << deSerializeString(is) << " for non-existing peer id " << peer_id << std::endl; continue; } else if (player->isLocal()) { infostream<<"Client: ignoring player item " << deSerializeString(is) << " for local player" << std::endl; continue; } else { InventoryList *inv = player->inventory.getList("main"); std::string itemstring(deSerializeString(is)); if (itemstring.empty()) { inv->deleteItem(0); infostream <<"Client: empty player item for peer " << peer_id << std::endl; } else { std::istringstream iss(itemstring); delete inv->changeItem(0, InventoryItem::deSerialize(iss)); infostream<<"Client: player item for peer " << peer_id << ": "; player->getWieldItem()->serialize(infostream); infostream<<std::endl; } } } } else if(command == TOCLIENT_DEATHSCREEN) { std::string datastring((char*)&data[2], datasize-2); std::istringstream is(datastring, std::ios_base::binary); bool set_camera_point_target = readU8(is); v3f camera_point_target = readV3F1000(is); ClientEvent event; event.type = CE_DEATHSCREEN; event.deathscreen.set_camera_point_target = set_camera_point_target; event.deathscreen.camera_point_target_x = camera_point_target.X; event.deathscreen.camera_point_target_y = camera_point_target.Y; event.deathscreen.camera_point_target_z = camera_point_target.Z; m_client_event_queue.push_back(event); } else { infostream<<"Client: Ignoring unknown command " <<command<<std::endl; } }
void ContentFeatures::deSerialize(std::istream &is) { // version detection int version = readU8(is); if (version < 12) throw SerializationError("unsupported ContentFeatures version"); // general 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; } 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) throw SerializationError("unsupported tile count"); for (TileDef &td : tiledef) td.deSerialize(is, version, drawtype); for (TileDef &td : tiledef_overlay) td.deSerialize(is, version, drawtype); if (readU8(is) != CF_SPECIAL_COUNT) throw SerializationError("unsupported CF_SPECIAL_COUNT"); for (TileDef &td : tiledef_special) td.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.push_back(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)); 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); 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); liquid_range = readU8(is); drowning = readU8(is); floodable = readU8(is); // node boxes node_box.deSerialize(is); selection_box.deSerialize(is); collision_box.deSerialize(is); // sounds deSerializeSimpleSoundSpec(sound_footstep, is, version); deSerializeSimpleSoundSpec(sound_dig, is, version); deSerializeSimpleSoundSpec(sound_dug, is, version); // read legacy properties legacy_facedir_simple = readU8(is); legacy_wallmounted = readU8(is); try { node_dig_prediction = deSerializeString(is); } catch(SerializationError &e) {}; }
/* Initialise the map structure */ GAMEMAP *mapLoad(char *filename) { char path[PATH_MAX]; GAMEMAP *map = (GAMEMAP *)malloc(sizeof(*map)); uint32_t i, j, gwVersion; char aFileType[4]; bool littleEndian = true; PHYSFS_file *fp = NULL; bool counted[MAX_PLAYERS]; uint16_t pType; // this cries out for a class based design #define readU8(v) ( littleEndian ? PHYSFS_readULE8(fp, v) : PHYSFS_readUBE8(fp, v) ) #define readU16(v) ( littleEndian ? PHYSFS_readULE16(fp, v) : PHYSFS_readUBE16(fp, v) ) #define readU32(v) ( littleEndian ? PHYSFS_readULE32(fp, v) : PHYSFS_readUBE32(fp, v) ) #define readS8(v) ( littleEndian ? PHYSFS_readSLE8(fp, v) : PHYSFS_readSBE8(fp, v) ) #define readS16(v) ( littleEndian ? PHYSFS_readSLE16(fp, v) : PHYSFS_readSBE16(fp, v) ) #define readS32(v) ( littleEndian ? PHYSFS_readSLE32(fp, v) : PHYSFS_readSBE32(fp, v) ) /* === Load map data === */ strcpy(path, filename); strcat(path, "/game.map"); fp = PHYSFS_openRead(path); map->mGateways = NULL; map->mMapTiles = NULL; if (!fp) { debug(LOG_ERROR, "Could not open %s", path); map->mapVersion = 0; map->width = UINT32_MAX; map->height = UINT32_MAX; map->mMapTiles = NULL; goto mapfailure; } else if (PHYSFS_read(fp, aFileType, 4, 1) != 1 || !readU32(&map->mapVersion) || !readU32(&map->width) || !readU32(&map->height) || aFileType[0] != 'm' || aFileType[1] != 'a' || aFileType[2] != 'p') { debug(LOG_ERROR, "Bad header in %s", path); goto failure; } else if (map->mapVersion <= 9) { debug(LOG_ERROR, "%s: Unsupported save format version %u", path, map->mapVersion); goto failure; } else if (map->mapVersion > 36) { debug(LOG_ERROR, "%s: Undefined save format version %u", path, map->mapVersion); goto failure; } else if (map->width * map->height > MAP_MAXAREA) { debug(LOG_ERROR, "Map %s too large : %d %d", path, map->width, map->height); goto failure; } /* Allocate the memory for the map */ map->mMapTiles = (MAPTILE *)calloc(map->width * map->height, sizeof(*map->mMapTiles)); if (!map->mMapTiles) { debug(LOG_ERROR, "Out of memory"); goto failure; } /* Load in the map data */ for (i = 0; i < map->width * map->height; i++) { uint16_t texture; uint8_t height; if (!readU16(&texture) || !readU8(&height)) { debug(LOG_ERROR, "%s: Error during savegame load", path); goto failure; } map->mMapTiles[i].texture = static_cast<TerrainType>(texture); map->mMapTiles[i].height = height; for (j = 0; j < MAX_PLAYERS; j++) { map->mMapTiles[i].tileVisBits = (uint8_t)(map->mMapTiles[i].tileVisBits &~ (uint8_t)(1 << j)); } } if (!readU32(&gwVersion) || !readU32(&map->numGateways) || gwVersion != 1) { debug(LOG_ERROR, "Bad gateway in %s", path); goto failure; } map->mGateways = (GATEWAY *)calloc(map->numGateways, sizeof(*map->mGateways)); for (i = 0; i < map->numGateways; i++) { if (!readU8(&map->mGateways[i].x1) || !readU8(&map->mGateways[i].y1) || !readU8(&map->mGateways[i].x2) || !readU8(&map->mGateways[i].y2)) { debug(LOG_ERROR, "%s: Failed to read gateway info", path); goto failure; } } PHYSFS_close(fp); mapfailure: /* === Load game data === */ strcpy(path, filename); strcat(path, ".gam"); fp = PHYSFS_openRead(path); if (!fp) { debug(LOG_ERROR, "Game file %s not found", path); goto failure; } else if (PHYSFS_read(fp, aFileType, 4, 1) != 1 || aFileType[0] != 'g' || aFileType[1] != 'a' || aFileType[2] != 'm' || aFileType[3] != 'e' || !readU32(&map->gameVersion)) { debug(LOG_ERROR, "Bad header in %s", path); goto failure; } if (map->gameVersion > 35) // big-endian { littleEndian = false; } if (!readU32(&map->gameTime) || !readU32(&map->gameType) || !readS32(&map->scrollMinX) || !readS32(&map->scrollMinY) || !readU32(&map->scrollMaxX) || !readU32(&map->scrollMaxY) || PHYSFS_read(fp, map->levelName, 20, 1) != 1) { debug(LOG_ERROR, "Bad data in %s", filename); goto failure; } for (i = 0; i < 8; i++) { if (map->gameVersion >= 10) { uint32_t dummy; // extracted power, not used if (!readU32(&map->power[i]) || !readU32(&dummy)) { debug(LOG_ERROR, "Bad power data in %s", filename); goto failure; } } else { map->power[i] = 0; // TODO... is there a default? } } PHYSFS_close(fp); /* === Load feature data === */ littleEndian = true; strcpy(path, filename); strcat(path, "/feat.bjo"); fp = PHYSFS_openRead(path); if (!fp) { debug(LOG_ERROR, "Feature file %s not found", path); map->featVersion = 0; map->numFeatures = 0; map->mLndObjects[IMD_FEATURE] = NULL; goto featfailure; } else if (PHYSFS_read(fp, aFileType, 4, 1) != 1 || aFileType[0] != 'f' || aFileType[1] != 'e' || aFileType[2] != 'a' || aFileType[3] != 't' || !readU32(&map->featVersion) || !readU32(&map->numFeatures)) { debug(LOG_ERROR, "Bad features header in %s", path); goto failure; } map->mLndObjects[IMD_FEATURE] = (LND_OBJECT *)malloc(sizeof(*map->mLndObjects[IMD_FEATURE]) * map->numFeatures); for(i = 0; i < map->numFeatures; i++) { LND_OBJECT *psObj = &map->mLndObjects[IMD_FEATURE][i]; int nameLength = 60; uint32_t dummy; uint8_t visibility[8]; if (map->featVersion <= 19) { nameLength = 40; } if (PHYSFS_read(fp, psObj->name, nameLength, 1) != 1 || !readU32(&psObj->id) || !readU32(&psObj->x) || !readU32(&psObj->y) || !readU32(&psObj->z) || !readU32(&psObj->direction) || !readU32(&psObj->player) || !readU32(&dummy) // BOOL inFire || !readU32(&dummy) // burnStart || !readU32(&dummy)) // burnDamage { debug(LOG_ERROR, "Failed to read feature from %s", path); goto failure; } psObj->player = 0; // work around invalid feature owner if (map->featVersion >= 14 && PHYSFS_read(fp, &visibility, 1, 8) != 8) { debug(LOG_ERROR, "Failed to read feature visibility from %s", path); goto failure; } psObj->type = 0; // IMD LND type for feature // Sanity check data if (psObj->x >= map->width * TILE_WIDTH || psObj->y >= map->height * TILE_HEIGHT) { debug(LOG_ERROR, "Bad feature coordinate %u(%u, %u)", psObj->id, psObj->x, psObj->y); goto failure; } } PHYSFS_close(fp); featfailure: /* === Load terrain data === */ littleEndian = true; strcpy(path, filename); strcat(path, "/ttypes.ttp"); fp = PHYSFS_openRead(path); if (!fp) { map->terrainVersion = 0; goto terrainfailure; } else if (PHYSFS_read(fp, aFileType, 4, 1) != 1 || aFileType[0] != 't' || aFileType[1] != 't' || aFileType[2] != 'y' || aFileType[3] != 'p' || !readU32(&map->terrainVersion) || !readU32(&map->numTerrainTypes)) { debug(LOG_ERROR, "Bad features header in %s", path); goto failure; } if (map->numTerrainTypes >= MAX_TILE_TEXTURES) { // Workaround for fugly map editor bug, since we can't fix the map editor map->numTerrainTypes = MAX_TILE_TEXTURES - 1; } // reset the terrain table memset(terrainTypes, 0, sizeof(terrainTypes)); for (i = 0; i < map->numTerrainTypes; i++) { readU16(&pType); if (pType > TER_MAX) { debug(LOG_ERROR, "loadTerrainTypeMap: terrain type out of range"); goto terrainfailure; } terrainTypes[i] = (uint8_t)pType; } if (terrainTypes[0] == 1 && terrainTypes[1] == 0 && terrainTypes[2] == 2) { map->tileset = TILESET_ARIZONA; } else if (terrainTypes[0] == 2 && terrainTypes[1] == 2 && terrainTypes[2] == 2) { map->tileset = TILESET_URBAN; } else if (terrainTypes[0] == 0 && terrainTypes[1] == 0 && terrainTypes[2] == 2) { map->tileset = TILESET_ROCKIES; } else { debug(LOG_ERROR, "Unknown terrain signature in %s: %u %u %u", path, terrainTypes[0], terrainTypes[1], terrainTypes[2]); goto failure; } PHYSFS_close(fp); terrainfailure: /* === Load structure data === */ map->mLndObjects[IMD_STRUCTURE] = NULL; map->numStructures = 0; littleEndian = true; strcpy(path, filename); strcat(path, "/struct.bjo"); map->mLndObjects[IMD_STRUCTURE] = NULL; fp = PHYSFS_openRead(path); if (fp) { if (PHYSFS_read(fp, aFileType, 4, 1) != 1 || aFileType[0] != 's' || aFileType[1] != 't' || aFileType[2] != 'r' || aFileType[3] != 'u' || !readU32(&map->structVersion) || !readU32(&map->numStructures)) { debug(LOG_ERROR, "Bad structure header in %s", path); goto failure; } map->mLndObjects[IMD_STRUCTURE] = (LND_OBJECT *)malloc(sizeof(*map->mLndObjects[IMD_STRUCTURE]) * map->numStructures); for (i = 0; i < map->numStructures; i++) { LND_OBJECT *psObj = &map->mLndObjects[IMD_STRUCTURE][i]; int nameLength = 60; uint32_t dummy; uint8_t visibility[8], dummy8; int16_t dummyS16; int32_t dummyS32; char researchName[60]; if (map->structVersion <= 19) { nameLength = 40; } if (PHYSFS_read(fp, psObj->name, nameLength, 1) != 1 || !readU32(&psObj->id) || !readU32(&psObj->x) || !readU32(&psObj->y) || !readU32(&psObj->z) || !readU32(&psObj->direction) || !readU32(&psObj->player) || !readU32(&dummy) // BOOL inFire || !readU32(&dummy) // burnStart || !readU32(&dummy) // burnDamage || !readU8(&dummy8) // status - causes structure padding || !readU8(&dummy8) // structure padding || !readU8(&dummy8) // structure padding || !readU8(&dummy8) // structure padding || !readS32(&dummyS32) // currentBuildPts - aligned on 4 byte boundary || !readU32(&dummy) // body || !readU32(&dummy) // armour || !readU32(&dummy) // resistance || !readU32(&dummy) // dummy1 || !readU32(&dummy) // subjectInc || !readU32(&dummy) // timeStarted || !readU32(&dummy) // output || !readU32(&dummy) // capacity || !readU32(&dummy)) // quantity { debug(LOG_ERROR, "Failed to read structure from %s", path); goto failure; } if (map->structVersion >= 12 && (!readU32(&dummy) // factoryInc || !readU8(&dummy8) // loopsPerformed - causes structure padding || !readU8(&dummy8) // structure padding || !readU8(&dummy8) // structure padding || !readU8(&dummy8) // structure padding || !readU32(&dummy) // powerAccrued - aligned on 4 byte boundary || !readU32(&dummy) // dummy2 || !readU32(&dummy) // droidTimeStarted || !readU32(&dummy) // timeToBuild || !readU32(&dummy))) // timeStartHold { debug(LOG_ERROR, "Failed to read structure v12 part from %s", path); goto failure; } if (map->structVersion >= 14 && PHYSFS_read(fp, &visibility, 1, 8) != 8) { debug(LOG_ERROR, "Failed to read structure visibility from %s", path); goto failure; } if (map->structVersion >= 15 && PHYSFS_read(fp, researchName, nameLength, 1) != 1) { // If version < 20, then this causes no padding, but the short below // will still cause two bytes padding; however, if version >= 20, we // will cause 4 bytes padding, but the short below will eat 2 of them, // leaving us again with only two bytes padding before the next word. debug(LOG_ERROR, "Failed to read structure v15 part from %s", path); goto failure; } if (map->structVersion >= 17 && !readS16(&dummyS16)) { debug(LOG_ERROR, "Failed to read structure v17 part from %s", path); goto failure; } if (map->structVersion >= 15 && !readS16(&dummyS16)) // structure padding { debug(LOG_ERROR, "Failed to read 16 bits of structure padding from %s", path); goto failure; } if (map->structVersion >= 21 && !readU32(&dummy)) { debug(LOG_ERROR, "Failed to read structure v21 part from %s", path); goto failure; } psObj->type = IMD_STRUCTURE; // Sanity check data if (psObj->player > MAX_PLAYERS) { debug(LOG_ERROR, "Bad structure owner %u for structure %d id=%u", psObj->player, i, psObj->id); goto failure; } if (psObj->x >= map->width * TILE_WIDTH || psObj->y >= map->height * TILE_HEIGHT) { debug(LOG_ERROR, "Bad structure %d coordinate %u(%u, %u)", i, psObj->id, psObj->x, psObj->y); goto failure; } } PHYSFS_close(fp); } /* === Load droid data === */ map->mLndObjects[IMD_DROID] = NULL; map->numDroids = 0; littleEndian = true; strcpy(path, filename); strcat(path, "/dinit.bjo"); map->mLndObjects[IMD_DROID] = NULL; fp = PHYSFS_openRead(path); if (fp) { if (PHYSFS_read(fp, aFileType, 4, 1) != 1 || aFileType[0] != 'd' || aFileType[1] != 'i' || aFileType[2] != 'n' || aFileType[3] != 't' || !readU32(&map->droidVersion) || !readU32(&map->numDroids)) { debug(LOG_ERROR, "Bad droid header in %s", path); goto failure; } map->mLndObjects[IMD_DROID] = (LND_OBJECT *)malloc(sizeof(*map->mLndObjects[IMD_DROID]) * map->numDroids); for (i = 0; i < map->numDroids; i++) { LND_OBJECT *psObj = &map->mLndObjects[IMD_DROID][i]; int nameLength = 60; uint32_t dummy; if (map->droidVersion <= 19) { nameLength = 40; } if (PHYSFS_read(fp, psObj->name, nameLength, 1) != 1 || !readU32(&psObj->id) || !readU32(&psObj->x) || !readU32(&psObj->y) || !readU32(&psObj->z) || !readU32(&psObj->direction) || !readU32(&psObj->player) || !readU32(&dummy) // BOOL inFire || !readU32(&dummy) // burnStart || !readU32(&dummy)) // burnDamage { debug(LOG_ERROR, "Failed to read droid from %s", path); goto failure; } psObj->type = IMD_DROID; // Sanity check data if (psObj->x >= map->width * TILE_WIDTH || psObj->y >= map->height * TILE_HEIGHT) { debug(LOG_ERROR, "Bad droid coordinate %u(%u, %u)", psObj->id, psObj->x, psObj->y); goto failure; } } PHYSFS_close(fp); } // Count players by looking for the obligatory construction droids map->numPlayers = 0; memset(counted, 0, sizeof(counted)); for(i = 0; i < map->numDroids; i++) { LND_OBJECT *psObj = &map->mLndObjects[IMD_DROID][i]; if (counted[psObj->player] == false && (strcmp(psObj->name, "ConstructorDroid") == 0 || strcmp(psObj->name, "ConstructionDroid") == 0)) { counted[psObj->player] = true; map->numPlayers++; } } return map; failure: mapFree(map); if (fp) { PHYSFS_close(fp); } return NULL; }
void MapBlockObjectList::update(std::istream &is, u8 version, scene::ISceneManager *smgr, u32 daynight_ratio) { JMutexAutoLock lock(m_mutex); /* Collect all existing ids to a set. As things are updated, they are removed from this. All remaining ones are deleted. */ core::map<s16, bool> ids_to_delete; for(core::map<s16, MapBlockObject*>::Iterator i = m_objects.getIterator(); i.atEnd() == false; i++) { ids_to_delete.insert(i.getNode()->getKey(), true); } u8 buf[6]; is.read((char*)buf, 2); u16 count = readU16(buf); for(u16 i=0; i<count; i++) { // Read id is.read((char*)buf, 2); s16 id = readS16(buf); // Read position // stored as x1000/BS v3s16 is.read((char*)buf, 6); v3s16 pos_i = readV3S16(buf); v3f pos((f32)pos_i.X/1000*BS, (f32)pos_i.Y/1000*BS, (f32)pos_i.Z/1000*BS); // Read typeId is.read((char*)buf, 2); u16 type_id = readU16(buf); bool create_new = false; // Find an object with the id core::map<s16, MapBlockObject*>::Node *n; n = m_objects.find(id); // If no entry is found for id if(n == NULL) { // Insert dummy pointer node m_objects.insert(id, NULL); // Get node n = m_objects.find(id); // A new object will be created at this node create_new = true; } // If type_id differs else if(n->getValue()->getTypeId() != type_id) { // Delete old object delete n->getValue(); // A new object will be created at this node create_new = true; } MapBlockObject *obj = NULL; if(create_new) { /*dstream<<"MapBlockObjectList adding new object" " id="<<id <<std::endl;*/ if(type_id == MAPBLOCKOBJECT_TYPE_SIGN) { obj = new SignObject(m_block, id, pos); } else if(type_id == MAPBLOCKOBJECT_TYPE_RAT) { obj = new RatObject(m_block, id, pos); } else if(type_id == MAPBLOCKOBJECT_TYPE_ITEM) { obj = new ItemObject(m_block, id, pos); } else { // This is fatal because we cannot know the length // of the object's data throw SerializationError ("MapBlockObjectList::update(): Unknown MapBlockObject type"); } if(smgr != NULL) //obj->addToScene(smgr, daynight_ratio); obj->addToScene(smgr); n->setValue(obj); } else { obj = n->getValue(); obj->updatePos(pos); /*if(daynight_ratio != m_last_update_daynight_ratio) { obj->removeFromScene(); obj->addToScene(smgr, daynight_ratio); }*/ } // Now there is an object in obj. // Update it. obj->update(is, version); obj->setBlockChanged(); /* Update light on client */ if(smgr != NULL) { u8 light = LIGHT_MAX; try{ v3s16 relpos_i = floatToInt(obj->m_pos, BS); MapNode n = m_block->getNodeParent(relpos_i); light = n.getLightBlend(daynight_ratio); } catch(InvalidPositionException &e) {} obj->updateLight(light); } // Remove from deletion list if(ids_to_delete.find(id) != NULL) ids_to_delete.remove(id); } // Delete all objects whose ids_to_delete remain in ids_to_delete for(core::map<s16, bool>::Iterator i = ids_to_delete.getIterator(); i.atEnd() == false; i++) { s16 id = i.getNode()->getKey(); /*dstream<<"MapBlockObjectList deleting object" " id="<<id <<std::endl;*/ MapBlockObject *obj = m_objects[id]; obj->removeFromScene(); delete obj; m_objects.remove(id); } m_last_update_daynight_ratio = daynight_ratio; }
status WAVEFile::parseFormat(const Tag &id, uint32_t size) { Track *track = getTrack(); uint16_t formatTag; readU16(&formatTag); uint16_t channelCount; readU16(&channelCount); uint32_t sampleRate; readU32(&sampleRate); uint32_t averageBytesPerSecond; readU32(&averageBytesPerSecond); uint16_t blockAlign; readU16(&blockAlign); track->f.channelCount = channelCount; track->f.sampleRate = sampleRate; track->f.byteOrder = AF_BYTEORDER_LITTLEENDIAN; /* Default to uncompressed audio data. */ track->f.compressionType = AF_COMPRESSION_NONE; switch (formatTag) { case WAVE_FORMAT_PCM: { uint16_t bitsPerSample; readU16(&bitsPerSample); track->f.sampleWidth = bitsPerSample; if (bitsPerSample == 0 || bitsPerSample > 32) { _af_error(AF_BAD_WIDTH, "bad sample width of %d bits", bitsPerSample); return AF_FAIL; } if (bitsPerSample <= 8) track->f.sampleFormat = AF_SAMPFMT_UNSIGNED; else track->f.sampleFormat = AF_SAMPFMT_TWOSCOMP; } break; case WAVE_FORMAT_MULAW: case IBM_FORMAT_MULAW: track->f.sampleWidth = 16; track->f.sampleFormat = AF_SAMPFMT_TWOSCOMP; track->f.byteOrder = _AF_BYTEORDER_NATIVE; track->f.compressionType = AF_COMPRESSION_G711_ULAW; break; case WAVE_FORMAT_ALAW: case IBM_FORMAT_ALAW: track->f.sampleWidth = 16; track->f.sampleFormat = AF_SAMPFMT_TWOSCOMP; track->f.byteOrder = _AF_BYTEORDER_NATIVE; track->f.compressionType = AF_COMPRESSION_G711_ALAW; break; case WAVE_FORMAT_IEEE_FLOAT: { uint16_t bitsPerSample; readU16(&bitsPerSample); if (bitsPerSample == 64) { track->f.sampleWidth = 64; track->f.sampleFormat = AF_SAMPFMT_DOUBLE; } else { track->f.sampleWidth = 32; track->f.sampleFormat = AF_SAMPFMT_FLOAT; } } break; case WAVE_FORMAT_ADPCM: { uint16_t bitsPerSample, extraByteCount, samplesPerBlock, numCoefficients; if (track->f.channelCount != 1 && track->f.channelCount != 2) { _af_error(AF_BAD_CHANNELS, "WAVE file with MS ADPCM compression " "must have 1 or 2 channels"); } readU16(&bitsPerSample); readU16(&extraByteCount); readU16(&samplesPerBlock); readU16(&numCoefficients); /* numCoefficients should be at least 7. */ assert(numCoefficients >= 7 && numCoefficients <= 255); for (int i=0; i<numCoefficients; i++) { int16_t a0, a1; readS16(&a0); readS16(&a1); msadpcmCoefficients[i][0] = a0; msadpcmCoefficients[i][1] = a1; } track->f.sampleWidth = 16; track->f.sampleFormat = AF_SAMPFMT_TWOSCOMP; track->f.compressionType = AF_COMPRESSION_MS_ADPCM; track->f.byteOrder = _AF_BYTEORDER_NATIVE; /* Create the parameter list. */ long l; void *v; AUpvlist pv = AUpvnew(4); AUpvsetparam(pv, 0, _AF_MS_ADPCM_NUM_COEFFICIENTS); AUpvsetvaltype(pv, 0, AU_PVTYPE_LONG); l = numCoefficients; AUpvsetval(pv, 0, &l); AUpvsetparam(pv, 1, _AF_MS_ADPCM_COEFFICIENTS); AUpvsetvaltype(pv, 1, AU_PVTYPE_PTR); v = msadpcmCoefficients; AUpvsetval(pv, 1, &v); AUpvsetparam(pv, 2, _AF_FRAMES_PER_BLOCK); AUpvsetvaltype(pv, 2, AU_PVTYPE_LONG); l = samplesPerBlock; AUpvsetval(pv, 2, &l); AUpvsetparam(pv, 3, _AF_BLOCK_SIZE); AUpvsetvaltype(pv, 3, AU_PVTYPE_LONG); l = blockAlign; AUpvsetval(pv, 3, &l); track->f.compressionParams = pv; } break; case WAVE_FORMAT_DVI_ADPCM: { uint16_t bitsPerSample, extraByteCount, samplesPerBlock; readU16(&bitsPerSample); readU16(&extraByteCount); readU16(&samplesPerBlock); if (bitsPerSample != 4) { _af_error(AF_BAD_NOT_IMPLEMENTED, "IMA ADPCM compression supports only 4 bits per sample"); } int bytesPerBlock = (samplesPerBlock + 14) / 8 * 4 * channelCount; if (bytesPerBlock > blockAlign || (samplesPerBlock % 8) != 1) { _af_error(AF_BAD_CODEC_CONFIG, "Invalid samples per block for IMA ADPCM compression"); } track->f.sampleWidth = 16; track->f.sampleFormat = AF_SAMPFMT_TWOSCOMP; track->f.compressionType = AF_COMPRESSION_IMA; track->f.byteOrder = _AF_BYTEORDER_NATIVE; /* Create the parameter list. */ long l; AUpvlist pv = AUpvnew(2); AUpvsetparam(pv, 0, _AF_FRAMES_PER_BLOCK); AUpvsetvaltype(pv, 0, AU_PVTYPE_LONG); l = samplesPerBlock; AUpvsetval(pv, 0, &l); AUpvsetparam(pv, 1, _AF_BLOCK_SIZE); AUpvsetvaltype(pv, 1, AU_PVTYPE_LONG); l = blockAlign; AUpvsetval(pv, 1, &l); track->f.compressionParams = pv; } break; case WAVE_FORMAT_EXTENSIBLE: { uint16_t bitsPerSample; readU16(&bitsPerSample); uint16_t extraByteCount; readU16(&extraByteCount); uint16_t reserved; readU16(&reserved); uint32_t channelMask; readU32(&channelMask); UUID subformat; readUUID(&subformat); if (subformat == _af_wave_guid_pcm) { track->f.sampleWidth = bitsPerSample; if (bitsPerSample == 0 || bitsPerSample > 32) { _af_error(AF_BAD_WIDTH, "bad sample width of %d bits", bitsPerSample); return AF_FAIL; } // Use valid bits per sample if bytes per sample is the same. if (reserved <= bitsPerSample && (reserved + 7) / 8 == (bitsPerSample + 7) / 8) track->f.sampleWidth = reserved; if (bitsPerSample <= 8) track->f.sampleFormat = AF_SAMPFMT_UNSIGNED; else track->f.sampleFormat = AF_SAMPFMT_TWOSCOMP; } else if (subformat == _af_wave_guid_ieee_float) { if (bitsPerSample == 64) { track->f.sampleWidth = 64; track->f.sampleFormat = AF_SAMPFMT_DOUBLE; } else { track->f.sampleWidth = 32; track->f.sampleFormat = AF_SAMPFMT_FLOAT; } } else if (subformat == _af_wave_guid_alaw || subformat == _af_wave_guid_ulaw) { track->f.compressionType = subformat == _af_wave_guid_alaw ? AF_COMPRESSION_G711_ALAW : AF_COMPRESSION_G711_ULAW; track->f.sampleWidth = 16; track->f.sampleFormat = AF_SAMPFMT_TWOSCOMP; track->f.byteOrder = _AF_BYTEORDER_NATIVE; } else { _af_error(AF_BAD_NOT_IMPLEMENTED, "WAVE extensible data format %s is not currently supported", subformat.name().c_str()); return AF_FAIL; } } break; case WAVE_FORMAT_YAMAHA_ADPCM: case WAVE_FORMAT_OKI_ADPCM: case WAVE_FORMAT_CREATIVE_ADPCM: case IBM_FORMAT_ADPCM: _af_error(AF_BAD_NOT_IMPLEMENTED, "WAVE ADPCM data format 0x%x is not currently supported", formatTag); return AF_FAIL; break; case WAVE_FORMAT_MPEG: _af_error(AF_BAD_NOT_IMPLEMENTED, "WAVE MPEG data format is not supported"); return AF_FAIL; break; case WAVE_FORMAT_MPEGLAYER3: _af_error(AF_BAD_NOT_IMPLEMENTED, "WAVE MPEG layer 3 data format is not supported"); return AF_FAIL; break; default: _af_error(AF_BAD_NOT_IMPLEMENTED, "WAVE file data format 0x%x not currently supported != 0xfffe ? %d, != EXTENSIBLE? %d", formatTag, formatTag != 0xfffe, formatTag != WAVE_FORMAT_EXTENSIBLE); return AF_FAIL; break; } _af_set_sample_format(&track->f, track->f.sampleFormat, track->f.sampleWidth); return AF_SUCCEED; }
void FlcPlayer::fliSS2() { Uint8 *pSrc, *pDst, *pTmpDst; Sint8 countData; Uint8 columSkip, fill1, fill2; Uint16 lines; Sint16 count; bool setLastByte = false; Uint8 lastByte = 0; pSrc = _chunkData + 6; pDst = (Uint8*)_mainScreen->pixels + _offset; readU16(lines, pSrc); pSrc += 2; while (lines--) { readS16(count, (Sint8 *)pSrc); pSrc += 2; if ((count & MASK) == SKIP_LINES) { pDst += (-count)*_mainScreen->pitch; ++lines; continue; } else if ((count & MASK) == LAST_PIXEL) { setLastByte = true; lastByte = (count & 0x00FF); readS16(count, (Sint8 *)pSrc); pSrc += 2; } if ((count & MASK) == PACKETS_COUNT) { pTmpDst = pDst; while (count--) { columSkip = *(pSrc++); pTmpDst += columSkip; countData = *(pSrc++); if (countData > 0) { std::copy(pSrc, pSrc + (2 * countData), pTmpDst); pTmpDst += (2 * countData); pSrc += (2 * countData); } else { if (countData < 0) { countData = -countData; fill1 = *(pSrc++); fill2 = *(pSrc++); while (countData--) { *(pTmpDst++) = fill1; *(pTmpDst++) = fill2; } } } } if (setLastByte) { setLastByte = false; *(pDst + _mainScreen->pitch - 1) = lastByte; } pDst += _mainScreen->pitch; } } }