2 (c) 2010 Perttu Ahola <celeron55@gmail.com>
5 #ifndef MAPBLOCKOBJECT_HEADER
6 #define MAPBLOCKOBJECT_HEADER
8 #include "common_irrlicht.h"
11 #include "serialization.h"
13 #include "constants.h"
18 MAPBLOCKOBJECT_TYPE_TEST=0,
19 MAPBLOCKOBJECT_TYPE_TEST2=1,
20 MAPBLOCKOBJECT_TYPE_SIGN=2,
21 MAPBLOCKOBJECT_TYPE_RAT=3,
29 MapBlockObject(MapBlock *block, s16 id, v3f pos):
30 m_collision_box(NULL),
31 m_selection_box(NULL),
37 virtual ~MapBlockObject()
50 // Writes id, pos and typeId
51 void serializeBase(std::ostream &os, u8 version)
57 os.write((char*)buf, 2);
60 // stored as x1000/BS v3s16
61 v3s16 pos_i(m_pos.X*1000/BS, m_pos.Y*1000/BS, m_pos.Z*1000/BS);
62 writeV3S16(buf, pos_i);
63 os.write((char*)buf, 6);
66 writeU16(buf, getTypeId());
67 os.write((char*)buf, 2);
70 // Get floating point position on map
73 void setBlockChanged();
75 // Shootline is relative to block
76 bool isSelected(core::line3d<f32> shootline)
78 if(m_selection_box == NULL)
81 core::aabbox3d<f32> offsetted_box(
82 m_selection_box->MinEdge + m_pos,
83 m_selection_box->MaxEdge + m_pos
86 return offsetted_box.intersectsWithLine(shootline);
89 core::aabbox3d<f32> getSelectionBoxOnMap()
91 v3f absolute_pos = getAbsolutePos();
93 core::aabbox3d<f32> box(
94 m_selection_box->MinEdge + absolute_pos,
95 m_selection_box->MaxEdge + absolute_pos
102 Implementation interface
105 virtual u16 getTypeId() const = 0;
106 // Shall call serializeBase and then write the parameters
107 virtual void serialize(std::ostream &os, u8 version) = 0;
108 // Shall read parameters from stream
109 virtual void update(std::istream &is, u8 version) = 0;
111 virtual std::string getInventoryString() { return "None"; }
113 // Reimplementation shall call this.
114 virtual void updatePos(v3f pos)
119 // Shall move the object around, modify it and possibly delete it.
120 // Typical dtimes are 0.2 and 10000.
121 // A return value of true requests deletion of the object by the caller.
122 // NOTE: Only server calls this.
123 virtual bool serverStep(float dtime) { return false; };
124 // This should do slight animations only or so
125 virtual void clientStep(float dtime) {};
127 // NOTE: These functions should do nothing if the asked state is
128 // same as the current state
129 // Shall add and remove relevant scene nodes for rendering the
130 // object in the game world
131 virtual void addToScene(scene::ISceneManager *smgr) {};
132 // Shall remove stuff from the scene
133 // Should return silently if there is nothing to remove
134 // NOTE: This has to be called before calling destructor
135 virtual void removeFromScene() {};
137 virtual std::string infoText() { return ""; }
139 // Shall be left NULL if doesn't collide
140 // Position is relative to m_pos in block
141 core::aabbox3d<f32> * m_collision_box;
143 // Shall be left NULL if can't be selected
144 core::aabbox3d<f32> * m_selection_box;
148 // This differentiates the instance of the object
149 // Not same as typeId.
151 // Position of the object inside the block
152 // Units is node coordinates * BS
155 friend class MapBlockObjectList;
158 class TestObject : public MapBlockObject
161 // The constructor of every MapBlockObject should be like this
162 TestObject(MapBlock *block, s16 id, v3f pos):
163 MapBlockObject(block, id, pos),
167 virtual ~TestObject()
172 Implementation interface
174 virtual u16 getTypeId() const
176 return MAPBLOCKOBJECT_TYPE_TEST;
178 virtual void serialize(std::ostream &os, u8 version)
180 serializeBase(os, version);
182 // Write subpos_c * 100
184 writeU16(buf, m_subpos_c * 100);
185 os.write((char*)buf, 2);
187 virtual void update(std::istream &is, u8 version)
189 // Read subpos_c * 100
191 is.read((char*)buf, 2);
192 m_subpos_c = (f32)readU16(buf) / 100;
196 virtual bool serverStep(float dtime)
198 m_subpos_c += dtime * 3.0;
204 virtual void addToScene(scene::ISceneManager *smgr)
209 //dstream<<"Adding to scene"<<std::endl;
211 video::IVideoDriver* driver = smgr->getVideoDriver();
213 scene::SMesh *mesh = new scene::SMesh();
214 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
215 video::SColor c(255,255,255,255);
216 video::S3DVertex vertices[4] =
218 video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
219 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
220 video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0),
221 video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0),
223 u16 indices[] = {0,1,2,2,3,0};
224 buf->append(vertices, 4, indices, 6);
226 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
227 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
228 buf->getMaterial().setTexture
229 (0, driver->getTexture("../data/player.png"));
230 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
231 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
233 mesh->addMeshBuffer(buf);
235 m_node = smgr->addMeshSceneNode(mesh, NULL);
237 m_node->setPosition(getAbsolutePos());
239 virtual void removeFromScene()
241 //dstream<<"Removing from scene"<<std::endl;
255 m_subpos = BS*2.0 * v3f(sin(m_subpos_c), sin(m_subpos_c+1.0), sin(-m_subpos_c));
259 m_node->setPosition(getAbsolutePos() + m_subpos);
264 scene::IMeshSceneNode *m_node;
271 class MovingObject : public MapBlockObject
274 // The constructor of every MapBlockObject should be like this
275 MovingObject(MapBlock *block, s16 id, v3f pos):
276 MapBlockObject(block, id, pos),
279 m_touching_ground = false;
281 virtual ~MovingObject()
286 Implementation interface
289 virtual u16 getTypeId() const = 0;
291 virtual void serialize(std::ostream &os, u8 version)
293 serializeBase(os, version);
298 // stored as x100/BS v3s16
299 v3s16 speed_i(m_speed.X*100/BS, m_speed.Y*100/BS, m_speed.Z*100/BS);
300 writeV3S16(buf, speed_i);
301 os.write((char*)buf, 6);
303 virtual void update(std::istream &is, u8 version)
308 // stored as x100/BS v3s16
309 is.read((char*)buf, 6);
310 v3s16 speed_i = readV3S16(buf);
311 v3f speed((f32)speed_i.X/100*BS,
312 (f32)speed_i.Y/100*BS,
313 (f32)speed_i.Z/100*BS);
318 virtual bool serverStep(float dtime) { return false; };
319 virtual void clientStep(float dtime) {};
321 virtual void addToScene(scene::ISceneManager *smgr) = 0;
322 virtual void removeFromScene() = 0;
328 // Moves with collision detection
329 void move(float dtime, v3f acceleration);
333 bool m_touching_ground;
336 class Test2Object : public MovingObject
339 // The constructor of every MapBlockObject should be like this
340 Test2Object(MapBlock *block, s16 id, v3f pos):
341 MovingObject(block, id, pos),
344 m_collision_box = new core::aabbox3d<f32>
345 (-BS*0.3,0,-BS*0.3, BS*0.3,BS*1.7,BS*0.3);
347 virtual ~Test2Object()
349 delete m_collision_box;
353 Implementation interface
355 virtual u16 getTypeId() const
357 return MAPBLOCKOBJECT_TYPE_TEST2;
359 virtual void serialize(std::ostream &os, u8 version)
361 MovingObject::serialize(os, version);
363 virtual void update(std::istream &is, u8 version)
365 MovingObject::update(is, version);
370 virtual bool serverStep(float dtime)
375 if(m_touching_ground)
377 static float count = 0;
386 move(dtime, v3f(0, -9.81*BS, 0));
393 virtual void clientStep(float dtime)
395 m_pos += m_speed * dtime;
400 virtual void addToScene(scene::ISceneManager *smgr)
405 //dstream<<"Adding to scene"<<std::endl;
407 video::IVideoDriver* driver = smgr->getVideoDriver();
409 scene::SMesh *mesh = new scene::SMesh();
410 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
411 video::SColor c(255,255,255,255);
412 video::S3DVertex vertices[4] =
414 video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
415 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
416 video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0),
417 video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0),
419 u16 indices[] = {0,1,2,2,3,0};
420 buf->append(vertices, 4, indices, 6);
422 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
423 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
424 buf->getMaterial().setTexture
425 (0, driver->getTexture("../data/player.png"));
426 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
427 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
429 mesh->addMeshBuffer(buf);
431 m_node = smgr->addMeshSceneNode(mesh, NULL);
433 m_node->setPosition(getAbsolutePos());
435 virtual void removeFromScene()
437 //dstream<<"Removing from scene"<<std::endl;
451 //m_subpos = BS*2.0 * v3f(sin(m_subpos_c), sin(m_subpos_c+1.0), sin(-m_subpos_c));
455 //m_node->setPosition(getAbsolutePos() + m_subpos);
456 m_node->setPosition(getAbsolutePos());
461 scene::IMeshSceneNode *m_node;
464 class RatObject : public MovingObject
467 RatObject(MapBlock *block, s16 id, v3f pos):
468 MovingObject(block, id, pos),
471 m_collision_box = new core::aabbox3d<f32>
472 (-BS*0.3,0,-BS*0.3, BS*0.3,BS*0.5,BS*0.3);
473 m_selection_box = new core::aabbox3d<f32>
474 (-BS*0.3,0,-BS*0.3, BS*0.3,BS*0.5,BS*0.3);
481 delete m_collision_box;
482 delete m_selection_box;
486 Implementation interface
488 virtual u16 getTypeId() const
490 return MAPBLOCKOBJECT_TYPE_RAT;
492 virtual void serialize(std::ostream &os, u8 version)
494 MovingObject::serialize(os, version);
498 writeS16(buf, m_yaw * 10);
499 os.write((char*)buf, 2);
502 virtual void update(std::istream &is, u8 version)
504 MovingObject::update(is, version);
508 is.read((char*)buf, 2);
509 s16 yaw_i = readS16(buf);
510 m_yaw = (f32)yaw_i / 10;
515 virtual bool serverStep(float dtime)
517 v3f dir(cos(m_yaw/180*PI),0,sin(m_yaw/180*PI));
521 m_speed.X = speed * dir.X;
522 m_speed.Z = speed * dir.Z;
524 if(m_touching_ground && (m_oldpos - m_pos).getLength() < dtime*speed/2)
538 m_counter2 += (float)(rand()%100)/100*3.0;
539 m_yaw += ((float)(rand()%200)-100)/100*180;
540 m_yaw = wrapDegrees(m_yaw);
548 move(dtime, v3f(0, -9.81*BS, 0));
555 virtual void clientStep(float dtime)
557 m_pos += m_speed * dtime;
562 virtual void addToScene(scene::ISceneManager *smgr)
567 video::IVideoDriver* driver = smgr->getVideoDriver();
569 scene::SMesh *mesh = new scene::SMesh();
570 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
571 video::SColor c(255,255,255,255);
572 video::S3DVertex vertices[4] =
574 video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
575 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
576 video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0),
577 video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 0,0),
579 u16 indices[] = {0,1,2,2,3,0};
580 buf->append(vertices, 4, indices, 6);
582 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
583 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
584 buf->getMaterial().setTexture
585 (0, driver->getTexture("../data/rat.png"));
586 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
587 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
589 mesh->addMeshBuffer(buf);
591 m_node = smgr->addMeshSceneNode(mesh, NULL);
593 m_node->setPosition(getAbsolutePos());
595 virtual void removeFromScene()
604 virtual std::string getInventoryString()
606 // There must be a space after the name
608 return std::string("Rat ");
619 m_node->setPosition(getAbsolutePos());
620 m_node->setRotation(v3f(0, -m_yaw+180, 0));
625 scene::IMeshSceneNode *m_node;
633 class SignObject : public MapBlockObject
636 // The constructor of every MapBlockObject should be like this
637 SignObject(MapBlock *block, s16 id, v3f pos):
638 MapBlockObject(block, id, pos),
641 m_selection_box = new core::aabbox3d<f32>
642 (-BS*0.4,-BS*0.5,-BS*0.4, BS*0.4,BS*0.5,BS*0.4);
644 virtual ~SignObject()
646 delete m_selection_box;
650 Implementation interface
652 virtual u16 getTypeId() const
654 return MAPBLOCKOBJECT_TYPE_SIGN;
656 virtual void serialize(std::ostream &os, u8 version)
658 serializeBase(os, version);
662 writeS16(buf, m_yaw * 10);
663 os.write((char*)buf, 2);
666 writeU16(buf, m_text.size());
667 os.write((char*)buf, 2);
670 os.write(m_text.c_str(), m_text.size());
672 virtual void update(std::istream &is, u8 version)
677 is.read((char*)buf, 2);
678 s16 yaw_i = readS16(buf);
679 m_yaw = (f32)yaw_i / 10;
682 is.read((char*)buf, 2);
683 u16 size = readU16(buf);
687 for(u16 i=0; i<size; i++)
689 is.read((char*)buf, 1);
695 virtual bool serverStep(float dtime)
699 virtual void addToScene(scene::ISceneManager *smgr)
704 video::IVideoDriver* driver = smgr->getVideoDriver();
706 scene::SMesh *mesh = new scene::SMesh();
708 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
709 video::SColor c(255,255,255,255);
710 video::S3DVertex vertices[4] =
712 video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c, 0,1),
713 video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c, 1,1),
714 video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 1,0),
715 video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 0,0),
717 u16 indices[] = {0,1,2,2,3,0};
718 buf->append(vertices, 4, indices, 6);
720 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
721 //buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
722 buf->getMaterial().setTexture
723 (0, driver->getTexture("../data/sign.png"));
724 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
725 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
727 mesh->addMeshBuffer(buf);
731 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
732 video::SColor c(255,255,255,255);
733 video::S3DVertex vertices[4] =
735 video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c, 0,1),
736 video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c, 1,1),
737 video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0),
738 video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 0,0),
740 u16 indices[] = {0,1,2,2,3,0};
741 buf->append(vertices, 4, indices, 6);
743 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
744 //buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
745 buf->getMaterial().setTexture
746 (0, driver->getTexture("../data/sign_back.png"));
747 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
748 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
750 mesh->addMeshBuffer(buf);
753 m_node = smgr->addMeshSceneNode(mesh, NULL);
758 virtual void removeFromScene()
767 virtual std::string infoText()
769 return std::string("\"") + m_text + "\"";
772 virtual std::string getInventoryString()
774 return std::string("Sign ")+m_text;
781 void updateSceneNode()
785 m_node->setPosition(getAbsolutePos());
786 m_node->setRotation(v3f(0, m_yaw, 0));
790 void setText(std::string text)
792 if(text.size() > SIGN_TEXT_MAX_LENGTH)
793 text = text.substr(0, SIGN_TEXT_MAX_LENGTH);
807 scene::IMeshSceneNode *m_node;
812 struct DistanceSortedObject
814 DistanceSortedObject(MapBlockObject *a_obj, f32 a_d)
823 bool operator < (DistanceSortedObject &other)
829 class MapBlockObjectList
832 MapBlockObjectList(MapBlock *block);
833 ~MapBlockObjectList();
834 // Writes the count, id, the type id and the parameters of all objects
835 void serialize(std::ostream &os, u8 version);
836 // Reads ids, type_ids and parameters.
837 // Creates, updates and deletes objects.
838 // If smgr!=NULL, new objects are added to the scene
839 void update(std::istream &is, u8 version, scene::ISceneManager *smgr);
840 // Finds a new unique id
841 s16 getFreeId() throw(ContainerFullException);
844 Set id to -1 to have this set it to a suitable one.
845 The block pointer member is set to this block.
847 void add(MapBlockObject *object)
848 throw(ContainerFullException, AlreadyExistsException);
850 // Deletes and removes all objects
855 Ignores inexistent objects
859 References an object.
860 The object will not be valid after step() or of course if
862 Grabbing the lock is recommended while processing.
864 MapBlockObject * get(s16 id);
866 // You'll want to grab this in a SharedPtr
867 JMutexAutoLock * getLock()
869 return new JMutexAutoLock(m_mutex);
872 // Steps all objects and if server==true, removes those that
873 // want to be removed
874 void step(float dtime, bool server);
876 // Wraps an object that wants to move onto this block from an another
877 // Returns true if wrapping was impossible
878 bool wrapObject(MapBlockObject *object);
880 // origin is relative to block
881 void getObjects(v3f origin, f32 max_d,
882 core::array<DistanceSortedObject> &dest);
887 return m_objects.size();
893 core::map<s16, MapBlockObject*> m_objects;