defaultsettings.cpp
mapnode.cpp
voxel.cpp
- mapblockobject.cpp
inventory.cpp
debug.cpp
serialization.cpp
# Client sources
set(minetest_SRCS
${common_SRCS}
+ MyBillboardSceneNode.cpp
content_mapblock.cpp
content_cao.cpp
mapblock_mesh.cpp
--- /dev/null
+// Copyright (C) 2002-2010 Nikolaus Gebhardt\r
+// This file is part of the "Irrlicht Engine".\r
+// For conditions of distribution and use, see copyright notice in irrlicht.h\r
+\r
+#include "MyBillboardSceneNode.h"\r
+#include "IVideoDriver.h"\r
+#include "ISceneManager.h"\r
+#include "ICameraSceneNode.h"\r
+\r
+namespace irr\r
+{\r
+namespace scene\r
+{\r
+\r
+//! constructor\r
+MyBillboardSceneNode::MyBillboardSceneNode(ISceneNode* parent,\r
+ ISceneManager* mgr, s32 id,\r
+ const core::vector3df& position, const core::dimension2d<f32>& size)\r
+ : IBillboardSceneNode(parent, mgr, id, position)\r
+{\r
+ #ifdef _DEBUG\r
+ setDebugName("MyBillboardSceneNode");\r
+ #endif\r
+\r
+ setSize(size);\r
+\r
+ indices[0] = 0;\r
+ indices[1] = 2;\r
+ indices[2] = 1;\r
+ indices[3] = 0;\r
+ indices[4] = 3;\r
+ indices[5] = 2;\r
+\r
+ video::SColor colorTop = video::SColor(0xFFFFFFFF);\r
+ video::SColor colorBottom = video::SColor(0xFFFFFFFF);\r
+\r
+ vertices[0].TCoords.set(1.0f, 1.0f);\r
+ vertices[0].Color = colorBottom;\r
+\r
+ vertices[1].TCoords.set(1.0f, 0.0f);\r
+ vertices[1].Color = colorTop;\r
+\r
+ vertices[2].TCoords.set(0.0f, 0.0f);\r
+ vertices[2].Color = colorTop;\r
+\r
+ vertices[3].TCoords.set(0.0f, 1.0f);\r
+ vertices[3].Color = colorBottom;\r
+}\r
+\r
+\r
+//! pre render event\r
+void MyBillboardSceneNode::OnRegisterSceneNode()\r
+{\r
+ if (IsVisible)\r
+ SceneManager->registerNodeForRendering(this);\r
+\r
+ ISceneNode::OnRegisterSceneNode();\r
+}\r
+\r
+\r
+//! render\r
+void MyBillboardSceneNode::render()\r
+{\r
+ video::IVideoDriver* driver = SceneManager->getVideoDriver();\r
+ ICameraSceneNode* camera = SceneManager->getActiveCamera();\r
+\r
+ if (!camera || !driver)\r
+ return;\r
+\r
+ // make billboard look to camera\r
+\r
+ core::vector3df pos = getAbsolutePosition();\r
+\r
+ core::vector3df campos = camera->getAbsolutePosition();\r
+ core::vector3df target = camera->getTarget();\r
+ core::vector3df up = camera->getUpVector();\r
+ core::vector3df view = target - campos;\r
+ view.normalize();\r
+\r
+ core::vector3df horizontal = up.crossProduct(view);\r
+ if ( horizontal.getLength() == 0 )\r
+ {\r
+ horizontal.set(up.Y,up.X,up.Z);\r
+ }\r
+ horizontal.normalize();\r
+ horizontal *= 0.5f * Size.Width;\r
+\r
+ core::vector3df vertical = horizontal.crossProduct(view);\r
+ vertical.normalize();\r
+ vertical *= 0.5f * Size.Height;\r
+\r
+ view *= -1.0f;\r
+\r
+ for (s32 i=0; i<4; ++i)\r
+ vertices[i].Normal = view;\r
+\r
+ vertices[0].Pos = pos + horizontal + vertical;\r
+ vertices[1].Pos = pos + horizontal - vertical;\r
+ vertices[2].Pos = pos - horizontal - vertical;\r
+ vertices[3].Pos = pos - horizontal + vertical;\r
+\r
+ // draw\r
+\r
+ if ( DebugDataVisible & scene::EDS_BBOX )\r
+ {\r
+ driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);\r
+ video::SMaterial m;\r
+ m.Lighting = false;\r
+ driver->setMaterial(m);\r
+ driver->draw3DBox(BBox, video::SColor(0,208,195,152));\r
+ }\r
+\r
+ driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);\r
+\r
+ driver->setMaterial(Material);\r
+\r
+ driver->drawIndexedTriangleList(vertices, 4, indices, 2);\r
+}\r
+\r
+\r
+//! returns the axis aligned bounding box of this node\r
+const core::aabbox3d<f32>& MyBillboardSceneNode::getBoundingBox() const\r
+{\r
+ return BBox;\r
+}\r
+\r
+\r
+//! sets the size of the billboard\r
+void MyBillboardSceneNode::setSize(const core::dimension2d<f32>& size)\r
+{\r
+ Size = size;\r
+\r
+ if (Size.Width == 0.0f)\r
+ Size.Width = 1.0f;\r
+\r
+ if (Size.Height == 0.0f )\r
+ Size.Height = 1.0f;\r
+\r
+ f32 avg = (size.Width + size.Height)/6;\r
+ BBox.MinEdge.set(-avg,-avg,-avg);\r
+ BBox.MaxEdge.set(avg,avg,avg);\r
+}\r
+\r
+\r
+video::SMaterial& MyBillboardSceneNode::getMaterial(u32 i)\r
+{\r
+ return Material;\r
+}\r
+\r
+\r
+//! returns amount of materials used by this scene node.\r
+u32 MyBillboardSceneNode::getMaterialCount() const\r
+{\r
+ return 1;\r
+}\r
+\r
+\r
+//! gets the size of the billboard\r
+const core::dimension2d<f32>& MyBillboardSceneNode::getSize() const\r
+{\r
+ return Size;\r
+}\r
+\r
+\r
+//! Set the color of all vertices of the billboard\r
+//! \param overallColor: the color to set\r
+void MyBillboardSceneNode::setColor(const video::SColor & overallColor)\r
+{\r
+ for(u32 vertex = 0; vertex < 4; ++vertex)\r
+ vertices[vertex].Color = overallColor;\r
+}\r
+\r
+\r
+//! Set the color of the top and bottom vertices of the billboard\r
+//! \param topColor: the color to set the top vertices\r
+//! \param bottomColor: the color to set the bottom vertices\r
+void MyBillboardSceneNode::setColor(const video::SColor & topColor, const video::SColor & bottomColor)\r
+{\r
+ vertices[0].Color = bottomColor;\r
+ vertices[1].Color = topColor;\r
+ vertices[2].Color = topColor;\r
+ vertices[3].Color = bottomColor;\r
+}\r
+\r
+\r
+//! Gets the color of the top and bottom vertices of the billboard\r
+//! \param[out] topColor: stores the color of the top vertices\r
+//! \param[out] bottomColor: stores the color of the bottom vertices\r
+void MyBillboardSceneNode::getColor(video::SColor & topColor, video::SColor & bottomColor) const\r
+{\r
+ bottomColor = vertices[0].Color;\r
+ topColor = vertices[1].Color;\r
+}\r
+ \r
+void MyBillboardSceneNode::setTCoords(u32 i, core::vector2d<f32> c)\r
+{\r
+ vertices[i].TCoords = c;\r
+}\r
+\r
+} // end namespace scene\r
+} // end namespace irr\r
+\r
--- /dev/null
+// Copyright (C) 2002-2010 Nikolaus Gebhardt\r
+// This file is part of the "Irrlicht Engine".\r
+// For conditions of distribution and use, see copyright notice in irrlicht.h\r
+\r
+#ifndef __C_BILLBOARD_SCENE_NODE_H_INCLUDED__\r
+#define __C_BILLBOARD_SCENE_NODE_H_INCLUDED__\r
+\r
+#include "IBillboardSceneNode.h"\r
+#include "S3DVertex.h"\r
+\r
+namespace irr\r
+{\r
+namespace scene\r
+{\r
+\r
+//! Scene node which is a billboard. A billboard is like a 3d sprite: A 2d element,\r
+//! which always looks to the camera. \r
+class MyBillboardSceneNode : virtual public IBillboardSceneNode\r
+{\r
+public:\r
+\r
+ //! constructor\r
+ MyBillboardSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id,\r
+ const core::vector3df& position, const core::dimension2d<f32>& size);\r
+\r
+ //! pre render event\r
+ virtual void OnRegisterSceneNode();\r
+\r
+ //! render\r
+ virtual void render();\r
+\r
+ //! returns the axis aligned bounding box of this node\r
+ virtual const core::aabbox3d<f32>& getBoundingBox() const;\r
+\r
+ //! sets the size of the billboard\r
+ virtual void setSize(const core::dimension2d<f32>& size);\r
+\r
+ //! gets the size of the billboard\r
+ virtual const core::dimension2d<f32>& getSize() const;\r
+\r
+ virtual video::SMaterial& getMaterial(u32 i);\r
+ \r
+ //! returns amount of materials used by this scene node.\r
+ virtual u32 getMaterialCount() const;\r
+ \r
+ //! Set the color of all vertices of the billboard\r
+ //! \param overallColor: the color to set\r
+ virtual void setColor(const video::SColor & overallColor);\r
+\r
+ //! Set the color of the top and bottom vertices of the billboard\r
+ //! \param topColor: the color to set the top vertices\r
+ //! \param bottomColor: the color to set the bottom vertices\r
+ virtual void setColor(const video::SColor & topColor, const video::SColor & bottomColor);\r
+\r
+ //! Gets the color of the top and bottom vertices of the billboard\r
+ //! \param[out] topColor: stores the color of the top vertices\r
+ //! \param[out] bottomColor: stores the color of the bottom vertices\r
+ virtual void getColor(video::SColor& topColor, video::SColor& bottomColor) const;\r
+\r
+ virtual void setTCoords(u32 i, core::vector2d<f32> c);\r
+\r
+private:\r
+\r
+ core::dimension2d<f32> Size;\r
+ core::aabbox3d<f32> BBox;\r
+ video::SMaterial Material;\r
+\r
+ video::S3DVertex vertices[4];\r
+ u16 indices[6];\r
+};\r
+\r
+\r
+} // end namespace scene\r
+} // end namespace irr\r
+\r
+#endif\r
+\r
// Step environment
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
*/
}
//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];
/*
/*
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)
{
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){
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)
{
/*
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,
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);
Inventory* getInventory(InventoryContext *c, std::string id);
void inventoryAction(InventoryAction *a);
- // 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(
{
// If factory is not found, just return.
dstream<<"WARNING: ClientActiveObject: No factory for type="
- <<type<<std::endl;
+ <<(int)type<<std::endl;
return NULL;
}
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){}
#include "content_cao.h"
#include "tile.h"
#include "environment.h"
+#include "settings.h"
+#include <ICameraSceneNode.h>
core::map<u16, ClientActiveObject::Factory> ClientActiveObject::m_types;
}
else if(cmd == 1)
{
- u16 damage = readU8(is);
+ //u16 damage = readU8(is);
m_damage_visual_timer = 1.0;
}
}
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();
+}
+
+
#include "clientobject.h"
#include "content_object.h"
#include "utility.h" // For IntervalLimiter
+class Settings;
+#include "MyBillboardSceneNode.h"
/*
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);
+ }
};
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
#define ACTIVEOBJECT_TYPE_RAT 3
#define ACTIVEOBJECT_TYPE_OERKKI1 4
#define ACTIVEOBJECT_TYPE_FIREFLY 5
+#define ACTIVEOBJECT_TYPE_MOBV2 6
#endif
#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
*/
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));
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
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);
+ }
+}
+
+
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
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");
}
}
+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);
/*
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,
}
}
/*
- 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));
// 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());
}
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);
}
}
-
}
}
}
// 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;
/*
TEST CODE
*/
-#if 1
+#if 0
m_random_spawn_timer -= dtime;
if(m_random_spawn_timer < 0)
{
pos = player->getPosition();
pos += v3f(
myrand_range(-3,3)*BS,
- 0,
+ 5,
myrand_range(-3,3)*BS
);
//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
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
obj->setId(id);
- addActiveObject(obj);
-
obj->initialize(init_data);
+
+ addActiveObject(obj);
}
void ClientEnvironment::removeActiveObject(u16 id)
*/
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
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)
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;
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);
}
*/
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);
}
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();
{
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;
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");
{
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;
}
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();
dtime = 0;
lasttime = time;
+ /* Run timers */
+
+ object_hit_delay_timer -= dtime;
+
/*
Log frametime for visualization
*/
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
if(counter < 0)
{
counter = 30.0;
- client.printDebugInfo(std::cout);
+ client.printDebugInfo(dstream);
}
}
}
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{
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))
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;
}
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
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);
}
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
*/
{
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);
}
}
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)
} // selected_object == NULL
- if(input->getLeftClicked())
+ if(left_punch || (input->getLeftClicked() && !left_punch_muted))
{
camera.setDigging(0); // left click animation
}
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
}
{
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
//timer3.stop();
- //std::cout<<DTIME<<"smgr->drawAll()"<<std::endl;
+ //dstream<<DTIME<<"smgr->drawAll()"<<std::endl;
{
TimeTaker timer("smgr");
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<<")"
{
std::string inventorystring;
std::getline(is, inventorystring, '|');
- return new MapBlockObjectItem(inventorystring);
+ throw SerializationError("MBOItem not supported anymore");
}
else if(name == "CraftItem")
{
return false;
}
-/*
- MapBlockObjectItem DEPRECATED
- TODO: Remove
-*/
-#ifndef SERVER
-video::ITexture * MapBlockObjectItem::getImage() const
-{
- if(m_inventorystring.substr(0,3) == "Rat")
- return g_texturesource->getTextureRaw("rat.png");
-
- if(m_inventorystring.substr(0,4) == "Sign")
- return g_texturesource->getTextureRaw("sign.png");
-
- return NULL;
-}
-#endif
-std::string MapBlockObjectItem::getText()
-{
- if(m_inventorystring.substr(0,3) == "Rat")
- return "";
-
- if(m_inventorystring.substr(0,4) == "Sign")
- return "";
-
- return "obj";
-}
-
-MapBlockObject * MapBlockObjectItem::createObject
- (v3f pos, f32 player_yaw, f32 player_pitch)
-{
- std::istringstream is(m_inventorystring);
- std::string name;
- std::getline(is, name, ' ');
-
- if(name == "None")
- {
- return NULL;
- }
- else if(name == "Sign")
- {
- std::string text;
- std::getline(is, text, '|');
- SignObject *obj = new SignObject(NULL, -1, pos);
- obj->setText(text);
- obj->setYaw(-player_yaw);
- return obj;
- }
- else if(name == "Rat")
- {
- RatObject *obj = new RatObject(NULL, -1, pos);
- return obj;
- }
- else if(name == "ItemObj")
- {
- /*
- Now we are an inventory item containing the serialization
- string of an object that contains the serialization
- string of an inventory item. Fuck this.
- */
- //assert(0);
- dstream<<__FUNCTION_NAME<<": WARNING: Ignoring ItemObj "
- <<"because an item-object should never be inside "
- <<"an object-item."<<std::endl;
- return NULL;
- }
- else
- {
- return NULL;
- }
-}
-
/*
Inventory
*/
#include <string>
#include "common_irrlicht.h"
#include "debug.h"
-#include "mapblockobject.h"
#include "main.h" // For g_materials
#include "mapnode.h" // For content_t
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:
m_lighting_expired(true),
m_day_night_differs(false),
m_generated(false),
- m_objects(this),
m_timestamp(BLOCK_TIMESTAMP_UNDEFINED),
m_usage_timer(0)
{
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)
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);
}
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;
+ }
}
/*
#include "exceptions.h"
#include "serialization.h"
#include "constants.h"
-#include "mapblockobject.h"
#include "voxel.h"
#include "nodemetadata.h"
#include "staticobject.h"
// 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
bool m_generated;
- // DEPRECATED
- MapBlockObjectList m_objects;
-
#ifndef SERVER // Only on client
/*
Set to true if the mesh has been ordered to be updated
+++ /dev/null
-/*
-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
+++ /dev/null
-/*
-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
-
*/
void add_random_objects(MapBlock *block)
{
+#if 0
for(s16 z0=0; z0<MAP_BLOCKSIZE; z0++)
for(s16 x0=0; x0<MAP_BLOCKSIZE; x0++)
{
}
}
block->setChangedFlag();
+#endif
}
void make_block(BlockMakeData *data)
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
*/
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();
}
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)
{
*/
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);
#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)
{
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)
{
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;
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;
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);
image->drop();
}
}
+ /*
+ "[makealpha:R,G,B:filename.png"
+ Use an image with converting one color to transparent.
+ */
+ else if(part_of_name.substr(0,11) == "[makealpha:")
+ {
+ if(baseimg != NULL)
+ {
+ dstream<<"WARNING: generate_image(): baseimg!=NULL "
+ <<"for part_of_name=\""<<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 &.
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;