diff options
Diffstat (limited to 'src/content_cao.cpp')
-rw-r--r-- | src/content_cao.cpp | 1071 |
1 files changed, 212 insertions, 859 deletions
diff --git a/src/content_cao.cpp b/src/content_cao.cpp index da4ab6144..ba2011a51 100644 --- a/src/content_cao.cpp +++ b/src/content_cao.cpp @@ -39,6 +39,8 @@ with this program; if not, write to the Free Software Foundation, Inc., class Settings; struct ToolCapabilities; +#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")" + core::map<u16, ClientActiveObject::Factory> ClientActiveObject::m_types; /* @@ -533,823 +535,6 @@ void ItemCAO::initialize(const std::string &data) } /* - LuaEntityCAO -*/ - -#include "luaentity_common.h" - -class LuaEntityCAO : public ClientActiveObject -{ -private: - scene::ISceneManager *m_smgr; - core::aabbox3d<f32> m_selection_box; - scene::IMeshSceneNode *m_meshnode; - scene::IBillboardSceneNode *m_spritenode; - v3f m_position; - v3f m_velocity; - v3f m_acceleration; - float m_yaw; - s16 m_hp; - struct LuaEntityProperties *m_prop; - SmoothTranslator pos_translator; - // Spritesheet/animation stuff - v2f m_tx_size; - v2s16 m_tx_basepos; - bool m_tx_select_horiz_by_yawpitch; - int m_anim_frame; - int m_anim_num_frames; - float m_anim_framelength; - float m_anim_timer; - ItemGroupList m_armor_groups; - float m_reset_textures_timer; - -public: - LuaEntityCAO(IGameDef *gamedef, ClientEnvironment *env): - ClientActiveObject(0, gamedef, env), - m_smgr(NULL), - m_selection_box(-BS/3.,-BS/3.,-BS/3., BS/3.,BS/3.,BS/3.), - m_meshnode(NULL), - m_spritenode(NULL), - m_position(v3f(0,10*BS,0)), - m_velocity(v3f(0,0,0)), - m_acceleration(v3f(0,0,0)), - m_yaw(0), - m_hp(1), - m_prop(new LuaEntityProperties), - m_tx_size(1,1), - m_tx_basepos(0,0), - m_tx_select_horiz_by_yawpitch(false), - m_anim_frame(0), - m_anim_num_frames(1), - m_anim_framelength(0.2), - m_anim_timer(0), - m_reset_textures_timer(-1) - { - if(gamedef == NULL) - ClientActiveObject::registerType(getType(), create); - } - - void initialize(const std::string &data) - { - infostream<<"LuaEntityCAO: Got init data"<<std::endl; - - std::istringstream is(data, std::ios::binary); - // version - u8 version = readU8(is); - // check version - if(version != 1) - return; - // pos - m_position = readV3F1000(is); - // yaw - m_yaw = readF1000(is); - // hp - m_hp = readS16(is); - // properties - std::istringstream prop_is(deSerializeLongString(is), std::ios::binary); - m_prop->deSerialize(prop_is); - - infostream<<"m_prop: "<<m_prop->dump()<<std::endl; - - m_selection_box = m_prop->collisionbox; - m_selection_box.MinEdge *= BS; - m_selection_box.MaxEdge *= BS; - - pos_translator.init(m_position); - - m_tx_size.X = 1.0 / m_prop->spritediv.X; - m_tx_size.Y = 1.0 / m_prop->spritediv.Y; - m_tx_basepos.X = m_tx_size.X * m_prop->initial_sprite_basepos.X; - m_tx_basepos.Y = m_tx_size.Y * m_prop->initial_sprite_basepos.Y; - - updateNodePos(); - } - - ~LuaEntityCAO() - { - delete m_prop; - } - - static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env) - { - return new LuaEntityCAO(gamedef, env); - } - - u8 getType() const - { - return ACTIVEOBJECT_TYPE_LUAENTITY; - } - core::aabbox3d<f32>* getSelectionBox() - { - return &m_selection_box; - } - v3f getPosition() - { - return pos_translator.vect_show; - } - - void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc, - IrrlichtDevice *irr) - { - m_smgr = smgr; - - if(m_meshnode != NULL || m_spritenode != NULL) - return; - - //video::IVideoDriver* driver = smgr->getVideoDriver(); - - if(m_prop->visual == "sprite"){ - infostream<<"LuaEntityCAO::addToScene(): single_sprite"<<std::endl; - m_spritenode = smgr->addBillboardSceneNode( - NULL, v2f(1, 1), v3f(0,0,0), -1); - m_spritenode->setMaterialTexture(0, - tsrc->getTextureRaw("unknown_block.png")); - m_spritenode->setMaterialFlag(video::EMF_LIGHTING, false); - m_spritenode->setMaterialFlag(video::EMF_BILINEAR_FILTER, false); - m_spritenode->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF); - m_spritenode->setMaterialFlag(video::EMF_FOG_ENABLE, true); - m_spritenode->setColor(video::SColor(255,0,0,0)); - m_spritenode->setVisible(false); /* Set visible when brightness is known */ - m_spritenode->setSize(m_prop->visual_size*BS); - { - const float txs = 1.0 / 1; - const float tys = 1.0 / 1; - setBillboardTextureMatrix(m_spritenode, - txs, tys, 0, 0); - } - } else if(m_prop->visual == "cube"){ - infostream<<"LuaEntityCAO::addToScene(): cube"<<std::endl; - scene::IMesh *mesh = createCubeMesh(v3f(BS,BS,BS)); - m_meshnode = smgr->addMeshSceneNode(mesh, NULL); - mesh->drop(); - - m_meshnode->setScale(v3f(1)); - // Will be shown when we know the brightness - m_meshnode->setVisible(false); - } else { - infostream<<"LuaEntityCAO::addToScene(): \""<<m_prop->visual - <<"\" not supported"<<std::endl; - } - updateTextures(""); - updateNodePos(); - } - - void removeFromScene() - { - if(m_meshnode){ - m_meshnode->remove(); - m_meshnode = NULL; - } - if(m_spritenode){ - m_spritenode->remove(); - m_spritenode = NULL; - } - } - - void updateLight(u8 light_at_pos) - { - bool is_visible = (m_hp != 0); - u8 li = decode_light(light_at_pos); - video::SColor color(255,li,li,li); - if(m_meshnode){ - setMeshColor(m_meshnode->getMesh(), color); - m_meshnode->setVisible(is_visible); - } - if(m_spritenode){ - m_spritenode->setColor(color); - m_spritenode->setVisible(is_visible); - } - } - - v3s16 getLightPosition() - { - return floatToInt(m_position, BS); - } - - void updateNodePos() - { - if(m_meshnode){ - m_meshnode->setPosition(pos_translator.vect_show); - } - if(m_spritenode){ - m_spritenode->setPosition(pos_translator.vect_show); - } - } - - void step(float dtime, ClientEnvironment *env) - { - if(m_prop->physical){ - core::aabbox3d<f32> box = m_prop->collisionbox; - box.MinEdge *= BS; - box.MaxEdge *= BS; - collisionMoveResult moveresult; - f32 pos_max_d = BS*0.25; // Distance per iteration - v3f p_pos = m_position; - v3f p_velocity = m_velocity; - IGameDef *gamedef = env->getGameDef(); - moveresult = collisionMovePrecise(&env->getMap(), gamedef, - pos_max_d, box, dtime, p_pos, p_velocity); - // Apply results - m_position = p_pos; - m_velocity = p_velocity; - - bool is_end_position = moveresult.collides; - pos_translator.update(m_position, is_end_position, dtime); - pos_translator.translate(dtime); - updateNodePos(); - - m_velocity += dtime * m_acceleration; - } else { - m_position += dtime * m_velocity + 0.5 * dtime * dtime * m_acceleration; - m_velocity += dtime * m_acceleration; - pos_translator.update(m_position, pos_translator.aim_is_end, pos_translator.anim_time); - pos_translator.translate(dtime); - updateNodePos(); - } - - m_anim_timer += dtime; - if(m_anim_timer >= m_anim_framelength){ - m_anim_timer -= m_anim_framelength; - m_anim_frame++; - if(m_anim_frame >= m_anim_num_frames) - m_anim_frame = 0; - } - - updateTexturePos(); - - if(m_reset_textures_timer >= 0){ - m_reset_textures_timer -= dtime; - if(m_reset_textures_timer <= 0){ - m_reset_textures_timer = -1; - updateTextures(""); - } - } - } - - void updateTexturePos() - { - if(m_spritenode){ - scene::ICameraSceneNode* camera = - m_spritenode->getSceneManager()->getActiveCamera(); - if(!camera) - return; - v3f cam_to_entity = m_spritenode->getAbsolutePosition() - - camera->getAbsolutePosition(); - cam_to_entity.normalize(); - - int row = m_tx_basepos.Y; - int col = m_tx_basepos.X; - - if(m_tx_select_horiz_by_yawpitch) - { - if(cam_to_entity.Y > 0.75) - col += 5; - else if(cam_to_entity.Y < -0.75) - col += 4; - else{ - float mob_dir = atan2(cam_to_entity.Z, cam_to_entity.X) / PI * 180.; - float dir = mob_dir - m_yaw; - dir = wrapDegrees_180(dir); - //infostream<<"id="<<m_id<<" dir="<<dir<<std::endl; - if(fabs(wrapDegrees_180(dir - 0)) <= 45.1) - col += 2; - else if(fabs(wrapDegrees_180(dir - 90)) <= 45.1) - col += 3; - else if(fabs(wrapDegrees_180(dir - 180)) <= 45.1) - col += 0; - else if(fabs(wrapDegrees_180(dir + 90)) <= 45.1) - col += 1; - else - col += 4; - } - } - - // Animation goes downwards - row += m_anim_frame; - - float txs = m_tx_size.X; - float tys = m_tx_size.Y; - setBillboardTextureMatrix(m_spritenode, - txs, tys, col, row); - } - } - - void updateTextures(const std::string &mod) - { - ITextureSource *tsrc = m_gamedef->tsrc(); - - if(m_spritenode){ - std::string texturestring = "unknown_block.png"; - if(m_prop->textures.size() >= 1) - texturestring = m_prop->textures[0]; - texturestring += mod; - m_spritenode->setMaterialTexture(0, - tsrc->getTextureRaw(texturestring)); - } - if(m_meshnode){ - for (u32 i = 0; i < 6; ++i) - { - std::string texturestring = "unknown_block.png"; - if(m_prop->textures.size() > i) - texturestring = m_prop->textures[i]; - texturestring += mod; - AtlasPointer ap = tsrc->getTexture(texturestring); - - // Get the tile texture and atlas transformation - video::ITexture* atlas = ap.atlas; - v2f pos = ap.pos; - v2f size = ap.size; - - // Set material flags and texture - video::SMaterial& material = m_meshnode->getMaterial(i); - material.setFlag(video::EMF_LIGHTING, false); - material.setFlag(video::EMF_BILINEAR_FILTER, false); - material.setTexture(0, atlas); - material.getTextureMatrix(0).setTextureTranslate(pos.X, pos.Y); - material.getTextureMatrix(0).setTextureScale(size.X, size.Y); - } - } - } - - void processMessage(const std::string &data) - { - //infostream<<"LuaEntityCAO: Got message"<<std::endl; - std::istringstream is(data, std::ios::binary); - // command - u8 cmd = readU8(is); - if(cmd == LUAENTITY_CMD_UPDATE_POSITION) // update position - { - // do_interpolate - bool do_interpolate = readU8(is); - // pos - m_position = readV3F1000(is); - // velocity - m_velocity = readV3F1000(is); - // acceleration - m_acceleration = readV3F1000(is); - // yaw - m_yaw = readF1000(is); - // is_end_position (for interpolation) - bool is_end_position = readU8(is); - // update_interval - float update_interval = readF1000(is); - - if(do_interpolate){ - if(!m_prop->physical) - pos_translator.update(m_position, is_end_position, update_interval); - } else { - pos_translator.init(m_position); - } - updateNodePos(); - } - else if(cmd == LUAENTITY_CMD_SET_TEXTURE_MOD) // set texture modification - { - std::string mod = deSerializeString(is); - updateTextures(mod); - } - else if(cmd == LUAENTITY_CMD_SET_SPRITE) // set sprite - { - v2s16 p = readV2S16(is); - int num_frames = readU16(is); - float framelength = readF1000(is); - bool select_horiz_by_yawpitch = readU8(is); - - m_tx_basepos = p; - m_anim_num_frames = num_frames; - m_anim_framelength = framelength; - m_tx_select_horiz_by_yawpitch = select_horiz_by_yawpitch; - - updateTexturePos(); - } - else if(cmd == LUAENTITY_CMD_PUNCHED) - { - /*s16 damage =*/ readS16(is); - s16 result_hp = readS16(is); - - m_hp = result_hp; - // TODO: Execute defined fast response - } - else if(cmd == LUAENTITY_CMD_UPDATE_ARMOR_GROUPS) - { - m_armor_groups.clear(); - int armor_groups_size = readU16(is); - for(int i=0; i<armor_groups_size; i++){ - std::string name = deSerializeString(is); - int rating = readS16(is); - m_armor_groups[name] = rating; - } - } - } - - bool directReportPunch(v3f dir, const ItemStack *punchitem=NULL, - float time_from_last_punch=1000000) - { - assert(punchitem); - const ToolCapabilities *toolcap = - &punchitem->getToolCapabilities(m_gamedef->idef()); - PunchDamageResult result = getPunchDamage( - m_armor_groups, - toolcap, - punchitem, - time_from_last_punch); - - if(result.did_punch && result.damage != 0) - { - if(result.damage < m_hp){ - m_hp -= result.damage; - } else { - m_hp = 0; - // TODO: Execute defined fast response - // As there is no definition, make a smoke puff - ClientSimpleObject *simple = createSmokePuff( - m_smgr, m_env, m_position, - m_prop->visual_size * BS); - m_env->addSimpleObject(simple); - } - // TODO: Execute defined fast response - // Flashing shall suffice as there is no definition - updateTextures("^[brighten"); - m_reset_textures_timer = 0.1; - } - - return false; - } - - std::string debugInfoText() - { - std::ostringstream os(std::ios::binary); - os<<"LuaEntityCAO hp="<<m_hp<<"\n"; - os<<"armor={"; - for(ItemGroupList::const_iterator i = m_armor_groups.begin(); - i != m_armor_groups.end(); i++){ - os<<i->first<<"="<<i->second<<", "; - } - os<<"}"; - return os.str(); - } -}; - -// Prototype -LuaEntityCAO proto_LuaEntityCAO(NULL, NULL); - -/* - PlayerCAO -*/ - -class PlayerCAO : public ClientActiveObject -{ -private: - core::aabbox3d<f32> m_selection_box; - scene::IMeshSceneNode *m_node; - scene::ITextSceneNode* m_text; - std::string m_name; - v3f m_position; - float m_yaw; - SmoothTranslator pos_translator; - bool m_is_local_player; - LocalPlayer *m_local_player; - float m_damage_visual_timer; - bool m_dead; - float m_step_distance_counter; - std::string m_wielded_item; - -public: - PlayerCAO(IGameDef *gamedef, ClientEnvironment *env): - ClientActiveObject(0, gamedef, env), - m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2.0,BS/3.), - m_node(NULL), - m_text(NULL), - m_position(v3f(0,10*BS,0)), - m_yaw(0), - m_is_local_player(false), - m_local_player(NULL), - m_damage_visual_timer(0), - m_dead(false), - m_step_distance_counter(0), - m_wielded_item("") - { - if(gamedef == NULL) - ClientActiveObject::registerType(getType(), create); - } - - void initialize(const std::string &data) - { - infostream<<"PlayerCAO: Got init data"<<std::endl; - - std::istringstream is(data, std::ios::binary); - // version - u8 version = readU8(is); - // check version - if(version != 0) - return; - // name - m_name = deSerializeString(is); - // pos - m_position = readV3F1000(is); - // yaw - m_yaw = readF1000(is); - // dead - m_dead = readU8(is); - // wielded item - try{ - m_wielded_item = deSerializeString(is); - } - catch(SerializationError &e){} - - pos_translator.init(m_position); - - Player *player = m_env->getPlayer(m_name.c_str()); - if(player && player->isLocal()){ - m_is_local_player = true; - m_local_player = (LocalPlayer*)player; - } - } - - ~PlayerCAO() - { - if(m_node) - m_node->remove(); - } - - static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env) - { - return new PlayerCAO(gamedef, env); - } - - u8 getType() const - { - return ACTIVEOBJECT_TYPE_PLAYER; - } - core::aabbox3d<f32>* getSelectionBox() - { - if(m_is_local_player) - return NULL; - if(m_dead) - return NULL; - return &m_selection_box; - } - v3f getPosition() - { - return pos_translator.vect_show; - } - - void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc, - IrrlichtDevice *irr) - { - if(m_node != NULL) - return; - if(m_is_local_player) - return; - - //video::IVideoDriver* driver = smgr->getVideoDriver(); - gui::IGUIEnvironment* gui = irr->getGUIEnvironment(); - - scene::SMesh *mesh = new scene::SMesh(); - { // Front - scene::IMeshBuffer *buf = new scene::SMeshBuffer(); - video::SColor c(255,255,255,255); - video::S3DVertex vertices[4] = - { - video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1), - video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1), - video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0), - video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0), - }; - u16 indices[] = {0,1,2,2,3,0}; - buf->append(vertices, 4, indices, 6); - // Set material - buf->getMaterial().setFlag(video::EMF_LIGHTING, false); - buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false); - buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true); - buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; - // Add to mesh - mesh->addMeshBuffer(buf); - buf->drop(); - } - { // Back - scene::IMeshBuffer *buf = new scene::SMeshBuffer(); - video::SColor c(255,255,255,255); - video::S3DVertex vertices[4] = - { - video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1), - video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1), - video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0), - video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0), - }; - u16 indices[] = {0,1,2,2,3,0}; - buf->append(vertices, 4, indices, 6); - // Set material - buf->getMaterial().setFlag(video::EMF_LIGHTING, false); - buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false); - buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true); - buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; - // Add to mesh - mesh->addMeshBuffer(buf); - buf->drop(); - } - m_node = smgr->addMeshSceneNode(mesh, NULL); - mesh->drop(); - // Set it to use the materials of the meshbuffers directly. - // This is needed for changing the texture in the future - m_node->setReadOnlyMaterials(true); - updateNodePos(); - - // Add a text node for showing the name - std::wstring wname = narrow_to_wide(m_name); - m_text = smgr->addTextSceneNode(gui->getBuiltInFont(), - wname.c_str(), video::SColor(255,255,255,255), m_node); - m_text->setPosition(v3f(0, (f32)BS*2.1, 0)); - - updateTextures(""); - updateVisibility(); - updateNodePos(); - } - - void removeFromScene() - { - if(m_node == NULL) - return; - - m_node->remove(); - m_node = NULL; - } - - void updateLight(u8 light_at_pos) - { - if(m_node == NULL) - return; - - u8 li = decode_light(light_at_pos); - video::SColor color(255,li,li,li); - setMeshColor(m_node->getMesh(), color); - - updateVisibility(); - } - - v3s16 getLightPosition() - { - return floatToInt(m_position+v3f(0,BS*1.5,0), BS); - } - - void updateVisibility() - { - if(m_node == NULL) - return; - - m_node->setVisible(!m_dead); - } - - void updateNodePos() - { - if(m_node == NULL) - return; - - m_node->setPosition(pos_translator.vect_show); - - v3f rot = m_node->getRotation(); - rot.Y = -m_yaw; - m_node->setRotation(rot); - } - - void step(float dtime, ClientEnvironment *env) - { - v3f lastpos = pos_translator.vect_show; - pos_translator.translate(dtime); - float moved = lastpos.getDistanceFrom(pos_translator.vect_show); - updateVisibility(); - updateNodePos(); - - if(m_damage_visual_timer > 0){ - m_damage_visual_timer -= dtime; - if(m_damage_visual_timer <= 0){ - updateTextures(""); - } - } - - m_step_distance_counter += moved; - if(m_step_distance_counter > 1.5*BS){ - m_step_distance_counter = 0; - if(!m_is_local_player){ - INodeDefManager *ndef = m_gamedef->ndef(); - v3s16 p = floatToInt(getPosition()+v3f(0,-0.5*BS, 0), BS); - MapNode n = m_env->getMap().getNodeNoEx(p); - SimpleSoundSpec spec = ndef->get(n).sound_footstep; - m_gamedef->sound()->playSoundAt(spec, false, getPosition()); - } - } - } - - void processMessage(const std::string &data) - { - //infostream<<"PlayerCAO: Got message"<<std::endl; - std::istringstream is(data, std::ios::binary); - // command - u8 cmd = readU8(is); - if(cmd == 0) // update position - { - // pos - m_position = readV3F1000(is); - // yaw - m_yaw = readF1000(is); - - pos_translator.update(m_position, false); - - updateNodePos(); - } - else if(cmd == 1) // punched - { - // damage - s16 damage = readS16(is); - m_damage_visual_timer = 0.05; - if(damage >= 2) - m_damage_visual_timer += 0.05 * damage; - updateTextures("^[brighten"); - } - else if(cmd == 2) // died or respawned - { - m_dead = readU8(is); - updateVisibility(); - } - else if(cmd == 3) // wielded item - { - m_wielded_item = deSerializeString(is); - updateWieldedItem(); - } - } - - void updateTextures(const std::string &mod) - { - if(!m_node) - return; - ITextureSource *tsrc = m_gamedef->tsrc(); - scene::IMesh *mesh = m_node->getMesh(); - if(mesh){ - { - std::string tname = "player.png"; - tname += mod; - scene::IMeshBuffer *buf = mesh->getMeshBuffer(0); - buf->getMaterial().setTexture(0, - tsrc->getTextureRaw(tname)); - } - { - std::string tname = "player_back.png"; - tname += mod; - scene::IMeshBuffer *buf = mesh->getMeshBuffer(1); - buf->getMaterial().setTexture(0, - tsrc->getTextureRaw(tname)); - } - } - } - - void updateWieldedItem() - { - if(m_is_local_player) - { - // ignoring player item for local player - return; - } - - ItemStack item; - try - { - item.deSerialize(m_wielded_item, m_gamedef->idef()); - } - catch(SerializationError &e) - { - errorstream<<"PlayerCAO: SerializationError " - "while reading wielded item: " - <<m_wielded_item<<std::endl; - return; - } - - // do something with the item, for example: - Player *player = m_env->getPlayer(m_name.c_str()); - if(player) - { - InventoryList *inv = player->inventory.getList("main"); - assert(inv); - inv->changeItem(0, item); - } - - if(item.empty()) - { - infostream<<"PlayerCAO: empty player item for player " - <<m_name<<std::endl; - } - else - { - infostream<<"PlayerCAO: player item for player " - <<m_name<<": " - <<item.getItemString()<<std::endl; - } - } - -}; - -// Prototype -PlayerCAO proto_PlayerCAO(NULL, NULL); - -/* GenericCAO */ @@ -1358,6 +543,10 @@ PlayerCAO proto_PlayerCAO(NULL, NULL); class GenericCAO : public ClientActiveObject { private: + // Only set at initialization + std::string m_name; + bool m_is_player; + bool m_is_local_player; // determined locally // Property-ish things s16 m_hp_max; bool m_physical; @@ -1367,11 +556,15 @@ private: v2f m_visual_size; core::array<std::string> m_textures; v2s16 m_spritediv; + bool m_is_visible; + bool m_makes_footstep_sound; // scene::ISceneManager *m_smgr; + IrrlichtDevice *m_irr; core::aabbox3d<f32> m_selection_box; scene::IMeshSceneNode *m_meshnode; scene::IBillboardSceneNode *m_spritenode; + scene::ITextSceneNode* m_textnode; v3f m_position; v3f m_velocity; v3f m_acceleration; @@ -1388,11 +581,16 @@ private: float m_anim_timer; ItemGroupList m_armor_groups; float m_reset_textures_timer; + bool m_visuals_expired; + float m_step_distance_counter; public: GenericCAO(IGameDef *gamedef, ClientEnvironment *env): ClientActiveObject(0, gamedef, env), // + m_is_player(false), + m_is_local_player(false), + // m_hp_max(1), m_physical(false), m_weight(5), @@ -1400,11 +598,15 @@ public: m_visual("sprite"), m_visual_size(1,1), m_spritediv(1,1), + m_is_visible(true), + m_makes_footstep_sound(false), // m_smgr(NULL), + m_irr(NULL), m_selection_box(-BS/3.,-BS/3.,-BS/3., BS/3.,BS/3.,BS/3.), m_meshnode(NULL), m_spritenode(NULL), + m_textnode(NULL), m_position(v3f(0,10*BS,0)), m_velocity(v3f(0,0,0)), m_acceleration(v3f(0,0,0)), @@ -1417,7 +619,9 @@ public: m_anim_num_frames(1), m_anim_framelength(0.2), m_anim_timer(0), - m_reset_textures_timer(-1) + m_reset_textures_timer(-1), + m_visuals_expired(false), + m_step_distance_counter(0) { m_textures.push_back("unknown_object.png"); if(gamedef == NULL) @@ -1427,23 +631,36 @@ public: void initialize(const std::string &data) { infostream<<"GenericCAO: Got init data"<<std::endl; - std::istringstream is(data, std::ios::binary); // version u8 version = readU8(is); // check version - if(version != 1) + if(version != 0){ + errorstream<<"GenericCAO: Unsupported init data version" + <<std::endl; return; - // pos + } + m_name = deSerializeString(is); + m_is_player = readU8(is); m_position = readV3F1000(is); - // yaw m_yaw = readF1000(is); - // hp m_hp = readS16(is); + + int num_messages = readU8(is); + for(int i=0; i<num_messages; i++){ + std::string message = deSerializeLongString(is); + processMessage(message); + } pos_translator.init(m_position); - updateNodePos(); + + if(m_is_player){ + Player *player = m_env->getPlayer(m_name.c_str()); + if(player && player->isLocal()){ + m_is_local_player = true; + } + } } ~GenericCAO() @@ -1461,6 +678,8 @@ public: } core::aabbox3d<f32>* getSelectionBox() { + if(!m_is_visible || m_is_local_player) + return NULL; return &m_selection_box; } v3f getPosition() @@ -1484,10 +703,16 @@ public: IrrlichtDevice *irr) { m_smgr = smgr; + m_irr = irr; if(m_meshnode != NULL || m_spritenode != NULL) return; + m_visuals_expired = false; + + if(!m_is_visible || m_is_local_player) + return; + //video::IVideoDriver* driver = smgr->getVideoDriver(); if(m_visual == "sprite"){ @@ -1509,7 +734,61 @@ public: setBillboardTextureMatrix(m_spritenode, txs, tys, 0, 0); } - } else if(m_visual == "cube"){ + } + else if(m_visual == "upright_sprite") + { + scene::SMesh *mesh = new scene::SMesh(); + double dx = BS*m_visual_size.X/2; + double dy = BS*m_visual_size.Y/2; + { // Front + scene::IMeshBuffer *buf = new scene::SMeshBuffer(); + video::SColor c(255,255,255,255); + video::S3DVertex vertices[4] = + { + video::S3DVertex(-dx,-dy,0, 0,0,0, c, 0,1), + video::S3DVertex(dx,-dy,0, 0,0,0, c, 1,1), + video::S3DVertex(dx,dy,0, 0,0,0, c, 1,0), + video::S3DVertex(-dx,dy,0, 0,0,0, c, 0,0), + }; + u16 indices[] = {0,1,2,2,3,0}; + buf->append(vertices, 4, indices, 6); + // Set material + buf->getMaterial().setFlag(video::EMF_LIGHTING, false); + buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false); + buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true); + buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; + // Add to mesh + mesh->addMeshBuffer(buf); + buf->drop(); + } + { // Back + scene::IMeshBuffer *buf = new scene::SMeshBuffer(); + video::SColor c(255,255,255,255); + video::S3DVertex vertices[4] = + { + video::S3DVertex(dx,-dy,0, 0,0,0, c, 1,1), + video::S3DVertex(-dx,-dy,0, 0,0,0, c, 0,1), + video::S3DVertex(-dx,dy,0, 0,0,0, c, 0,0), + video::S3DVertex(dx,dy,0, 0,0,0, c, 1,0), + }; + u16 indices[] = {0,1,2,2,3,0}; + buf->append(vertices, 4, indices, 6); + // Set material + buf->getMaterial().setFlag(video::EMF_LIGHTING, false); + buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false); + buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true); + buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; + // Add to mesh + mesh->addMeshBuffer(buf); + buf->drop(); + } + m_meshnode = smgr->addMeshSceneNode(mesh, NULL); + mesh->drop(); + // Set it to use the materials of the meshbuffers directly. + // This is needed for changing the texture in the future + m_meshnode->setReadOnlyMaterials(true); + } + else if(m_visual == "cube"){ infostream<<"GenericCAO::addToScene(): cube"<<std::endl; scene::IMesh *mesh = createCubeMesh(v3f(BS,BS,BS)); m_meshnode = smgr->addMeshSceneNode(mesh, NULL); @@ -1523,14 +802,27 @@ public: <<"\" not supported"<<std::endl; } updateTextures(""); + + scene::ISceneNode *node = NULL; + if(m_spritenode) + node = m_spritenode; + else if(m_meshnode) + node = m_meshnode; + if(node && m_is_player && !m_is_local_player){ + // Add a text node for showing the name + gui::IGUIEnvironment* gui = irr->getGUIEnvironment(); + std::wstring wname = narrow_to_wide(m_name); + m_textnode = smgr->addTextSceneNode(gui->getBuiltInFont(), + wname.c_str(), video::SColor(255,255,255,255), node); + m_textnode->setPosition(v3f(0, BS*1.1, 0)); + } + updateNodePos(); } - void updateVisuals() + void expireVisuals() { - removeFromScene(); - // We haven't got any IrrlichtDevices but it isn't actually needed - addToScene(m_smgr, m_gamedef->tsrc(), NULL); + m_visuals_expired = true; } void updateLight(u8 light_at_pos) @@ -1557,6 +849,9 @@ public: { if(m_meshnode){ m_meshnode->setPosition(pos_translator.vect_show); + v3f rot = m_meshnode->getRotation(); + rot.Y = -m_yaw; + m_meshnode->setRotation(rot); } if(m_spritenode){ m_spritenode->setPosition(pos_translator.vect_show); @@ -1565,6 +860,14 @@ public: void step(float dtime, ClientEnvironment *env) { + v3f lastpos = pos_translator.vect_show; + + if(m_visuals_expired && m_smgr && m_irr){ + m_visuals_expired = false; + removeFromScene(); + addToScene(m_smgr, m_gamedef->tsrc(), m_irr); + } + if(m_physical){ core::aabbox3d<f32> box = m_collisionbox; box.MinEdge *= BS; @@ -1594,6 +897,19 @@ public: updateNodePos(); } + float moved = lastpos.getDistanceFrom(pos_translator.vect_show); + m_step_distance_counter += moved; + if(m_step_distance_counter > 1.5*BS){ + m_step_distance_counter = 0; + if(!m_is_local_player && m_makes_footstep_sound){ + INodeDefManager *ndef = m_gamedef->ndef(); + v3s16 p = floatToInt(getPosition()+v3f(0,-0.5*BS, 0), BS); + MapNode n = m_env->getMap().getNodeNoEx(p); + SimpleSoundSpec spec = ndef->get(n).sound_footstep; + m_gamedef->sound()->playSoundAt(spec, false, getPosition()); + } + } + m_anim_timer += dtime; if(m_anim_timer >= m_anim_framelength){ m_anim_timer -= m_anim_framelength; @@ -1665,35 +981,67 @@ public: { ITextureSource *tsrc = m_gamedef->tsrc(); - if(m_spritenode){ - std::string texturestring = "unknown_block.png"; - if(m_textures.size() >= 1) - texturestring = m_textures[0]; - texturestring += mod; - m_spritenode->setMaterialTexture(0, - tsrc->getTextureRaw(texturestring)); - } - if(m_meshnode){ - for (u32 i = 0; i < 6; ++i) + if(m_spritenode) + { + if(m_visual == "sprite") { std::string texturestring = "unknown_block.png"; - if(m_textures.size() > i) - texturestring = m_textures[i]; + if(m_textures.size() >= 1) + texturestring = m_textures[0]; texturestring += mod; - AtlasPointer ap = tsrc->getTexture(texturestring); - - // Get the tile texture and atlas transformation - video::ITexture* atlas = ap.atlas; - v2f pos = ap.pos; - v2f size = ap.size; - - // Set material flags and texture - video::SMaterial& material = m_meshnode->getMaterial(i); - material.setFlag(video::EMF_LIGHTING, false); - material.setFlag(video::EMF_BILINEAR_FILTER, false); - material.setTexture(0, atlas); - material.getTextureMatrix(0).setTextureTranslate(pos.X, pos.Y); - material.getTextureMatrix(0).setTextureScale(size.X, size.Y); + m_spritenode->setMaterialTexture(0, + tsrc->getTextureRaw(texturestring)); + } + } + if(m_meshnode) + { + if(m_visual == "cube") + { + for (u32 i = 0; i < 6; ++i) + { + std::string texturestring = "unknown_block.png"; + if(m_textures.size() > i) + texturestring = m_textures[i]; + texturestring += mod; + AtlasPointer ap = tsrc->getTexture(texturestring); + + // Get the tile texture and atlas transformation + video::ITexture* atlas = ap.atlas; + v2f pos = ap.pos; + v2f size = ap.size; + + // Set material flags and texture + video::SMaterial& material = m_meshnode->getMaterial(i); + material.setFlag(video::EMF_LIGHTING, false); + material.setFlag(video::EMF_BILINEAR_FILTER, false); + material.setTexture(0, atlas); + material.getTextureMatrix(0).setTextureTranslate(pos.X, pos.Y); + material.getTextureMatrix(0).setTextureScale(size.X, size.Y); + } + } + else if(m_visual == "upright_sprite") + { + scene::IMesh *mesh = m_meshnode->getMesh(); + { + std::string tname = "unknown_object.png"; + if(m_textures.size() >= 1) + tname = m_textures[0]; + tname += mod; + scene::IMeshBuffer *buf = mesh->getMeshBuffer(0); + buf->getMaterial().setTexture(0, + tsrc->getTextureRaw(tname)); + } + { + std::string tname = "unknown_object.png"; + if(m_textures.size() >= 2) + tname = m_textures[1]; + else if(m_textures.size() >= 1) + tname = m_textures[0]; + tname += mod; + scene::IMeshBuffer *buf = mesh->getMeshBuffer(1); + buf->getMaterial().setTexture(0, + tsrc->getTextureRaw(tname)); + } } } } @@ -1719,7 +1067,9 @@ public: m_textures.push_back(deSerializeString(is)); } m_spritediv = readV2S16(is); - + m_is_visible = readU8(is); + m_makes_footstep_sound = readU8(is); + m_selection_box = m_collisionbox; m_selection_box.MinEdge *= BS; m_selection_box.MaxEdge *= BS; @@ -1727,7 +1077,7 @@ public: m_tx_size.X = 1.0 / m_spritediv.X; m_tx_size.Y = 1.0 / m_spritediv.Y; - updateVisuals(); + expireVisuals(); } else if(cmd == GENERIC_CMD_UPDATE_POSITION) { @@ -1772,7 +1122,6 @@ public: s16 result_hp = readS16(is); m_hp = result_hp; - // TODO: Execute defined fast response } else if(cmd == GENERIC_CMD_UPDATE_ARMOR_GROUPS) { @@ -1797,6 +1146,8 @@ public: toolcap, punchitem, time_from_last_punch); + + dstream<<"Directly did_punch="<<result.did_punch<<" result.damage="<<result.damage<<std::endl; if(result.did_punch && result.damage != 0) { @@ -1813,8 +1164,10 @@ public: } // TODO: Execute defined fast response // Flashing shall suffice as there is no definition + m_reset_textures_timer = 0.05; + if(result.damage >= 2) + m_reset_textures_timer += 0.05 * result.damage; updateTextures("^[brighten"); - m_reset_textures_timer = 0.1; } return false; |