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"
31 #define MAPBLOCKOBJECT_TYPE_TEST 0
32 #define MAPBLOCKOBJECT_TYPE_TEST2 1
33 #define MAPBLOCKOBJECT_TYPE_SIGN 2
34 #define MAPBLOCKOBJECT_TYPE_RAT 3
35 // Used for handling selecting special stuff
36 //#define MAPBLOCKOBJECT_TYPE_PSEUDO 4
43 MapBlockObject(MapBlock *block, s16 id, v3f pos):
44 m_collision_box(NULL),
45 m_selection_box(NULL),
51 virtual ~MapBlockObject()
64 // Writes id, pos and typeId
65 void serializeBase(std::ostream &os, u8 version)
71 os.write((char*)buf, 2);
74 // stored as x1000/BS v3s16
75 v3s16 pos_i(m_pos.X*1000/BS, m_pos.Y*1000/BS, m_pos.Z*1000/BS);
76 writeV3S16(buf, pos_i);
77 os.write((char*)buf, 6);
80 writeU16(buf, getTypeId());
81 os.write((char*)buf, 2);
84 // Get floating point position on map
87 void setBlockChanged();
89 // Shootline is relative to block
90 bool isSelected(core::line3d<f32> shootline)
92 if(m_selection_box == NULL)
95 core::aabbox3d<f32> offsetted_box(
96 m_selection_box->MinEdge + m_pos,
97 m_selection_box->MaxEdge + m_pos
100 return offsetted_box.intersectsWithLine(shootline);
103 core::aabbox3d<f32> getSelectionBoxOnMap()
105 v3f absolute_pos = getAbsolutePos();
107 core::aabbox3d<f32> box(
108 m_selection_box->MinEdge + absolute_pos,
109 m_selection_box->MaxEdge + absolute_pos
116 Implementation interface
119 virtual u16 getTypeId() const = 0;
120 // Shall call serializeBase and then write the parameters
121 virtual void serialize(std::ostream &os, u8 version) = 0;
122 // Shall read parameters from stream
123 virtual void update(std::istream &is, u8 version) = 0;
125 virtual std::string getInventoryString() { return "None"; }
127 // Reimplementation shall call this.
128 virtual void updatePos(v3f pos)
133 // Shall move the object around, modify it and possibly delete it.
134 // Typical dtimes are 0.2 and 10000.
135 // A return value of true requests deletion of the object by the caller.
136 // NOTE: Only server calls this.
137 virtual bool serverStep(float dtime) { return false; };
138 // This should do slight animations only or so
139 virtual void clientStep(float dtime) {};
141 // NOTE: These functions should do nothing if the asked state is
142 // same as the current state
143 // Shall add and remove relevant scene nodes for rendering the
144 // object in the game world
145 virtual void addToScene(scene::ISceneManager *smgr) {};
146 // Shall remove stuff from the scene
147 // Should return silently if there is nothing to remove
148 // NOTE: This has to be called before calling destructor
149 virtual void removeFromScene() {};
151 virtual std::string infoText() { return ""; }
153 // Shall be left NULL if doesn't collide
154 // Position is relative to m_pos in block
155 core::aabbox3d<f32> * m_collision_box;
157 // Shall be left NULL if can't be selected
158 core::aabbox3d<f32> * m_selection_box;
162 // This differentiates the instance of the object
163 // Not same as typeId.
165 // Position of the object inside the block
166 // Units is node coordinates * BS
169 friend class MapBlockObjectList;
174 Used for handling selections of special stuff
176 class PseudoMBObject : public MapBlockObject
179 // The constructor of every MapBlockObject should be like this
180 PseudoMBObject(MapBlock *block, s16 id, v3f pos):
181 MapBlockObject(block, id, pos)
184 virtual ~PseudoMBObject()
187 delete m_selection_box;
191 Implementation interface
193 virtual u16 getTypeId() const
195 return MAPBLOCKOBJECT_TYPE_PSEUDO;
197 virtual void serialize(std::ostream &os, u8 version)
201 virtual void update(std::istream &is, u8 version)
205 virtual bool serverStep(float dtime)
214 void setSelectionBox(core::aabbox3d<f32> box)
216 m_selection_box = new core::aabbox3d<f32>(box);
223 class TestObject : public MapBlockObject
226 // The constructor of every MapBlockObject should be like this
227 TestObject(MapBlock *block, s16 id, v3f pos):
228 MapBlockObject(block, id, pos),
232 virtual ~TestObject()
237 Implementation interface
239 virtual u16 getTypeId() const
241 return MAPBLOCKOBJECT_TYPE_TEST;
243 virtual void serialize(std::ostream &os, u8 version)
245 serializeBase(os, version);
247 // Write subpos_c * 100
249 writeU16(buf, m_subpos_c * 100);
250 os.write((char*)buf, 2);
252 virtual void update(std::istream &is, u8 version)
254 // Read subpos_c * 100
256 is.read((char*)buf, 2);
257 m_subpos_c = (f32)readU16(buf) / 100;
261 virtual bool serverStep(float dtime)
263 m_subpos_c += dtime * 3.0;
269 virtual void addToScene(scene::ISceneManager *smgr)
274 //dstream<<"Adding to scene"<<std::endl;
276 video::IVideoDriver* driver = smgr->getVideoDriver();
278 scene::SMesh *mesh = new scene::SMesh();
279 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
280 video::SColor c(255,255,255,255);
281 video::S3DVertex vertices[4] =
283 video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
284 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
285 video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0),
286 video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0),
288 u16 indices[] = {0,1,2,2,3,0};
289 buf->append(vertices, 4, indices, 6);
291 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
292 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
293 buf->getMaterial().setTexture
294 (0, driver->getTexture("../data/player.png"));
295 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
296 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
298 mesh->addMeshBuffer(buf);
300 m_node = smgr->addMeshSceneNode(mesh, NULL);
302 m_node->setPosition(getAbsolutePos());
304 virtual void removeFromScene()
306 //dstream<<"Removing from scene"<<std::endl;
320 m_subpos = BS*2.0 * v3f(sin(m_subpos_c), sin(m_subpos_c+1.0), sin(-m_subpos_c));
324 m_node->setPosition(getAbsolutePos() + m_subpos);
329 scene::IMeshSceneNode *m_node;
336 class MovingObject : public MapBlockObject
339 // The constructor of every MapBlockObject should be like this
340 MovingObject(MapBlock *block, s16 id, v3f pos):
341 MapBlockObject(block, id, pos),
344 m_touching_ground = false;
346 virtual ~MovingObject()
351 Implementation interface
354 virtual u16 getTypeId() const = 0;
356 virtual void serialize(std::ostream &os, u8 version)
358 serializeBase(os, version);
363 // stored as x100/BS v3s16
364 v3s16 speed_i(m_speed.X*100/BS, m_speed.Y*100/BS, m_speed.Z*100/BS);
365 writeV3S16(buf, speed_i);
366 os.write((char*)buf, 6);
368 virtual void update(std::istream &is, u8 version)
373 // stored as x100/BS v3s16
374 is.read((char*)buf, 6);
375 v3s16 speed_i = readV3S16(buf);
376 v3f speed((f32)speed_i.X/100*BS,
377 (f32)speed_i.Y/100*BS,
378 (f32)speed_i.Z/100*BS);
383 virtual bool serverStep(float dtime) { return false; };
384 virtual void clientStep(float dtime) {};
386 virtual void addToScene(scene::ISceneManager *smgr) = 0;
387 virtual void removeFromScene() = 0;
393 // Moves with collision detection
394 void move(float dtime, v3f acceleration);
398 bool m_touching_ground;
401 class Test2Object : public MovingObject
404 // The constructor of every MapBlockObject should be like this
405 Test2Object(MapBlock *block, s16 id, v3f pos):
406 MovingObject(block, id, pos),
409 m_collision_box = new core::aabbox3d<f32>
410 (-BS*0.3,0,-BS*0.3, BS*0.3,BS*1.7,BS*0.3);
412 virtual ~Test2Object()
414 delete m_collision_box;
418 Implementation interface
420 virtual u16 getTypeId() const
422 return MAPBLOCKOBJECT_TYPE_TEST2;
424 virtual void serialize(std::ostream &os, u8 version)
426 MovingObject::serialize(os, version);
428 virtual void update(std::istream &is, u8 version)
430 MovingObject::update(is, version);
435 virtual bool serverStep(float dtime)
440 if(m_touching_ground)
442 static float count = 0;
451 move(dtime, v3f(0, -9.81*BS, 0));
458 virtual void clientStep(float dtime)
460 m_pos += m_speed * dtime;
465 virtual void addToScene(scene::ISceneManager *smgr)
470 //dstream<<"Adding to scene"<<std::endl;
472 video::IVideoDriver* driver = smgr->getVideoDriver();
474 scene::SMesh *mesh = new scene::SMesh();
475 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
476 video::SColor c(255,255,255,255);
477 video::S3DVertex vertices[4] =
479 video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
480 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
481 video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0),
482 video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0),
484 u16 indices[] = {0,1,2,2,3,0};
485 buf->append(vertices, 4, indices, 6);
487 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
488 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
489 buf->getMaterial().setTexture
490 (0, driver->getTexture("../data/player.png"));
491 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
492 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
494 mesh->addMeshBuffer(buf);
496 m_node = smgr->addMeshSceneNode(mesh, NULL);
498 m_node->setPosition(getAbsolutePos());
500 virtual void removeFromScene()
502 //dstream<<"Removing from scene"<<std::endl;
516 //m_subpos = BS*2.0 * v3f(sin(m_subpos_c), sin(m_subpos_c+1.0), sin(-m_subpos_c));
520 //m_node->setPosition(getAbsolutePos() + m_subpos);
521 m_node->setPosition(getAbsolutePos());
526 scene::IMeshSceneNode *m_node;
529 class RatObject : public MovingObject
532 RatObject(MapBlock *block, s16 id, v3f pos):
533 MovingObject(block, id, pos),
536 m_collision_box = new core::aabbox3d<f32>
537 (-BS*0.3,0,-BS*0.3, BS*0.3,BS*0.5,BS*0.3);
538 m_selection_box = new core::aabbox3d<f32>
539 (-BS*0.3,0,-BS*0.3, BS*0.3,BS*0.5,BS*0.3);
546 delete m_collision_box;
547 delete m_selection_box;
551 Implementation interface
553 virtual u16 getTypeId() const
555 return MAPBLOCKOBJECT_TYPE_RAT;
557 virtual void serialize(std::ostream &os, u8 version)
559 MovingObject::serialize(os, version);
563 writeS16(buf, m_yaw * 10);
564 os.write((char*)buf, 2);
567 virtual void update(std::istream &is, u8 version)
569 MovingObject::update(is, version);
573 is.read((char*)buf, 2);
574 s16 yaw_i = readS16(buf);
575 m_yaw = (f32)yaw_i / 10;
580 virtual bool serverStep(float dtime)
582 v3f dir(cos(m_yaw/180*PI),0,sin(m_yaw/180*PI));
586 m_speed.X = speed * dir.X;
587 m_speed.Z = speed * dir.Z;
589 if(m_touching_ground && (m_oldpos - m_pos).getLength() < dtime*speed/2)
603 m_counter2 += (float)(rand()%100)/100*3.0;
604 m_yaw += ((float)(rand()%200)-100)/100*180;
605 m_yaw = wrapDegrees(m_yaw);
613 move(dtime, v3f(0, -9.81*BS, 0));
620 virtual void clientStep(float dtime)
622 m_pos += m_speed * dtime;
627 virtual void addToScene(scene::ISceneManager *smgr)
632 video::IVideoDriver* driver = smgr->getVideoDriver();
634 scene::SMesh *mesh = new scene::SMesh();
635 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
636 video::SColor c(255,255,255,255);
637 video::S3DVertex vertices[4] =
639 video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
640 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
641 video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0),
642 video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 0,0),
644 u16 indices[] = {0,1,2,2,3,0};
645 buf->append(vertices, 4, indices, 6);
647 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
648 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
649 buf->getMaterial().setTexture
650 (0, driver->getTexture("../data/rat.png"));
651 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
652 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
654 mesh->addMeshBuffer(buf);
656 m_node = smgr->addMeshSceneNode(mesh, NULL);
658 m_node->setPosition(getAbsolutePos());
660 virtual void removeFromScene()
669 virtual std::string getInventoryString()
671 // There must be a space after the name
673 return std::string("Rat ");
684 m_node->setPosition(getAbsolutePos());
685 m_node->setRotation(v3f(0, -m_yaw+180, 0));
690 scene::IMeshSceneNode *m_node;
698 class SignObject : public MapBlockObject
701 // The constructor of every MapBlockObject should be like this
702 SignObject(MapBlock *block, s16 id, v3f pos):
703 MapBlockObject(block, id, pos),
706 m_selection_box = new core::aabbox3d<f32>
707 (-BS*0.4,-BS*0.5,-BS*0.4, BS*0.4,BS*0.5,BS*0.4);
709 virtual ~SignObject()
711 delete m_selection_box;
715 Implementation interface
717 virtual u16 getTypeId() const
719 return MAPBLOCKOBJECT_TYPE_SIGN;
721 virtual void serialize(std::ostream &os, u8 version)
723 serializeBase(os, version);
727 writeS16(buf, m_yaw * 10);
728 os.write((char*)buf, 2);
731 writeU16(buf, m_text.size());
732 os.write((char*)buf, 2);
735 os.write(m_text.c_str(), m_text.size());
737 virtual void update(std::istream &is, u8 version)
742 is.read((char*)buf, 2);
743 s16 yaw_i = readS16(buf);
744 m_yaw = (f32)yaw_i / 10;
747 is.read((char*)buf, 2);
748 u16 size = readU16(buf);
752 for(u16 i=0; i<size; i++)
754 is.read((char*)buf, 1);
760 virtual bool serverStep(float dtime)
764 virtual void addToScene(scene::ISceneManager *smgr)
769 video::IVideoDriver* driver = smgr->getVideoDriver();
771 scene::SMesh *mesh = new scene::SMesh();
773 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
774 video::SColor c(255,255,255,255);
775 video::S3DVertex vertices[4] =
777 video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c, 0,1),
778 video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c, 1,1),
779 video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 1,0),
780 video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 0,0),
782 u16 indices[] = {0,1,2,2,3,0};
783 buf->append(vertices, 4, indices, 6);
785 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
786 //buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
787 buf->getMaterial().setTexture
788 (0, driver->getTexture("../data/sign.png"));
789 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
790 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
792 mesh->addMeshBuffer(buf);
796 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
797 video::SColor c(255,255,255,255);
798 video::S3DVertex vertices[4] =
800 video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c, 0,1),
801 video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c, 1,1),
802 video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0),
803 video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 0,0),
805 u16 indices[] = {0,1,2,2,3,0};
806 buf->append(vertices, 4, indices, 6);
808 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
809 //buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
810 buf->getMaterial().setTexture
811 (0, driver->getTexture("../data/sign_back.png"));
812 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
813 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
815 mesh->addMeshBuffer(buf);
818 m_node = smgr->addMeshSceneNode(mesh, NULL);
823 virtual void removeFromScene()
832 virtual std::string infoText()
834 return std::string("\"") + m_text + "\"";
837 virtual std::string getInventoryString()
839 return std::string("Sign ")+m_text;
846 void updateSceneNode()
850 m_node->setPosition(getAbsolutePos());
851 m_node->setRotation(v3f(0, m_yaw, 0));
855 void setText(std::string text)
857 if(text.size() > SIGN_TEXT_MAX_LENGTH)
858 text = text.substr(0, SIGN_TEXT_MAX_LENGTH);
872 scene::IMeshSceneNode *m_node;
877 struct DistanceSortedObject
879 DistanceSortedObject(MapBlockObject *a_obj, f32 a_d)
888 bool operator < (DistanceSortedObject &other)
894 class MapBlockObjectList
897 MapBlockObjectList(MapBlock *block);
898 ~MapBlockObjectList();
899 // Writes the count, id, the type id and the parameters of all objects
900 void serialize(std::ostream &os, u8 version);
901 // Reads ids, type_ids and parameters.
902 // Creates, updates and deletes objects.
903 // If smgr!=NULL, new objects are added to the scene
904 void update(std::istream &is, u8 version, scene::ISceneManager *smgr);
905 // Finds a new unique id
906 s16 getFreeId() throw(ContainerFullException);
909 Set id to -1 to have this set it to a suitable one.
910 The block pointer member is set to this block.
912 void add(MapBlockObject *object)
913 throw(ContainerFullException, AlreadyExistsException);
915 // Deletes and removes all objects
920 Ignores inexistent objects
924 References an object.
925 The object will not be valid after step() or of course if
927 Grabbing the lock is recommended while processing.
929 MapBlockObject * get(s16 id);
931 // You'll want to grab this in a SharedPtr
932 JMutexAutoLock * getLock()
934 return new JMutexAutoLock(m_mutex);
937 // Steps all objects and if server==true, removes those that
938 // want to be removed
939 void step(float dtime, bool server);
941 // Wraps an object that wants to move onto this block from an another
942 // Returns true if wrapping was impossible
943 bool wrapObject(MapBlockObject *object);
945 // origin is relative to block
946 void getObjects(v3f origin, f32 max_d,
947 core::array<DistanceSortedObject> &dest);
952 return m_objects.size();
958 core::map<s16, MapBlockObject*> m_objects;