3 Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #ifndef MAPBLOCKOBJECT_HEADER
21 #define MAPBLOCKOBJECT_HEADER
23 #include "common_irrlicht.h"
26 #include "serialization.h"
28 #include "constants.h"
33 MAPBLOCKOBJECT_TYPE_TEST=0,
34 MAPBLOCKOBJECT_TYPE_TEST2=1,
35 MAPBLOCKOBJECT_TYPE_SIGN=2,
36 MAPBLOCKOBJECT_TYPE_RAT=3,
44 MapBlockObject(MapBlock *block, s16 id, v3f pos):
45 m_collision_box(NULL),
46 m_selection_box(NULL),
52 virtual ~MapBlockObject()
65 // Writes id, pos and typeId
66 void serializeBase(std::ostream &os, u8 version)
72 os.write((char*)buf, 2);
75 // stored as x1000/BS v3s16
76 v3s16 pos_i(m_pos.X*1000/BS, m_pos.Y*1000/BS, m_pos.Z*1000/BS);
77 writeV3S16(buf, pos_i);
78 os.write((char*)buf, 6);
81 writeU16(buf, getTypeId());
82 os.write((char*)buf, 2);
85 // Get floating point position on map
88 void setBlockChanged();
90 // Shootline is relative to block
91 bool isSelected(core::line3d<f32> shootline)
93 if(m_selection_box == NULL)
96 core::aabbox3d<f32> offsetted_box(
97 m_selection_box->MinEdge + m_pos,
98 m_selection_box->MaxEdge + m_pos
101 return offsetted_box.intersectsWithLine(shootline);
104 core::aabbox3d<f32> getSelectionBoxOnMap()
106 v3f absolute_pos = getAbsolutePos();
108 core::aabbox3d<f32> box(
109 m_selection_box->MinEdge + absolute_pos,
110 m_selection_box->MaxEdge + absolute_pos
117 Implementation interface
120 virtual u16 getTypeId() const = 0;
121 // Shall call serializeBase and then write the parameters
122 virtual void serialize(std::ostream &os, u8 version) = 0;
123 // Shall read parameters from stream
124 virtual void update(std::istream &is, u8 version) = 0;
126 virtual std::string getInventoryString() { return "None"; }
128 // Reimplementation shall call this.
129 virtual void updatePos(v3f pos)
134 // Shall move the object around, modify it and possibly delete it.
135 // Typical dtimes are 0.2 and 10000.
136 // A return value of true requests deletion of the object by the caller.
137 // NOTE: Only server calls this.
138 virtual bool serverStep(float dtime) { return false; };
139 // This should do slight animations only or so
140 virtual void clientStep(float dtime) {};
142 // NOTE: These functions should do nothing if the asked state is
143 // same as the current state
144 // Shall add and remove relevant scene nodes for rendering the
145 // object in the game world
146 virtual void addToScene(scene::ISceneManager *smgr) {};
147 // Shall remove stuff from the scene
148 // Should return silently if there is nothing to remove
149 // NOTE: This has to be called before calling destructor
150 virtual void removeFromScene() {};
152 virtual std::string infoText() { return ""; }
154 // Shall be left NULL if doesn't collide
155 // Position is relative to m_pos in block
156 core::aabbox3d<f32> * m_collision_box;
158 // Shall be left NULL if can't be selected
159 core::aabbox3d<f32> * m_selection_box;
163 // This differentiates the instance of the object
164 // Not same as typeId.
166 // Position of the object inside the block
167 // Units is node coordinates * BS
170 friend class MapBlockObjectList;
173 class TestObject : public MapBlockObject
176 // The constructor of every MapBlockObject should be like this
177 TestObject(MapBlock *block, s16 id, v3f pos):
178 MapBlockObject(block, id, pos),
182 virtual ~TestObject()
187 Implementation interface
189 virtual u16 getTypeId() const
191 return MAPBLOCKOBJECT_TYPE_TEST;
193 virtual void serialize(std::ostream &os, u8 version)
195 serializeBase(os, version);
197 // Write subpos_c * 100
199 writeU16(buf, m_subpos_c * 100);
200 os.write((char*)buf, 2);
202 virtual void update(std::istream &is, u8 version)
204 // Read subpos_c * 100
206 is.read((char*)buf, 2);
207 m_subpos_c = (f32)readU16(buf) / 100;
211 virtual bool serverStep(float dtime)
213 m_subpos_c += dtime * 3.0;
219 virtual void addToScene(scene::ISceneManager *smgr)
224 //dstream<<"Adding to scene"<<std::endl;
226 video::IVideoDriver* driver = smgr->getVideoDriver();
228 scene::SMesh *mesh = new scene::SMesh();
229 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
230 video::SColor c(255,255,255,255);
231 video::S3DVertex vertices[4] =
233 video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
234 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
235 video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0),
236 video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0),
238 u16 indices[] = {0,1,2,2,3,0};
239 buf->append(vertices, 4, indices, 6);
241 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
242 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
243 buf->getMaterial().setTexture
244 (0, driver->getTexture("../data/player.png"));
245 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
246 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
248 mesh->addMeshBuffer(buf);
250 m_node = smgr->addMeshSceneNode(mesh, NULL);
252 m_node->setPosition(getAbsolutePos());
254 virtual void removeFromScene()
256 //dstream<<"Removing from scene"<<std::endl;
270 m_subpos = BS*2.0 * v3f(sin(m_subpos_c), sin(m_subpos_c+1.0), sin(-m_subpos_c));
274 m_node->setPosition(getAbsolutePos() + m_subpos);
279 scene::IMeshSceneNode *m_node;
286 class MovingObject : public MapBlockObject
289 // The constructor of every MapBlockObject should be like this
290 MovingObject(MapBlock *block, s16 id, v3f pos):
291 MapBlockObject(block, id, pos),
294 m_touching_ground = false;
296 virtual ~MovingObject()
301 Implementation interface
304 virtual u16 getTypeId() const = 0;
306 virtual void serialize(std::ostream &os, u8 version)
308 serializeBase(os, version);
313 // stored as x100/BS v3s16
314 v3s16 speed_i(m_speed.X*100/BS, m_speed.Y*100/BS, m_speed.Z*100/BS);
315 writeV3S16(buf, speed_i);
316 os.write((char*)buf, 6);
318 virtual void update(std::istream &is, u8 version)
323 // stored as x100/BS v3s16
324 is.read((char*)buf, 6);
325 v3s16 speed_i = readV3S16(buf);
326 v3f speed((f32)speed_i.X/100*BS,
327 (f32)speed_i.Y/100*BS,
328 (f32)speed_i.Z/100*BS);
333 virtual bool serverStep(float dtime) { return false; };
334 virtual void clientStep(float dtime) {};
336 virtual void addToScene(scene::ISceneManager *smgr) = 0;
337 virtual void removeFromScene() = 0;
343 // Moves with collision detection
344 void move(float dtime, v3f acceleration);
348 bool m_touching_ground;
351 class Test2Object : public MovingObject
354 // The constructor of every MapBlockObject should be like this
355 Test2Object(MapBlock *block, s16 id, v3f pos):
356 MovingObject(block, id, pos),
359 m_collision_box = new core::aabbox3d<f32>
360 (-BS*0.3,0,-BS*0.3, BS*0.3,BS*1.7,BS*0.3);
362 virtual ~Test2Object()
364 delete m_collision_box;
368 Implementation interface
370 virtual u16 getTypeId() const
372 return MAPBLOCKOBJECT_TYPE_TEST2;
374 virtual void serialize(std::ostream &os, u8 version)
376 MovingObject::serialize(os, version);
378 virtual void update(std::istream &is, u8 version)
380 MovingObject::update(is, version);
385 virtual bool serverStep(float dtime)
390 if(m_touching_ground)
392 static float count = 0;
401 move(dtime, v3f(0, -9.81*BS, 0));
408 virtual void clientStep(float dtime)
410 m_pos += m_speed * dtime;
415 virtual void addToScene(scene::ISceneManager *smgr)
420 //dstream<<"Adding to scene"<<std::endl;
422 video::IVideoDriver* driver = smgr->getVideoDriver();
424 scene::SMesh *mesh = new scene::SMesh();
425 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
426 video::SColor c(255,255,255,255);
427 video::S3DVertex vertices[4] =
429 video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
430 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
431 video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0),
432 video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0),
434 u16 indices[] = {0,1,2,2,3,0};
435 buf->append(vertices, 4, indices, 6);
437 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
438 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
439 buf->getMaterial().setTexture
440 (0, driver->getTexture("../data/player.png"));
441 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
442 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
444 mesh->addMeshBuffer(buf);
446 m_node = smgr->addMeshSceneNode(mesh, NULL);
448 m_node->setPosition(getAbsolutePos());
450 virtual void removeFromScene()
452 //dstream<<"Removing from scene"<<std::endl;
466 //m_subpos = BS*2.0 * v3f(sin(m_subpos_c), sin(m_subpos_c+1.0), sin(-m_subpos_c));
470 //m_node->setPosition(getAbsolutePos() + m_subpos);
471 m_node->setPosition(getAbsolutePos());
476 scene::IMeshSceneNode *m_node;
479 class RatObject : public MovingObject
482 RatObject(MapBlock *block, s16 id, v3f pos):
483 MovingObject(block, id, pos),
486 m_collision_box = new core::aabbox3d<f32>
487 (-BS*0.3,0,-BS*0.3, BS*0.3,BS*0.5,BS*0.3);
488 m_selection_box = new core::aabbox3d<f32>
489 (-BS*0.3,0,-BS*0.3, BS*0.3,BS*0.5,BS*0.3);
496 delete m_collision_box;
497 delete m_selection_box;
501 Implementation interface
503 virtual u16 getTypeId() const
505 return MAPBLOCKOBJECT_TYPE_RAT;
507 virtual void serialize(std::ostream &os, u8 version)
509 MovingObject::serialize(os, version);
513 writeS16(buf, m_yaw * 10);
514 os.write((char*)buf, 2);
517 virtual void update(std::istream &is, u8 version)
519 MovingObject::update(is, version);
523 is.read((char*)buf, 2);
524 s16 yaw_i = readS16(buf);
525 m_yaw = (f32)yaw_i / 10;
530 virtual bool serverStep(float dtime)
532 v3f dir(cos(m_yaw/180*PI),0,sin(m_yaw/180*PI));
536 m_speed.X = speed * dir.X;
537 m_speed.Z = speed * dir.Z;
539 if(m_touching_ground && (m_oldpos - m_pos).getLength() < dtime*speed/2)
553 m_counter2 += (float)(rand()%100)/100*3.0;
554 m_yaw += ((float)(rand()%200)-100)/100*180;
555 m_yaw = wrapDegrees(m_yaw);
563 move(dtime, v3f(0, -9.81*BS, 0));
570 virtual void clientStep(float dtime)
572 m_pos += m_speed * dtime;
577 virtual void addToScene(scene::ISceneManager *smgr)
582 video::IVideoDriver* driver = smgr->getVideoDriver();
584 scene::SMesh *mesh = new scene::SMesh();
585 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
586 video::SColor c(255,255,255,255);
587 video::S3DVertex vertices[4] =
589 video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
590 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
591 video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0),
592 video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 0,0),
594 u16 indices[] = {0,1,2,2,3,0};
595 buf->append(vertices, 4, indices, 6);
597 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
598 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
599 buf->getMaterial().setTexture
600 (0, driver->getTexture("../data/rat.png"));
601 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
602 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
604 mesh->addMeshBuffer(buf);
606 m_node = smgr->addMeshSceneNode(mesh, NULL);
608 m_node->setPosition(getAbsolutePos());
610 virtual void removeFromScene()
619 virtual std::string getInventoryString()
621 // There must be a space after the name
623 return std::string("Rat ");
634 m_node->setPosition(getAbsolutePos());
635 m_node->setRotation(v3f(0, -m_yaw+180, 0));
640 scene::IMeshSceneNode *m_node;
648 class SignObject : public MapBlockObject
651 // The constructor of every MapBlockObject should be like this
652 SignObject(MapBlock *block, s16 id, v3f pos):
653 MapBlockObject(block, id, pos),
656 m_selection_box = new core::aabbox3d<f32>
657 (-BS*0.4,-BS*0.5,-BS*0.4, BS*0.4,BS*0.5,BS*0.4);
659 virtual ~SignObject()
661 delete m_selection_box;
665 Implementation interface
667 virtual u16 getTypeId() const
669 return MAPBLOCKOBJECT_TYPE_SIGN;
671 virtual void serialize(std::ostream &os, u8 version)
673 serializeBase(os, version);
677 writeS16(buf, m_yaw * 10);
678 os.write((char*)buf, 2);
681 writeU16(buf, m_text.size());
682 os.write((char*)buf, 2);
685 os.write(m_text.c_str(), m_text.size());
687 virtual void update(std::istream &is, u8 version)
692 is.read((char*)buf, 2);
693 s16 yaw_i = readS16(buf);
694 m_yaw = (f32)yaw_i / 10;
697 is.read((char*)buf, 2);
698 u16 size = readU16(buf);
702 for(u16 i=0; i<size; i++)
704 is.read((char*)buf, 1);
710 virtual bool serverStep(float dtime)
714 virtual void addToScene(scene::ISceneManager *smgr)
719 video::IVideoDriver* driver = smgr->getVideoDriver();
721 scene::SMesh *mesh = new scene::SMesh();
723 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
724 video::SColor c(255,255,255,255);
725 video::S3DVertex vertices[4] =
727 video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c, 0,1),
728 video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c, 1,1),
729 video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 1,0),
730 video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 0,0),
732 u16 indices[] = {0,1,2,2,3,0};
733 buf->append(vertices, 4, indices, 6);
735 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
736 //buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
737 buf->getMaterial().setTexture
738 (0, driver->getTexture("../data/sign.png"));
739 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
740 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
742 mesh->addMeshBuffer(buf);
746 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
747 video::SColor c(255,255,255,255);
748 video::S3DVertex vertices[4] =
750 video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c, 0,1),
751 video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c, 1,1),
752 video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0),
753 video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 0,0),
755 u16 indices[] = {0,1,2,2,3,0};
756 buf->append(vertices, 4, indices, 6);
758 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
759 //buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
760 buf->getMaterial().setTexture
761 (0, driver->getTexture("../data/sign_back.png"));
762 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
763 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
765 mesh->addMeshBuffer(buf);
768 m_node = smgr->addMeshSceneNode(mesh, NULL);
773 virtual void removeFromScene()
782 virtual std::string infoText()
784 return std::string("\"") + m_text + "\"";
787 virtual std::string getInventoryString()
789 return std::string("Sign ")+m_text;
796 void updateSceneNode()
800 m_node->setPosition(getAbsolutePos());
801 m_node->setRotation(v3f(0, m_yaw, 0));
805 void setText(std::string text)
807 if(text.size() > SIGN_TEXT_MAX_LENGTH)
808 text = text.substr(0, SIGN_TEXT_MAX_LENGTH);
822 scene::IMeshSceneNode *m_node;
827 struct DistanceSortedObject
829 DistanceSortedObject(MapBlockObject *a_obj, f32 a_d)
838 bool operator < (DistanceSortedObject &other)
844 class MapBlockObjectList
847 MapBlockObjectList(MapBlock *block);
848 ~MapBlockObjectList();
849 // Writes the count, id, the type id and the parameters of all objects
850 void serialize(std::ostream &os, u8 version);
851 // Reads ids, type_ids and parameters.
852 // Creates, updates and deletes objects.
853 // If smgr!=NULL, new objects are added to the scene
854 void update(std::istream &is, u8 version, scene::ISceneManager *smgr);
855 // Finds a new unique id
856 s16 getFreeId() throw(ContainerFullException);
859 Set id to -1 to have this set it to a suitable one.
860 The block pointer member is set to this block.
862 void add(MapBlockObject *object)
863 throw(ContainerFullException, AlreadyExistsException);
865 // Deletes and removes all objects
870 Ignores inexistent objects
874 References an object.
875 The object will not be valid after step() or of course if
877 Grabbing the lock is recommended while processing.
879 MapBlockObject * get(s16 id);
881 // You'll want to grab this in a SharedPtr
882 JMutexAutoLock * getLock()
884 return new JMutexAutoLock(m_mutex);
887 // Steps all objects and if server==true, removes those that
888 // want to be removed
889 void step(float dtime, bool server);
891 // Wraps an object that wants to move onto this block from an another
892 // Returns true if wrapping was impossible
893 bool wrapObject(MapBlockObject *object);
895 // origin is relative to block
896 void getObjects(v3f origin, f32 max_d,
897 core::array<DistanceSortedObject> &dest);
902 return m_objects.size();
908 core::map<s16, MapBlockObject*> m_objects;