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_PLAYER 0
32 #define MAPBLOCKOBJECT_TYPE_SIGN 2
33 #define MAPBLOCKOBJECT_TYPE_RAT 3
34 #define MAPBLOCKOBJECT_TYPE_ITEM 4
35 // Used for handling selecting special stuff
36 //#define MAPBLOCKOBJECT_TYPE_PSEUDO 1000
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 // Position where the object is drawn relative to block
85 virtual v3f getRelativeShowPos()
89 // Get floating point position on map
92 void setBlockChanged();
94 // Shootline is relative to block
95 bool isSelected(core::line3d<f32> shootline)
97 if(m_selection_box == NULL)
100 core::aabbox3d<f32> offsetted_box(
101 m_selection_box->MinEdge + m_pos,
102 m_selection_box->MaxEdge + m_pos
105 return offsetted_box.intersectsWithLine(shootline);
108 core::aabbox3d<f32> getSelectionBoxOnMap()
110 v3f absolute_pos = getAbsolutePos();
112 core::aabbox3d<f32> box(
113 m_selection_box->MinEdge + absolute_pos,
114 m_selection_box->MaxEdge + absolute_pos
121 Implementation interface
124 virtual u16 getTypeId() const = 0;
125 // Shall call serializeBase and then write the parameters
126 virtual void serialize(std::ostream &os, u8 version) = 0;
127 // Shall read parameters from stream
128 virtual void update(std::istream &is, u8 version) = 0;
130 virtual std::string getInventoryString() { return "None"; }
132 // Reimplementation shall call this.
133 virtual void updatePos(v3f pos)
138 // Shall move the object around, modify it and possibly delete it.
139 // Typical dtimes are 0.2 and 10000.
140 // A return value of true requests deletion of the object by the caller.
141 // NOTE: Only server calls this.
142 virtual bool serverStep(float dtime, u32 daynight_ratio)
146 void clientStep(float dtime) {};
147 void addToScene(void *smgr) {};
148 void removeFromScene() {};
149 void updateLight(u8 light_at_pos) {};
151 // This should do slight animations only or so
152 virtual void clientStep(float dtime) {};
154 // NOTE: These functions should do nothing if the asked state is
155 // same as the current state
156 // Shall add and remove relevant scene nodes for rendering the
157 // object in the game world
158 virtual void addToScene(scene::ISceneManager *smgr) = 0;
159 // Shall remove stuff from the scene
160 // Should return silently if there is nothing to remove
161 // NOTE: This has to be called before calling destructor
162 virtual void removeFromScene() = 0;
164 // 0 <= light_at_pos <= LIGHT_SUN
165 virtual void updateLight(u8 light_at_pos) {};
168 virtual std::string infoText() { return ""; }
170 // Shall be left NULL if doesn't collide
171 // Position is relative to m_pos in block
172 core::aabbox3d<f32> * m_collision_box;
174 // Shall be left NULL if can't be selected
175 core::aabbox3d<f32> * m_selection_box;
179 // This differentiates the instance of the object
180 // Not same as typeId.
182 // Position of the object inside the block
183 // Units is node coordinates * BS
186 friend class MapBlockObjectList;
191 Used for handling selections of special stuff
193 class PseudoMBObject : public MapBlockObject
196 // The constructor of every MapBlockObject should be like this
197 PseudoMBObject(MapBlock *block, s16 id, v3f pos):
198 MapBlockObject(block, id, pos)
201 virtual ~PseudoMBObject()
204 delete m_selection_box;
208 Implementation interface
210 virtual u16 getTypeId() const
212 return MAPBLOCKOBJECT_TYPE_PSEUDO;
214 virtual void serialize(std::ostream &os, u8 version)
218 virtual void update(std::istream &is, u8 version)
222 virtual bool serverStep(float dtime, u32 daynight_ratio)
231 void setSelectionBox(core::aabbox3d<f32> box)
233 m_selection_box = new core::aabbox3d<f32>(box);
240 class MovingObject : public MapBlockObject
243 // The constructor of every MapBlockObject should be like this
244 MovingObject(MapBlock *block, s16 id, v3f pos):
245 MapBlockObject(block, id, pos),
248 m_pos_animation_time(0),
251 m_touching_ground = false;
253 virtual ~MovingObject()
258 Implementation interface
261 virtual u16 getTypeId() const = 0;
263 virtual void serialize(std::ostream &os, u8 version)
265 serializeBase(os, version);
270 // stored as x100/BS v3s16
271 v3s16 speed_i(m_speed.X*100/BS, m_speed.Y*100/BS, m_speed.Z*100/BS);
272 writeV3S16(buf, speed_i);
273 os.write((char*)buf, 6);
275 virtual void update(std::istream &is, u8 version)
280 // stored as x100/BS v3s16
281 is.read((char*)buf, 6);
282 v3s16 speed_i = readV3S16(buf);
283 v3f speed((f32)speed_i.X/100*BS,
284 (f32)speed_i.Y/100*BS,
285 (f32)speed_i.Z/100*BS);
290 // Reimplementation shall call this.
291 virtual void updatePos(v3f pos)
293 m_oldpos = m_showpos;
296 if(m_pos_animation_time < 0.001 || m_pos_animation_time > 1.0)
297 m_pos_animation_time = m_pos_animation_time_counter;
299 m_pos_animation_time = m_pos_animation_time * 0.9
300 + m_pos_animation_time_counter * 0.1;
301 m_pos_animation_time_counter = 0;
302 m_pos_animation_counter = 0;
305 // Position where the object is drawn relative to block
306 virtual v3f getRelativeShowPos()
310 // Returns m_showpos relative to whole map
311 v3f getAbsoluteShowPos();
313 virtual bool serverStep(float dtime, u32 daynight_ratio)
315 virtual void clientStep(float dtime)
318 /*virtual void addToScene(scene::ISceneManager *smgr) = 0;
319 virtual void removeFromScene() = 0;*/
325 // Move with collision detection, server side
326 void move(float dtime, v3f acceleration);
328 // Move from old position to new position, client side
329 void simpleMove(float dtime);
333 bool m_touching_ground;
334 // Client-side moving
336 f32 m_pos_animation_counter;
337 f32 m_pos_animation_time;
338 f32 m_pos_animation_time_counter;
342 class SignObject : public MapBlockObject
345 // The constructor of every MapBlockObject should be like this
346 SignObject(MapBlock *block, s16 id, v3f pos):
347 MapBlockObject(block, id, pos),
350 m_selection_box = new core::aabbox3d<f32>
351 (-BS*0.4,-BS*0.5,-BS*0.4, BS*0.4,BS*0.5,BS*0.4);
353 virtual ~SignObject()
355 delete m_selection_box;
359 Implementation interface
361 virtual u16 getTypeId() const
363 return MAPBLOCKOBJECT_TYPE_SIGN;
365 virtual void serialize(std::ostream &os, u8 version)
367 serializeBase(os, version);
371 writeS16(buf, m_yaw * 10);
372 os.write((char*)buf, 2);
375 writeU16(buf, m_text.size());
376 os.write((char*)buf, 2);
379 os.write(m_text.c_str(), m_text.size());
381 virtual void update(std::istream &is, u8 version)
386 is.read((char*)buf, 2);
387 s16 yaw_i = readS16(buf);
388 m_yaw = (f32)yaw_i / 10;
391 is.read((char*)buf, 2);
392 u16 size = readU16(buf);
396 for(u16 i=0; i<size; i++)
398 is.read((char*)buf, 1);
404 virtual bool serverStep(float dtime, u32 daynight_ratio)
409 virtual void addToScene(scene::ISceneManager *smgr)
414 video::IVideoDriver* driver = smgr->getVideoDriver();
416 scene::SMesh *mesh = new scene::SMesh();
418 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
419 video::SColor c(255,255,255,255);
420 video::S3DVertex vertices[4] =
422 video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c, 0,1),
423 video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c, 1,1),
424 video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 1,0),
425 video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 0,0),
427 u16 indices[] = {0,1,2,2,3,0};
428 buf->append(vertices, 4, indices, 6);
430 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
431 //buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
432 buf->getMaterial().setTexture
433 (0, driver->getTexture(porting::getDataPath("sign.png").c_str()));
434 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
435 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
436 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
438 mesh->addMeshBuffer(buf);
442 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
443 video::SColor c(255,255,255,255);
444 video::S3DVertex vertices[4] =
446 video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c, 0,1),
447 video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c, 1,1),
448 video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0),
449 video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 0,0),
451 u16 indices[] = {0,1,2,2,3,0};
452 buf->append(vertices, 4, indices, 6);
454 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
455 //buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
456 buf->getMaterial().setTexture
457 (0, driver->getTexture(porting::getDataPath("sign_back.png").c_str()));
458 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
459 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
460 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
462 mesh->addMeshBuffer(buf);
465 m_node = smgr->addMeshSceneNode(mesh, NULL);
470 virtual void removeFromScene()
478 virtual void updateLight(u8 light_at_pos)
483 u8 li = decode_light(light_at_pos);
484 video::SColor color(255,li,li,li);
486 scene::IMesh *mesh = m_node->getMesh();
488 u16 mc = mesh->getMeshBufferCount();
489 for(u16 j=0; j<mc; j++)
491 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
492 video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
493 u16 vc = buf->getVertexCount();
494 for(u16 i=0; i<vc; i++)
496 vertices[i].Color = color;
502 virtual std::string infoText()
504 return std::string("\"") + m_text + "\"";
507 virtual std::string getInventoryString()
509 return std::string("Sign ")+m_text;
515 void updateSceneNode()
520 m_node->setPosition(getAbsolutePos());
521 m_node->setRotation(v3f(0, m_yaw, 0));
526 void setText(std::string text)
528 if(text.size() > SIGN_TEXT_MAX_LENGTH)
529 text = text.substr(0, SIGN_TEXT_MAX_LENGTH);
535 std::string getText()
548 scene::IMeshSceneNode *m_node;
553 class RatObject : public MovingObject
556 RatObject(MapBlock *block, s16 id, v3f pos):
557 MovingObject(block, id, pos),
560 m_collision_box = new core::aabbox3d<f32>
561 (-BS*0.3,-BS*.25,-BS*0.3, BS*0.3,BS*0.25,BS*0.3);
562 m_selection_box = new core::aabbox3d<f32>
563 (-BS*0.3,-BS*.25,-BS*0.3, BS*0.3,BS*0.25,BS*0.3);
571 delete m_collision_box;
572 delete m_selection_box;
576 Implementation interface
578 virtual u16 getTypeId() const
580 return MAPBLOCKOBJECT_TYPE_RAT;
582 virtual void serialize(std::ostream &os, u8 version)
584 MovingObject::serialize(os, version);
588 writeS16(buf, m_yaw * 10);
589 os.write((char*)buf, 2);
592 virtual void update(std::istream &is, u8 version)
594 MovingObject::update(is, version);
598 is.read((char*)buf, 2);
599 s16 yaw_i = readS16(buf);
600 m_yaw = (f32)yaw_i / 10;
605 virtual bool serverStep(float dtime, u32 daynight_ratio)
612 v3f dir(cos(m_yaw/180*PI),0,sin(m_yaw/180*PI));
616 m_speed.X = speed * dir.X;
617 m_speed.Z = speed * dir.Z;
619 if(m_touching_ground && (m_oldpos - m_pos).getLength() < dtime*speed/2)
633 m_counter2 += (float)(myrand()%100)/100*3.0;
634 m_yaw += ((float)(myrand()%200)-100)/100*180;
635 m_yaw = wrapDegrees(m_yaw);
643 move(dtime, v3f(0, -9.81*BS, 0));
650 virtual void clientStep(float dtime)
652 //m_pos += m_speed * dtime;
653 MovingObject::simpleMove(dtime);
658 virtual void addToScene(scene::ISceneManager *smgr);
660 virtual void removeFromScene()
669 virtual void updateLight(u8 light_at_pos)
674 u8 li = decode_light(light_at_pos);
675 video::SColor color(255,li,li,li);
677 scene::IMesh *mesh = m_node->getMesh();
679 u16 mc = mesh->getMeshBufferCount();
680 for(u16 j=0; j<mc; j++)
682 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
683 video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
684 u16 vc = buf->getVertexCount();
685 for(u16 i=0; i<vc; i++)
687 vertices[i].Color = color;
694 virtual std::string getInventoryString()
696 // There must be a space after the name
698 return std::string("Rat ");
710 m_node->setPosition(getAbsoluteShowPos());
711 m_node->setRotation(v3f(0, -m_yaw+180, 0));
715 scene::IMeshSceneNode *m_node;
724 An object on the map that represents an inventory item
729 class ItemObject : public MapBlockObject
732 // The constructor of every MapBlockObject should be like this
733 ItemObject(MapBlock *block, s16 id, v3f pos):
734 MapBlockObject(block, id, pos),
737 /*m_selection_box = new core::aabbox3d<f32>
738 (-BS*0.4,-BS*0.5,-BS*0.4, BS*0.4,BS*0.5,BS*0.4);*/
739 m_selection_box = new core::aabbox3d<f32>
740 (-BS/3,-BS/2,-BS/3, BS/3,-BS/2+BS*2/3,BS/3);
743 virtual ~ItemObject()
745 delete m_selection_box;
749 Implementation interface
751 virtual u16 getTypeId() const
753 return MAPBLOCKOBJECT_TYPE_ITEM;
755 virtual void serialize(std::ostream &os, u8 version)
757 serializeBase(os, version);
761 writeU16(buf, m_itemstring.size());
762 os.write((char*)buf, 2);
765 os.write(m_itemstring.c_str(), m_itemstring.size());
767 virtual void update(std::istream &is, u8 version)
772 is.read((char*)buf, 2);
773 u16 size = readU16(buf);
776 std::string old_itemstring = m_itemstring;
777 m_itemstring.clear();
778 for(u16 i=0; i<size; i++)
780 is.read((char*)buf, 1);
781 m_itemstring += buf[0];
785 if(m_itemstring != old_itemstring && m_node)
790 video::ITexture *texture = getItemImage();
791 scene::IMesh *mesh = m_node->getMesh();
792 if(mesh->getMeshBufferCount() >= 1)
794 scene::IMeshBuffer *buf = mesh->getMeshBuffer(0);
795 //dstream<<"Setting texture "<<texture<<std::endl;
796 buf->getMaterial().setTexture(0, texture);
804 virtual bool serverStep(float dtime, u32 daynight_ratio)
810 virtual void clientStep(float dtime)
819 virtual void addToScene(scene::ISceneManager *smgr);
821 virtual void removeFromScene()
829 virtual void updateLight(u8 light_at_pos)
834 u8 li = decode_light(light_at_pos);
835 video::SColor color(255,li,li,li);
837 scene::IMesh *mesh = m_node->getMesh();
839 u16 mc = mesh->getMeshBufferCount();
840 for(u16 j=0; j<mc; j++)
842 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
843 video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
844 u16 vc = buf->getVertexCount();
845 for(u16 i=0; i<vc; i++)
847 vertices[i].Color = color;
853 virtual std::string infoText()
855 return std::string("\"") + m_itemstring + "\"";
858 virtual std::string getInventoryString()
860 return std::string("ItemObj ")+m_itemstring;
867 InventoryItem * createInventoryItem();
870 video::ITexture * getItemImage();
872 void updateSceneNode()
876 m_node->setPosition(getAbsolutePos());
877 m_node->setRotation(v3f(0, m_yaw, 0));
882 void setItemString(std::string inventorystring)
884 m_itemstring = inventorystring;
888 std::string getItemString()
894 scene::IMeshSceneNode *m_node;
895 std::string m_itemstring;
902 class PlayerObject : public MovingObject
905 PlayerObject(MapBlock *block, s16 id, v3f pos):
906 MovingObject(block, id, pos),
909 m_collision_box = new core::aabbox3d<f32>
910 (-BS*0.3,-BS*.25,-BS*0.3, BS*0.3,BS*0.25,BS*0.3);
911 /*m_selection_box = new core::aabbox3d<f32>
912 (-BS*0.3,-BS*.25,-BS*0.3, BS*0.3,BS*0.25,BS*0.3);*/
914 virtual ~PlayerObject()
917 delete m_collision_box;
919 delete m_selection_box;
923 Implementation interface
925 virtual u16 getTypeId() const
927 return MAPBLOCKOBJECT_TYPE_PLAYER;
929 virtual void serialize(std::ostream &os, u8 version)
931 // Object data is generated from actual player
933 virtual void update(std::istream &is, u8 version)
935 MovingObject::update(is, version);
939 is.read((char*)buf, 2);
940 s16 yaw_i = readS16(buf);
941 m_yaw = (f32)yaw_i / 10;
946 virtual bool serverStep(float dtime, u32 daynight_ratio)
948 // Player is handled elsewhere.
951 // Actually, fail very loudly:
956 virtual void clientStep(float dtime)
958 MovingObject::simpleMove(dtime);
963 virtual void addToScene(scene::ISceneManager *smgr);
965 virtual void removeFromScene()
974 virtual void updateLight(u8 light_at_pos)
979 u8 li = decode_light(light_at_pos);
980 video::SColor color(255,li,li,li);
982 scene::IMesh *mesh = m_node->getMesh();
984 u16 mc = mesh->getMeshBufferCount();
985 for(u16 j=0; j<mc; j++)
987 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
988 video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
989 u16 vc = buf->getVertexCount();
990 for(u16 i=0; i<vc; i++)
992 vertices[i].Color = color;
1003 void updateNodePos()
1008 m_node->setPosition(getAbsoluteShowPos());
1009 m_node->setRotation(v3f(0, -m_yaw+180, 0));
1013 scene::IMeshSceneNode *m_node;
1019 struct DistanceSortedObject
1021 DistanceSortedObject(MapBlockObject *a_obj, f32 a_d)
1027 MapBlockObject *obj;
1030 bool operator < (DistanceSortedObject &other)
1036 class MapBlockObjectList
1039 MapBlockObjectList(MapBlock *block);
1040 ~MapBlockObjectList();
1042 // Writes the count, id, the type id and the parameters of all objects
1043 void serialize(std::ostream &os, u8 version);
1045 // Reads ids, type_ids and parameters.
1046 // Creates, updates and deletes objects.
1047 // If smgr!=NULL, new objects are added to the scene
1048 void update(std::istream &is, u8 version, scene::ISceneManager *smgr,
1049 u32 daynight_ratio);
1051 // Finds a new unique id
1052 s16 getFreeId() throw(ContainerFullException);
1055 Set id to -1 to have this set it to a suitable one.
1056 The block pointer member is set to this block.
1058 void add(MapBlockObject *object)
1059 throw(ContainerFullException, AlreadyExistsException);
1061 // Deletes and removes all objects
1066 Ignores inexistent objects
1068 void remove(s16 id);
1070 References an object.
1071 The object will not be valid after step() or of course if
1073 Grabbing the lock is recommended while processing.
1075 MapBlockObject * get(s16 id);
1077 // You'll want to grab this in a SharedPtr
1078 JMutexAutoLock * getLock()
1080 return new JMutexAutoLock(m_mutex);
1083 // Steps all objects and if server==true, removes those that
1084 // want to be removed
1085 void step(float dtime, bool server, u32 daynight_ratio);
1087 // Wraps an object that wants to move onto this block from an another
1088 // Returns true if wrapping was impossible
1089 bool wrapObject(MapBlockObject *object);
1091 // origin is relative to block
1092 void getObjects(v3f origin, f32 max_d,
1093 core::array<DistanceSortedObject> &dest);
1095 // Number of objects
1098 return m_objects.size();
1104 core::map<s16, MapBlockObject*> m_objects;
1107 u32 m_last_update_daynight_ratio;