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 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("../data/sign.png"));
434 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
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().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
460 mesh->addMeshBuffer(buf);
463 m_node = smgr->addMeshSceneNode(mesh, NULL);
468 virtual void removeFromScene()
476 virtual void updateLight(u8 light_at_pos)
481 u8 li = decode_light(light_at_pos);
482 video::SColor color(255,li,li,li);
484 scene::IMesh *mesh = m_node->getMesh();
486 u16 mc = mesh->getMeshBufferCount();
487 for(u16 j=0; j<mc; j++)
489 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
490 video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
491 u16 vc = buf->getVertexCount();
492 for(u16 i=0; i<vc; i++)
494 vertices[i].Color = color;
500 virtual std::string infoText()
502 return std::string("\"") + m_text + "\"";
505 virtual std::string getInventoryString()
507 return std::string("Sign ")+m_text;
513 void updateSceneNode()
518 m_node->setPosition(getAbsolutePos());
519 m_node->setRotation(v3f(0, m_yaw, 0));
524 void setText(std::string text)
526 if(text.size() > SIGN_TEXT_MAX_LENGTH)
527 text = text.substr(0, SIGN_TEXT_MAX_LENGTH);
541 scene::IMeshSceneNode *m_node;
546 class RatObject : public MovingObject
549 RatObject(MapBlock *block, s16 id, v3f pos):
550 MovingObject(block, id, pos),
553 m_collision_box = new core::aabbox3d<f32>
554 (-BS*0.3,-BS*.25,-BS*0.3, BS*0.3,BS*0.25,BS*0.3);
555 m_selection_box = new core::aabbox3d<f32>
556 (-BS*0.3,-BS*.25,-BS*0.3, BS*0.3,BS*0.25,BS*0.3);
564 delete m_collision_box;
565 delete m_selection_box;
569 Implementation interface
571 virtual u16 getTypeId() const
573 return MAPBLOCKOBJECT_TYPE_RAT;
575 virtual void serialize(std::ostream &os, u8 version)
577 MovingObject::serialize(os, version);
581 writeS16(buf, m_yaw * 10);
582 os.write((char*)buf, 2);
585 virtual void update(std::istream &is, u8 version)
587 MovingObject::update(is, version);
591 is.read((char*)buf, 2);
592 s16 yaw_i = readS16(buf);
593 m_yaw = (f32)yaw_i / 10;
598 virtual bool serverStep(float dtime, u32 daynight_ratio)
605 v3f dir(cos(m_yaw/180*PI),0,sin(m_yaw/180*PI));
609 m_speed.X = speed * dir.X;
610 m_speed.Z = speed * dir.Z;
612 if(m_touching_ground && (m_oldpos - m_pos).getLength() < dtime*speed/2)
626 m_counter2 += (float)(rand()%100)/100*3.0;
627 m_yaw += ((float)(rand()%200)-100)/100*180;
628 m_yaw = wrapDegrees(m_yaw);
636 move(dtime, v3f(0, -9.81*BS, 0));
643 virtual void clientStep(float dtime)
645 //m_pos += m_speed * dtime;
646 MovingObject::simpleMove(dtime);
651 virtual void addToScene(scene::ISceneManager *smgr);
653 virtual void removeFromScene()
662 virtual void updateLight(u8 light_at_pos)
667 u8 li = decode_light(light_at_pos);
668 video::SColor color(255,li,li,li);
670 scene::IMesh *mesh = m_node->getMesh();
672 u16 mc = mesh->getMeshBufferCount();
673 for(u16 j=0; j<mc; j++)
675 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
676 video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
677 u16 vc = buf->getVertexCount();
678 for(u16 i=0; i<vc; i++)
680 vertices[i].Color = color;
687 virtual std::string getInventoryString()
689 // There must be a space after the name
691 return std::string("Rat ");
703 m_node->setPosition(getAbsoluteShowPos());
704 m_node->setRotation(v3f(0, -m_yaw+180, 0));
708 scene::IMeshSceneNode *m_node;
717 struct DistanceSortedObject
719 DistanceSortedObject(MapBlockObject *a_obj, f32 a_d)
728 bool operator < (DistanceSortedObject &other)
734 class MapBlockObjectList
737 MapBlockObjectList(MapBlock *block);
738 ~MapBlockObjectList();
740 // Writes the count, id, the type id and the parameters of all objects
741 void serialize(std::ostream &os, u8 version);
743 // Reads ids, type_ids and parameters.
744 // Creates, updates and deletes objects.
745 // If smgr!=NULL, new objects are added to the scene
746 void update(std::istream &is, u8 version, scene::ISceneManager *smgr,
749 // Finds a new unique id
750 s16 getFreeId() throw(ContainerFullException);
753 Set id to -1 to have this set it to a suitable one.
754 The block pointer member is set to this block.
756 void add(MapBlockObject *object)
757 throw(ContainerFullException, AlreadyExistsException);
759 // Deletes and removes all objects
764 Ignores inexistent objects
768 References an object.
769 The object will not be valid after step() or of course if
771 Grabbing the lock is recommended while processing.
773 MapBlockObject * get(s16 id);
775 // You'll want to grab this in a SharedPtr
776 JMutexAutoLock * getLock()
778 return new JMutexAutoLock(m_mutex);
781 // Steps all objects and if server==true, removes those that
782 // want to be removed
783 void step(float dtime, bool server, u32 daynight_ratio);
785 // Wraps an object that wants to move onto this block from an another
786 // Returns true if wrapping was impossible
787 bool wrapObject(MapBlockObject *object);
789 // origin is relative to block
790 void getObjects(v3f origin, f32 max_d,
791 core::array<DistanceSortedObject> &dest);
796 return m_objects.size();
802 core::map<s16, MapBlockObject*> m_objects;
805 u32 m_last_update_daynight_ratio;