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 // Used for handling selecting special stuff
35 //#define MAPBLOCKOBJECT_TYPE_PSEUDO 1000
42 MapBlockObject(MapBlock *block, s16 id, v3f pos):
43 m_collision_box(NULL),
44 m_selection_box(NULL),
50 virtual ~MapBlockObject()
63 // Writes id, pos and typeId
64 void serializeBase(std::ostream &os, u8 version)
70 os.write((char*)buf, 2);
73 // stored as x1000/BS v3s16
74 v3s16 pos_i(m_pos.X*1000/BS, m_pos.Y*1000/BS, m_pos.Z*1000/BS);
75 writeV3S16(buf, pos_i);
76 os.write((char*)buf, 6);
79 writeU16(buf, getTypeId());
80 os.write((char*)buf, 2);
83 // Position where the object is drawn relative to block
84 virtual v3f getRelativeShowPos()
88 // Get floating point position on map
91 void setBlockChanged();
93 // Shootline is relative to block
94 bool isSelected(core::line3d<f32> shootline)
96 if(m_selection_box == NULL)
99 core::aabbox3d<f32> offsetted_box(
100 m_selection_box->MinEdge + m_pos,
101 m_selection_box->MaxEdge + m_pos
104 return offsetted_box.intersectsWithLine(shootline);
107 core::aabbox3d<f32> getSelectionBoxOnMap()
109 v3f absolute_pos = getAbsolutePos();
111 core::aabbox3d<f32> box(
112 m_selection_box->MinEdge + absolute_pos,
113 m_selection_box->MaxEdge + absolute_pos
120 Implementation interface
123 virtual u16 getTypeId() const = 0;
124 // Shall call serializeBase and then write the parameters
125 virtual void serialize(std::ostream &os, u8 version) = 0;
126 // Shall read parameters from stream
127 virtual void update(std::istream &is, u8 version) = 0;
129 virtual std::string getInventoryString() { return "None"; }
131 // Reimplementation shall call this.
132 virtual void updatePos(v3f pos)
137 // Shall move the object around, modify it and possibly delete it.
138 // Typical dtimes are 0.2 and 10000.
139 // A return value of true requests deletion of the object by the caller.
140 // NOTE: Only server calls this.
141 virtual bool serverStep(float dtime, u32 daynight_ratio)
145 void clientStep(float dtime) {};
146 void addToScene(void *smgr) {};
147 void removeFromScene() {};
148 void updateLight(u8 light_at_pos) {};
150 // This should do slight animations only or so
151 virtual void clientStep(float dtime) {};
153 // NOTE: These functions should do nothing if the asked state is
154 // same as the current state
155 // Shall add and remove relevant scene nodes for rendering the
156 // object in the game world
157 virtual void addToScene(scene::ISceneManager *smgr) = 0;
158 // Shall remove stuff from the scene
159 // Should return silently if there is nothing to remove
160 // NOTE: This has to be called before calling destructor
161 virtual void removeFromScene() = 0;
163 // 0 <= light_at_pos <= LIGHT_SUN
164 virtual void updateLight(u8 light_at_pos) {};
167 virtual std::string infoText() { return ""; }
169 // Shall be left NULL if doesn't collide
170 // Position is relative to m_pos in block
171 core::aabbox3d<f32> * m_collision_box;
173 // Shall be left NULL if can't be selected
174 core::aabbox3d<f32> * m_selection_box;
178 // This differentiates the instance of the object
179 // Not same as typeId.
181 // Position of the object inside the block
182 // Units is node coordinates * BS
185 friend class MapBlockObjectList;
190 Used for handling selections of special stuff
192 class PseudoMBObject : public MapBlockObject
195 // The constructor of every MapBlockObject should be like this
196 PseudoMBObject(MapBlock *block, s16 id, v3f pos):
197 MapBlockObject(block, id, pos)
200 virtual ~PseudoMBObject()
203 delete m_selection_box;
207 Implementation interface
209 virtual u16 getTypeId() const
211 return MAPBLOCKOBJECT_TYPE_PSEUDO;
213 virtual void serialize(std::ostream &os, u8 version)
217 virtual void update(std::istream &is, u8 version)
221 virtual bool serverStep(float dtime, u32 daynight_ratio)
230 void setSelectionBox(core::aabbox3d<f32> box)
232 m_selection_box = new core::aabbox3d<f32>(box);
239 class MovingObject : public MapBlockObject
242 // The constructor of every MapBlockObject should be like this
243 MovingObject(MapBlock *block, s16 id, v3f pos):
244 MapBlockObject(block, id, pos),
247 m_pos_animation_time(0),
250 m_touching_ground = false;
252 virtual ~MovingObject()
257 Implementation interface
260 virtual u16 getTypeId() const = 0;
262 virtual void serialize(std::ostream &os, u8 version)
264 serializeBase(os, version);
269 // stored as x100/BS v3s16
270 v3s16 speed_i(m_speed.X*100/BS, m_speed.Y*100/BS, m_speed.Z*100/BS);
271 writeV3S16(buf, speed_i);
272 os.write((char*)buf, 6);
274 virtual void update(std::istream &is, u8 version)
279 // stored as x100/BS v3s16
280 is.read((char*)buf, 6);
281 v3s16 speed_i = readV3S16(buf);
282 v3f speed((f32)speed_i.X/100*BS,
283 (f32)speed_i.Y/100*BS,
284 (f32)speed_i.Z/100*BS);
289 // Reimplementation shall call this.
290 virtual void updatePos(v3f pos)
292 m_oldpos = m_showpos;
295 if(m_pos_animation_time < 0.001 || m_pos_animation_time > 1.0)
296 m_pos_animation_time = m_pos_animation_time_counter;
298 m_pos_animation_time = m_pos_animation_time * 0.9
299 + m_pos_animation_time_counter * 0.1;
300 m_pos_animation_time_counter = 0;
301 m_pos_animation_counter = 0;
304 // Position where the object is drawn relative to block
305 virtual v3f getRelativeShowPos()
309 // Returns m_showpos relative to whole map
310 v3f getAbsoluteShowPos();
312 virtual bool serverStep(float dtime, u32 daynight_ratio)
314 virtual void clientStep(float dtime)
317 /*virtual void addToScene(scene::ISceneManager *smgr) = 0;
318 virtual void removeFromScene() = 0;*/
324 // Move with collision detection, server side
325 void move(float dtime, v3f acceleration);
327 // Move from old position to new position, client side
328 void simpleMove(float dtime);
332 bool m_touching_ground;
333 // Client-side moving
335 f32 m_pos_animation_counter;
336 f32 m_pos_animation_time;
337 f32 m_pos_animation_time_counter;
341 class SignObject : public MapBlockObject
344 // The constructor of every MapBlockObject should be like this
345 SignObject(MapBlock *block, s16 id, v3f pos):
346 MapBlockObject(block, id, pos),
349 m_selection_box = new core::aabbox3d<f32>
350 (-BS*0.4,-BS*0.5,-BS*0.4, BS*0.4,BS*0.5,BS*0.4);
352 virtual ~SignObject()
354 delete m_selection_box;
358 Implementation interface
360 virtual u16 getTypeId() const
362 return MAPBLOCKOBJECT_TYPE_SIGN;
364 virtual void serialize(std::ostream &os, u8 version)
366 serializeBase(os, version);
370 writeS16(buf, m_yaw * 10);
371 os.write((char*)buf, 2);
374 writeU16(buf, m_text.size());
375 os.write((char*)buf, 2);
378 os.write(m_text.c_str(), m_text.size());
380 virtual void update(std::istream &is, u8 version)
385 is.read((char*)buf, 2);
386 s16 yaw_i = readS16(buf);
387 m_yaw = (f32)yaw_i / 10;
390 is.read((char*)buf, 2);
391 u16 size = readU16(buf);
395 for(u16 i=0; i<size; i++)
397 is.read((char*)buf, 1);
403 virtual bool serverStep(float dtime, u32 daynight_ratio)
408 virtual void addToScene(scene::ISceneManager *smgr)
413 video::IVideoDriver* driver = smgr->getVideoDriver();
415 scene::SMesh *mesh = new scene::SMesh();
417 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
418 video::SColor c(255,255,255,255);
419 video::S3DVertex vertices[4] =
421 video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c, 0,1),
422 video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c, 1,1),
423 video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 1,0),
424 video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 0,0),
426 u16 indices[] = {0,1,2,2,3,0};
427 buf->append(vertices, 4, indices, 6);
429 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
430 //buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
431 buf->getMaterial().setTexture
432 (0, driver->getTexture("../data/sign.png"));
433 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
434 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
435 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
437 mesh->addMeshBuffer(buf);
441 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
442 video::SColor c(255,255,255,255);
443 video::S3DVertex vertices[4] =
445 video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c, 0,1),
446 video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c, 1,1),
447 video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0),
448 video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 0,0),
450 u16 indices[] = {0,1,2,2,3,0};
451 buf->append(vertices, 4, indices, 6);
453 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
454 //buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
455 buf->getMaterial().setTexture
456 (0, driver->getTexture("../data/sign_back.png"));
457 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
458 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
459 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
461 mesh->addMeshBuffer(buf);
464 m_node = smgr->addMeshSceneNode(mesh, NULL);
469 virtual void removeFromScene()
477 virtual void updateLight(u8 light_at_pos)
482 u8 li = decode_light(light_at_pos);
483 video::SColor color(255,li,li,li);
485 scene::IMesh *mesh = m_node->getMesh();
487 u16 mc = mesh->getMeshBufferCount();
488 for(u16 j=0; j<mc; j++)
490 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
491 video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
492 u16 vc = buf->getVertexCount();
493 for(u16 i=0; i<vc; i++)
495 vertices[i].Color = color;
501 virtual std::string infoText()
503 return std::string("\"") + m_text + "\"";
506 virtual std::string getInventoryString()
508 return std::string("Sign ")+m_text;
514 void updateSceneNode()
519 m_node->setPosition(getAbsolutePos());
520 m_node->setRotation(v3f(0, m_yaw, 0));
525 void setText(std::string text)
527 if(text.size() > SIGN_TEXT_MAX_LENGTH)
528 text = text.substr(0, SIGN_TEXT_MAX_LENGTH);
534 std::string getText()
547 scene::IMeshSceneNode *m_node;
552 class RatObject : public MovingObject
555 RatObject(MapBlock *block, s16 id, v3f pos):
556 MovingObject(block, id, pos),
559 m_collision_box = new core::aabbox3d<f32>
560 (-BS*0.3,-BS*.25,-BS*0.3, BS*0.3,BS*0.25,BS*0.3);
561 m_selection_box = new core::aabbox3d<f32>
562 (-BS*0.3,-BS*.25,-BS*0.3, BS*0.3,BS*0.25,BS*0.3);
570 delete m_collision_box;
571 delete m_selection_box;
575 Implementation interface
577 virtual u16 getTypeId() const
579 return MAPBLOCKOBJECT_TYPE_RAT;
581 virtual void serialize(std::ostream &os, u8 version)
583 MovingObject::serialize(os, version);
587 writeS16(buf, m_yaw * 10);
588 os.write((char*)buf, 2);
591 virtual void update(std::istream &is, u8 version)
593 MovingObject::update(is, version);
597 is.read((char*)buf, 2);
598 s16 yaw_i = readS16(buf);
599 m_yaw = (f32)yaw_i / 10;
604 virtual bool serverStep(float dtime, u32 daynight_ratio)
611 v3f dir(cos(m_yaw/180*PI),0,sin(m_yaw/180*PI));
615 m_speed.X = speed * dir.X;
616 m_speed.Z = speed * dir.Z;
618 if(m_touching_ground && (m_oldpos - m_pos).getLength() < dtime*speed/2)
632 m_counter2 += (float)(rand()%100)/100*3.0;
633 m_yaw += ((float)(rand()%200)-100)/100*180;
634 m_yaw = wrapDegrees(m_yaw);
642 move(dtime, v3f(0, -9.81*BS, 0));
649 virtual void clientStep(float dtime)
651 //m_pos += m_speed * dtime;
652 MovingObject::simpleMove(dtime);
657 virtual void addToScene(scene::ISceneManager *smgr);
659 virtual void removeFromScene()
668 virtual void updateLight(u8 light_at_pos)
673 u8 li = decode_light(light_at_pos);
674 video::SColor color(255,li,li,li);
676 scene::IMesh *mesh = m_node->getMesh();
678 u16 mc = mesh->getMeshBufferCount();
679 for(u16 j=0; j<mc; j++)
681 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
682 video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
683 u16 vc = buf->getVertexCount();
684 for(u16 i=0; i<vc; i++)
686 vertices[i].Color = color;
693 virtual std::string getInventoryString()
695 // There must be a space after the name
697 return std::string("Rat ");
709 m_node->setPosition(getAbsoluteShowPos());
710 m_node->setRotation(v3f(0, -m_yaw+180, 0));
714 scene::IMeshSceneNode *m_node;
725 class PlayerObject : public MovingObject
728 PlayerObject(MapBlock *block, s16 id, v3f pos):
729 MovingObject(block, id, pos),
732 m_collision_box = new core::aabbox3d<f32>
733 (-BS*0.3,-BS*.25,-BS*0.3, BS*0.3,BS*0.25,BS*0.3);
734 /*m_selection_box = new core::aabbox3d<f32>
735 (-BS*0.3,-BS*.25,-BS*0.3, BS*0.3,BS*0.25,BS*0.3);*/
737 virtual ~PlayerObject()
740 delete m_collision_box;
742 delete m_selection_box;
746 Implementation interface
748 virtual u16 getTypeId() const
750 return MAPBLOCKOBJECT_TYPE_PLAYER;
752 virtual void serialize(std::ostream &os, u8 version)
754 // Object data is generated from actual player
756 virtual void update(std::istream &is, u8 version)
758 MovingObject::update(is, version);
762 is.read((char*)buf, 2);
763 s16 yaw_i = readS16(buf);
764 m_yaw = (f32)yaw_i / 10;
769 virtual bool serverStep(float dtime, u32 daynight_ratio)
771 // Player is handled elsewhere.
774 // Actually, fail very loudly:
779 virtual void clientStep(float dtime)
781 MovingObject::simpleMove(dtime);
786 virtual void addToScene(scene::ISceneManager *smgr);
788 virtual void removeFromScene()
797 virtual void updateLight(u8 light_at_pos)
802 u8 li = decode_light(light_at_pos);
803 video::SColor color(255,li,li,li);
805 scene::IMesh *mesh = m_node->getMesh();
807 u16 mc = mesh->getMeshBufferCount();
808 for(u16 j=0; j<mc; j++)
810 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
811 video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
812 u16 vc = buf->getVertexCount();
813 for(u16 i=0; i<vc; i++)
815 vertices[i].Color = color;
831 m_node->setPosition(getAbsoluteShowPos());
832 m_node->setRotation(v3f(0, -m_yaw+180, 0));
836 scene::IMeshSceneNode *m_node;
842 struct DistanceSortedObject
844 DistanceSortedObject(MapBlockObject *a_obj, f32 a_d)
853 bool operator < (DistanceSortedObject &other)
859 class MapBlockObjectList
862 MapBlockObjectList(MapBlock *block);
863 ~MapBlockObjectList();
865 // Writes the count, id, the type id and the parameters of all objects
866 void serialize(std::ostream &os, u8 version);
868 // Reads ids, type_ids and parameters.
869 // Creates, updates and deletes objects.
870 // If smgr!=NULL, new objects are added to the scene
871 void update(std::istream &is, u8 version, scene::ISceneManager *smgr,
874 // Finds a new unique id
875 s16 getFreeId() throw(ContainerFullException);
878 Set id to -1 to have this set it to a suitable one.
879 The block pointer member is set to this block.
881 void add(MapBlockObject *object)
882 throw(ContainerFullException, AlreadyExistsException);
884 // Deletes and removes all objects
889 Ignores inexistent objects
893 References an object.
894 The object will not be valid after step() or of course if
896 Grabbing the lock is recommended while processing.
898 MapBlockObject * get(s16 id);
900 // You'll want to grab this in a SharedPtr
901 JMutexAutoLock * getLock()
903 return new JMutexAutoLock(m_mutex);
906 // Steps all objects and if server==true, removes those that
907 // want to be removed
908 void step(float dtime, bool server, u32 daynight_ratio);
910 // Wraps an object that wants to move onto this block from an another
911 // Returns true if wrapping was impossible
912 bool wrapObject(MapBlockObject *object);
914 // origin is relative to block
915 void getObjects(v3f origin, f32 max_d,
916 core::array<DistanceSortedObject> &dest);
921 return m_objects.size();
927 core::map<s16, MapBlockObject*> m_objects;
930 u32 m_last_update_daynight_ratio;