diff options
-rw-r--r-- | data/dungeon_master.png | bin | 0 -> 5998 bytes | |||
-rw-r--r-- | data/fireball.png | bin | 0 -> 603 bytes | |||
-rw-r--r-- | src/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/MyBillboardSceneNode.cpp | 202 | ||||
-rw-r--r-- | src/MyBillboardSceneNode.h | 77 | ||||
-rw-r--r-- | src/client.cpp | 255 | ||||
-rw-r--r-- | src/client.h | 10 | ||||
-rw-r--r-- | src/clientobject.cpp | 2 | ||||
-rw-r--r-- | src/clientobject.h | 1 | ||||
-rw-r--r-- | src/content_cao.cpp | 378 | ||||
-rw-r--r-- | src/content_cao.h | 75 | ||||
-rw-r--r-- | src/content_object.h | 1 | ||||
-rw-r--r-- | src/content_sao.cpp | 513 | ||||
-rw-r--r-- | src/content_sao.h | 47 | ||||
-rw-r--r-- | src/defaultsettings.cpp | 3 | ||||
-rw-r--r-- | src/environment.cpp | 139 | ||||
-rw-r--r-- | src/environment.h | 8 | ||||
-rw-r--r-- | src/game.cpp | 185 | ||||
-rw-r--r-- | src/inventory.cpp | 73 | ||||
-rw-r--r-- | src/inventory.h | 51 | ||||
-rw-r--r-- | src/mapblock.cpp | 26 | ||||
-rw-r--r-- | src/mapblock.h | 66 | ||||
-rw-r--r-- | src/mapblockobject.cpp | 939 | ||||
-rw-r--r-- | src/mapblockobject.h | 1091 | ||||
-rw-r--r-- | src/mapgen.cpp | 2 | ||||
-rw-r--r-- | src/server.cpp | 246 | ||||
-rw-r--r-- | src/settings.h | 74 | ||||
-rw-r--r-- | src/tile.cpp | 114 | ||||
-rw-r--r-- | src/utility.h | 29 |
29 files changed, 1720 insertions, 2889 deletions
diff --git a/data/dungeon_master.png b/data/dungeon_master.png Binary files differnew file mode 100644 index 000000000..77e015c16 --- /dev/null +++ b/data/dungeon_master.png diff --git a/data/fireball.png b/data/fireball.png Binary files differnew file mode 100644 index 000000000..523142850 --- /dev/null +++ b/data/fireball.png 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<f32>& 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<f32>& MyBillboardSceneNode::getBoundingBox() const
+{
+ return BBox;
+}
+
+
+//! sets the size of the billboard
+void MyBillboardSceneNode::setSize(const core::dimension2d<f32>& 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<f32>& 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<f32> 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<f32>& size);
+
+ //! pre render event
+ virtual void OnRegisterSceneNode();
+
+ //! render
+ virtual void render();
+
+ //! returns the axis aligned bounding box of this node
+ virtual const core::aabbox3d<f32>& getBoundingBox() const;
+
+ //! sets the size of the billboard
+ virtual void setSize(const core::dimension2d<f32>& size);
+
+ //! gets the size of the billboard
+ virtual const core::dimension2d<f32>& 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<f32> c);
+
+private:
+
+ core::dimension2d<f32> Size;
+ core::aabbox3d<f32> 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 @@ -523,24 +523,6 @@ void Client::step(float dtime) m_env.step(dtime); /* - Handle active blocks - NOTE: These old objects are DEPRECATED. TODO: Remove - */ - for(core::map<v3s16, bool>::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 */ for(;;) @@ -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<v3s16, bool> abs_to_delete; - for(core::map<v3s16, bool>::Iterator - i = m_active_blocks.getIterator(); - i.atEnd() == false; i++) - { - v3s16 p = i.getNode()->getKey(); - /*dstream<<"adding " - <<"("<<p.x<<","<<p.y<<","<<p.z<<") " - <<" to abs_to_delete" - <<std::endl;*/ - abs_to_delete.insert(p, true); - } - - /*dstream<<"Initial delete queue size: "<<abs_to_delete.size() - <<std::endl;*/ - - for(u16 i=0; i<blockcount; i++) - { - // Read blockpos - is.read((char*)buf, 6); - v3s16 p = readV3S16(buf); - // Get block from somewhere - MapBlock *block = NULL; - try{ - block = m_env.getMap().getBlockNoCreate(p); - } - catch(InvalidPositionException &e) - { - //TODO: Create a dummy block? - } - if(block == NULL) - { - dstream<<"WARNING: " - <<"Could not get block at blockpos " - <<"("<<p.X<<","<<p.Y<<","<<p.Z<<") " - <<"in TOCLIENT_OBJECTDATA. Ignoring " - <<"following block object data." - <<std::endl; - return; - } - - /*dstream<<"Client updating objects for block " - <<"("<<p.X<<","<<p.Y<<","<<p.Z<<")" - <<std::endl;*/ - - // Insert to active block list - m_active_blocks.insert(p, true); - - // Remove from deletion queue - if(abs_to_delete.find(p) != NULL) - abs_to_delete.remove(p); - - /* - Update objects of block - - NOTE: Be sure this is done in the main thread. - */ - block->updateObjects(is, m_server_ser_ver, - m_device->getSceneManager(), m_env.getDayNightRatio()); - } - - /*dstream<<"Final delete queue size: "<<abs_to_delete.size() - <<std::endl;*/ - - // Delete objects of blocks in delete queue - for(core::map<v3s16, bool>::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 " - <<"("<<p.X<<","<<p.Y<<","<<p.Z<<")" - <<" because block was not found" - <<std::endl; - // Ignore - } + u16 blockcount = readU16(is); + if(blockcount != 0){ + dstream<<"WARNING: TOCLIENT_OBJECTDATA: blockcount != 0 " + "not supported"<<std::endl; + return; } - - } //envlock } else if(command == TOCLIENT_TIME_OF_DAY) { @@ -1636,32 +1523,6 @@ void Client::groundAction(u8 action, v3s16 nodepos_undersurface, Send(0, data, true); } -void Client::clickObject(u8 button, v3s16 blockpos, s16 id, u16 item) -{ - if(connectedAndInitialized() == false){ - dout_client<<DTIME<<"Client::clickObject() " - "cancelled (not connected)" - <<std::endl; - return; - } - - /* - [0] u16 command=TOSERVER_CLICK_OBJECT - [2] u8 button (0=left, 1=right) - [3] v3s16 block - [9] s16 id - [11] u16 item - */ - u8 datasize = 2 + 1 + 6 + 2 + 2; - SharedBuffer<u8> 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<u8> 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<f32> shootline_on_map - ) -{ - //JMutexAutoLock envlock(m_env_mutex); //bulk comment-out - - core::array<DistanceSortedObject> objects; - - for(core::map<v3s16, bool>::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 "<<objects.size()<<" nearby objects"<<std::endl; - - // Sort them. - // After this, the closest object is the first in the array. - objects.sort(); - - for(u32 i=0; i<objects.size(); i++) - { - MapBlockObject *obj = objects[i].obj; - MapBlock *block = obj->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<f32> 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"<<std::endl; - return obj; - } - } - - //dstream<<"No object selected; returning NULL."<<std::endl; - return NULL; -} - ClientActiveObject * Client::getSelectedActiveObject( f32 max_d, v3f from_pos_f_on_map, diff --git a/src/client.h b/src/client.h index 930987c02..87c7e328d 100644 --- a/src/client.h +++ b/src/client.h @@ -183,10 +183,8 @@ public: void groundAction(u8 action, v3s16 nodepos_undersurface, v3s16 nodepos_oversurface, u16 item); - void clickObject(u8 button, v3s16 blockpos, s16 id, u16 item); void clickActiveObject(u8 button, u16 id, u16 item); - void sendSignText(v3s16 blockpos, s16 id, std::string text); void sendSignNodeText(v3s16 p, std::string text); void sendInventoryAction(InventoryAction *a); void sendChatMessage(const std::wstring &message); @@ -227,14 +225,6 @@ public: // Gets closest object pointed by the shootline // Returns NULL if not found - MapBlockObject * getSelectedObject( - f32 max_d, - v3f from_pos_f_on_map, - core::line3d<f32> shootline_on_map - ); - - // Gets closest object pointed by the shootline - // Returns NULL if not found ClientActiveObject * getSelectedActiveObject( f32 max_d, v3f from_pos_f_on_map, 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=" - <<type<<std::endl; + <<(int)type<<std::endl; return NULL; } diff --git a/src/clientobject.h b/src/clientobject.h index c90648483..6a12c718b 100644 --- a/src/clientobject.h +++ b/src/clientobject.h @@ -51,6 +51,7 @@ public: virtual core::aabbox3d<f32>* getSelectionBox(){return NULL;} virtual core::aabbox3d<f32>* 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 <ICameraSceneNode.h> core::map<u16, ClientActiveObject::Factory> 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="<<texture_name<<std::endl; + std::string texture_string = "[makealpha2:128,0,0;128,128,0:"; + texture_string += texture_name; + + scene::MyBillboardSceneNode *bill = new scene::MyBillboardSceneNode( + smgr->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 \""<<m_sprite_type<<"\"" + <<std::endl; + } + + m_node = bill; + + updateNodePos(); +} + +void MobV2CAO::removeFromScene() +{ + if(m_node == NULL) + return; + + m_node->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_id<<" dir="<<dir<<std::endl; + if(fabs(wrapDegrees_180(dir - 0)) <= 45.1) + col = 2; + else if(fabs(wrapDegrees_180(dir - 90)) <= 45.1) + col = 3; + else if(fabs(wrapDegrees_180(dir - 180)) <= 45.1) + col = 0; + else if(fabs(wrapDegrees_180(dir + 90)) <= 45.1) + col = 1; + else + col = 4; + } + + int row = 0; + if(m_shooting){ + row = 3; + } else if(m_walking){ + m_walk_timer += dtime; + if(m_walk_timer >= 0.5){ + m_walk_frame = (m_walk_frame + 1) % 2; + m_walk_timer = 0; + } + if(m_walk_frame == 0) + row = 1; + else + row = 2; + } + + 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+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 if(m_sprite_type == "simple"){ + m_walk_timer += dtime; + if(m_walk_timer >= 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 \"" + <<m_sprite_type<<"\""<<std::endl; + } + + updateNodePos(); + + /* Damage local player */ + if(m_player_hit_damage && m_player_hit_timer <= 0.0){ + LocalPlayer *player = env->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="<<m_id<<" damage visual ended"<<std::endl; + } + } + + m_walking_unset_timer += dtime; + if(m_walking_unset_timer >= 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"<<std::endl; + std::istringstream is(data, std::ios::binary); + // command + u8 cmd = readU8(is); + + // Move + if(cmd == 0) + { + // pos + m_position = readV3F1000(is); + pos_translator.update(m_position); + // yaw + m_yaw = readF1000(is); + + m_walking = true; + m_walking_unset_timer = 0; + + updateNodePos(); + } + // Damage + else if(cmd == 1) + { + //u16 damage = readU16(is); + + u8 li = decode_light(m_last_light); + if(li >= 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"<<std::endl; + + { + std::istringstream is(data, std::ios::binary); + // version + u8 version = readU8(is); + // check version + if(version != 0){ + dstream<<__FUNCTION_NAME<<": Invalid version"<<std::endl; + return; + } + + std::ostringstream tmp_os(std::ios::binary); + decompressZlib(is, tmp_os); + std::istringstream tmp_is(tmp_os.str(), std::ios::binary); + m_properties->parseConfigLines(tmp_is, "MobArgsEnd"); + + /*dstream<<"INFO: MobV2CAO::initialize(): got properties:"<<std::endl; + m_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<f32>( + -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<f32>* 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<f32> 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<u16, ServerActiveObject::Factory> 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<<std::endl; + + updateProperties(); + + std::ostringstream os(std::ios::binary); + + // version + writeU8(os, 0); + + Settings client_properties; + + /*client_properties.set("version", "0"); + client_properties.updateValue(*m_properties, "pos"); + client_properties.updateValue(*m_properties, "yaw"); + client_properties.updateValue(*m_properties, "hp");*/ + + // Just send everything for simplicity + client_properties.update(*m_properties); + + std::ostringstream os2(std::ios::binary); + client_properties.writeLines(os2); + compressZlib(os2.str(), os); + + return os.str(); +} + +bool checkFreePosition(Map *map, v3s16 p0, v3s16 size) +{ + for(int dx=0; dx<size.X; dx++) + for(int dy=0; dy<size.Y; dy++) + for(int dz=0; dz<size.Z; dz++){ + v3s16 dp(dx, dy, dz); + v3s16 p = p0 + dp; + MapNode n = map->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<len; i++) + a[i] = i; + n = len; + while(n > 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<v3s16, MapBlock*> modified_blocks; + + for(int dx=0; dx<size.X; dx++) + for(int dy=0; dy<size.Y; dy++) + for(int dz=0; dz<size.Z; dz++){ + v3s16 dp(dx - size.X/2, dy - size.Y/2, dz - size.Z/2); + v3s16 p = p0 + dp; + MapNode n = map->getNodeNoEx(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<v3s16, MapBlock*>::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 "<<PP(pos) + <<" at speed "<<PP(speed)<<std::endl; + Settings properties; + properties.setV3F("speed", speed); + properties.setFloat("die_age", 5.0); + properties.set("move_type", "constant_speed"); + properties.set("texture_name", "fireball.png"); + properties.setV3F("sprite_pos", v3f(0.0, 0.0, 0.0)); + properties.setV2F("sprite_size", v2f(1.0, 1.0)); + properties.set("sprite_type", "simple"); + properties.set("simple_anim_frames", "3"); + properties.set("simple_anim_frametime", "0.1"); + properties.setFloat("hp", 1000); + properties.set("lock_full_brightness", "true"); + properties.set("player_hit_damage", "9"); + properties.set("player_hit_distance", "2"); + properties.set("player_hit_interval", "1"); + ServerActiveObject *obj = new MobV2SAO(m_env, 0, + pos, &properties); + //m_env->addActiveObjectAsStatic(obj); + m_env->addActiveObject(obj); + } else { + dstream<<__FUNCTION_NAME<<": Unknown shoot_type="<<shoot_type + <<std::endl; + } + } + + m_shoot_reload_timer += dtime; + + if(m_shoot_reload_timer >= 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="<<m_id<<": arrived to "<<PP(m_next_pos_i)<<std::endl; + m_next_pos_exists = false; + } + } + + v3s16 pos_i = floatToInt(m_base_position, BS); + v3s16 size_blocks = v3s16(m_size.X+0.5,m_size.Y+0.5,m_size.X+0.5); + v3s16 pos_size_off(0,0,0); + if(m_size.X >= 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 "<<PP(pos_i)<<"; Random array: "; + for(int i=0; i<num_dps; i++){ + dstream<<order[i]<<" "; + } + dstream<<std::endl;*/ + for(int i=0; i<num_dps; i++){ + v3s16 p = dps[order[i]] + pos_i; + bool is_free = checkFreeAndWalkablePosition(map, + p + pos_size_off, size_blocks); + //dstream<<PP(p)<<" is_free="<<is_free<<std::endl; + if(!is_free) + continue; + m_next_pos_i = p; + m_next_pos_exists = true; + break; + } + } + } + } + else if(m_move_type == "constant_speed") + { + m_base_position += m_speed * dtime; + + v3s16 pos_i = floatToInt(m_base_position, BS); + v3s16 size_blocks = v3s16(m_size.X+0.5,m_size.Y+0.5,m_size.X+0.5); + v3s16 pos_size_off(0,0,0); + if(m_size.X >= 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="<<m_id<<" unknown move_type=\"" + <<m_move_type<<"\""<<std::endl; + } + + if(send_recommended == false) + return; + + if(m_base_position.getDistanceFrom(m_last_sent_position) > 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="<<m_id<<": punch with \""<<toolname<<"\""<<std::endl; + /* See tool names in inventory.h */ + if(toolname == "WSword") + amount = 4; + if(toolname == "STSword") + amount = 7; + if(toolname == "SteelSword") + amount = 10; + if(toolname == "STAxe") + amount = 3; + if(toolname == "SteelAxe") + amount = 4; + if(toolname == "SteelPick") + amount = 3; + doDamage(amount); + return 65536/100; +} + +void MobV2SAO::setPropertyDefaults() +{ + m_properties->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="<<m_hp<<" damage="<<d<<std::endl; + + if(d < m_hp) + { + m_hp -= d; + } + else + { + // Die + m_hp = 0; + m_removed = true; + } + + { + std::ostringstream os(std::ios::binary); + // command (1 = damage) + writeU8(os, 1); + // amount + writeU16(os, d); + // create message and add to list + ActiveObjectMessage aom(getId(), false, os.str()); + m_messages_out.push_back(aom); + } +} + + diff --git a/src/content_sao.h b/src/content_sao.h index 060c18341..078feb273 100644 --- a/src/content_sao.h +++ b/src/content_sao.h @@ -139,5 +139,52 @@ private: bool m_touching_ground; }; +class Settings; + +class MobV2SAO : public ServerActiveObject +{ +public: + MobV2SAO(ServerEnvironment *env, u16 id, v3f pos, + Settings *init_properties); + virtual ~MobV2SAO(); + u8 getType() const + {return ACTIVEOBJECT_TYPE_MOBV2;} + static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos, + const std::string &data); + std::string getStaticData(); + std::string getClientInitializationData(); + void step(float dtime, bool send_recommended); + InventoryItem* createPickedUpItem(){return NULL;} + u16 punch(const std::string &toolname, v3f dir); +private: + void setPropertyDefaults(); + void readProperties(); + void updateProperties(); + void doDamage(u16 d); + + std::string m_move_type; + v3f m_speed; + v3f m_last_sent_position; + v3f m_oldpos; + float m_yaw; + float m_counter1; + float m_counter2; + float m_age; + bool m_touching_ground; + int m_hp; + bool m_walk_around; + float m_walk_around_timer; + bool m_next_pos_exists; + v3s16 m_next_pos_i; + float m_shoot_reload_timer; + bool m_shooting; + float m_shooting_timer; + float m_die_age; + v2f m_size; + bool m_falling; + + Settings *m_properties; +}; + #endif diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index e25bc90e9..05b0611e9 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -89,7 +89,8 @@ void set_default_settings(Settings *settings) settings->setDefault("fixed_map_seed", ""); settings->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<v3s16, bool> blocks_removed; core::map<v3s16, bool> 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<v3s16, MapBlock*> modified_blocks; - v3s16 tree_p = p; + core::map<v3s16, MapBlock*> 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<v3s16, MapBlock*> lighting_modified_blocks; for(core::map<v3s16, MapBlock*>::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<v3s16, MapBlock*>::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<<DTIME<<"INFO: Server: Spawning MobV2SAO at " + <<"("<<pos.X<<","<<pos.Y<<","<<pos.Z<<")"<<std::endl; + + Settings properties; + getMob_dungeon_master(properties); + ServerActiveObject *obj = new MobV2SAO(this, 0, pos, &properties); addActiveObject(obj); } #endif @@ -1110,6 +1172,47 @@ u16 ServerEnvironment::addActiveObject(ServerActiveObject *object) return id; } +bool ServerEnvironment::addActiveObjectAsStatic(ServerActiveObject *obj) +{ + assert(obj); + + v3f objectpos = obj->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"<<std::endl; + succeeded = false; + } + + delete obj; + + return succeeded; +} + /* Finds out what new objects have been added to inside a radius around a position @@ -1894,9 +1997,9 @@ void ClientEnvironment::addActiveObject(u16 id, u8 type, obj->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 @@ -176,6 +176,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: " - <<ntext<<std::endl; - m_client->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=("<<pos_i.X<<","<<pos_i.Y<<","<<pos_i.Z<<")" + /*dstream<<"pos_i=("<<pos_i.X<<","<<pos_i.Y<<","<<pos_i.Z<<")" <<std::endl;*/ s16 a = d; @@ -705,7 +684,7 @@ void the_game( SharedPtr<Server> server; if(address == ""){ draw_load_screen(L"Creating server...", driver, font); - std::cout<<DTIME<<"Creating server"<<std::endl; + dstream<<DTIME<<"Creating server"<<std::endl; server = new Server(map_dir, configpath); server->start(port); } @@ -715,7 +694,7 @@ void the_game( */ draw_load_screen(L"Creating client...", driver, font); - std::cout<<DTIME<<"Creating client"<<std::endl; + dstream<<DTIME<<"Creating client"<<std::endl; MapDrawControl draw_control; Client client(device, playername.c_str(), password, draw_control); @@ -730,7 +709,7 @@ void the_game( } catch(ResolveError &e) { - std::cout<<DTIME<<"Couldn't resolve address"<<std::endl; + dstream<<DTIME<<"Couldn't resolve address"<<std::endl; //return 0; error_message = L"Couldn't resolve address"; //gui_loadingtext->remove(); @@ -799,12 +778,12 @@ void the_game( { error_message = L"Access denied. Reason: " +client.accessDeniedReason(); - std::cout<<DTIME<<wide_to_narrow(error_message)<<std::endl; + dstream<<DTIME<<wide_to_narrow(error_message)<<std::endl; } else { error_message = L"Connection timed out."; - std::cout<<DTIME<<"Timed out."<<std::endl; + dstream<<DTIME<<"Timed out."<<std::endl; } //gui_loadingtext->remove(); return; @@ -924,8 +903,16 @@ void the_game( core::list<float> 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<<DTIME<<wide_to_narrow(error_message)<<std::endl; + dstream<<DTIME<<wide_to_narrow(error_message)<<std::endl; break; } @@ -1018,7 +1005,7 @@ void the_game( busytime = busytime_u32 / 1000.0; } - //std::cout<<"busytime_u32="<<busytime_u32<<std::endl; + //dstream<<"busytime_u32="<<busytime_u32<<std::endl; // Necessary for device->getTimer()->getTime() device->run(); @@ -1053,6 +1040,10 @@ void the_game( dtime = 0; lasttime = time; + /* Run timers */ + + object_hit_delay_timer -= dtime; + /* Log frametime for visualization */ @@ -1067,8 +1058,8 @@ void the_game( Visualize frametime in terminal */ /*for(u32 i=0; i<dtime*400; i++) - std::cout<<"X"; - std::cout<<std::endl;*/ + dstream<<"X"; + dstream<<std::endl;*/ /* Time average and jitter calculation @@ -1133,7 +1124,7 @@ void the_game( if(counter < 0) { counter = 30.0; - client.printDebugInfo(std::cout); + client.printDebugInfo(dstream); } } @@ -1359,7 +1350,7 @@ void the_game( } if(first_loop_after_window_activation){ - //std::cout<<"window active, first loop"<<std::endl; + //dstream<<"window active, first loop"<<std::endl; first_loop_after_window_activation = false; } else{ @@ -1367,7 +1358,7 @@ void the_game( s32 dy = input->getMousePos().Y - displaycenter.Y; if(invert_mouse) dy = -dy; - //std::cout<<"window active, pos difference "<<dx<<","<<dy<<std::endl; + //dstream<<"window active, pos difference "<<dx<<","<<dy<<std::endl; /*const float keyspeed = 500; if(input->isKeyDown(irr::KEY_UP)) @@ -1391,7 +1382,7 @@ void the_game( if(device->getCursorControl()->isVisible() == false) device->getCursorControl()->setVisible(true); - //std::cout<<"window inactive"<<std::endl; + //dstream<<"window inactive"<<std::endl; first_loop_after_window_activation = true; } @@ -1500,71 +1491,23 @@ void the_game( core::line3d<f32> 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"<<std::endl; - - core::aabbox3d<f32> 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<<DTIME<<"Left-clicked object"<<std::endl; - client.clickObject(0, selected_object->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<<DTIME<<"Right-clicked object"<<std::endl; - /* - Check if we want to modify the object ourselves - */ - if(selected_object->getTypeId() == MAPBLOCKOBJECT_TYPE_SIGN) - { - dstream<<"Sign object right-clicked"<<std::endl; - - if(random_input == false) - { - // Get a new text for it - - TextDest *dest = new TextDestSign( - selected_object->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"<<std::endl; core::aabbox3d<f32> *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<<DTIME<<"Left-clicked object"<<std::endl; - client.clickActiveObject(0, - selected_active_object->getId(), g_selected_item); + if(object_hit_delay_timer <= 0.0){ + dstream<<DTIME<<"Left-clicked object"<<std::endl; + client.clickActiveObject(0, + selected_active_object->getId(), g_selected_item); + object_hit_delay_timer = object_hit_delay; + left_punch = true; + } else { + dstream<<DTIME<<"Left-clicked object faster than allowed" + <<std::endl; + left_punch_muted = true; + } } else if(input->getRightClicked()) { - std::cout<<DTIME<<"Right-clicked object"<<std::endl; + dstream<<DTIME<<"Right-clicked object"<<std::endl; client.clickActiveObject(1, selected_active_object->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<<DTIME<<"Pointing at ("<<nodepos.X<<"," + dstream<<DTIME<<"Pointing at ("<<nodepos.X<<"," <<nodepos.Y<<","<<nodepos.Z<<")"<<std::endl; if(nodepos_old != v3s16(-32768,-32768,-32768)) { client.clearTempMod(nodepos_old); dig_time = 0.0; + nodepos_old = v3s16(-32768,-32768,-32768); } } @@ -1771,7 +1724,7 @@ void the_game( if(input->getRightClicked()) { - std::cout<<DTIME<<"Ground right-clicked"<<std::endl; + dstream<<DTIME<<"Ground right-clicked"<<std::endl; // If metadata provides an inventory view, activate it if(meta && meta->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<<DTIME<<"Left button released (stopped digging)" + dstream<<DTIME<<"Left button released (stopped digging)" <<std::endl; client.groundAction(2, v3s16(0,0,0), v3s16(0,0,0), 0); } if(input->getRightReleased()) { - //std::cout<<DTIME<<"Right released"<<std::endl; + //dstream<<DTIME<<"Right released"<<std::endl; // Nothing here } @@ -2097,7 +2050,7 @@ void the_game( { client.selectPlayerItem(g_selected_item); old_selected_item = g_selected_item; - //std::cout<<"Updating local inventory"<<std::endl; + //dstream<<"Updating local inventory"<<std::endl; client.getLocalInventory(local_inventory); // Update wielded tool @@ -2136,7 +2089,7 @@ void the_game( //timer3.stop(); - //std::cout<<DTIME<<"smgr->drawAll()"<<std::endl; + //dstream<<DTIME<<"smgr->drawAll()"<<std::endl; { TimeTaker timer("smgr"); @@ -2162,7 +2115,7 @@ void the_game( for(core::list< core::aabbox3d<f32> >::Iterator i=hilightboxes.begin(); i != hilightboxes.end(); i++) { - /*std::cout<<"hilightbox min=" + /*dstream<<"hilightbox min=" <<"("<<i->MinEdge.X<<","<<i->MinEdge.Y<<","<<i->MinEdge.Z<<")" <<" max=" <<"("<<i->MaxEdge.X<<","<<i->MaxEdge.Y<<","<<i->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") { @@ -220,77 +220,6 @@ bool CraftItem::use(ServerEnvironment *env, Player *player) } /* - 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."<<std::endl; - return NULL; - } - else - { - return NULL; - } -} - -/* Inventory */ diff --git a/src/inventory.h b/src/inventory.h index 3e05015ef..490cab73e 100644 --- a/src/inventory.h +++ b/src/inventory.h @@ -29,7 +29,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include <string> #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<<getName(); - os<<" "; - os<<sane_string; - os<<"|"; - } - virtual InventoryItem* clone() - { - return new MapBlockObjectItem(m_inventorystring); - } - -#ifndef SERVER - video::ITexture * getImage() const; -#endif - std::string getText(); - - /* - Special methods - */ - std::string getInventoryString() - { - return m_inventorystring; - } - - MapBlockObject * createObject(v3f pos, f32 player_yaw, f32 player_pitch); - -private: - std::string m_inventorystring; -}; - /* An item that is used as a mid-product when crafting. Subnames: diff --git a/src/mapblock.cpp b/src/mapblock.cpp index 6613f388a..dd47c6ffc 100644 --- a/src/mapblock.cpp +++ b/src/mapblock.cpp @@ -36,7 +36,6 @@ MapBlock::MapBlock(Map *parent, v3s16 pos, bool dummy): m_lighting_expired(true), m_day_night_differs(false), m_generated(false), - m_objects(this), m_timestamp(BLOCK_TIMESTAMP_UNDEFINED), m_usage_timer(0) { @@ -434,18 +433,6 @@ void MapBlock::copyFrom(VoxelManipulator &dst) getPosRelative(), data_size); } -void MapBlock::stepObjects(float dtime, bool server, u32 daynight_ratio) -{ - /* - Step objects - */ - m_objects.step(dtime, server, daynight_ratio); - - //setChangedFlag(); - raiseModified(MOD_STATE_WRITE_AT_UNLOAD); -} - - void MapBlock::updateDayNightDiff() { if(data == NULL) @@ -818,10 +805,9 @@ void MapBlock::deSerialize(std::istream &is, u8 version) void MapBlock::serializeDiskExtra(std::ostream &os, u8 version) { - // Versions up from 9 have block objects. + // Versions up from 9 have block objects. (DEPRECATED) if(version >= 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"<<std::endl; + return; + } } /* diff --git a/src/mapblock.h b/src/mapblock.h index 368290065..22b3b7db6 100644 --- a/src/mapblock.h +++ b/src/mapblock.h @@ -29,7 +29,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "exceptions.h" #include "serialization.h" #include "constants.h" -#include "mapblockobject.h" #include "voxel.h" #include "nodemetadata.h" #include "staticobject.h" @@ -423,68 +422,6 @@ public: // Copies data from VoxelManipulator getPosRelative() void copyFrom(VoxelManipulator &dst); - /* - MapBlockObject stuff - DEPRECATED - */ - - /*void serializeObjects(std::ostream &os, u8 version) - { - m_objects.serialize(os, version); - }*/ - // If smgr!=NULL, new objects are added to the scene - void updateObjects(std::istream &is, u8 version, - scene::ISceneManager *smgr, u32 daynight_ratio) - { - m_objects.update(is, version, smgr, daynight_ratio); - - raiseModified(MOD_STATE_WRITE_NEEDED); - } - void clearObjects() - { - m_objects.clear(); - - raiseModified(MOD_STATE_WRITE_NEEDED); - } - void addObject(MapBlockObject *object) - throw(ContainerFullException, AlreadyExistsException) - { - m_objects.add(object); - - raiseModified(MOD_STATE_WRITE_NEEDED); - } - void removeObject(s16 id) - { - m_objects.remove(id); - - raiseModified(MOD_STATE_WRITE_NEEDED); - } - MapBlockObject * getObject(s16 id) - { - return m_objects.get(id); - } - JMutexAutoLock * getObjectLock() - { - return m_objects.getLock(); - } - - /* - Moves objects, deletes objects and spawns new objects - */ - void stepObjects(float dtime, bool server, u32 daynight_ratio); - - // origin is relative to block - void getObjects(v3f origin, f32 max_d, - core::array<DistanceSortedObject> &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 <celeron55@gmail.com> - -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=("<<oldpos_i.X<<","<<oldpos_i.Y<<"," - <<oldpos_i.Z<<")"<<std::endl;*/ - - // Maximum time increment (for collision detection etc) - // Allow 0.1 blocks per increment - // time = distance / speed - // NOTE: In the loop below collisions are detected at 0.15*BS radius - float speedlength = m_speed.getLength(); - f32 dtime_max_increment; - if(fabs(speedlength) > 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<f32> objectbox( - m_collision_box->MinEdge + position, - m_collision_box->MaxEdge + position - ); - - core::aabbox3d<f32> 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<f32> 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=\"" - <<m_itemstring<<"\" -> item="<<item - <<std::endl; - return item; - } - catch(SerializationError &e) - { - dstream<<__FUNCTION_NAME<<": serialization error: " - <<"m_itemstring=\""<<m_itemstring<<"\""<<std::endl; - return NULL; - } -} - -/* - PlayerObject -*/ -#ifndef SERVER -void PlayerObject::addToScene(scene::ISceneManager *smgr) -{ - if(m_node != NULL) - return; - - video::IVideoDriver* driver = smgr->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<s16, MapBlockObject*>::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<s16, bool> ids_to_delete; - for(core::map<s16, MapBlockObject*>::Iterator - i = m_objects.getIterator(); - i.atEnd() == false; i++) - { - ids_to_delete.insert(i.getNode()->getKey(), true); - } - - u8 buf[6]; - - is.read((char*)buf, 2); - u16 count = readU16(buf); - - for(u16 i=0; i<count; i++) - { - // Read id - is.read((char*)buf, 2); - s16 id = readS16(buf); - - // Read position - // stored as x1000/BS v3s16 - is.read((char*)buf, 6); - v3s16 pos_i = readV3S16(buf); - v3f pos((f32)pos_i.X/1000*BS, - (f32)pos_i.Y/1000*BS, - (f32)pos_i.Z/1000*BS); - - // Read typeId - is.read((char*)buf, 2); - u16 type_id = readU16(buf); - - bool create_new = false; - - // Find an object with the id - core::map<s16, MapBlockObject*>::Node *n; - n = m_objects.find(id); - // If no entry is found for id - if(n == NULL) - { - // Insert dummy pointer node - m_objects.insert(id, NULL); - // Get node - n = m_objects.find(id); - // A new object will be created at this node - create_new = true; - } - // If type_id differs - else if(n->getValue()->getTypeId() != type_id) - { - // Delete old object - delete n->getValue(); - // A new object will be created at this node - create_new = true; - } - - MapBlockObject *obj = NULL; - - if(create_new) - { - /*dstream<<"MapBlockObjectList adding new object" - " id="<<id - <<std::endl;*/ - - if(type_id == MAPBLOCKOBJECT_TYPE_SIGN) - { - obj = new SignObject(m_block, id, pos); - } - else if(type_id == MAPBLOCKOBJECT_TYPE_RAT) - { - obj = new RatObject(m_block, id, pos); - } - else if(type_id == MAPBLOCKOBJECT_TYPE_ITEM) - { - obj = new ItemObject(m_block, id, pos); - } - else - { - // This is fatal because we cannot know the length - // of the object's data - throw SerializationError - ("MapBlockObjectList::update(): Unknown MapBlockObject type"); - } - - if(smgr != NULL) - //obj->addToScene(smgr, daynight_ratio); - obj->addToScene(smgr); - - n->setValue(obj); - } - else - { - obj = n->getValue(); - obj->updatePos(pos); - /*if(daynight_ratio != m_last_update_daynight_ratio) - { - obj->removeFromScene(); - obj->addToScene(smgr, daynight_ratio); - }*/ - } - - // Now there is an object in obj. - // Update it. - - obj->update(is, version); - - /* - Update light on client - */ - if(smgr != NULL) - { - u8 light = LIGHT_MAX; - try{ - v3s16 relpos_i = floatToInt(obj->m_pos, BS); - MapNode n = m_block->getNodeParent(relpos_i); - light = n.getLightBlend(daynight_ratio); - } - catch(InvalidPositionException &e) {} - obj->updateLight(light); - } - - // Remove from deletion list - if(ids_to_delete.find(id) != NULL) - ids_to_delete.remove(id); - } - - // Delete all objects whose ids_to_delete remain in ids_to_delete - for(core::map<s16, bool>::Iterator - i = ids_to_delete.getIterator(); - i.atEnd() == false; i++) - { - s16 id = i.getNode()->getKey(); - - /*dstream<<"MapBlockObjectList deleting object" - " id="<<id - <<std::endl;*/ - - MapBlockObject *obj = m_objects[id]; - obj->removeFromScene(); - delete obj; - m_objects.remove(id); - } - - m_last_update_daynight_ratio = daynight_ratio; -} - -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"<<std::endl; - return; - } - - JMutexAutoLock lock(m_mutex); - - // Create unique id if id==-1 - if(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"<<std::endl; - throw AlreadyExistsException - ("MapBlockObjectList already has given id"); - } - - object->m_block = m_block; - - /*v3f p = object->m_pos; - dstream<<"MapBlockObjectList::add(): " - <<"m_block->getPos()=(" - <<m_block->getPos().X<<"," - <<m_block->getPos().Y<<"," - <<m_block->getPos().Z<<")" - <<" inserting object with id="<<object->m_id - <<" pos=" - <<"("<<p.X<<","<<p.Y<<","<<p.Z<<")" - <<std::endl;*/ - - m_objects.insert(object->m_id, object); -} - -void MapBlockObjectList::clear() -{ - JMutexAutoLock lock(m_mutex); - - for(core::map<s16, MapBlockObject*>::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<s16, MapBlockObject*>::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<s16, MapBlockObject*>::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<s16, bool> ids_to_delete; - - { - DSTACKF("%s: stepping objects", __FUNCTION_NAME); - - for(core::map<s16, MapBlockObject*>::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<s16, bool>::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<s16, MapBlockObject*>::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" - <<"("<<pos_blocks_on_map.X - <<","<<pos_blocks_on_map.Y - <<","<<pos_blocks_on_map.Z - <<")"<<std::endl;*/ - /*dstream<<"pos_f_on_oldblock=(" - <<pos_f_on_oldblock.X<<"," - <<pos_f_on_oldblock.Y<<"," - <<pos_f_on_oldblock.Z<<")" - <<std::endl;*/ - return true; - } - - if(newblock == m_block) - { - dstream<<"WARNING: Wrapping object not possible: " - "newblock == oldblock"<<std::endl; - return true; - } - - // Calculate position on new block - v3f oldblock_pos_f_on_map = intToFloat(oldblock_pos_i_on_map, BS); - v3s16 newblock_pos_i_on_map = newblock->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"<<std::endl; - - return false; -} - -void MapBlockObjectList::getObjects(v3f origin, f32 max_d, - core::array<DistanceSortedObject> &dest) -{ - for(core::map<s16, MapBlockObject*>::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 <celeron55@gmail.com> - -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 <math.h> -#include <string> -#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<f32> shootline) - { - if(m_selection_box == NULL) - return false; - - core::aabbox3d<f32> offsetted_box( - m_selection_box->MinEdge + m_pos, - m_selection_box->MaxEdge + m_pos - ); - - return offsetted_box.intersectsWithLine(shootline); - } - - core::aabbox3d<f32> getSelectionBoxOnMap() - { - v3f absolute_pos = getAbsolutePos(); - - core::aabbox3d<f32> 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<f32> * m_collision_box; - - // Shall be left NULL if can't be selected - core::aabbox3d<f32> * 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<f32> box) - { - m_selection_box = new core::aabbox3d<f32>(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<f32> - (-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; i<size; i++) - { - is.read((char*)buf, 1); - m_text += buf[0]; - } - - updateSceneNode(); - } - virtual bool serverStep(float dtime, u32 daynight_ratio) - { - return false; - } -#ifndef SERVER - virtual void addToScene(scene::ISceneManager *smgr) - { - if(m_node != NULL) - return; - - video::IVideoDriver* driver = smgr->getVideoDriver(); - - 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<f32> - (-BS*0.3,-BS*.25,-BS*0.3, BS*0.3,BS*0.25,BS*0.3); - m_selection_box = new core::aabbox3d<f32> - (-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<f32> - (-BS*0.4,-BS*0.5,-BS*0.4, BS*0.4,BS*0.5,BS*0.4);*/ - m_selection_box = new core::aabbox3d<f32> - (-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; i<size; i++) - { - is.read((char*)buf, 1); - m_itemstring += buf[0]; - } - -#ifndef SERVER - if(m_itemstring != old_itemstring && m_node) - { - /* - Update texture - */ - video::ITexture *texture = getItemImage(); - scene::IMesh *mesh = m_node->getMesh(); - if(mesh->getMeshBufferCount() >= 1) - { - scene::IMeshBuffer *buf = mesh->getMeshBuffer(0); - //dstream<<"Setting texture "<<texture<<std::endl; - buf->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<f32> - (-BS*0.3,-BS*.25,-BS*0.3, BS*0.3,BS*0.25,BS*0.3); - /*m_selection_box = new core::aabbox3d<f32> - (-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<DistanceSortedObject> &dest); - - // Number of objects - s32 getCount() - { - return m_objects.size(); - } - -private: - JMutex m_mutex; - // Key is id - core::map<s16, MapBlockObject*> 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; z0<MAP_BLOCKSIZE; z0++) for(s16 x0=0; x0<MAP_BLOCKSIZE; x0++) { @@ -1465,6 +1466,7 @@ void add_random_objects(MapBlock *block) } } block->setChangedFlag(); +#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<v3s16> list; - getFacePositions(list, d); - - core::list<v3s16>::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<JMutexAutoLock> 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<<bos.str(); - /* Send data */ @@ -1431,7 +1334,8 @@ void Server::AsyncRunStep() ScopeProfiler sp(g_profiler, "Server: checking added and deleted objects"); // Radius inside which objects are active - s16 radius = 32; + s16 radius = g_settings->getS16("active_object_send_range_blocks"); + radius *= MAP_BLOCKSIZE; for(core::map<u16, RemoteClient*>::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"<<std::endl; - return; - } - - MapBlockObject *obj = block->getObject(id); - - if(obj == NULL) - { - derr_server<<"CLICK_OBJECT object not found"<<std::endl; - return; - } - - //TODO: Check that object is reasonably close - - // Left click - if(button == 0) - { - InventoryList *ilist = player->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"<<std::endl; - return; - } - - /* - Create the inventory item - */ - InventoryItem *item = NULL; - // If it is an item-object, take the item from it - if(obj->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"<<std::endl; + return; } else if(command == TOSERVER_CLICK_ACTIVEOBJECT) { @@ -2442,7 +2267,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) */ u8 button = readU8(&data[2]); u16 id = readS16(&data[3]); - u16 item_i = readU16(&data[11]); + u16 item_i = readU16(&data[5]); ServerActiveObject *obj = m_env.getActiveObject(id); @@ -3076,62 +2901,9 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) #endif else if(command == TOSERVER_SIGNTEXT) { - if((getPlayerPrivs(player) & PRIV_BUILD) == 0) - return; - /* - u16 command - v3s16 blockpos - s16 id - u16 textlen - textdata - */ - std::string datastring((char*)&data[2], datasize-2); - std::istringstream is(datastring, std::ios_base::binary); - u8 buf[6]; - // Read stuff - is.read((char*)buf, 6); - v3s16 blockpos = readV3S16(buf); - is.read((char*)buf, 2); - s16 id = readS16(buf); - is.read((char*)buf, 2); - u16 textlen = readU16(buf); - std::string text; - for(u16 i=0; i<textlen; i++) - { - is.read((char*)buf, 1); - text += (char)buf[0]; - } - - MapBlock *block = NULL; - try - { - block = m_env.getMap().getBlockNoCreate(blockpos); - } - catch(InvalidPositionException &e) - { - derr_server<<"Error while setting sign text: " - "block not found"<<std::endl; - return; - } - - MapBlockObject *obj = block->getObject(id); - if(obj == NULL) - { - derr_server<<"Error while setting sign text: " - "object not found"<<std::endl; - return; - } - - if(obj->getTypeId() != MAPBLOCKOBJECT_TYPE_SIGN) - { - derr_server<<"Error while setting sign text: " - "object is not a sign"<<std::endl; - return; - } - - ((SignObject*)obj)->setText(text); - - obj->getBlock()->setChangedFlag(); + derr_server<<"Server: TOSERVER_SIGNTEXT not supported anymore" + <<std::endl; + return; } else if(command == TOSERVER_SIGNNODETEXT) { diff --git a/src/settings.h b/src/settings.h index f972ce3ec..e8f376938 100644 --- a/src/settings.h +++ b/src/settings.h @@ -102,6 +102,22 @@ public: return true; } + void parseConfigLines(std::istream &is, const std::string &endstring) + { + for(;;){ + if(is.eof()) + break; + std::string line; + std::getline(is, line); + std::string trimmedline = trim(line); + if(endstring != ""){ + if(trimmedline == endstring) + break; + } + parseConfigLine(line); + } + } + // Returns false on EOF bool parseConfigObject(std::istream &is) { @@ -481,6 +497,16 @@ public: return value; } + v2f getV2F(std::string name) + { + v2f value; + Strfnd f(get(name)); + f.next("("); + value.X = stof(f.next(",")); + value.Y = stof(f.next(")")); + return value; + } + u64 getU64(std::string name) { u64 value = 0; @@ -515,6 +541,13 @@ public: set(name, os.str()); } + void setV2F(std::string name, v2f value) + { + std::ostringstream os; + os<<"("<<value.X<<","<<value.Y<<")"; + set(name, os.str()); + } + void setU64(std::string name, u64 value) { std::ostringstream os; @@ -530,6 +563,47 @@ public: m_defaults.clear(); } + void updateValue(Settings &other, const std::string &name) + { + JMutexAutoLock lock(m_mutex); + + if(&other == this) + return; + + try{ + std::string val = other.get(name); + m_settings[name] = val; + } catch(SettingNotFoundException &e){ + } + + return; + } + + void update(Settings &other) + { + JMutexAutoLock lock(m_mutex); + JMutexAutoLock lock2(other.m_mutex); + + if(&other == this) + return; + + for(core::map<std::string, std::string>::Iterator + i = other.m_settings.getIterator(); + i.atEnd() == false; i++) + { + m_settings[i.getNode()->getKey()] = i.getNode()->getValue(); + } + + for(core::map<std::string, std::string>::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 @@ -1055,6 +1055,120 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg, } } /* + "[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=\""<<part_of_name + <<"\", cancelling."<<std::endl; + return false; + } + + Strfnd sf(part_of_name.substr(11)); + u32 r1 = stoi(sf.next(",")); + u32 g1 = stoi(sf.next(",")); + u32 b1 = stoi(sf.next(":")); + std::string filename = sf.next(""); + + std::string path = getTexturePath(filename.c_str()); + + dstream<<"INFO: generate_image(): Loading path \""<<path + <<"\""<<std::endl; + + video::IImage *image = driver->createImageFromFile(path.c_str()); + + if(image == NULL) + { + dstream<<"WARNING: generate_image(): Loading path \"" + <<path<<"\" failed"<<std::endl; + } + else + { + core::dimension2d<u32> dim = image->getDimension(); + baseimg = driver->createImage(video::ECF_A8R8G8B8, dim); + + for(u32 y=0; y<dim.Height; y++) + for(u32 x=0; x<dim.Width; x++) + { + video::SColor c = image->getPixel(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=\""<<part_of_name + <<"\", cancelling."<<std::endl; + return false; + } + + Strfnd sf(part_of_name.substr(12)); + u32 r1 = stoi(sf.next(",")); + u32 g1 = stoi(sf.next(",")); + u32 b1 = stoi(sf.next(";")); + u32 r2 = stoi(sf.next(",")); + u32 g2 = stoi(sf.next(",")); + u32 b2 = stoi(sf.next(":")); + std::string filename = sf.next(""); + + std::string path = getTexturePath(filename.c_str()); + + dstream<<"INFO: generate_image(): Loading path \""<<path + <<"\""<<std::endl; + + video::IImage *image = driver->createImageFromFile(path.c_str()); + + if(image == NULL) + { + dstream<<"WARNING: generate_image(): Loading path \"" + <<path<<"\" failed"<<std::endl; + } + else + { + core::dimension2d<u32> dim = image->getDimension(); + baseimg = driver->createImage(video::ECF_A8R8G8B8, dim); + + for(u32 y=0; y<dim.Height; y++) + for(u32 x=0; x<dim.Width; x++) + { + video::SColor c = image->getPixel(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 &. Create an "inventory cube". 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; |