diff --git a/data/dungeon_master.png b/data/dungeon_master.png new file mode 100644 index 000000000..77e015c16 Binary files /dev/null and b/data/dungeon_master.png differ diff --git a/data/fireball.png b/data/fireball.png new file mode 100644 index 000000000..523142850 Binary files /dev/null and b/data/fireball.png differ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1d3218bcd..ab50394f7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -107,7 +107,6 @@ set(common_SRCS defaultsettings.cpp mapnode.cpp voxel.cpp - mapblockobject.cpp inventory.cpp debug.cpp serialization.cpp @@ -137,6 +136,7 @@ endif() # Client sources set(minetest_SRCS ${common_SRCS} + MyBillboardSceneNode.cpp content_mapblock.cpp content_cao.cpp mapblock_mesh.cpp diff --git a/src/MyBillboardSceneNode.cpp b/src/MyBillboardSceneNode.cpp new file mode 100644 index 000000000..0dfa59bed --- /dev/null +++ b/src/MyBillboardSceneNode.cpp @@ -0,0 +1,202 @@ +// Copyright (C) 2002-2010 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#include "MyBillboardSceneNode.h" +#include "IVideoDriver.h" +#include "ISceneManager.h" +#include "ICameraSceneNode.h" + +namespace irr +{ +namespace scene +{ + +//! constructor +MyBillboardSceneNode::MyBillboardSceneNode(ISceneNode* parent, + ISceneManager* mgr, s32 id, + const core::vector3df& position, const core::dimension2d& size) + : IBillboardSceneNode(parent, mgr, id, position) +{ + #ifdef _DEBUG + setDebugName("MyBillboardSceneNode"); + #endif + + setSize(size); + + indices[0] = 0; + indices[1] = 2; + indices[2] = 1; + indices[3] = 0; + indices[4] = 3; + indices[5] = 2; + + video::SColor colorTop = video::SColor(0xFFFFFFFF); + video::SColor colorBottom = video::SColor(0xFFFFFFFF); + + vertices[0].TCoords.set(1.0f, 1.0f); + vertices[0].Color = colorBottom; + + vertices[1].TCoords.set(1.0f, 0.0f); + vertices[1].Color = colorTop; + + vertices[2].TCoords.set(0.0f, 0.0f); + vertices[2].Color = colorTop; + + vertices[3].TCoords.set(0.0f, 1.0f); + vertices[3].Color = colorBottom; +} + + +//! pre render event +void MyBillboardSceneNode::OnRegisterSceneNode() +{ + if (IsVisible) + SceneManager->registerNodeForRendering(this); + + ISceneNode::OnRegisterSceneNode(); +} + + +//! render +void MyBillboardSceneNode::render() +{ + video::IVideoDriver* driver = SceneManager->getVideoDriver(); + ICameraSceneNode* camera = SceneManager->getActiveCamera(); + + if (!camera || !driver) + return; + + // make billboard look to camera + + core::vector3df pos = getAbsolutePosition(); + + core::vector3df campos = camera->getAbsolutePosition(); + core::vector3df target = camera->getTarget(); + core::vector3df up = camera->getUpVector(); + core::vector3df view = target - campos; + view.normalize(); + + core::vector3df horizontal = up.crossProduct(view); + if ( horizontal.getLength() == 0 ) + { + horizontal.set(up.Y,up.X,up.Z); + } + horizontal.normalize(); + horizontal *= 0.5f * Size.Width; + + core::vector3df vertical = horizontal.crossProduct(view); + vertical.normalize(); + vertical *= 0.5f * Size.Height; + + view *= -1.0f; + + for (s32 i=0; i<4; ++i) + vertices[i].Normal = view; + + vertices[0].Pos = pos + horizontal + vertical; + vertices[1].Pos = pos + horizontal - vertical; + vertices[2].Pos = pos - horizontal - vertical; + vertices[3].Pos = pos - horizontal + vertical; + + // draw + + if ( DebugDataVisible & scene::EDS_BBOX ) + { + driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); + video::SMaterial m; + m.Lighting = false; + driver->setMaterial(m); + driver->draw3DBox(BBox, video::SColor(0,208,195,152)); + } + + driver->setTransform(video::ETS_WORLD, core::IdentityMatrix); + + driver->setMaterial(Material); + + driver->drawIndexedTriangleList(vertices, 4, indices, 2); +} + + +//! returns the axis aligned bounding box of this node +const core::aabbox3d& MyBillboardSceneNode::getBoundingBox() const +{ + return BBox; +} + + +//! sets the size of the billboard +void MyBillboardSceneNode::setSize(const core::dimension2d& size) +{ + Size = size; + + if (Size.Width == 0.0f) + Size.Width = 1.0f; + + if (Size.Height == 0.0f ) + Size.Height = 1.0f; + + f32 avg = (size.Width + size.Height)/6; + BBox.MinEdge.set(-avg,-avg,-avg); + BBox.MaxEdge.set(avg,avg,avg); +} + + +video::SMaterial& MyBillboardSceneNode::getMaterial(u32 i) +{ + return Material; +} + + +//! returns amount of materials used by this scene node. +u32 MyBillboardSceneNode::getMaterialCount() const +{ + return 1; +} + + +//! gets the size of the billboard +const core::dimension2d& MyBillboardSceneNode::getSize() const +{ + return Size; +} + + +//! Set the color of all vertices of the billboard +//! \param overallColor: the color to set +void MyBillboardSceneNode::setColor(const video::SColor & overallColor) +{ + for(u32 vertex = 0; vertex < 4; ++vertex) + vertices[vertex].Color = overallColor; +} + + +//! Set the color of the top and bottom vertices of the billboard +//! \param topColor: the color to set the top vertices +//! \param bottomColor: the color to set the bottom vertices +void MyBillboardSceneNode::setColor(const video::SColor & topColor, const video::SColor & bottomColor) +{ + vertices[0].Color = bottomColor; + vertices[1].Color = topColor; + vertices[2].Color = topColor; + vertices[3].Color = bottomColor; +} + + +//! Gets the color of the top and bottom vertices of the billboard +//! \param[out] topColor: stores the color of the top vertices +//! \param[out] bottomColor: stores the color of the bottom vertices +void MyBillboardSceneNode::getColor(video::SColor & topColor, video::SColor & bottomColor) const +{ + bottomColor = vertices[0].Color; + topColor = vertices[1].Color; +} + +void MyBillboardSceneNode::setTCoords(u32 i, core::vector2d c) +{ + vertices[i].TCoords = c; +} + +} // end namespace scene +} // end namespace irr + diff --git a/src/MyBillboardSceneNode.h b/src/MyBillboardSceneNode.h new file mode 100644 index 000000000..935993d8f --- /dev/null +++ b/src/MyBillboardSceneNode.h @@ -0,0 +1,77 @@ +// Copyright (C) 2002-2010 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __C_BILLBOARD_SCENE_NODE_H_INCLUDED__ +#define __C_BILLBOARD_SCENE_NODE_H_INCLUDED__ + +#include "IBillboardSceneNode.h" +#include "S3DVertex.h" + +namespace irr +{ +namespace scene +{ + +//! Scene node which is a billboard. A billboard is like a 3d sprite: A 2d element, +//! which always looks to the camera. +class MyBillboardSceneNode : virtual public IBillboardSceneNode +{ +public: + + //! constructor + MyBillboardSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id, + const core::vector3df& position, const core::dimension2d& size); + + //! pre render event + virtual void OnRegisterSceneNode(); + + //! render + virtual void render(); + + //! returns the axis aligned bounding box of this node + virtual const core::aabbox3d& getBoundingBox() const; + + //! sets the size of the billboard + virtual void setSize(const core::dimension2d& size); + + //! gets the size of the billboard + virtual const core::dimension2d& getSize() const; + + virtual video::SMaterial& getMaterial(u32 i); + + //! returns amount of materials used by this scene node. + virtual u32 getMaterialCount() const; + + //! Set the color of all vertices of the billboard + //! \param overallColor: the color to set + virtual void setColor(const video::SColor & overallColor); + + //! Set the color of the top and bottom vertices of the billboard + //! \param topColor: the color to set the top vertices + //! \param bottomColor: the color to set the bottom vertices + virtual void setColor(const video::SColor & topColor, const video::SColor & bottomColor); + + //! Gets the color of the top and bottom vertices of the billboard + //! \param[out] topColor: stores the color of the top vertices + //! \param[out] bottomColor: stores the color of the bottom vertices + virtual void getColor(video::SColor& topColor, video::SColor& bottomColor) const; + + virtual void setTCoords(u32 i, core::vector2d c); + +private: + + core::dimension2d Size; + core::aabbox3d BBox; + video::SMaterial Material; + + video::S3DVertex vertices[4]; + u16 indices[6]; +}; + + +} // end namespace scene +} // end namespace irr + +#endif + diff --git a/src/client.cpp b/src/client.cpp index ee66e648e..1e81a464c 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -522,24 +522,6 @@ void Client::step(float dtime) // Step environment m_env.step(dtime); - /* - Handle active blocks - NOTE: These old objects are DEPRECATED. TODO: Remove - */ - for(core::map::Iterator - i = m_active_blocks.getIterator(); - i.atEnd() == false; i++) - { - v3s16 p = i.getNode()->getKey(); - - MapBlock *block = m_env.getMap().getBlockNoCreateNoEx(p); - if(block == NULL) - continue; - - // Step MapBlockObjects - block->stepObjects(dtime, false, m_env.getDayNightRatio()); - } - /* Get events */ @@ -1191,16 +1173,11 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) } //DEBUG else if(command == TOCLIENT_OBJECTDATA) - //else if(0) { // Strip command word and create a stringstream std::string datastring((char*)&data[2], datasize-2); std::istringstream is(datastring, std::ios_base::binary); - { //envlock - - //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out - u8 buf[12]; /* @@ -1250,106 +1227,16 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) /* Read block objects - NOTE: Deprecated stuff here, TODO: Remove + NOTE: Deprecated stuff */ // Read active block count - is.read((char*)buf, 2); - u16 blockcount = readU16(buf); - - // Initialize delete queue with all active blocks - core::map abs_to_delete; - for(core::map::Iterator - i = m_active_blocks.getIterator(); - i.atEnd() == false; i++) - { - v3s16 p = i.getNode()->getKey(); - /*dstream<<"adding " - <<"("<updateObjects(is, m_server_ser_ver, - m_device->getSceneManager(), m_env.getDayNightRatio()); - } - - /*dstream<<"Final delete queue size: "<::Iterator - i = abs_to_delete.getIterator(); - i.atEnd() == false; i++) - { - v3s16 p = i.getNode()->getKey(); - try - { - MapBlock *block = m_env.getMap().getBlockNoCreate(p); - - // Clear objects - block->clearObjects(); - // Remove from active blocks list - m_active_blocks.remove(p); - } - catch(InvalidPositionException &e) - { - dstream<<"WARNAING: Client: " - <<"Couldn't clear objects of active->inactive" - <<" block " - <<"("< data(datasize); - writeU16(&data[0], TOSERVER_CLICK_OBJECT); - writeU8(&data[2], button); - writeV3S16(&data[3], blockpos); - writeS16(&data[9], id); - writeU16(&data[11], item); - Send(0, data, true); -} - void Client::clickActiveObject(u8 button, u16 id, u16 item) { if(connectedAndInitialized() == false){ @@ -1687,45 +1548,6 @@ void Client::clickActiveObject(u8 button, u16 id, u16 item) Send(0, data, true); } -void Client::sendSignText(v3s16 blockpos, s16 id, std::string text) -{ - /* - u16 command - v3s16 blockpos - s16 id - u16 textlen - textdata - */ - std::ostringstream os(std::ios_base::binary); - u8 buf[12]; - - // Write command - writeU16(buf, TOSERVER_SIGNTEXT); - os.write((char*)buf, 2); - - // Write blockpos - writeV3S16(buf, blockpos); - os.write((char*)buf, 6); - - // Write id - writeS16(buf, id); - os.write((char*)buf, 2); - - u16 textlen = text.size(); - // Write text length - writeS16(buf, textlen); - os.write((char*)buf, 2); - - // Write text - os.write((char*)text.c_str(), textlen); - - // Make data buffer - std::string s = os.str(); - SharedBuffer data((u8*)s.c_str(), s.size()); - // Send as reliable - Send(0, data, true); -} - void Client::sendSignNodeText(v3s16 p, std::string text) { /* @@ -2083,71 +1905,6 @@ void Client::inventoryAction(InventoryAction *a) sendInventoryAction(a); } -MapBlockObject * Client::getSelectedObject( - f32 max_d, - v3f from_pos_f_on_map, - core::line3d shootline_on_map - ) -{ - //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out - - core::array objects; - - for(core::map::Iterator - i = m_active_blocks.getIterator(); - i.atEnd() == false; i++) - { - v3s16 p = i.getNode()->getKey(); - - MapBlock *block = NULL; - try - { - block = m_env.getMap().getBlockNoCreate(p); - } - catch(InvalidPositionException &e) - { - continue; - } - - // Calculate from_pos relative to block - v3s16 block_pos_i_on_map = block->getPosRelative(); - v3f block_pos_f_on_map = intToFloat(block_pos_i_on_map, BS); - v3f from_pos_f_on_block = from_pos_f_on_map - block_pos_f_on_map; - - block->getObjects(from_pos_f_on_block, max_d, objects); - //block->getPseudoObjects(from_pos_f_on_block, max_d, objects); - } - - //dstream<<"Collected "<getBlock(); - - // Calculate shootline relative to block - v3s16 block_pos_i_on_map = block->getPosRelative(); - v3f block_pos_f_on_map = intToFloat(block_pos_i_on_map, BS); - core::line3d shootline_on_block( - shootline_on_map.start - block_pos_f_on_map, - shootline_on_map.end - block_pos_f_on_map - ); - - if(obj->isSelected(shootline_on_block)) - { - //dstream<<"Returning selected object"< shootline_on_map - ); - // Gets closest object pointed by the shootline // Returns NULL if not found ClientActiveObject * getSelectedActiveObject( diff --git a/src/clientobject.cpp b/src/clientobject.cpp index bec9f46fd..ee2ad0b9f 100644 --- a/src/clientobject.cpp +++ b/src/clientobject.cpp @@ -45,7 +45,7 @@ ClientActiveObject* ClientActiveObject::create(u8 type) { // If factory is not found, just return. dstream<<"WARNING: ClientActiveObject: No factory for type=" - <* getSelectionBox(){return NULL;} virtual core::aabbox3d* getCollisionBox(){return NULL;} virtual v3f getPosition(){return v3f(0,0,0);} + virtual bool doShowSelectionBox(){return true;} // Step object in time virtual void step(float dtime, ClientEnvironment *env){} diff --git a/src/content_cao.cpp b/src/content_cao.cpp index b6543061a..88c8d58a9 100644 --- a/src/content_cao.cpp +++ b/src/content_cao.cpp @@ -20,6 +20,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "content_cao.h" #include "tile.h" #include "environment.h" +#include "settings.h" +#include core::map ClientActiveObject::m_types; @@ -683,7 +685,7 @@ void Oerkki1CAO::processMessage(const std::string &data) } else if(cmd == 1) { - u16 damage = readU8(is); + //u16 damage = readU8(is); m_damage_visual_timer = 1.0; } } @@ -850,3 +852,377 @@ void FireflyCAO::initialize(const std::string &data) updateNodePos(); } + +/* + MobV2CAO +*/ + +// Prototype +MobV2CAO proto_MobV2CAO; + +MobV2CAO::MobV2CAO(): + ClientActiveObject(0), + m_selection_box(-0.4*BS,-0.4*BS,-0.4*BS, 0.4*BS,0.8*BS,0.4*BS), + m_node(NULL), + m_position(v3f(0,10*BS,0)), + m_yaw(0), + m_walking(false), + m_walking_unset_timer(0), + m_walk_timer(0), + m_walk_frame(0), + m_damage_visual_timer(0), + m_last_light(0), + m_shooting(0), + m_shooting_unset_timer(0), + m_bright_shooting(false), + m_player_hit_timer(0) +{ + ClientActiveObject::registerType(getType(), create); + + m_properties = new Settings; +} + +MobV2CAO::~MobV2CAO() +{ + delete m_properties; +} + +ClientActiveObject* MobV2CAO::create() +{ + return new MobV2CAO(); +} + +void MobV2CAO::addToScene(scene::ISceneManager *smgr) +{ + if(m_node != NULL) + return; + + std::string texture_name = m_properties->get("texture_name"); + //dstream<<"MobV2CAO::addToScene using texture_name="<getRootSceneNode(), smgr, -1, v3f(0,0,0), v2f(1,1)); + bill->setMaterialTexture(0, g_texturesource->getTextureRaw(texture_string)); + bill->setMaterialFlag(video::EMF_LIGHTING, false); + bill->setMaterialFlag(video::EMF_BILINEAR_FILTER, false); + bill->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF); + bill->setMaterialFlag(video::EMF_FOG_ENABLE, true); + bill->setColor(video::SColor(255,0,0,0)); + bill->setVisible(false); /* Set visible when brightness is known */ + bill->setSize(m_sprite_size); + if(m_sprite_type == "humanoid_1"){ + const float txp = 1./192; + const float txs = txp*32; + const float typ = 1./240; + const float tys = typ*48; + bill->setTCoords(0, v2f(txs*1, tys*1)); + bill->setTCoords(1, v2f(txs*1, tys*0)); + bill->setTCoords(2, v2f(txs*0, tys*0)); + bill->setTCoords(3, v2f(txs*0, tys*1)); + } else if(m_sprite_type == "simple"){ + const float txs = 1.0; + const float tys = 1.0 / m_simple_anim_frames; + bill->setTCoords(0, v2f(txs*1, tys*1)); + bill->setTCoords(1, v2f(txs*1, tys*0)); + bill->setTCoords(2, v2f(txs*0, tys*0)); + bill->setTCoords(3, v2f(txs*0, tys*1)); + } else { + dstream<<"MobV2CAO: Unknown sprite type \""<drop(); + m_node->remove(); + m_node = NULL; +} + +void MobV2CAO::updateLight(u8 light_at_pos) +{ + if(m_lock_full_brightness) + light_at_pos = 15; + + m_last_light = light_at_pos; + + if(m_node == NULL) + return; + + if(m_damage_visual_timer > 0) + return; + + if(m_shooting && m_bright_shooting) + return; + + /*if(light_at_pos <= 2){ + m_node->setVisible(false); + return; + }*/ + + m_node->setVisible(true); + + u8 li = decode_light(light_at_pos); + video::SColor color(255,li,li,li); + m_node->setColor(color); +} + +v3s16 MobV2CAO::getLightPosition() +{ + return floatToInt(m_position+v3f(0,0,0), BS); +} + +void MobV2CAO::updateNodePos() +{ + if(m_node == NULL) + return; + + m_node->setPosition(pos_translator.vect_show + m_sprite_pos); +} + +void MobV2CAO::step(float dtime, ClientEnvironment *env) +{ + scene::MyBillboardSceneNode *bill = m_node; + + pos_translator.translate(dtime); + + if(m_sprite_type == "humanoid_1"){ + scene::ICameraSceneNode* camera = m_node->getSceneManager()->getActiveCamera(); + v3f cam_to_mob = m_node->getAbsolutePosition() - camera->getAbsolutePosition(); + cam_to_mob.normalize(); + int col = 0; + if(cam_to_mob.Y > 0.7) + col = 5; + else if(cam_to_mob.Y < -0.7) + col = 4; + else{ + float mob_dir = atan2(cam_to_mob.Z, cam_to_mob.X) / M_PI * 180.; + float dir = mob_dir - m_yaw; + dir = wrapDegrees_180(dir); + //dstream<<"id="<= m_simple_anim_frametime){ + m_walk_frame = (m_walk_frame + 1) % m_simple_anim_frames; + m_walk_timer = 0; + } + int col = 0; + int row = m_walk_frame; + const float txs = 1.0; + const float tys = 1.0 / m_simple_anim_frames; + bill->setTCoords(0, v2f(txs*(1+col), tys*(1+row))); + bill->setTCoords(1, v2f(txs*(1+col), tys*(0+row))); + bill->setTCoords(2, v2f(txs*(0+col), tys*(0+row))); + bill->setTCoords(3, v2f(txs*(0+col), tys*(1+row))); + } else { + dstream<<"MobV2CAO::step(): Unknown sprite type \"" + <getLocalPlayer(); + assert(player); + + v3f playerpos = player->getPosition(); + v2f playerpos_2d(playerpos.X,playerpos.Z); + v2f objectpos_2d(m_position.X,m_position.Z); + + if(fabs(m_position.Y - playerpos.Y) < m_player_hit_distance*BS && + objectpos_2d.getDistanceFrom(playerpos_2d) < m_player_hit_distance*BS) + { + env->damageLocalPlayer(m_player_hit_damage); + m_player_hit_timer = m_player_hit_interval; + } + } + + /* Run timers */ + + m_player_hit_timer -= dtime; + + if(m_damage_visual_timer >= 0){ + m_damage_visual_timer -= dtime; + if(m_damage_visual_timer <= 0){ + dstream<<"id="<= 1.0){ + m_walking = false; + } + + m_shooting_unset_timer -= dtime; + if(m_shooting_unset_timer <= 0.0){ + if(m_bright_shooting){ + u8 li = decode_light(m_last_light); + video::SColor color(255,li,li,li); + bill->setColor(color); + m_bright_shooting = false; + } + m_shooting = false; + } + +} + +void MobV2CAO::processMessage(const std::string &data) +{ + //dstream<<"MobV2CAO: Got message"<= 100) + li = 30; + else + li = 255; + video::SColor color(255,li,li,li); + m_node->setColor(color); + + m_damage_visual_timer = 0.2; + } + // Trigger shooting + else if(cmd == 2) + { + // length + m_shooting_unset_timer = readF1000(is); + // bright? + m_bright_shooting = readU8(is); + if(m_bright_shooting){ + u8 li = 255; + video::SColor color(255,li,li,li); + m_node->setColor(color); + } + + m_shooting = true; + } +} + +void MobV2CAO::initialize(const std::string &data) +{ + //dstream<<"MobV2CAO: Got init data"<parseConfigLines(tmp_is, "MobArgsEnd"); + + /*dstream<<"INFO: MobV2CAO::initialize(): got properties:"<writeLines(dstream);*/ + + m_properties->setDefault("texture_name", "stone.png"); + m_properties->setDefault("yaw", "0"); + m_properties->setDefault("pos", "(0,0,0)"); + m_properties->setDefault("sprite_size", "(1,1)"); + m_properties->setDefault("sprite_pos", "(0,0,0)"); + m_properties->setDefault("selection_size", "(0.4,0.4)"); + m_properties->setDefault("selection_y", "-0.4"); + m_properties->setDefault("sprite_type", "humanoid_1"); + m_properties->setDefault("simple_anim_frames", "1"); + m_properties->setDefault("simple_anim_frametime", "0.5"); + m_properties->setDefault("lock_full_brightness", "false"); + m_properties->setDefault("player_hit_damage", "0"); + m_properties->setDefault("player_hit_distance", "1.5"); + m_properties->setDefault("player_hit_interval", "1.5"); + + m_yaw = m_properties->getFloat("yaw"); + m_position = m_properties->getV3F("pos"); + m_sprite_size = m_properties->getV2F("sprite_size") * BS; + m_sprite_pos = m_properties->getV3F("sprite_pos") * BS; + v2f selection_size = m_properties->getV2F("selection_size") * BS; + float selection_y = m_properties->getFloat("selection_y") * BS; + m_selection_box = core::aabbox3d( + -selection_size.X, selection_y, -selection_size.X, + selection_size.X, selection_y+selection_size.Y, + selection_size.X); + m_sprite_type = m_properties->get("sprite_type"); + m_simple_anim_frames = m_properties->getS32("simple_anim_frames"); + m_simple_anim_frametime = m_properties->getFloat("simple_anim_frametime"); + m_lock_full_brightness = m_properties->getBool("lock_full_brightness"); + m_player_hit_damage = m_properties->getS32("player_hit_damage"); + m_player_hit_distance = m_properties->getFloat("player_hit_distance"); + m_player_hit_interval = m_properties->getFloat("player_hit_interval"); + + pos_translator.init(m_position); + } + + updateNodePos(); +} + + diff --git a/src/content_cao.h b/src/content_cao.h index 319f90380..e240d7392 100644 --- a/src/content_cao.h +++ b/src/content_cao.h @@ -23,6 +23,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "clientobject.h" #include "content_object.h" #include "utility.h" // For IntervalLimiter +class Settings; +#include "MyBillboardSceneNode.h" /* SmoothTranslator @@ -74,11 +76,16 @@ struct SmoothTranslator if(anim_time > 0.001) moveratio = anim_time_counter / anim_time; // Move a bit less than should, to avoid oscillation - moveratio = moveratio * 0.8; + moveratio = moveratio * 0.5; if(moveratio > 1.5) moveratio = 1.5; vect_show = vect_old + vect_move * moveratio; } + + bool is_moving() + { + return ((anim_time_counter / anim_time) < 1.4); + } }; @@ -286,6 +293,72 @@ private: SmoothTranslator pos_translator; }; +/* + MobV2CAO +*/ + +class MobV2CAO : public ClientActiveObject +{ +public: + MobV2CAO(); + virtual ~MobV2CAO(); + + u8 getType() const + { + return ACTIVEOBJECT_TYPE_MOBV2; + } + + static ClientActiveObject* create(); + + void addToScene(scene::ISceneManager *smgr); + void removeFromScene(); + void updateLight(u8 light_at_pos); + v3s16 getLightPosition(); + void updateNodePos(); + + void step(float dtime, ClientEnvironment *env); + + void processMessage(const std::string &data); + + void initialize(const std::string &data); + + core::aabbox3d* getSelectionBox() + {return &m_selection_box;} + v3f getPosition() + {return pos_translator.vect_show;} + //{return m_position;} + bool doShowSelectionBox(){return false;} + +private: + IntervalLimiter m_attack_interval; + core::aabbox3d m_selection_box; + scene::MyBillboardSceneNode *m_node; + v3f m_position; + float m_yaw; + SmoothTranslator pos_translator; + bool m_walking; + float m_walking_unset_timer; + float m_walk_timer; + int m_walk_frame; + float m_damage_visual_timer; + u8 m_last_light; + bool m_shooting; + float m_shooting_unset_timer; + v2f m_sprite_size; + v3f m_sprite_pos; + bool m_bright_shooting; + std::string m_sprite_type; + int m_simple_anim_frames; + float m_simple_anim_frametime; + bool m_lock_full_brightness; + int m_player_hit_damage; + float m_player_hit_distance; + float m_player_hit_interval; + float m_player_hit_timer; + + Settings *m_properties; +}; + #endif diff --git a/src/content_object.h b/src/content_object.h index 47f93d7d4..a5fea7163 100644 --- a/src/content_object.h +++ b/src/content_object.h @@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #define ACTIVEOBJECT_TYPE_RAT 3 #define ACTIVEOBJECT_TYPE_OERKKI1 4 #define ACTIVEOBJECT_TYPE_FIREFLY 5 +#define ACTIVEOBJECT_TYPE_MOBV2 6 #endif diff --git a/src/content_sao.cpp b/src/content_sao.cpp index 0bb518c16..8c9761740 100644 --- a/src/content_sao.cpp +++ b/src/content_sao.cpp @@ -20,9 +20,29 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "content_sao.h" #include "collision.h" #include "environment.h" +#include "settings.h" core::map ServerActiveObject::m_types; +/* Some helper functions */ + +// Y is copied, X and Z change is limited +void accelerate_xz(v3f &speed, v3f target_speed, f32 max_increase) +{ + v3f d_wanted = target_speed - speed; + d_wanted.Y = 0; + f32 dl_wanted = d_wanted.getLength(); + f32 dl = dl_wanted; + if(dl > max_increase) + dl = max_increase; + + v3f d = d_wanted.normalize() * dl; + + speed.X += d.X; + speed.Z += d.Z; + speed.Y = target_speed.Y; +} + /* TestSAO */ @@ -422,23 +442,6 @@ InventoryItem* RatSAO::createPickedUpItem() Oerkki1SAO */ -// Y is copied, X and Z change is limited -void accelerate_xz(v3f &speed, v3f target_speed, f32 max_increase) -{ - v3f d_wanted = target_speed - speed; - d_wanted.Y = 0; - f32 dl_wanted = d_wanted.getLength(); - f32 dl = dl_wanted; - if(dl > max_increase) - dl = max_increase; - - v3f d = d_wanted.normalize() * dl; - - speed.X += d.X; - speed.Z += d.Z; - speed.Y = target_speed.Y; -} - // Prototype Oerkki1SAO proto_Oerkki1SAO(NULL, 0, v3f(0,0,0)); @@ -617,7 +620,7 @@ void Oerkki1SAO::step(float dtime, bool send_recommended) m_touching_ground = moveresult.touching_ground; // Do collision damage - float tolerance = BS*12; + float tolerance = BS*30; float factor = BS*0.5; v3f speed_diff = old_speed - m_speed_f; // Increase effect in X and Z @@ -886,3 +889,477 @@ InventoryItem* FireflySAO::createPickedUpItem() InventoryItem *item = InventoryItem::deSerialize(is); return item; } + +/* + MobV2SAO +*/ + +// Prototype +MobV2SAO proto_MobV2SAO(NULL, 0, v3f(0,0,0), NULL); + +MobV2SAO::MobV2SAO(ServerEnvironment *env, u16 id, v3f pos, + Settings *init_properties): + ServerActiveObject(env, id, pos), + m_move_type("ground_nodes"), + m_speed(0,0,0), + m_last_sent_position(0,0,0), + m_oldpos(0,0,0), + m_yaw(0), + m_counter1(0), + m_counter2(0), + m_age(0), + m_touching_ground(false), + m_hp(10), + m_walk_around(false), + m_walk_around_timer(0), + m_next_pos_exists(false), + m_shoot_reload_timer(0), + m_shooting(false), + m_shooting_timer(0), + m_falling(false) +{ + ServerActiveObject::registerType(getType(), create); + + m_properties = new Settings(); + if(init_properties) + m_properties->update(*init_properties); + + m_properties->setV3F("pos", pos); + + setPropertyDefaults(); + readProperties(); +} + +MobV2SAO::~MobV2SAO() +{ + delete m_properties; +} + +ServerActiveObject* MobV2SAO::create(ServerEnvironment *env, u16 id, v3f pos, + const std::string &data) +{ + std::istringstream is(data, std::ios::binary); + Settings properties; + properties.parseConfigLines(is, "MobArgsEnd"); + MobV2SAO *o = new MobV2SAO(env, id, pos, &properties); + return o; +} + +std::string MobV2SAO::getStaticData() +{ + updateProperties(); + + std::ostringstream os(std::ios::binary); + m_properties->writeLines(os); + return os.str(); +} + +std::string MobV2SAO::getClientInitializationData() +{ + //dstream<<__FUNCTION_NAME<getNodeNoEx(p); + if(n.getContent() != CONTENT_AIR) + return false; + } + return true; +} + +bool checkWalkablePosition(Map *map, v3s16 p0) +{ + v3s16 p = p0 + v3s16(0,-1,0); + MapNode n = map->getNodeNoEx(p); + if(n.getContent() != CONTENT_AIR) + return true; + return false; +} + +bool checkFreeAndWalkablePosition(Map *map, v3s16 p0, v3s16 size) +{ + if(!checkFreePosition(map, p0, size)) + return false; + if(!checkWalkablePosition(map, p0)) + return false; + return true; +} + +static void get_random_u32_array(u32 a[], u32 len) +{ + u32 i, n; + for(i=0; i 1){ + u32 k = myrand() % n; + n--; + u32 temp = a[n]; + a[n] = a[k]; + a[k] = temp; + } +} + +#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")" + +static void explodeSquare(Map *map, v3s16 p0, v3s16 size) +{ + core::map modified_blocks; + + for(int dx=0; dxgetNodeNoEx(p); + if(n.getContent() == CONTENT_IGNORE) + continue; + //map->removeNodeWithEvent(p); + map->removeNodeAndUpdate(p, modified_blocks); + } + + // Send a MEET_OTHER event + MapEditEvent event; + event.type = MEET_OTHER; + for(core::map::Iterator + i = modified_blocks.getIterator(); + i.atEnd() == false; i++) + { + v3s16 p = i.getNode()->getKey(); + event.modified_blocks.insert(p, true); + } + map->dispatchEvent(&event); +} + +void MobV2SAO::step(float dtime, bool send_recommended) +{ + assert(m_env); + Map *map = &m_env->getMap(); + + m_age += dtime; + + if(m_die_age >= 0.0 && m_age >= m_die_age){ + m_removed = true; + return; + } + + if(!m_falling) + { + m_shooting_timer -= dtime; + if(m_shooting_timer <= 0.0 && m_shooting){ + m_shooting = false; + + std::string shoot_type = m_properties->get("shoot_type"); + v3f shoot_pos(0,0,0); + shoot_pos.Y += m_properties->getFloat("shoot_y") * BS; + if(shoot_type == "fireball"){ + v3f dir(cos(m_yaw/180*PI),0,sin(m_yaw/180*PI)); + v3f speed = dir * BS * 10.0; + v3f pos = m_base_position + shoot_pos; + dstream<<__FUNCTION_NAME<<": Shooting fireball from "<addActiveObjectAsStatic(obj); + m_env->addActiveObject(obj); + } else { + dstream<<__FUNCTION_NAME<<": Unknown shoot_type="<= 5.0 && !m_next_pos_exists) + { + m_shoot_reload_timer = 0.0; + m_shooting = true; + m_shooting_timer = 1.5; + { + std::ostringstream os(std::ios::binary); + // command (2 = shooting) + writeU8(os, 2); + // time + writeF1000(os, m_shooting_timer + 0.1); + // bright? + writeU8(os, true); + // create message and add to list + ActiveObjectMessage aom(getId(), false, os.str()); + m_messages_out.push_back(aom); + } + } + } + + if(m_move_type == "ground_nodes") + { + if(!m_shooting){ + m_walk_around_timer -= dtime; + if(m_walk_around_timer <= 0.0){ + m_walk_around = !m_walk_around; + if(m_walk_around) + m_walk_around_timer = 0.1*myrand_range(10,50); + else + m_walk_around_timer = 0.1*myrand_range(30,70); + } + } + + /* Move */ + if(m_next_pos_exists){ + v3f pos_f = m_base_position; + v3f next_pos_f = intToFloat(m_next_pos_i, BS); + + v3f v = next_pos_f - pos_f; + m_yaw = atan2(v.Z, v.X) / M_PI * 180; + + v3f diff = next_pos_f - pos_f; + v3f dir = diff; + dir.normalize(); + float speed = BS * 0.5; + if(m_falling) + speed = BS * 3.0; + dir *= dtime * speed; + bool arrived = false; + if(dir.getLength() > diff.getLength()){ + dir = diff; + arrived = true; + } + pos_f += dir; + m_base_position = pos_f; + + if((pos_f - next_pos_f).getLength() < 0.1 || arrived){ + //dstream<<"id="<= 2.5){ + pos_size_off.X = -1; + pos_size_off.Y = -1; + } + + if(!m_next_pos_exists){ + /* Check whether to drop down */ + if(checkFreePosition(map, + pos_i + pos_size_off + v3s16(0,-1,0), size_blocks)){ + m_next_pos_i = pos_i + v3s16(0,-1,0); + m_next_pos_exists = true; + m_falling = true; + } else { + m_falling = false; + } + } + + if(m_walk_around) + { + if(!m_next_pos_exists){ + /* Find some position where to go next */ + v3s16 dps[3*3*3]; + int num_dps = 0; + for(int dx=-1; dx<=1; dx++) + for(int dy=-1; dy<=1; dy++) + for(int dz=-1; dz<=1; dz++){ + if(dx == 0 && dy == 0) + continue; + if(dx != 0 && dz != 0 && dy != 0) + continue; + dps[num_dps++] = v3s16(dx,dy,dz); + } + u32 order[3*3*3]; + get_random_u32_array(order, num_dps); + /*dstream<<"At pos "<= 2.5){ + pos_size_off.X = -1; + pos_size_off.Y = -1; + } + bool free = checkFreePosition(map, pos_i + pos_size_off, size_blocks); + if(!free){ + explodeSquare(map, pos_i, v3s16(3,3,3)); + m_removed = true; + return; + } + } + else + { + dstream<<"MobV2SAO::step(): id="< 0.05*BS) + { + m_last_sent_position = m_base_position; + + std::ostringstream os(std::ios::binary); + // command (0 = update position) + writeU8(os, 0); + // pos + writeV3F1000(os, m_base_position); + // yaw + writeF1000(os, m_yaw); + // create message and add to list + ActiveObjectMessage aom(getId(), false, os.str()); + m_messages_out.push_back(aom); + } +} + +u16 MobV2SAO::punch(const std::string &toolname, v3f dir) +{ + u16 amount = 2; + dstream<<"id="<setDefault("move_type", "ground_nodes"); + m_properties->setDefault("speed", "(0,0,0)"); + m_properties->setDefault("age", "0"); + m_properties->setDefault("yaw", "0"); + m_properties->setDefault("pos", "(0,0,0)"); + m_properties->setDefault("hp", "0"); + m_properties->setDefault("die_age", "-1"); + m_properties->setDefault("size", "(1,2)"); + m_properties->setDefault("shoot_type", "fireball"); + m_properties->setDefault("shoot_y", "0"); +} +void MobV2SAO::readProperties() +{ + m_move_type = m_properties->get("move_type"); + m_speed = m_properties->getV3F("speed"); + m_age = m_properties->getFloat("age"); + m_yaw = m_properties->getFloat("yaw"); + m_base_position = m_properties->getV3F("pos"); + m_hp = m_properties->getS32("hp"); + m_die_age = m_properties->getFloat("die_age"); + m_size = m_properties->getV2F("size"); +} +void MobV2SAO::updateProperties() +{ + m_properties->set("move_type", m_move_type); + m_properties->setV3F("speed", m_speed); + m_properties->setFloat("age", m_age); + m_properties->setFloat("yaw", m_yaw); + m_properties->setV3F("pos", m_base_position); + m_properties->setS32("hp", m_hp); + m_properties->setFloat("die_age", m_die_age); + m_properties->setV2F("size", m_size); + + m_properties->setS32("version", 0); +} + +void MobV2SAO::doDamage(u16 d) +{ + dstream<<"MobV2 hp="<setDefault("objectdata_interval", "0.2"); - settings->setDefault("active_object_range", "2"); + settings->setDefault("active_object_send_range_blocks", "3"); + settings->setDefault("active_block_range", "5"); //settings->setDefault("max_simultaneous_block_sends_per_client", "1"); // This causes frametime jitter on client side, or does it? settings->setDefault("max_simultaneous_block_sends_per_client", "2"); diff --git a/src/environment.cpp b/src/environment.cpp index e1e0f8255..124e5631c 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -643,6 +643,24 @@ void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime) } } +static void getMob_dungeon_master(Settings &properties) +{ + properties.set("texture_name", "dungeon_master.png"); + properties.setV3F("sprite_pos", v3f(0.0, 0.85, 0.0)); + properties.setV2F("sprite_size", v2f(2.0, 3.0)); + properties.setFloat("selection_y", -0.4); + properties.setV2F("selection_size", v2f(0.4, 2.6)); + properties.setFloat("yaw", 1.57); + properties.setFloat("hp", 20); + properties.setBool("bright_shooting", true); + properties.set("shoot_type", "fireball"); + properties.set("shoot_y", "0.7"); + properties.set("sprite_type", "humanoid_1"); + properties.set("player_hit_damage", "1"); + properties.set("player_hit_distance", "1.0"); + properties.set("player_hit_interval", "0.5"); +} + void ServerEnvironment::step(float dtime) { DSTACK(__FUNCTION_NAME); @@ -725,7 +743,7 @@ void ServerEnvironment::step(float dtime) /* Update list of active blocks, collecting changes */ - const s16 active_block_range = 5; + const s16 active_block_range = g_settings->getS16("active_block_range"); core::map blocks_removed; core::map blocks_added; m_active_blocks.update(players_blockpos, active_block_range, @@ -926,14 +944,52 @@ void ServerEnvironment::step(float dtime) } } /* - Make trees from saplings! + Fun things spawn in caves and dungeons + */ + if(n.getContent() == CONTENT_STONE || + n.getContent() == CONTENT_MOSSYCOBBLE) + { + if(myrand()%200 == 0 && active_object_count_wider == 0) + { + v3s16 p1 = p + v3s16(0,1,0); + MapNode n1a = m_map->getNodeNoEx(p1+v3s16(0,0,0)); + if(n1a.getLightBlend(getDayNightRatio()) <= 3){ + MapNode n1b = m_map->getNodeNoEx(p1+v3s16(0,1,0)); + if(n1a.getContent() == CONTENT_AIR && + n1b.getContent() == CONTENT_AIR) + { + v3f pos = intToFloat(p1, BS); + int i = myrand()%5; + if(i == 0 || i == 1){ + Settings properties; + getMob_dungeon_master(properties); + ServerActiveObject *obj = new MobV2SAO( + this, 0, pos, &properties); + addActiveObject(obj); + } else if(i == 2 || i == 3){ + for(int j=0; j<3; j++){ + ServerActiveObject *obj = new RatSAO( + this, 0, pos); + addActiveObject(obj); + } + } else { + ServerActiveObject *obj = new Oerkki1SAO( + this, 0, pos); + addActiveObject(obj); + } + } + } + } + } + /* + Make trees from saplings! */ if(n.getContent() == CONTENT_SAPLING) { - if(myrand()%50 == 0) + if(myrand()%50 == 0) { - core::map modified_blocks; - v3s16 tree_p = p; + core::map modified_blocks; + v3s16 tree_p = p; ManualMapVoxelManipulator vmanip(m_map); v3s16 tree_blockp = getNodeBlockPos(tree_p); vmanip.initialEmerge(tree_blockp - v3s16(1,1,1), tree_blockp + v3s16(1,1,1)); @@ -944,8 +1000,8 @@ void ServerEnvironment::step(float dtime) // update lighting core::map lighting_modified_blocks; for(core::map::Iterator - i = modified_blocks.getIterator(); - i.atEnd() == false; i++) + i = modified_blocks.getIterator(); + i.atEnd() == false; i++) { lighting_modified_blocks.insert(i.getNode()->getKey(), i.getNode()->getValue()); } @@ -955,16 +1011,15 @@ void ServerEnvironment::step(float dtime) MapEditEvent event; event.type = MEET_OTHER; for(core::map::Iterator - i = modified_blocks.getIterator(); - i.atEnd() == false; i++) - { - v3s16 p = i.getNode()->getKey(); + i = modified_blocks.getIterator(); + i.atEnd() == false; i++) + { + v3s16 p = i.getNode()->getKey(); event.modified_blocks.insert(p, true); } m_map->dispatchEvent(&event); } } - } } } @@ -978,7 +1033,7 @@ void ServerEnvironment::step(float dtime) // This helps the objects to send data at the same time bool send_recommended = false; m_send_recommended_timer += dtime; - if(m_send_recommended_timer > 0.15) + if(m_send_recommended_timer > 0.10) { m_send_recommended_timer = 0; send_recommended = true; @@ -1020,7 +1075,7 @@ void ServerEnvironment::step(float dtime) /* TEST CODE */ -#if 1 +#if 0 m_random_spawn_timer -= dtime; if(m_random_spawn_timer < 0) { @@ -1042,7 +1097,7 @@ void ServerEnvironment::step(float dtime) pos = player->getPosition(); pos += v3f( myrand_range(-3,3)*BS, - 0, + 5, myrand_range(-3,3)*BS ); @@ -1054,7 +1109,14 @@ void ServerEnvironment::step(float dtime) //ServerActiveObject *obj = new ItemSAO(this, 0, pos, "CraftItem Stick 1"); //ServerActiveObject *obj = new RatSAO(this, 0, pos); //ServerActiveObject *obj = new Oerkki1SAO(this, 0, pos); - ServerActiveObject *obj = new FireflySAO(this, 0, pos); + //ServerActiveObject *obj = new FireflySAO(this, 0, pos); + + dstream<getBasePosition(); + + // The block in which the object resides in + v3s16 blockpos_o = getNodeBlockPos(floatToInt(objectpos, BS)); + + /* + Update the static data + */ + + // Create new static object + std::string staticdata = obj->getStaticData(); + StaticObject s_obj(obj->getType(), objectpos, staticdata); + // Add to the block where the object is located in + v3s16 blockpos = getNodeBlockPos(floatToInt(objectpos, BS)); + // Get or generate the block + MapBlock *block = m_map->emergeBlock(blockpos); + + bool succeeded = false; + + if(block) + { + block->m_static_objects.insert(0, s_obj); + block->raiseModified(MOD_STATE_WRITE_AT_UNLOAD); + succeeded = true; + } + else{ + dstream<<"WARNING: ServerEnvironment::addActiveObjectAsStatic: " + <<"Could not find or generate " + <<"a block for storing static object"<setId(id); - addActiveObject(obj); - obj->initialize(init_data); + + addActiveObject(obj); } void ClientEnvironment::removeActiveObject(u16 id) diff --git a/src/environment.h b/src/environment.h index 055e2b1f6..d93caac3b 100644 --- a/src/environment.h +++ b/src/environment.h @@ -175,6 +175,14 @@ public: */ u16 addActiveObject(ServerActiveObject *object); + /* + Add an active object as a static object to the corresponding + MapBlock. + Caller allocates memory, ServerEnvironment frees memory. + Return value: true if succeeded, false if failed. + */ + bool addActiveObjectAsStatic(ServerActiveObject *object); + /* Find out what new objects have been added to inside a radius around a position diff --git a/src/game.cpp b/src/game.cpp index 9e54e6ad3..e8d0238a3 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -89,27 +89,6 @@ u16 g_selected_item = 0; Text input system */ -struct TextDestSign : public TextDest -{ - TextDestSign(v3s16 blockpos, s16 id, Client *client) - { - m_blockpos = blockpos; - m_id = id; - m_client = client; - } - void gotText(std::wstring text) - { - std::string ntext = wide_to_narrow(text); - dstream<<"Changing text of a sign object: " - <sendSignText(m_blockpos, m_id, ntext); - } - - v3s16 m_blockpos; - s16 m_id; - Client *m_client; -}; - struct TextDestChat : public TextDest { TextDestChat(Client *client) @@ -298,7 +277,7 @@ void getPointedNode(Client *client, v3f player_position, v3s16 pos_i = floatToInt(player_position, BS); - /*std::cout<<"pos_i=("< server; if(address == ""){ draw_load_screen(L"Creating server...", driver, font); - std::cout<start(port); } @@ -715,7 +694,7 @@ void the_game( */ draw_load_screen(L"Creating client...", driver, font); - std::cout<remove(); @@ -799,12 +778,12 @@ void the_game( { error_message = L"Access denied. Reason: " +client.accessDeniedReason(); - std::cout<remove(); return; @@ -924,8 +903,16 @@ void the_game( core::list frametime_log; + float nodig_delay_counter = 0.0; + float dig_time = 0.0; + u16 dig_index = 0; + v3s16 nodepos_old(-32768,-32768,-32768); + float damage_flash_timer = 0; s16 farmesh_range = 20*MAP_BLOCKSIZE; + + const float object_hit_delay = 0.5; + float object_hit_delay_timer = 0.0; bool invert_mouse = g_settings->getBool("invert_mouse"); @@ -952,7 +939,7 @@ void the_game( { error_message = L"Access denied. Reason: " +client.accessDeniedReason(); - std::cout<getMousePos().Y - displaycenter.Y; if(invert_mouse) dy = -dy; - //std::cout<<"window active, pos difference "<isKeyDown(irr::KEY_UP)) @@ -1391,7 +1382,7 @@ void the_game( if(device->getCursorControl()->isVisible() == false) device->getCursorControl()->setVisible(true); - //std::cout<<"window inactive"< shootline(camera_position, camera_position + camera_direction * BS * (d+1)); - MapBlockObject *selected_object = client.getSelectedObject - (d*BS, camera_position, shootline); - ClientActiveObject *selected_active_object = client.getSelectedActiveObject (d*BS, camera_position, shootline); + + bool left_punch = false; + bool left_punch_muted = false; - if(selected_object != NULL) + if(selected_active_object != NULL) { - //dstream<<"Client returned selected_object != NULL"< box_on_map - = selected_object->getSelectionBoxOnMap(); - - hilightboxes.push_back(box_on_map); - - infotext = narrow_to_wide(selected_object->infoText()); - - if(input->getLeftClicked()) + /* Clear possible cracking animation */ + if(nodepos_old != v3s16(-32768,-32768,-32768)) { - std::cout<getBlock()->getPos(), - selected_object->getId(), g_selected_item); + client.clearTempMod(nodepos_old); + dig_time = 0.0; + nodepos_old = v3s16(-32768,-32768,-32768); } - else if(input->getRightClicked()) - { - std::cout<getTypeId() == MAPBLOCKOBJECT_TYPE_SIGN) - { - dstream<<"Sign object right-clicked"<getBlock()->getPos(), - selected_object->getId(), - &client); - - SignObject *sign_object = (SignObject*)selected_object; - - std::wstring wtext = - narrow_to_wide(sign_object->getText()); - - (new GUITextInputMenu(guienv, guiroot, -1, - &g_menumgr, dest, - wtext))->drop(); - } - } - /* - Otherwise pass the event to the server as-is - */ - else - { - client.clickObject(1, selected_object->getBlock()->getPos(), - selected_object->getId(), g_selected_item); - } - } - } - else if(selected_active_object != NULL) - { //dstream<<"Client returned selected_active_object != NULL"< *selection_box @@ -1579,21 +1522,31 @@ void the_game( selection_box->MinEdge + pos, selection_box->MaxEdge + pos ); - - hilightboxes.push_back(box_on_map); + + if(selected_active_object->doShowSelectionBox()) + hilightboxes.push_back(box_on_map); //infotext = narrow_to_wide("A ClientActiveObject"); infotext = narrow_to_wide(selected_active_object->infoText()); - if(input->getLeftClicked()) + //if(input->getLeftClicked()) + if(input->getLeftState()) { - std::cout<getId(), g_selected_item); + if(object_hit_delay_timer <= 0.0){ + dstream<getId(), g_selected_item); + object_hit_delay_timer = object_hit_delay; + left_punch = true; + } else { + dstream<getRightClicked()) { - std::cout<getId(), g_selected_item); } @@ -1616,15 +1569,14 @@ void the_game( nodepos, neighbourpos, nodehilightbox, d); - static float nodig_delay_counter = 0.0; - - if(nodefound) - { - static v3s16 nodepos_old(-32768,-32768,-32768); - - static float dig_time = 0.0; - static u16 dig_index = 0; - + if(!nodefound){ + if(nodepos_old != v3s16(-32768,-32768,-32768)) + { + client.clearTempMod(nodepos_old); + dig_time = 0.0; + nodepos_old = v3s16(-32768,-32768,-32768); + } + } else { /* Visualize selection */ @@ -1661,13 +1613,14 @@ void the_game( { if(nodepos != nodepos_old) { - std::cout<getRightClicked()) { - std::cout<getInventoryDrawSpecString() != "" && !random_input) @@ -1836,7 +1789,7 @@ void the_game( } // selected_object == NULL - if(input->getLeftClicked()) + if(left_punch || (input->getLeftClicked() && !left_punch_muted)) { camera.setDigging(0); // left click animation } @@ -1846,13 +1799,13 @@ void the_game( if(input->getLeftReleased()) { - std::cout<getRightReleased()) { - //std::cout<drawAll()"<drawAll()"< >::Iterator i=hilightboxes.begin(); i != hilightboxes.end(); i++) { - /*std::cout<<"hilightbox min=" + /*dstream<<"hilightbox min=" <<"("<MinEdge.X<<","<MinEdge.Y<<","<MinEdge.Z<<")" <<" max=" <<"("<MaxEdge.X<<","<MaxEdge.Y<<","<MaxEdge.Z<<")" diff --git a/src/inventory.cpp b/src/inventory.cpp index a3e35c92c..b8afbc81f 100644 --- a/src/inventory.cpp +++ b/src/inventory.cpp @@ -97,7 +97,7 @@ InventoryItem* InventoryItem::deSerialize(std::istream &is) { std::string inventorystring; std::getline(is, inventorystring, '|'); - return new MapBlockObjectItem(inventorystring); + throw SerializationError("MBOItem not supported anymore"); } else if(name == "CraftItem") { @@ -219,77 +219,6 @@ bool CraftItem::use(ServerEnvironment *env, Player *player) return false; } -/* - MapBlockObjectItem DEPRECATED - TODO: Remove -*/ -#ifndef SERVER -video::ITexture * MapBlockObjectItem::getImage() const -{ - if(m_inventorystring.substr(0,3) == "Rat") - return g_texturesource->getTextureRaw("rat.png"); - - if(m_inventorystring.substr(0,4) == "Sign") - return g_texturesource->getTextureRaw("sign.png"); - - return NULL; -} -#endif -std::string MapBlockObjectItem::getText() -{ - if(m_inventorystring.substr(0,3) == "Rat") - return ""; - - if(m_inventorystring.substr(0,4) == "Sign") - return ""; - - return "obj"; -} - -MapBlockObject * MapBlockObjectItem::createObject - (v3f pos, f32 player_yaw, f32 player_pitch) -{ - std::istringstream is(m_inventorystring); - std::string name; - std::getline(is, name, ' '); - - if(name == "None") - { - return NULL; - } - else if(name == "Sign") - { - std::string text; - std::getline(is, text, '|'); - SignObject *obj = new SignObject(NULL, -1, pos); - obj->setText(text); - obj->setYaw(-player_yaw); - return obj; - } - else if(name == "Rat") - { - RatObject *obj = new RatObject(NULL, -1, pos); - return obj; - } - else if(name == "ItemObj") - { - /* - Now we are an inventory item containing the serialization - string of an object that contains the serialization - string of an inventory item. Fuck this. - */ - //assert(0); - dstream<<__FUNCTION_NAME<<": WARNING: Ignoring ItemObj " - <<"because an item-object should never be inside " - <<"an object-item."< #include "common_irrlicht.h" #include "debug.h" -#include "mapblockobject.h" #include "main.h" // For g_materials #include "mapnode.h" // For content_t @@ -196,56 +195,6 @@ private: content_t m_content; }; -//TODO: Remove -class MapBlockObjectItem : public InventoryItem -{ -public: - MapBlockObjectItem(std::string inventorystring): - InventoryItem(1) - { - m_inventorystring = inventorystring; - } - - /* - Implementation interface - */ - virtual const char* getName() const - { - return "MBOItem"; - } - virtual void serialize(std::ostream &os) const - { - std::string sane_string(m_inventorystring); - str_replace_char(sane_string, '|', '?'); - os<= 9) { - //serializeObjects(os, version); // DEPRECATED // count=0 writeU16(os, 0); } @@ -842,11 +828,17 @@ void MapBlock::serializeDiskExtra(std::ostream &os, u8 version) void MapBlock::deSerializeDiskExtra(std::istream &is, u8 version) { /* - Versions up from 9 have block objects. + Versions up from 9 have block objects. (DEPRECATED) */ if(version >= 9) { - updateObjects(is, version, NULL, 0); + u16 count = readU16(is); + // Not supported and length not known if count is not 0 + if(count != 0){ + dstream<<"WARNING: MapBlock::deSerializeDiskExtra(): " + <<"Ignoring stuff coming at and after MBOs"< &dest) - { - m_objects.getObjects(origin, max_d, dest); - } - - s32 getObjectCount() - { - return m_objects.getCount(); - } - #ifndef SERVER // Only on client /* Methods for setting temporary modifications to nodes for @@ -688,9 +625,6 @@ private: bool m_generated; - // DEPRECATED - MapBlockObjectList m_objects; - #ifndef SERVER // Only on client /* Set to true if the mesh has been ordered to be updated diff --git a/src/mapblockobject.cpp b/src/mapblockobject.cpp deleted file mode 100644 index 071a14b0c..000000000 --- a/src/mapblockobject.cpp +++ /dev/null @@ -1,939 +0,0 @@ -/* -Minetest-c55 -Copyright (C) 2010 celeron55, Perttu Ahola - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along -with this program; if not, write to the Free Software Foundation, Inc., -51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -// This file contains the DEPRECATED MapBlockObject system - -#include "mapblockobject.h" -#include "mapblock.h" -// For object wrapping -#include "map.h" -#include "inventory.h" -#include "utility.h" -#include "mapblock.h" - -/* - MapBlockObject -*/ - -// This is here because it uses the MapBlock -v3f MapBlockObject::getAbsolutePos() -{ - if(m_block == NULL) - return m_pos; - - // getPosRelative gets nodepos relative to map origin - v3f blockpos = intToFloat(m_block->getPosRelative(), BS); - return blockpos + m_pos; -} - -void MapBlockObject::setBlockChanged() -{ - if(m_block) - m_block->setChangedFlag(); -} - -/* - MovingObject -*/ - -v3f MovingObject::getAbsoluteShowPos() -{ - if(m_block == NULL) - return m_pos; - - // getPosRelative gets nodepos relative to map origin - v3f blockpos = intToFloat(m_block->getPosRelative(), BS); - return blockpos + m_showpos; -} - -void MovingObject::move(float dtime, v3f acceleration) -{ - DSTACKF("%s: typeid=%i, pos=(%f,%f,%f), speed=(%f,%f,%f)" - ", dtime=%f, acc=(%f,%f,%f)", - __FUNCTION_NAME, - getTypeId(), - m_pos.X, m_pos.Y, m_pos.Z, - m_speed.X, m_speed.Y, m_speed.Z, - dtime, - acceleration.X, acceleration.Y, acceleration.Z - ); - - v3s16 oldpos_i = floatToInt(m_pos, BS); - - if(m_block->isValidPosition(oldpos_i) == false) - { - // Should have wrapped, cancelling further movement. - return; - } - - // No collisions if there is no collision box - if(m_collision_box == NULL) - { - m_speed += dtime * acceleration; - m_pos += m_speed * dtime; - return; - } - - // Set insane speed to zero - // Otherwise there will be divides by zero and other silly stuff - if(m_speed.getLength() > 1000.0*BS) - m_speed = v3f(0,0,0); - - // Limit speed to a reasonable value - float speed_limit = 20.0*BS; - if(m_speed.getLength() > speed_limit) - m_speed = m_speed * (speed_limit / m_speed.getLength()); - - v3f position = m_pos; - v3f oldpos = position; - - /*std::cout<<"oldpos_i=("< 0.001) - dtime_max_increment = 0.05*BS / speedlength; - else - dtime_max_increment = 0.5; - - m_touching_ground = false; - - u32 loopcount = 0; - do - { - loopcount++; - - f32 dtime_part; - if(dtime > dtime_max_increment) - dtime_part = dtime_max_increment; - else - dtime_part = dtime; - dtime -= dtime_part; - - // Begin of dtime limited code - - m_speed += acceleration * dtime_part; - position += m_speed * dtime_part; - - /* - Collision detection - */ - - v3s16 pos_i = floatToInt(position, BS); - - // The loop length is limited to the object moving a distance - f32 d = (float)BS * 0.15; - - core::aabbox3d objectbox( - m_collision_box->MinEdge + position, - m_collision_box->MaxEdge + position - ); - - core::aabbox3d objectbox_old( - m_collision_box->MinEdge + oldpos, - m_collision_box->MaxEdge + oldpos - ); - - //TODO: Get these ranges from somewhere - for(s16 y = oldpos_i.Y - 1; y <= oldpos_i.Y + 2; y++) - for(s16 z = oldpos_i.Z - 1; z <= oldpos_i.Z + 1; z++) - for(s16 x = oldpos_i.X - 1; x <= oldpos_i.X + 1; x++) - { - try{ - MapNode n = m_block->getNodeParent(v3s16(x,y,z)); - if(content_features(n).walkable == false) - continue; - } - catch(InvalidPositionException &e) - { - // Doing nothing here will block the object from - // walking over map borders - } - - core::aabbox3d nodebox = getNodeBox(v3s16(x,y,z), BS); - - // See if the object is touching ground - if( - fabs(nodebox.MaxEdge.Y-objectbox.MinEdge.Y) < d - && nodebox.MaxEdge.X-d > objectbox.MinEdge.X - && nodebox.MinEdge.X+d < objectbox.MaxEdge.X - && nodebox.MaxEdge.Z-d > objectbox.MinEdge.Z - && nodebox.MinEdge.Z+d < objectbox.MaxEdge.Z - ){ - m_touching_ground = true; - } - - if(objectbox.intersectsWithBox(nodebox)) - { - - v3f dirs[3] = { - v3f(0,0,1), // back - v3f(0,1,0), // top - v3f(1,0,0), // right - }; - for(u16 i=0; i<3; i++) - { - f32 nodemax = nodebox.MaxEdge.dotProduct(dirs[i]); - f32 nodemin = nodebox.MinEdge.dotProduct(dirs[i]); - f32 playermax = objectbox.MaxEdge.dotProduct(dirs[i]); - f32 playermin = objectbox.MinEdge.dotProduct(dirs[i]); - f32 playermax_old = objectbox_old.MaxEdge.dotProduct(dirs[i]); - f32 playermin_old = objectbox_old.MinEdge.dotProduct(dirs[i]); - - bool main_edge_collides = - ((nodemax > playermin && nodemax <= playermin_old + d - && m_speed.dotProduct(dirs[i]) < 0) - || - (nodemin < playermax && nodemin >= playermax_old - d - && m_speed.dotProduct(dirs[i]) > 0)); - - bool other_edges_collide = true; - for(u16 j=0; j<3; j++) - { - if(j == i) - continue; - f32 nodemax = nodebox.MaxEdge.dotProduct(dirs[j]); - f32 nodemin = nodebox.MinEdge.dotProduct(dirs[j]); - f32 playermax = objectbox.MaxEdge.dotProduct(dirs[j]); - f32 playermin = objectbox.MinEdge.dotProduct(dirs[j]); - if(!(nodemax - d > playermin && nodemin + d < playermax)) - { - other_edges_collide = false; - break; - } - } - - if(main_edge_collides && other_edges_collide) - { - m_speed -= m_speed.dotProduct(dirs[i]) * dirs[i]; - position -= position.dotProduct(dirs[i]) * dirs[i]; - position += oldpos.dotProduct(dirs[i]) * dirs[i]; - } - - } - - } // if(objectbox.intersectsWithBox(nodebox)) - } // for y - - } // End of dtime limited loop - while(dtime > 0.001); - - m_pos = position; -} - -void MovingObject::simpleMove(float dtime) -{ - m_pos_animation_time_counter += dtime; - m_pos_animation_counter += dtime; - v3f movevector = m_pos - m_oldpos; - f32 moveratio; - if(m_pos_animation_time < 0.001) - moveratio = 1.0; - else - moveratio = m_pos_animation_counter / m_pos_animation_time; - if(moveratio > 1.5) - moveratio = 1.5; - m_showpos = m_oldpos + movevector * moveratio; -} - -#ifndef SERVER -/* - RatObject -*/ -void RatObject::addToScene(scene::ISceneManager *smgr) -{ - if(m_node != NULL) - return; - - video::IVideoDriver* driver = smgr->getVideoDriver(); - - scene::SMesh *mesh = new scene::SMesh(); - scene::IMeshBuffer *buf = new scene::SMeshBuffer(); - video::SColor c(255,255,255,255); - video::S3DVertex vertices[4] = - { - video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1), - video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1), - video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0), - video::S3DVertex(-BS/2,BS/4,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_BACK_FACE_CULLING, false); - buf->getMaterial().setTexture - (0, driver->getTexture(getTexturePath("rat.png").c_str())); - 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(); - m_node = smgr->addMeshSceneNode(mesh, NULL); - mesh->drop(); - updateNodePos(); -} -#endif - -/* - ItemObject -*/ -#ifndef SERVER -void ItemObject::addToScene(scene::ISceneManager *smgr) -{ - if(m_node != NULL) - return; - - //video::IVideoDriver* driver = smgr->getVideoDriver(); - - // Get image of item for showing - video::ITexture *texture = getItemImage(); - - /* - Create a mesh - */ - - scene::SMesh *mesh = new scene::SMesh(); - { - scene::IMeshBuffer *buf = new scene::SMeshBuffer(); - video::SColor c(255,255,255,255); - video::S3DVertex vertices[4] = - { - /*video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c, 0,1), - video::S3DVertex(-BS/2,-BS/2,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),*/ - video::S3DVertex(BS/3,-BS/2,0, 0,0,0, c, 0,1), - video::S3DVertex(-BS/3,-BS/2,0, 0,0,0, c, 1,1), - video::S3DVertex(-BS/3,-BS/2+BS*2/3,0, 0,0,0, c, 1,0), - video::S3DVertex(BS/3,-BS/2+BS*2/3,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_BACK_FACE_CULLING, false); - buf->getMaterial().setTexture(0, texture); - 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); - // Set it to use the materials of the meshbuffers directly. - // This is needed for changing the texture in the future - ((scene::IMeshSceneNode*)m_node)->setReadOnlyMaterials(true); - mesh->drop(); - - updateSceneNode(); -} - -video::ITexture * ItemObject::getItemImage() -{ - /* - Create an inventory item to see what is its image - */ - video::ITexture *texture = NULL; - InventoryItem *item = createInventoryItem(); - if(item) - texture = item->getImage(); - if(item) - delete item; - return texture; -} - -#endif - -InventoryItem * ItemObject::createInventoryItem() -{ - try{ - std::istringstream is(m_itemstring, std::ios_base::binary); - InventoryItem *item = InventoryItem::deSerialize(is); - dstream<<__FUNCTION_NAME<<": m_itemstring=\"" - < item="<getVideoDriver(); - - // Attach a simple mesh to the player for showing an image - 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_BACK_FACE_CULLING, false); - buf->getMaterial().setTexture(0, driver->getTexture(getTexturePath("player.png").c_str())); - buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false); - buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true); - //buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; - buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; - // 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_BACK_FACE_CULLING, false); - buf->getMaterial().setTexture(0, driver->getTexture(getTexturePath("player_back.png").c_str())); - 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(); - updateNodePos(); -} -#endif - -/* - MapBlockObjectList -*/ - -MapBlockObjectList::MapBlockObjectList(MapBlock *block): - m_block(block) -{ - m_mutex.Init(); -} - -MapBlockObjectList::~MapBlockObjectList() -{ - clear(); -} - -/* - The serialization format: - [0] u16 number of entries - [2] entries (id, typeId, parameters) -*/ - -void MapBlockObjectList::serialize(std::ostream &os, u8 version) -{ - JMutexAutoLock lock(m_mutex); - - u8 buf[2]; - writeU16(buf, m_objects.size()); - os.write((char*)buf, 2); - - for(core::map::Iterator - i = m_objects.getIterator(); - i.atEnd() == false; i++) - { - i.getNode()->getValue()->serialize(os, version); - } -} - -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 ids_to_delete; - for(core::map::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::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="<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); - - /* - 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::Iterator - i = ids_to_delete.getIterator(); - i.atEnd() == false; i++) - { - s16 id = i.getNode()->getKey(); - - /*dstream<<"MapBlockObjectList deleting object" - " id="<removeFromScene(); - delete obj; - m_objects.remove(id); - } - - m_last_update_daynight_ratio = daynight_ratio; -} - -s16 MapBlockObjectList::getFreeId() throw(ContainerFullException) -{ - s16 id = 0; - for(;;) - { - if(m_objects.find(id) == NULL) - return id; - if(id == 32767) - throw ContainerFullException - ("MapBlockObjectList doesn't fit more objects"); - id++; - } -} - -void MapBlockObjectList::add(MapBlockObject *object) - throw(ContainerFullException, AlreadyExistsException) -{ - if(object == NULL) - { - dstream<<"MapBlockObjectList::add(): NULL object"<m_id == -1) - { - object->m_id = getFreeId(); - } - - if(m_objects.find(object->m_id) != NULL) - { - dstream<<"MapBlockObjectList::add(): " - "object with same id already exists"<m_block = m_block; - - /*v3f p = object->m_pos; - dstream<<"MapBlockObjectList::add(): " - <<"m_block->getPos()=(" - <getPos().X<<"," - <getPos().Y<<"," - <getPos().Z<<")" - <<" inserting object with id="<m_id - <<" pos=" - <<"("<m_id, object); -} - -void MapBlockObjectList::clear() -{ - JMutexAutoLock lock(m_mutex); - - for(core::map::Iterator - i = m_objects.getIterator(); - i.atEnd() == false; i++) - { - MapBlockObject *obj = i.getNode()->getValue(); - //FIXME: This really shouldn't be NULL at any time, - // but this condition was added because it was. - if(obj != NULL) - { - obj->removeFromScene(); - delete obj; - } - } - - m_objects.clear(); -} - -void MapBlockObjectList::remove(s16 id) -{ - JMutexAutoLock lock(m_mutex); - - core::map::Node *n; - n = m_objects.find(id); - if(n == NULL) - return; - - n->getValue()->removeFromScene(); - delete n->getValue(); - m_objects.remove(id); -} - -MapBlockObject * MapBlockObjectList::get(s16 id) -{ - core::map::Node *n; - n = m_objects.find(id); - if(n == NULL) - return NULL; - else - return n->getValue(); -} - -void MapBlockObjectList::step(float dtime, bool server, u32 daynight_ratio) -{ - DSTACK(__FUNCTION_NAME); - - JMutexAutoLock lock(m_mutex); - - core::map ids_to_delete; - - { - DSTACKF("%s: stepping objects", __FUNCTION_NAME); - - for(core::map::Iterator - i = m_objects.getIterator(); - i.atEnd() == false; i++) - { - MapBlockObject *obj = i.getNode()->getValue(); - - DSTACKF("%s: stepping object type %i", __FUNCTION_NAME, - obj->getTypeId()); - - if(server) - { - // Update light - 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); - - bool to_delete = obj->serverStep(dtime, daynight_ratio); - - if(to_delete) - ids_to_delete.insert(obj->m_id, true); - } - else - { - obj->clientStep(dtime); - } - } - } - - { - DSTACKF("%s: deleting objects", __FUNCTION_NAME); - - // Delete objects in delete queue - for(core::map::Iterator - i = ids_to_delete.getIterator(); - i.atEnd() == false; i++) - { - s16 id = i.getNode()->getKey(); - - MapBlockObject *obj = m_objects[id]; - obj->removeFromScene(); - delete obj; - m_objects.remove(id); - } - } - - /* - Wrap objects on server - */ - - if(server == false) - return; - - { - DSTACKF("%s: object wrap loop", __FUNCTION_NAME); - - for(core::map::Iterator - i = m_objects.getIterator(); - i.atEnd() == false; i++) - { - MapBlockObject *obj = i.getNode()->getValue(); - - v3s16 pos_i = floatToInt(obj->m_pos, BS); - - if(m_block->isValidPosition(pos_i)) - { - // No wrap - continue; - } - - bool impossible = wrapObject(obj); - - if(impossible) - { - // No wrap - continue; - } - - // Restart find - i = m_objects.getIterator(); - } - } -} - -bool MapBlockObjectList::wrapObject(MapBlockObject *object) -{ - DSTACK(__FUNCTION_NAME); - - // No lock here; this is called so that the lock is already locked. - //JMutexAutoLock lock(m_mutex); - - assert(object->m_block == m_block); - assert(m_objects.find(object->m_id) != NULL); - assert(m_objects[object->m_id] == object); - - Map *map = m_block->getParent(); - - // Calculate blockpos on map - v3s16 oldblock_pos_i_on_map = m_block->getPosRelative(); - v3f pos_f_on_oldblock = object->m_pos; - v3s16 pos_i_on_oldblock = floatToInt(pos_f_on_oldblock, BS); - v3s16 pos_i_on_map = pos_i_on_oldblock + oldblock_pos_i_on_map; - v3s16 pos_blocks_on_map = getNodeBlockPos(pos_i_on_map); - - // Get new block - MapBlock *newblock; - try{ - newblock = map->getBlockNoCreate(pos_blocks_on_map); - } - catch(InvalidPositionException &e) - { - // Couldn't find block -> not wrapping - /*dstream<<"WARNING: Wrapping object not possible: " - <<"could not find new block" - <<"("<getPosRelative(); - v3f newblock_pos_f_on_map = intToFloat(newblock_pos_i_on_map, BS); - v3f pos_f_on_newblock = pos_f_on_oldblock - - newblock_pos_f_on_map + oldblock_pos_f_on_map; - - // Remove object from this block - m_objects.remove(object->m_id); - - // Add object to new block - object->m_pos = pos_f_on_newblock; - object->m_id = -1; - object->m_block = NULL; - newblock->addObject(object); - - //dstream<<"NOTE: Wrapped object"< &dest) -{ - for(core::map::Iterator - i = m_objects.getIterator(); - i.atEnd() == false; i++) - { - MapBlockObject *obj = i.getNode()->getValue(); - - f32 d = (obj->getRelativeShowPos() - origin).getLength(); - - if(d > max_d) - continue; - - DistanceSortedObject dso(obj, d); - - dest.push_back(dso); - } -} - -//END diff --git a/src/mapblockobject.h b/src/mapblockobject.h deleted file mode 100644 index 406c32fce..000000000 --- a/src/mapblockobject.h +++ /dev/null @@ -1,1091 +0,0 @@ -/* -Minetest-c55 -Copyright (C) 2010 celeron55, Perttu Ahola - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along -with this program; if not, write to the Free Software Foundation, Inc., -51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -// This file contains the DEPRECATED MapBlockObject system - -#ifndef MAPBLOCKOBJECT_HEADER -#define MAPBLOCKOBJECT_HEADER - -#include "common_irrlicht.h" -#include -#include -#include "serialization.h" -#include "mapnode.h" -#include "constants.h" -#include "debug.h" - -#define MAPBLOCKOBJECT_TYPE_PLAYER 0 -#define MAPBLOCKOBJECT_TYPE_SIGN 2 -#define MAPBLOCKOBJECT_TYPE_RAT 3 -#define MAPBLOCKOBJECT_TYPE_ITEM 4 -// Used for handling selecting special stuff -//#define MAPBLOCKOBJECT_TYPE_PSEUDO 1000 - -class MapBlock; - -class MapBlockObject -{ -public: - MapBlockObject(MapBlock *block, s16 id, v3f pos): - m_collision_box(NULL), - m_selection_box(NULL), - m_block(block), - m_id(id), - m_pos(pos) - { - } - virtual ~MapBlockObject() - { - } - - s16 getId() - { - return m_id; - } - MapBlock* getBlock() - { - return m_block; - } - - // Writes id, pos and typeId - void serializeBase(std::ostream &os, u8 version) - { - u8 buf[6]; - - // id - writeS16(buf, m_id); - os.write((char*)buf, 2); - - // position - // stored as x1000/BS v3s16 - v3s16 pos_i(m_pos.X*1000/BS, m_pos.Y*1000/BS, m_pos.Z*1000/BS); - writeV3S16(buf, pos_i); - os.write((char*)buf, 6); - - // typeId - writeU16(buf, getTypeId()); - os.write((char*)buf, 2); - } - - // Position where the object is drawn relative to block - virtual v3f getRelativeShowPos() - { - return m_pos; - } - // Get floating point position on map - v3f getAbsolutePos(); - - void setBlockChanged(); - - // Shootline is relative to block - bool isSelected(core::line3d shootline) - { - if(m_selection_box == NULL) - return false; - - core::aabbox3d offsetted_box( - m_selection_box->MinEdge + m_pos, - m_selection_box->MaxEdge + m_pos - ); - - return offsetted_box.intersectsWithLine(shootline); - } - - core::aabbox3d getSelectionBoxOnMap() - { - v3f absolute_pos = getAbsolutePos(); - - core::aabbox3d box( - m_selection_box->MinEdge + absolute_pos, - m_selection_box->MaxEdge + absolute_pos - ); - - return box; - } - - /* - Implementation interface - */ - - virtual u16 getTypeId() const = 0; - // Shall call serializeBase and then write the parameters - virtual void serialize(std::ostream &os, u8 version) = 0; - // Shall read parameters from stream - virtual void update(std::istream &is, u8 version) = 0; - - virtual std::string getInventoryString() { return "None"; } - - // Reimplementation shall call this. - virtual void updatePos(v3f pos) - { - m_pos = pos; - } - - // Shall move the object around, modify it and possibly delete it. - // Typical dtimes are 0.2 and 10000. - // A return value of true requests deletion of the object by the caller. - // NOTE: Only server calls this. - virtual bool serverStep(float dtime, u32 daynight_ratio) - { return false; }; - -#ifdef SERVER - void clientStep(float dtime) {}; - void addToScene(void *smgr) {}; - void removeFromScene() {}; - void updateLight(u8 light_at_pos) {}; -#else - // This should do slight animations only or so - virtual void clientStep(float dtime) {}; - - // NOTE: These functions should do nothing if the asked state is - // same as the current state - // Shall add and remove relevant scene nodes for rendering the - // object in the game world - virtual void addToScene(scene::ISceneManager *smgr) = 0; - // Shall remove stuff from the scene - // Should return silently if there is nothing to remove - // NOTE: This has to be called before calling destructor - virtual void removeFromScene() = 0; - - // 0 <= light_at_pos <= LIGHT_SUN - virtual void updateLight(u8 light_at_pos) {}; -#endif - - virtual std::string infoText() { return ""; } - - // Shall be left NULL if doesn't collide - // Position is relative to m_pos in block - core::aabbox3d * m_collision_box; - - // Shall be left NULL if can't be selected - core::aabbox3d * m_selection_box; - -protected: - MapBlock *m_block; - // This differentiates the instance of the object - // Not same as typeId. - s16 m_id; - // Position of the object inside the block - // Units is node coordinates * BS - v3f m_pos; - - friend class MapBlockObjectList; -}; - -#if 0 -/* - Used for handling selections of special stuff -*/ -class PseudoMBObject : public MapBlockObject -{ -public: - // The constructor of every MapBlockObject should be like this - PseudoMBObject(MapBlock *block, s16 id, v3f pos): - MapBlockObject(block, id, pos) - { - } - virtual ~PseudoMBObject() - { - if(m_selection_box) - delete m_selection_box; - } - - /* - Implementation interface - */ - virtual u16 getTypeId() const - { - return MAPBLOCKOBJECT_TYPE_PSEUDO; - } - virtual void serialize(std::ostream &os, u8 version) - { - assert(0); - } - virtual void update(std::istream &is, u8 version) - { - assert(0); - } - virtual bool serverStep(float dtime, u32 daynight_ratio) - { - assert(0); - } - - /* - Special methods - */ - - void setSelectionBox(core::aabbox3d box) - { - m_selection_box = new core::aabbox3d(box); - } - -protected: -}; -#endif - -class MovingObject : public MapBlockObject -{ -public: - // The constructor of every MapBlockObject should be like this - MovingObject(MapBlock *block, s16 id, v3f pos): - MapBlockObject(block, id, pos), - m_speed(0,0,0), - m_oldpos(pos), - m_pos_animation_time(0), - m_showpos(pos) - { - m_touching_ground = false; - } - virtual ~MovingObject() - { - } - - /* - Implementation interface - */ - - virtual u16 getTypeId() const = 0; - - virtual void serialize(std::ostream &os, u8 version) - { - serializeBase(os, version); - - u8 buf[6]; - - // Write speed - // stored as x100/BS v3s16 - v3s16 speed_i(m_speed.X*100/BS, m_speed.Y*100/BS, m_speed.Z*100/BS); - writeV3S16(buf, speed_i); - os.write((char*)buf, 6); - } - virtual void update(std::istream &is, u8 version) - { - u8 buf[6]; - - // Read speed - // stored as x100/BS v3s16 - is.read((char*)buf, 6); - v3s16 speed_i = readV3S16(buf); - v3f speed((f32)speed_i.X/100*BS, - (f32)speed_i.Y/100*BS, - (f32)speed_i.Z/100*BS); - - m_speed = speed; - } - - // Reimplementation shall call this. - virtual void updatePos(v3f pos) - { - m_oldpos = m_showpos; - m_pos = pos; - - if(m_pos_animation_time < 0.001 || m_pos_animation_time > 1.0) - m_pos_animation_time = m_pos_animation_time_counter; - else - m_pos_animation_time = m_pos_animation_time * 0.9 - + m_pos_animation_time_counter * 0.1; - m_pos_animation_time_counter = 0; - m_pos_animation_counter = 0; - } - - // Position where the object is drawn relative to block - virtual v3f getRelativeShowPos() - { - return m_showpos; - } - // Returns m_showpos relative to whole map - v3f getAbsoluteShowPos(); - - virtual bool serverStep(float dtime, u32 daynight_ratio) - { return false; }; - virtual void clientStep(float dtime) - {}; - - /*virtual void addToScene(scene::ISceneManager *smgr) = 0; - virtual void removeFromScene() = 0;*/ - - /* - Special methods - */ - - // Move with collision detection, server side - void move(float dtime, v3f acceleration); - - // Move from old position to new position, client side - void simpleMove(float dtime); - -protected: - v3f m_speed; - bool m_touching_ground; - // Client-side moving - v3f m_oldpos; - f32 m_pos_animation_counter; - f32 m_pos_animation_time; - f32 m_pos_animation_time_counter; - v3f m_showpos; -}; - -class SignObject : public MapBlockObject -{ -public: - // The constructor of every MapBlockObject should be like this - SignObject(MapBlock *block, s16 id, v3f pos): - MapBlockObject(block, id, pos) -#ifndef SERVER - ,m_node(NULL) -#endif - { - m_selection_box = new core::aabbox3d - (-BS*0.4,-BS*0.5,-BS*0.4, BS*0.4,BS*0.5,BS*0.4); - } - virtual ~SignObject() - { - delete m_selection_box; - } - - /* - Implementation interface - */ - virtual u16 getTypeId() const - { - return MAPBLOCKOBJECT_TYPE_SIGN; - } - virtual void serialize(std::ostream &os, u8 version) - { - serializeBase(os, version); - u8 buf[2]; - - // Write yaw * 10 - writeS16(buf, m_yaw * 10); - os.write((char*)buf, 2); - - // Write text length - writeU16(buf, m_text.size()); - os.write((char*)buf, 2); - - // Write text - os.write(m_text.c_str(), m_text.size()); - } - virtual void update(std::istream &is, u8 version) - { - u8 buf[2]; - - // Read yaw * 10 - is.read((char*)buf, 2); - s16 yaw_i = readS16(buf); - m_yaw = (f32)yaw_i / 10; - - // Read text length - is.read((char*)buf, 2); - u16 size = readU16(buf); - - // Read text - m_text.clear(); - for(u16 i=0; igetVideoDriver(); - - 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,-BS/2,0, 0,0,0, c, 0,1), - video::S3DVertex(-BS/2,-BS/2,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_BACK_FACE_CULLING, false); - buf->getMaterial().setTexture - (0, driver->getTexture(getTexturePath("sign.png").c_str())); - 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(); - } - { // Back - scene::IMeshBuffer *buf = new scene::SMeshBuffer(); - video::SColor c(255,255,255,255); - video::S3DVertex vertices[4] = - { - video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c, 0,1), - video::S3DVertex(BS/2,-BS/2,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_BACK_FACE_CULLING, false); - buf->getMaterial().setTexture - (0, driver->getTexture(getTexturePath("sign_back.png").c_str())); - 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(); - - updateSceneNode(); - } - virtual void removeFromScene() - { - if(m_node != NULL) - { - m_node->remove(); - m_node = NULL; - } - } - virtual 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); - setMeshVerticesColor(m_node->getMesh(), color); - } -#endif - - virtual std::string infoText() - { - return std::string("\"") + m_text + "\""; - } - - virtual std::string getInventoryString() - { - return std::string("Sign ")+m_text; - } - - /* - Special methods - */ - void updateSceneNode() - { -#ifndef SERVER - if(m_node != NULL) - { - m_node->setPosition(getAbsolutePos()); - m_node->setRotation(v3f(0, m_yaw, 0)); - } -#endif - } - - void setText(std::string text) - { - if(text.size() > SIGN_TEXT_MAX_LENGTH) - text = text.substr(0, SIGN_TEXT_MAX_LENGTH); - m_text = text; - - setBlockChanged(); - } - - std::string getText() - { - return m_text; - } - - void setYaw(f32 yaw) - { - m_yaw = yaw; - - setBlockChanged(); - } - -protected: -#ifndef SERVER - scene::IMeshSceneNode *m_node; -#endif - std::string m_text; - f32 m_yaw; -}; - -class RatObject : public MovingObject -{ -public: - RatObject(MapBlock *block, s16 id, v3f pos): - MovingObject(block, id, pos) -#ifndef SERVER - ,m_node(NULL) -#endif - { - m_collision_box = new core::aabbox3d - (-BS*0.3,-BS*.25,-BS*0.3, BS*0.3,BS*0.25,BS*0.3); - m_selection_box = new core::aabbox3d - (-BS*0.3,-BS*.25,-BS*0.3, BS*0.3,BS*0.25,BS*0.3); - - m_yaw = 0; - m_counter1 = 0; - m_counter2 = 0; - m_age = 0; - } - virtual ~RatObject() - { - delete m_collision_box; - delete m_selection_box; - } - - /* - Implementation interface - */ - virtual u16 getTypeId() const - { - return MAPBLOCKOBJECT_TYPE_RAT; - } - virtual void serialize(std::ostream &os, u8 version) - { - MovingObject::serialize(os, version); - u8 buf[2]; - - // Write yaw * 10 - writeS16(buf, m_yaw * 10); - os.write((char*)buf, 2); - - } - virtual void update(std::istream &is, u8 version) - { - MovingObject::update(is, version); - u8 buf[2]; - - // Read yaw * 10 - is.read((char*)buf, 2); - s16 yaw_i = readS16(buf); - m_yaw = (f32)yaw_i / 10; - - updateNodePos(); - } - - virtual bool serverStep(float dtime, u32 daynight_ratio) - { - m_age += dtime; - if(m_age > 60) - // Die - return true; - - v3f dir(cos(m_yaw/180*PI),0,sin(m_yaw/180*PI)); - - f32 speed = 2*BS; - - m_speed.X = speed * dir.X; - m_speed.Z = speed * dir.Z; - - if(m_touching_ground && (m_oldpos - m_pos).getLength() < dtime*speed/2) - { - m_counter1 -= dtime; - if(m_counter1 < 0.0) - { - m_counter1 += 1.0; - m_speed.Y = 5.0*BS; - } - } - - { - m_counter2 -= dtime; - if(m_counter2 < 0.0) - { - m_counter2 += (float)(myrand()%100)/100*3.0; - m_yaw += ((float)(myrand()%200)-100)/100*180; - m_yaw = wrapDegrees(m_yaw); - } - } - - m_oldpos = m_pos; - - //m_yaw += dtime*90; - - move(dtime, v3f(0, -9.81*BS, 0)); - - //updateNodePos(); - - return false; - } -#ifndef SERVER - virtual void clientStep(float dtime) - { - //m_pos += m_speed * dtime; - MovingObject::simpleMove(dtime); - - updateNodePos(); - } - - virtual void addToScene(scene::ISceneManager *smgr); - - virtual void removeFromScene() - { - if(m_node == NULL) - return; - - m_node->remove(); - m_node = NULL; - } - - virtual 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); - setMeshVerticesColor(m_node->getMesh(), color); - } - -#endif - - virtual std::string getInventoryString() - { - // There must be a space after the name - // Or does there? - return std::string("Rat "); - } - - /* - Special methods - */ - - void updateNodePos() - { -#ifndef SERVER - if(m_node == NULL) - return; - - m_node->setPosition(getAbsoluteShowPos()); - m_node->setRotation(v3f(0, -m_yaw+180, 0)); -#endif - } - -protected: -#ifndef SERVER - scene::IMeshSceneNode *m_node; -#endif - float m_yaw; - - float m_counter1; - float m_counter2; - float m_age; -}; - -/* - An object on the map that represents an inventory item -*/ - -class InventoryItem; - -class ItemObject : public MapBlockObject -{ -public: - // The constructor of every MapBlockObject should be like this - ItemObject(MapBlock *block, s16 id, v3f pos): - MapBlockObject(block, id, pos) -#ifndef SERVER - ,m_node(NULL) -#endif - { - /*m_selection_box = new core::aabbox3d - (-BS*0.4,-BS*0.5,-BS*0.4, BS*0.4,BS*0.5,BS*0.4);*/ - m_selection_box = new core::aabbox3d - (-BS/3,-BS/2,-BS/3, BS/3,-BS/2+BS*2/3,BS/3); - m_yaw = 0.0; - } - virtual ~ItemObject() - { - delete m_selection_box; - } - - /* - Implementation interface - */ - virtual u16 getTypeId() const - { - return MAPBLOCKOBJECT_TYPE_ITEM; - } - virtual void serialize(std::ostream &os, u8 version) - { - serializeBase(os, version); - u8 buf[2]; - - // Write text length - writeU16(buf, m_itemstring.size()); - os.write((char*)buf, 2); - - // Write text - os.write(m_itemstring.c_str(), m_itemstring.size()); - } - virtual void update(std::istream &is, u8 version) - { - u8 buf[2]; - - // Read text length - is.read((char*)buf, 2); - u16 size = readU16(buf); - - // Read text - std::string old_itemstring = m_itemstring; - m_itemstring.clear(); - for(u16 i=0; igetMesh(); - if(mesh->getMeshBufferCount() >= 1) - { - scene::IMeshBuffer *buf = mesh->getMeshBuffer(0); - //dstream<<"Setting texture "<getMaterial().setTexture(0, texture); - } - } - - updateSceneNode(); -#endif - } - - virtual bool serverStep(float dtime, u32 daynight_ratio) - { - return false; - } - -#ifndef SERVER - virtual void clientStep(float dtime) - { - m_yaw += dtime * 60; - if(m_yaw >= 360.) - m_yaw -= 360.; - - updateSceneNode(); - } - - virtual void addToScene(scene::ISceneManager *smgr); - - virtual void removeFromScene() - { - if(m_node != NULL) - { - m_node->remove(); - m_node = NULL; - } - } - virtual 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); - setMeshVerticesColor(m_node->getMesh(), color); - } -#endif - - virtual std::string infoText() - { - return std::string("\"") + m_itemstring + "\""; - } - - virtual std::string getInventoryString() - { - return std::string("ItemObj ")+m_itemstring; - } - - /* - Special methods - */ - - InventoryItem * createInventoryItem(); - -#ifndef SERVER - video::ITexture * getItemImage(); - - void updateSceneNode() - { - if(m_node != NULL) - { - m_node->setPosition(getAbsolutePos()); - m_node->setRotation(v3f(0, m_yaw, 0)); - } - } -#endif - - void setItemString(std::string inventorystring) - { - m_itemstring = inventorystring; - setBlockChanged(); - } - - std::string getItemString() - { - return m_itemstring; - } - -protected: -#ifndef SERVER - scene::IMeshSceneNode *m_node; -#endif - std::string m_itemstring; - f32 m_yaw; -}; - -/* - NOTE: Not used. -*/ -class PlayerObject : public MovingObject -{ -public: - PlayerObject(MapBlock *block, s16 id, v3f pos): - MovingObject(block, id, pos), -#ifndef SERVER - m_node(NULL), -#endif - m_yaw(0) - { - m_collision_box = new core::aabbox3d - (-BS*0.3,-BS*.25,-BS*0.3, BS*0.3,BS*0.25,BS*0.3); - /*m_selection_box = new core::aabbox3d - (-BS*0.3,-BS*.25,-BS*0.3, BS*0.3,BS*0.25,BS*0.3);*/ - } - virtual ~PlayerObject() - { - if(m_collision_box) - delete m_collision_box; - if(m_selection_box) - delete m_selection_box; - } - - /* - Implementation interface - */ - virtual u16 getTypeId() const - { - return MAPBLOCKOBJECT_TYPE_PLAYER; - } - virtual void serialize(std::ostream &os, u8 version) - { - // Object data is generated from actual player - } - virtual void update(std::istream &is, u8 version) - { - MovingObject::update(is, version); - u8 buf[2]; - - // Read yaw * 10 - is.read((char*)buf, 2); - s16 yaw_i = readS16(buf); - m_yaw = (f32)yaw_i / 10; - - updateNodePos(); - } - - virtual bool serverStep(float dtime, u32 daynight_ratio) - { - // Player is handled elsewhere. - // Die. - //return true; - // Actually, fail very loudly: - assert(0); - } - -#ifndef SERVER - virtual void clientStep(float dtime) - { - MovingObject::simpleMove(dtime); - - updateNodePos(); - } - - virtual void addToScene(scene::ISceneManager *smgr); - - virtual void removeFromScene() - { - if(m_node == NULL) - return; - - m_node->remove(); - m_node = NULL; - } - - virtual 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); - setMeshVerticesColor(m_node->getMesh(), color); - } - -#endif - - /* - Special methods - */ - - void updateNodePos() - { -#ifndef SERVER - if(m_node == NULL) - return; - - m_node->setPosition(getAbsoluteShowPos()); - m_node->setRotation(v3f(0, -m_yaw+180, 0)); -#endif - } - -protected: -#ifndef SERVER - scene::IMeshSceneNode *m_node; -#endif - float m_yaw; - - v3f m_oldpos; -}; - -struct DistanceSortedObject -{ - DistanceSortedObject(MapBlockObject *a_obj, f32 a_d) - { - obj = a_obj; - d = a_d; - } - - MapBlockObject *obj; - f32 d; - - bool operator < (DistanceSortedObject &other) - { - return d < other.d; - } -}; - -namespace irr{ -namespace scene{ - class ISceneManager; -} -} -using namespace irr; - -class MapBlockObjectList -{ -public: - MapBlockObjectList(MapBlock *block); - ~MapBlockObjectList(); - - // Writes the count, id, the type id and the parameters of all objects - void serialize(std::ostream &os, u8 version); - - // Reads ids, type_ids and parameters. - // Creates, updates and deletes objects. - // If smgr!=NULL, new objects are added to the scene - void update(std::istream &is, u8 version, scene::ISceneManager *smgr, - u32 daynight_ratio); - - // Finds a new unique id - s16 getFreeId() throw(ContainerFullException); - /* - Adds an object. - Set id to -1 to have this set it to a suitable one. - The block pointer member is set to this block. - */ - void add(MapBlockObject *object) - throw(ContainerFullException, AlreadyExistsException); - - // Deletes and removes all objects - void clear(); - - /* - Removes an object. - Ignores inexistent objects - */ - void remove(s16 id); - /* - References an object. - The object will not be valid after step() or of course if - it is removed. - Grabbing the lock is recommended while processing. - */ - MapBlockObject * get(s16 id); - - // You'll want to grab this in a SharedPtr - JMutexAutoLock * getLock() - { - return new JMutexAutoLock(m_mutex); - } - - // Steps all objects and if server==true, removes those that - // want to be removed - void step(float dtime, bool server, u32 daynight_ratio); - - // Wraps an object that wants to move onto this block from an another - // Returns true if wrapping was impossible - bool wrapObject(MapBlockObject *object); - - // origin is relative to block - void getObjects(v3f origin, f32 max_d, - core::array &dest); - - // Number of objects - s32 getCount() - { - return m_objects.size(); - } - -private: - JMutex m_mutex; - // Key is id - core::map m_objects; - MapBlock *m_block; - - u32 m_last_update_daynight_ratio; -}; - - -#endif - diff --git a/src/mapgen.cpp b/src/mapgen.cpp index 9a7c7ba90..a74a91eeb 100644 --- a/src/mapgen.cpp +++ b/src/mapgen.cpp @@ -1405,6 +1405,7 @@ bool get_have_sand(u64 seed, v2s16 p2d) */ void add_random_objects(MapBlock *block) { +#if 0 for(s16 z0=0; z0setChangedFlag(); +#endif } void make_block(BlockMakeData *data) diff --git a/src/server.cpp b/src/server.cpp index 5b9903f5a..d78a00ea3 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -860,107 +860,10 @@ void RemoteClient::SendObjectData( v3s16 center_nodepos = floatToInt(playerpos, BS); v3s16 center = getNodeBlockPos(center_nodepos); - s16 d_max = g_settings->getS16("active_object_range"); - - // Number of blocks whose objects were written to bos - u16 blockcount = 0; - - std::ostringstream bos(std::ios_base::binary); - - for(s16 d = 0; d <= d_max; d++) - { - core::list list; - getFacePositions(list, d); - - core::list::Iterator li; - for(li=list.begin(); li!=list.end(); li++) - { - v3s16 p = *li + center; - - /* - Ignore blocks that haven't been sent to the client - */ - { - if(m_blocks_sent.find(p) == NULL) - continue; - } - - // Try stepping block and add it to a send queue - try - { - - // Get block - MapBlock *block = server->m_env.getMap().getBlockNoCreate(p); - - /* - Step block if not in stepped_blocks and add to stepped_blocks. - */ - if(stepped_blocks.find(p) == NULL) - { - block->stepObjects(dtime, true, server->m_env.getDayNightRatio()); - stepped_blocks.insert(p, true); - //block->setChangedFlag(); - } - - // Skip block if there are no objects - if(block->getObjectCount() == 0) - continue; - - /* - Write objects - */ - - // Write blockpos - writeV3S16(buf, p); - bos.write((char*)buf, 6); - - // Write objects - //block->serializeObjects(bos, serialization_version); // DEPRECATED - // count=0 - writeU16(bos, 0); - - blockcount++; - - /* - Stop collecting objects if data is already too big - */ - // Sum of player and object data sizes - s32 sum = (s32)os.tellp() + 2 + (s32)bos.tellp(); - // break out if data too big - if(sum > MAX_OBJECTDATA_SIZE) - { - goto skip_subsequent; - } - - } //try - catch(InvalidPositionException &e) - { - // Not in memory - // Add it to the emerge queue and trigger the thread. - // Fetch the block only if it is on disk. - - // Grab and increment counter - /*SharedPtr lock - (m_num_blocks_in_emerge_queue.getLock()); - m_num_blocks_in_emerge_queue.m_value++;*/ - - // Add to queue as an anonymous fetch from disk - u8 flags = BLOCK_EMERGE_FLAG_FROMDISK; - server->m_emerge_queue.addBlock(0, p, flags); - server->m_emergethread.trigger(); - } - } - } - -skip_subsequent: - // Write block count - writeU16(buf, blockcount); + writeU16(buf, 0); os.write((char*)buf, 2); - // Write block objects - os<getS16("active_object_send_range_blocks"); + radius *= MAP_BLOCKSIZE; for(core::map::Iterator i = m_clients.getIterator(); @@ -2343,87 +2247,8 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) } else if(command == TOSERVER_CLICK_OBJECT) { - if(datasize < 13) - return; - - if((getPlayerPrivs(player) & PRIV_BUILD) == 0) - return; - - /* - [0] u16 command - [2] u8 button (0=left, 1=right) - [3] v3s16 block - [9] s16 id - [11] u16 item - */ - u8 button = readU8(&data[2]); - v3s16 p; - p.X = readS16(&data[3]); - p.Y = readS16(&data[5]); - p.Z = readS16(&data[7]); - s16 id = readS16(&data[9]); - //u16 item_i = readU16(&data[11]); - - MapBlock *block = NULL; - try - { - block = m_env.getMap().getBlockNoCreate(p); - } - catch(InvalidPositionException &e) - { - derr_server<<"CLICK_OBJECT block not found"<getObject(id); - - if(obj == NULL) - { - derr_server<<"CLICK_OBJECT object not found"<inventory.getList("main"); - if(g_settings->getBool("creative_mode") == false && ilist != NULL) - { - - // Skip if inventory has no free space - if(ilist->getUsedSlots() == ilist->getSize()) - { - dout_server<<"Player inventory has no free space"<getTypeId() == MAPBLOCKOBJECT_TYPE_ITEM) - { - item = ((ItemObject*)obj)->createInventoryItem(); - } - // Else create an item of the object - else - { - item = new MapBlockObjectItem - (obj->getInventoryString()); - } - - // Add to inventory and send inventory - ilist->addItem(item); - UpdateCrafting(player->peer_id); - SendInventory(player->peer_id); - } - - // Remove from block - block->removeObject(id); - } + derr_server<<"Server: CLICK_OBJECT not supported anymore"<getObject(id); - if(obj == NULL) - { - derr_server<<"Error while setting sign text: " - "object not found"<getTypeId() != MAPBLOCKOBJECT_TYPE_SIGN) - { - derr_server<<"Error while setting sign text: " - "object is not a sign"<setText(text); - - obj->getBlock()->setChangedFlag(); + derr_server<<"Server: TOSERVER_SIGNTEXT not supported anymore" + <::Iterator + i = other.m_settings.getIterator(); + i.atEnd() == false; i++) + { + m_settings[i.getNode()->getKey()] = i.getNode()->getValue(); + } + + for(core::map::Iterator + i = other.m_defaults.getIterator(); + i.atEnd() == false; i++) + { + m_defaults[i.getNode()->getKey()] = i.getNode()->getValue(); + } + + return; + } + Settings & operator+=(Settings &other) { JMutexAutoLock lock(m_mutex); diff --git a/src/tile.cpp b/src/tile.cpp index ac5965e9f..986d6bbf1 100644 --- a/src/tile.cpp +++ b/src/tile.cpp @@ -1054,6 +1054,120 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg, image->drop(); } } + /* + "[makealpha:R,G,B:filename.png" + Use an image with converting one color to transparent. + */ + else if(part_of_name.substr(0,11) == "[makealpha:") + { + if(baseimg != NULL) + { + dstream<<"WARNING: generate_image(): baseimg!=NULL " + <<"for part_of_name=\""<createImageFromFile(path.c_str()); + + if(image == NULL) + { + dstream<<"WARNING: generate_image(): Loading path \"" + < dim = image->getDimension(); + baseimg = driver->createImage(video::ECF_A8R8G8B8, dim); + + for(u32 y=0; ygetPixel(x,y); + u32 r = c.getRed(); + u32 g = c.getGreen(); + u32 b = c.getBlue(); + if(!(r == r1 && g == g1 && b == b1)) + continue; + c.setAlpha(0); + image->setPixel(x,y,c); + } + // Blit + image->copyTo(baseimg); + + image->drop(); + } + } + /* + "[makealpha2:R,G,B;R2,G2,B2:filename.png" + Use an image with converting two colors to transparent. + */ + else if(part_of_name.substr(0,12) == "[makealpha2:") + { + if(baseimg != NULL) + { + dstream<<"WARNING: generate_image(): baseimg!=NULL " + <<"for part_of_name=\""<createImageFromFile(path.c_str()); + + if(image == NULL) + { + dstream<<"WARNING: generate_image(): Loading path \"" + < dim = image->getDimension(); + baseimg = driver->createImage(video::ECF_A8R8G8B8, dim); + + for(u32 y=0; ygetPixel(x,y); + u32 r = c.getRed(); + u32 g = c.getGreen(); + u32 b = c.getBlue(); + if(!(r == r1 && g == g1 && b == b1) && + !(r == r2 && g == g2 && b == b2)) + continue; + c.setAlpha(0); + image->setPixel(x,y,c); + } + // Blit + image->copyTo(baseimg); + + image->drop(); + } + } /* [inventorycube{topimage{leftimage{rightimage In every subimage, replace ^ with &. diff --git a/src/utility.h b/src/utility.h index f8cc34984..255b75c08 100644 --- a/src/utility.h +++ b/src/utility.h @@ -810,6 +810,35 @@ inline float wrapDegrees(float f) return f; } +/* Wrap to 0...360 */ +inline float wrapDegrees_0_360(float f) +{ + // Take examples of f=10, f=720.5, f=-0.5, f=-360.5 + // This results in + // 10, 720, -1, -361 + int i = floor(f); + // 0, 2, 0, -1 + int l = i / 360; + // Wrap to 0...360 + // 0, 2, -1, -2 + if(i < 0) + l -= 1; + // 0, 720, 0, -360 + int k = l * 360; + // 10, 0.5, -0.5, -0.5 + f -= float(k); + return f; +} + +/* Wrap to -180...180 */ +inline float wrapDegrees_180(float f) +{ + f += 180; + f = wrapDegrees_0_360(f); + f -= 180; + return f; +} + inline std::string lowercase(const std::string &s) { std::string s2;