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"
17 MAPBLOCKOBJECT_TYPE_TEST=0,
18 MAPBLOCKOBJECT_TYPE_TEST2=1,
19 MAPBLOCKOBJECT_TYPE_SIGN=2,
20 MAPBLOCKOBJECT_TYPE_RAT=3,
28 MapBlockObject(MapBlock *block, s16 id, v3f pos):
29 m_collision_box(NULL),
30 m_selection_box(NULL),
36 virtual ~MapBlockObject()
49 // Writes id, pos and typeId
50 void serializeBase(std::ostream &os, u8 version)
56 os.write((char*)buf, 2);
59 // stored as x1000/BS v3s16
60 v3s16 pos_i(m_pos.X*1000/BS, m_pos.Y*1000/BS, m_pos.Z*1000/BS);
61 writeV3S16(buf, pos_i);
62 os.write((char*)buf, 6);
65 writeU16(buf, getTypeId());
66 os.write((char*)buf, 2);
69 // Get floating point position on map
72 void setBlockChanged();
74 // Shootline is relative to block
75 bool isSelected(core::line3d<f32> shootline)
77 if(m_selection_box == NULL)
80 core::aabbox3d<f32> offsetted_box(
81 m_selection_box->MinEdge + m_pos,
82 m_selection_box->MaxEdge + m_pos
85 return offsetted_box.intersectsWithLine(shootline);
88 core::aabbox3d<f32> getSelectionBoxOnMap()
90 v3f absolute_pos = getAbsolutePos();
92 core::aabbox3d<f32> box(
93 m_selection_box->MinEdge + absolute_pos,
94 m_selection_box->MaxEdge + absolute_pos
101 Implementation interface
104 virtual u16 getTypeId() const = 0;
105 // Shall call serializeBase and then write the parameters
106 virtual void serialize(std::ostream &os, u8 version) = 0;
107 // Shall read parameters from stream
108 virtual void update(std::istream &is, u8 version) = 0;
110 virtual std::string getInventoryString() { return "None"; }
112 // Reimplementation shall call this.
113 virtual void updatePos(v3f pos)
118 // Shall move the object around, modify it and possibly delete it.
119 // Typical dtimes are 0.2 and 10000.
120 // A return value of true requests deletion of the object by the caller.
121 // NOTE: Only server calls this.
122 virtual bool serverStep(float dtime) { return false; };
123 // This should do slight animations only or so
124 virtual void clientStep(float dtime) {};
126 // NOTE: These functions should do nothing if the asked state is
127 // same as the current state
128 // Shall add and remove relevant scene nodes for rendering the
129 // object in the game world
130 virtual void addToScene(scene::ISceneManager *smgr) {};
131 // Shall remove stuff from the scene
132 // Should return silently if there is nothing to remove
133 // NOTE: This has to be called before calling destructor
134 virtual void removeFromScene() {};
136 virtual std::string infoText() { return ""; }
138 // Shall be left NULL if doesn't collide
139 // Position is relative to m_pos in block
140 core::aabbox3d<f32> * m_collision_box;
142 // Shall be left NULL if can't be selected
143 core::aabbox3d<f32> * m_selection_box;
147 // This differentiates the instance of the object
148 // Not same as typeId.
150 // Position of the object inside the block
151 // Units is node coordinates * BS
154 friend class MapBlockObjectList;
157 class TestObject : public MapBlockObject
160 // The constructor of every MapBlockObject should be like this
161 TestObject(MapBlock *block, s16 id, v3f pos):
162 MapBlockObject(block, id, pos),
166 virtual ~TestObject()
171 Implementation interface
173 virtual u16 getTypeId() const
175 return MAPBLOCKOBJECT_TYPE_TEST;
177 virtual void serialize(std::ostream &os, u8 version)
179 serializeBase(os, version);
181 // Write subpos_c * 100
183 writeU16(buf, m_subpos_c * 100);
184 os.write((char*)buf, 2);
186 virtual void update(std::istream &is, u8 version)
188 // Read subpos_c * 100
190 is.read((char*)buf, 2);
191 m_subpos_c = (f32)readU16(buf) / 100;
195 virtual bool serverStep(float dtime)
197 m_subpos_c += dtime * 3.0;
203 virtual void addToScene(scene::ISceneManager *smgr)
208 //dstream<<"Adding to scene"<<std::endl;
210 video::IVideoDriver* driver = smgr->getVideoDriver();
212 scene::SMesh *mesh = new scene::SMesh();
213 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
214 video::SColor c(255,255,255,255);
215 video::S3DVertex vertices[4] =
217 video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
218 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
219 video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0),
220 video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0),
222 u16 indices[] = {0,1,2,2,3,0};
223 buf->append(vertices, 4, indices, 6);
225 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
226 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
227 buf->getMaterial().setTexture
228 (0, driver->getTexture("../data/player.png"));
229 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
230 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
232 mesh->addMeshBuffer(buf);
234 m_node = smgr->addMeshSceneNode(mesh, NULL);
236 m_node->setPosition(getAbsolutePos());
238 virtual void removeFromScene()
240 //dstream<<"Removing from scene"<<std::endl;
254 m_subpos = BS*2.0 * v3f(sin(m_subpos_c), sin(m_subpos_c+1.0), sin(-m_subpos_c));
258 m_node->setPosition(getAbsolutePos() + m_subpos);
263 scene::IMeshSceneNode *m_node;
270 class MovingObject : public MapBlockObject
273 // The constructor of every MapBlockObject should be like this
274 MovingObject(MapBlock *block, s16 id, v3f pos):
275 MapBlockObject(block, id, pos),
278 m_touching_ground = false;
280 virtual ~MovingObject()
285 Implementation interface
288 virtual u16 getTypeId() const = 0;
290 virtual void serialize(std::ostream &os, u8 version)
292 serializeBase(os, version);
297 // stored as x100/BS v3s16
298 v3s16 speed_i(m_speed.X*100/BS, m_speed.Y*100/BS, m_speed.Z*100/BS);
299 writeV3S16(buf, speed_i);
300 os.write((char*)buf, 6);
302 virtual void update(std::istream &is, u8 version)
307 // stored as x100/BS v3s16
308 is.read((char*)buf, 6);
309 v3s16 speed_i = readV3S16(buf);
310 v3f speed((f32)speed_i.X/100*BS,
311 (f32)speed_i.Y/100*BS,
312 (f32)speed_i.Z/100*BS);
317 virtual bool serverStep(float dtime) { return false; };
318 virtual void clientStep(float dtime) {};
320 virtual void addToScene(scene::ISceneManager *smgr) = 0;
321 virtual void removeFromScene() = 0;
327 // Moves with collision detection
328 void move(float dtime, v3f acceleration);
332 bool m_touching_ground;
335 class Test2Object : public MovingObject
338 // The constructor of every MapBlockObject should be like this
339 Test2Object(MapBlock *block, s16 id, v3f pos):
340 MovingObject(block, id, pos),
343 m_collision_box = new core::aabbox3d<f32>
344 (-BS*0.3,0,-BS*0.3, BS*0.3,BS*1.7,BS*0.3);
346 virtual ~Test2Object()
348 delete m_collision_box;
352 Implementation interface
354 virtual u16 getTypeId() const
356 return MAPBLOCKOBJECT_TYPE_TEST2;
358 virtual void serialize(std::ostream &os, u8 version)
360 MovingObject::serialize(os, version);
362 virtual void update(std::istream &is, u8 version)
364 MovingObject::update(is, version);
369 virtual bool serverStep(float dtime)
374 if(m_touching_ground)
376 static float count = 0;
385 move(dtime, v3f(0, -9.81*BS, 0));
392 virtual void clientStep(float dtime)
394 m_pos += m_speed * dtime;
399 virtual void addToScene(scene::ISceneManager *smgr)
404 //dstream<<"Adding to scene"<<std::endl;
406 video::IVideoDriver* driver = smgr->getVideoDriver();
408 scene::SMesh *mesh = new scene::SMesh();
409 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
410 video::SColor c(255,255,255,255);
411 video::S3DVertex vertices[4] =
413 video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
414 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
415 video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0),
416 video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0),
418 u16 indices[] = {0,1,2,2,3,0};
419 buf->append(vertices, 4, indices, 6);
421 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
422 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
423 buf->getMaterial().setTexture
424 (0, driver->getTexture("../data/player.png"));
425 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
426 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
428 mesh->addMeshBuffer(buf);
430 m_node = smgr->addMeshSceneNode(mesh, NULL);
432 m_node->setPosition(getAbsolutePos());
434 virtual void removeFromScene()
436 //dstream<<"Removing from scene"<<std::endl;
450 //m_subpos = BS*2.0 * v3f(sin(m_subpos_c), sin(m_subpos_c+1.0), sin(-m_subpos_c));
454 //m_node->setPosition(getAbsolutePos() + m_subpos);
455 m_node->setPosition(getAbsolutePos());
460 scene::IMeshSceneNode *m_node;
463 class RatObject : public MovingObject
466 RatObject(MapBlock *block, s16 id, v3f pos):
467 MovingObject(block, id, pos),
470 m_collision_box = new core::aabbox3d<f32>
471 (-BS*0.3,0,-BS*0.3, BS*0.3,BS*0.5,BS*0.3);
472 m_selection_box = new core::aabbox3d<f32>
473 (-BS*0.3,0,-BS*0.3, BS*0.3,BS*0.5,BS*0.3);
480 delete m_collision_box;
481 delete m_selection_box;
485 Implementation interface
487 virtual u16 getTypeId() const
489 return MAPBLOCKOBJECT_TYPE_RAT;
491 virtual void serialize(std::ostream &os, u8 version)
493 MovingObject::serialize(os, version);
497 writeS16(buf, m_yaw * 10);
498 os.write((char*)buf, 2);
501 virtual void update(std::istream &is, u8 version)
503 MovingObject::update(is, version);
507 is.read((char*)buf, 2);
508 s16 yaw_i = readS16(buf);
509 m_yaw = (f32)yaw_i / 10;
514 virtual bool serverStep(float dtime)
516 v3f dir(cos(m_yaw/180*PI),0,sin(m_yaw/180*PI));
520 m_speed.X = speed * dir.X;
521 m_speed.Z = speed * dir.Z;
523 if(m_touching_ground && (m_oldpos - m_pos).getLength() < dtime*speed/2)
537 m_counter2 += (float)(rand()%100)/100*3.0;
538 m_yaw += ((float)(rand()%200)-100)/100*180;
539 m_yaw = wrapDegrees(m_yaw);
547 move(dtime, v3f(0, -9.81*BS, 0));
554 virtual void clientStep(float dtime)
556 m_pos += m_speed * dtime;
561 virtual void addToScene(scene::ISceneManager *smgr)
566 video::IVideoDriver* driver = smgr->getVideoDriver();
568 scene::SMesh *mesh = new scene::SMesh();
569 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
570 video::SColor c(255,255,255,255);
571 video::S3DVertex vertices[4] =
573 video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
574 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
575 video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0),
576 video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 0,0),
578 u16 indices[] = {0,1,2,2,3,0};
579 buf->append(vertices, 4, indices, 6);
581 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
582 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
583 buf->getMaterial().setTexture
584 (0, driver->getTexture("../data/rat.png"));
585 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
586 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
588 mesh->addMeshBuffer(buf);
590 m_node = smgr->addMeshSceneNode(mesh, NULL);
592 m_node->setPosition(getAbsolutePos());
594 virtual void removeFromScene()
603 virtual std::string getInventoryString()
605 // There must be a space after the name
607 return std::string("Rat ");
618 m_node->setPosition(getAbsolutePos());
619 m_node->setRotation(v3f(0, -m_yaw+180, 0));
624 scene::IMeshSceneNode *m_node;
632 class SignObject : public MapBlockObject
635 // The constructor of every MapBlockObject should be like this
636 SignObject(MapBlock *block, s16 id, v3f pos):
637 MapBlockObject(block, id, pos),
640 m_selection_box = new core::aabbox3d<f32>
641 (-BS*0.4,-BS*0.5,-BS*0.4, BS*0.4,BS*0.5,BS*0.4);
643 virtual ~SignObject()
645 delete m_selection_box;
649 Implementation interface
651 virtual u16 getTypeId() const
653 return MAPBLOCKOBJECT_TYPE_SIGN;
655 virtual void serialize(std::ostream &os, u8 version)
657 serializeBase(os, version);
661 writeS16(buf, m_yaw * 10);
662 os.write((char*)buf, 2);
665 writeU16(buf, m_text.size());
666 os.write((char*)buf, 2);
669 os.write(m_text.c_str(), m_text.size());
671 virtual void update(std::istream &is, u8 version)
676 is.read((char*)buf, 2);
677 s16 yaw_i = readS16(buf);
678 m_yaw = (f32)yaw_i / 10;
681 is.read((char*)buf, 2);
682 u16 size = readU16(buf);
686 for(u16 i=0; i<size; i++)
688 is.read((char*)buf, 1);
694 virtual bool serverStep(float dtime)
698 virtual void addToScene(scene::ISceneManager *smgr)
703 video::IVideoDriver* driver = smgr->getVideoDriver();
705 scene::SMesh *mesh = new scene::SMesh();
707 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
708 video::SColor c(255,255,255,255);
709 video::S3DVertex vertices[4] =
711 video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c, 0,1),
712 video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c, 1,1),
713 video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 1,0),
714 video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 0,0),
716 u16 indices[] = {0,1,2,2,3,0};
717 buf->append(vertices, 4, indices, 6);
719 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
720 //buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
721 buf->getMaterial().setTexture
722 (0, driver->getTexture("../data/sign.png"));
723 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
724 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
726 mesh->addMeshBuffer(buf);
730 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
731 video::SColor c(255,255,255,255);
732 video::S3DVertex vertices[4] =
734 video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c, 0,1),
735 video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c, 1,1),
736 video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0),
737 video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 0,0),
739 u16 indices[] = {0,1,2,2,3,0};
740 buf->append(vertices, 4, indices, 6);
742 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
743 //buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
744 buf->getMaterial().setTexture
745 (0, driver->getTexture("../data/sign_back.png"));
746 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
747 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
749 mesh->addMeshBuffer(buf);
752 m_node = smgr->addMeshSceneNode(mesh, NULL);
757 virtual void removeFromScene()
766 virtual std::string infoText()
768 return std::string("\"") + m_text + "\"";
771 virtual std::string getInventoryString()
773 return std::string("Sign ")+m_text;
780 void updateSceneNode()
784 m_node->setPosition(getAbsolutePos());
785 m_node->setRotation(v3f(0, m_yaw, 0));
789 void setText(std::string text)
791 if(text.size() > SIGN_TEXT_MAX_LENGTH)
792 text = text.substr(0, SIGN_TEXT_MAX_LENGTH);
806 scene::IMeshSceneNode *m_node;
811 struct DistanceSortedObject
813 DistanceSortedObject(MapBlockObject *a_obj, f32 a_d)
822 bool operator < (DistanceSortedObject &other)
828 class MapBlockObjectList
831 MapBlockObjectList(MapBlock *block);
832 ~MapBlockObjectList();
833 // Writes the count, id, the type id and the parameters of all objects
834 void serialize(std::ostream &os, u8 version);
835 // Reads ids, type_ids and parameters.
836 // Creates, updates and deletes objects.
837 // If smgr!=NULL, new objects are added to the scene
838 void update(std::istream &is, u8 version, scene::ISceneManager *smgr);
839 // Finds a new unique id
840 s16 getFreeId() throw(ContainerFullException);
843 Set id to -1 to have this set it to a suitable one.
844 The block pointer member is set to this block.
846 void add(MapBlockObject *object)
847 throw(ContainerFullException, AlreadyExistsException);
849 // Deletes and removes all objects
854 Ignores inexistent objects
858 References an object.
859 The object will not be valid after step() or of course if
861 Grabbing the lock is recommended while processing.
863 MapBlockObject * get(s16 id);
865 // You'll want to grab this in a SharedPtr
866 JMutexAutoLock * getLock()
868 return new JMutexAutoLock(m_mutex);
871 // Steps all objects and if server==true, removes those that
872 // want to be removed
873 void step(float dtime, bool server);
875 // Wraps an object that wants to move onto this block from an another
876 // Returns true if wrapping was impossible
877 bool wrapObject(MapBlockObject *object);
879 // origin is relative to block
880 void getObjects(v3f origin, f32 max_d,
881 core::array<DistanceSortedObject> &dest);
886 return m_objects.size();
892 core::map<s16, MapBlockObject*> m_objects;