]> git.lizzy.rs Git - dragonfireclient.git/blob - src/mapblockobject.h
a65ffd8e82b0df5a467aa1633bc8ad464c685e3e
[dragonfireclient.git] / src / mapblockobject.h
1 /*
2 Minetest-c55
3 Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
4
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.
9
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.
14
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.
18 */
19
20 #ifndef MAPBLOCKOBJECT_HEADER
21 #define MAPBLOCKOBJECT_HEADER
22
23 #include "common_irrlicht.h"
24 #include <math.h>
25 #include <string>
26 #include "serialization.h"
27 #include "mapnode.h"
28 #include "constants.h"
29 #include "debug.h"
30
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
36
37 class MapBlock;
38
39 class MapBlockObject
40 {
41 public:
42         MapBlockObject(MapBlock *block, s16 id, v3f pos):
43                 m_collision_box(NULL),
44                 m_selection_box(NULL),
45                 m_block(block),
46                 m_id(id),
47                 m_pos(pos)
48         {
49         }
50         virtual ~MapBlockObject()
51         {
52         }
53
54         s16 getId()
55         {
56                 return m_id;
57         }
58         MapBlock* getBlock()
59         {
60                 return m_block;
61         }
62         
63         // Writes id, pos and typeId
64         void serializeBase(std::ostream &os, u8 version)
65         {
66                 u8 buf[6];
67
68                 // id
69                 writeS16(buf, m_id);
70                 os.write((char*)buf, 2);
71                 
72                 // position
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);
77
78                 // typeId
79                 writeU16(buf, getTypeId());
80                 os.write((char*)buf, 2);
81         }
82         
83         // Position where the object is drawn relative to block
84         virtual v3f getRelativeShowPos()
85         {
86                 return m_pos;
87         }
88         // Get floating point position on map
89         v3f getAbsolutePos();
90
91         void setBlockChanged();
92
93         // Shootline is relative to block
94         bool isSelected(core::line3d<f32> shootline)
95         {
96                 if(m_selection_box == NULL)
97                         return false;
98
99                 core::aabbox3d<f32> offsetted_box(
100                                 m_selection_box->MinEdge + m_pos,
101                                 m_selection_box->MaxEdge + m_pos
102                 );
103
104                 return offsetted_box.intersectsWithLine(shootline);
105         }
106
107         core::aabbox3d<f32> getSelectionBoxOnMap()
108         {
109                 v3f absolute_pos = getAbsolutePos();
110
111                 core::aabbox3d<f32> box(
112                                 m_selection_box->MinEdge + absolute_pos,
113                                 m_selection_box->MaxEdge + absolute_pos
114                 );
115
116                 return box;
117         }
118         
119         /*
120                 Implementation interface
121         */
122
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;
128
129         virtual std::string getInventoryString() { return "None"; }
130         
131         // Reimplementation shall call this.
132         virtual void updatePos(v3f pos)
133         {
134                 m_pos = pos;
135         }
136         
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)
142         { return false; };
143
144 #ifdef SERVER
145         void clientStep(float dtime) {};
146         void addToScene(void *smgr) {};
147         void removeFromScene() {};
148         void updateLight(u8 light_at_pos) {};
149 #else
150         // This should do slight animations only or so
151         virtual void clientStep(float dtime) {};
152
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;
162         
163         // 0 <= light_at_pos <= LIGHT_SUN
164         virtual void updateLight(u8 light_at_pos) {};
165 #endif
166
167         virtual std::string infoText() { return ""; }
168         
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;
172         
173         // Shall be left NULL if can't be selected
174         core::aabbox3d<f32> * m_selection_box;
175
176 protected:
177         MapBlock *m_block;
178         // This differentiates the instance of the object
179         // Not same as typeId.
180         s16 m_id;
181         // Position of the object inside the block
182         // Units is node coordinates * BS
183         v3f m_pos;
184
185         friend class MapBlockObjectList;
186 };
187
188 #if 0
189 /*
190         Used for handling selections of special stuff
191 */
192 class PseudoMBObject : public MapBlockObject
193 {
194 public:
195         // The constructor of every MapBlockObject should be like this
196         PseudoMBObject(MapBlock *block, s16 id, v3f pos):
197                 MapBlockObject(block, id, pos)
198         {
199         }
200         virtual ~PseudoMBObject()
201         {
202                 if(m_selection_box)
203                         delete m_selection_box;
204         }
205         
206         /*
207                 Implementation interface
208         */
209         virtual u16 getTypeId() const
210         {
211                 return MAPBLOCKOBJECT_TYPE_PSEUDO;
212         }
213         virtual void serialize(std::ostream &os, u8 version)
214         {
215                 assert(0);
216         }
217         virtual void update(std::istream &is, u8 version)
218         {
219                 assert(0);
220         }
221         virtual bool serverStep(float dtime, u32 daynight_ratio)
222         {
223                 assert(0);
224         }
225
226         /*
227                 Special methods
228         */
229         
230         void setSelectionBox(core::aabbox3d<f32> box)
231         {
232                 m_selection_box = new core::aabbox3d<f32>(box);
233         }
234         
235 protected:
236 };
237 #endif
238
239 class MovingObject : public MapBlockObject
240 {
241 public:
242         // The constructor of every MapBlockObject should be like this
243         MovingObject(MapBlock *block, s16 id, v3f pos):
244                 MapBlockObject(block, id, pos),
245                 m_speed(0,0,0),
246                 m_oldpos(pos),
247                 m_pos_animation_time(0),
248                 m_showpos(pos)
249         {
250                 m_touching_ground = false;
251         }
252         virtual ~MovingObject()
253         {
254         }
255         
256         /*
257                 Implementation interface
258         */
259         
260         virtual u16 getTypeId() const = 0;
261
262         virtual void serialize(std::ostream &os, u8 version)
263         {
264                 serializeBase(os, version);
265
266                 u8 buf[6];
267
268                 // Write speed
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);
273         }
274         virtual void update(std::istream &is, u8 version)
275         {
276                 u8 buf[6];
277                 
278                 // Read speed
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);
285
286                 m_speed = speed;
287         }
288         
289         // Reimplementation shall call this.
290         virtual void updatePos(v3f pos)
291         {
292                 m_oldpos = m_showpos;
293                 m_pos = pos;
294                 
295                 if(m_pos_animation_time < 0.001 || m_pos_animation_time > 1.0)
296                         m_pos_animation_time = m_pos_animation_time_counter;
297                 else
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;
302         }
303         
304         // Position where the object is drawn relative to block
305         virtual v3f getRelativeShowPos()
306         {
307                 return m_showpos;
308         }
309         // Returns m_showpos relative to whole map
310         v3f getAbsoluteShowPos();
311
312         virtual bool serverStep(float dtime, u32 daynight_ratio)
313         { return false; };
314         virtual void clientStep(float dtime)
315         {};
316         
317         /*virtual void addToScene(scene::ISceneManager *smgr) = 0;
318         virtual void removeFromScene() = 0;*/
319
320         /*
321                 Special methods
322         */
323         
324         // Move with collision detection, server side
325         void move(float dtime, v3f acceleration);
326
327         // Move from old position to new position, client side
328         void simpleMove(float dtime);
329         
330 protected:
331         v3f m_speed;
332         bool m_touching_ground;
333         // Client-side moving
334         v3f m_oldpos;
335         f32 m_pos_animation_counter;
336         f32 m_pos_animation_time;
337         f32 m_pos_animation_time_counter;
338         v3f m_showpos;
339 };
340
341 class SignObject : public MapBlockObject
342 {
343 public:
344         // The constructor of every MapBlockObject should be like this
345         SignObject(MapBlock *block, s16 id, v3f pos):
346                 MapBlockObject(block, id, pos),
347                 m_node(NULL)
348         {
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);
351         }
352         virtual ~SignObject()
353         {
354                 delete m_selection_box;
355         }
356         
357         /*
358                 Implementation interface
359         */
360         virtual u16 getTypeId() const
361         {
362                 return MAPBLOCKOBJECT_TYPE_SIGN;
363         }
364         virtual void serialize(std::ostream &os, u8 version)
365         {
366                 serializeBase(os, version);
367                 u8 buf[2];
368
369                 // Write yaw * 10
370                 writeS16(buf, m_yaw * 10);
371                 os.write((char*)buf, 2);
372
373                 // Write text length
374                 writeU16(buf, m_text.size());
375                 os.write((char*)buf, 2);
376                 
377                 // Write text
378                 os.write(m_text.c_str(), m_text.size());
379         }
380         virtual void update(std::istream &is, u8 version)
381         {
382                 u8 buf[2];
383
384                 // Read yaw * 10
385                 is.read((char*)buf, 2);
386                 s16 yaw_i = readS16(buf);
387                 m_yaw = (f32)yaw_i / 10;
388
389                 // Read text length
390                 is.read((char*)buf, 2);
391                 u16 size = readU16(buf);
392
393                 // Read text
394                 m_text.clear();
395                 for(u16 i=0; i<size; i++)
396                 {
397                         is.read((char*)buf, 1);
398                         m_text += buf[0];
399                 }
400
401                 updateSceneNode();
402         }
403         virtual bool serverStep(float dtime, u32 daynight_ratio)
404         {
405                 return false;
406         }
407 #ifndef SERVER
408         virtual void addToScene(scene::ISceneManager *smgr)
409         {
410                 if(m_node != NULL)
411                         return;
412                 
413                 video::IVideoDriver* driver = smgr->getVideoDriver();
414                 
415                 scene::SMesh *mesh = new scene::SMesh();
416                 { // Front
417                 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
418                 video::SColor c(255,255,255,255);
419                 video::S3DVertex vertices[4] =
420                 {
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),
425                 };
426                 u16 indices[] = {0,1,2,2,3,0};
427                 buf->append(vertices, 4, indices, 6);
428                 // Set material
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;
436                 // Add to mesh
437                 mesh->addMeshBuffer(buf);
438                 buf->drop();
439                 }
440                 { // Back
441                 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
442                 video::SColor c(255,255,255,255);
443                 video::S3DVertex vertices[4] =
444                 {
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),
449                 };
450                 u16 indices[] = {0,1,2,2,3,0};
451                 buf->append(vertices, 4, indices, 6);
452                 // Set material
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;
460                 // Add to mesh
461                 mesh->addMeshBuffer(buf);
462                 buf->drop();
463                 }
464                 m_node = smgr->addMeshSceneNode(mesh, NULL);
465                 mesh->drop();
466
467                 updateSceneNode();
468         }
469         virtual void removeFromScene()
470         {
471                 if(m_node != NULL)
472                 {
473                         m_node->remove();
474                         m_node = NULL;
475                 }
476         }
477         virtual void updateLight(u8 light_at_pos)
478         {
479                 if(m_node == NULL)
480                         return;
481
482                 u8 li = decode_light(light_at_pos);
483                 video::SColor color(255,li,li,li);
484
485                 scene::IMesh *mesh = m_node->getMesh();
486                 
487                 u16 mc = mesh->getMeshBufferCount();
488                 for(u16 j=0; j<mc; j++)
489                 {
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++)
494                         {
495                                 vertices[i].Color = color;
496                         }
497                 }
498         }
499 #endif
500
501         virtual std::string infoText()
502         {
503                 return std::string("\"") + m_text + "\"";
504         }
505
506         virtual std::string getInventoryString()
507         {
508                 return std::string("Sign ")+m_text;
509         }
510
511         /*
512                 Special methods
513         */
514         void updateSceneNode()
515         {
516 #ifndef SERVER
517                 if(m_node != NULL)
518                 {
519                         m_node->setPosition(getAbsolutePos());
520                         m_node->setRotation(v3f(0, m_yaw, 0));
521                 }
522 #endif
523         }
524
525         void setText(std::string text)
526         {
527                 if(text.size() > SIGN_TEXT_MAX_LENGTH)
528                         text = text.substr(0, SIGN_TEXT_MAX_LENGTH);
529                 m_text = text;
530
531                 setBlockChanged();
532         }
533
534         std::string getText()
535         {
536                 return m_text;
537         }
538
539         void setYaw(f32 yaw)
540         {
541                 m_yaw = yaw;
542
543                 setBlockChanged();
544         }
545         
546 protected:
547         scene::IMeshSceneNode *m_node;
548         std::string m_text;
549         f32 m_yaw;
550 };
551
552 class RatObject : public MovingObject
553 {
554 public:
555         RatObject(MapBlock *block, s16 id, v3f pos):
556                 MovingObject(block, id, pos),
557                 m_node(NULL)
558         {
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);
563
564                 m_counter1 = 0;
565                 m_counter2 = 0;
566                 m_age = 0;
567         }
568         virtual ~RatObject()
569         {
570                 delete m_collision_box;
571                 delete m_selection_box;
572         }
573         
574         /*
575                 Implementation interface
576         */
577         virtual u16 getTypeId() const
578         {
579                 return MAPBLOCKOBJECT_TYPE_RAT;
580         }
581         virtual void serialize(std::ostream &os, u8 version)
582         {
583                 MovingObject::serialize(os, version);
584                 u8 buf[2];
585
586                 // Write yaw * 10
587                 writeS16(buf, m_yaw * 10);
588                 os.write((char*)buf, 2);
589
590         }
591         virtual void update(std::istream &is, u8 version)
592         {
593                 MovingObject::update(is, version);
594                 u8 buf[2];
595                 
596                 // Read yaw * 10
597                 is.read((char*)buf, 2);
598                 s16 yaw_i = readS16(buf);
599                 m_yaw = (f32)yaw_i / 10;
600
601                 updateNodePos();
602         }
603
604         virtual bool serverStep(float dtime, u32 daynight_ratio)
605         {
606                 m_age += dtime;
607                 if(m_age > 60)
608                         // Die
609                         return true;
610
611                 v3f dir(cos(m_yaw/180*PI),0,sin(m_yaw/180*PI));
612
613                 f32 speed = 2*BS;
614
615                 m_speed.X = speed * dir.X;
616                 m_speed.Z = speed * dir.Z;
617
618                 if(m_touching_ground && (m_oldpos - m_pos).getLength() < dtime*speed/2)
619                 {
620                         m_counter1 -= dtime;
621                         if(m_counter1 < 0.0)
622                         {
623                                 m_counter1 += 1.0;
624                                 m_speed.Y = 5.0*BS;
625                         }
626                 }
627
628                 {
629                         m_counter2 -= dtime;
630                         if(m_counter2 < 0.0)
631                         {
632                                 m_counter2 += (float)(rand()%100)/100*3.0;
633                                 m_yaw += ((float)(rand()%200)-100)/100*180;
634                                 m_yaw = wrapDegrees(m_yaw);
635                         }
636                 }
637
638                 m_oldpos = m_pos;
639
640                 //m_yaw += dtime*90;
641
642                 move(dtime, v3f(0, -9.81*BS, 0));
643
644                 //updateNodePos();
645
646                 return false;
647         }
648 #ifndef SERVER
649         virtual void clientStep(float dtime)
650         {
651                 //m_pos += m_speed * dtime;
652                 MovingObject::simpleMove(dtime);
653
654                 updateNodePos();
655         }
656         
657         virtual void addToScene(scene::ISceneManager *smgr);
658
659         virtual void removeFromScene()
660         {
661                 if(m_node == NULL)
662                         return;
663
664                 m_node->remove();
665                 m_node = NULL;
666         }
667
668         virtual void updateLight(u8 light_at_pos)
669         {
670                 if(m_node == NULL)
671                         return;
672
673                 u8 li = decode_light(light_at_pos);
674                 video::SColor color(255,li,li,li);
675
676                 scene::IMesh *mesh = m_node->getMesh();
677                 
678                 u16 mc = mesh->getMeshBufferCount();
679                 for(u16 j=0; j<mc; j++)
680                 {
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++)
685                         {
686                                 vertices[i].Color = color;
687                         }
688                 }
689         }
690         
691 #endif
692
693         virtual std::string getInventoryString()
694         {
695                 // There must be a space after the name
696                 // Or does there?
697                 return std::string("Rat ");
698         }
699
700         /*
701                 Special methods
702         */
703         
704         void updateNodePos()
705         {
706                 if(m_node == NULL)
707                         return;
708
709                 m_node->setPosition(getAbsoluteShowPos());
710                 m_node->setRotation(v3f(0, -m_yaw+180, 0));
711         }
712         
713 protected:
714         scene::IMeshSceneNode *m_node;
715         float m_yaw;
716
717         float m_counter1;
718         float m_counter2;
719         float m_age;
720 };
721
722 /*
723         NOTE: Not used.
724 */
725 class PlayerObject : public MovingObject
726 {
727 public:
728         PlayerObject(MapBlock *block, s16 id, v3f pos):
729                 MovingObject(block, id, pos),
730                 m_node(NULL)
731         {
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);*/
736         }
737         virtual ~PlayerObject()
738         {
739                 if(m_collision_box)
740                         delete m_collision_box;
741                 if(m_selection_box)
742                         delete m_selection_box;
743         }
744         
745         /*
746                 Implementation interface
747         */
748         virtual u16 getTypeId() const
749         {
750                 return MAPBLOCKOBJECT_TYPE_PLAYER;
751         }
752         virtual void serialize(std::ostream &os, u8 version)
753         {
754                 // Object data is generated from actual player
755         }
756         virtual void update(std::istream &is, u8 version)
757         {
758                 MovingObject::update(is, version);
759                 u8 buf[2];
760                 
761                 // Read yaw * 10
762                 is.read((char*)buf, 2);
763                 s16 yaw_i = readS16(buf);
764                 m_yaw = (f32)yaw_i / 10;
765
766                 updateNodePos();
767         }
768
769         virtual bool serverStep(float dtime, u32 daynight_ratio)
770         {
771                 // Player is handled elsewhere.
772                 // Die.
773                 //return true;
774                 // Actually, fail very loudly:
775                 assert(0);
776         }
777
778 #ifndef SERVER
779         virtual void clientStep(float dtime)
780         {
781                 MovingObject::simpleMove(dtime);
782
783                 updateNodePos();
784         }
785         
786         virtual void addToScene(scene::ISceneManager *smgr);
787
788         virtual void removeFromScene()
789         {
790                 if(m_node == NULL)
791                         return;
792
793                 m_node->remove();
794                 m_node = NULL;
795         }
796
797         virtual void updateLight(u8 light_at_pos)
798         {
799                 if(m_node == NULL)
800                         return;
801
802                 u8 li = decode_light(light_at_pos);
803                 video::SColor color(255,li,li,li);
804
805                 scene::IMesh *mesh = m_node->getMesh();
806                 
807                 u16 mc = mesh->getMeshBufferCount();
808                 for(u16 j=0; j<mc; j++)
809                 {
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++)
814                         {
815                                 vertices[i].Color = color;
816                         }
817                 }
818         }
819         
820 #endif
821
822         /*
823                 Special methods
824         */
825         
826         void updateNodePos()
827         {
828                 if(m_node == NULL)
829                         return;
830
831                 m_node->setPosition(getAbsoluteShowPos());
832                 m_node->setRotation(v3f(0, -m_yaw+180, 0));
833         }
834         
835 protected:
836         scene::IMeshSceneNode *m_node;
837         float m_yaw;
838
839         v3f m_oldpos;
840 };
841
842 struct DistanceSortedObject
843 {
844         DistanceSortedObject(MapBlockObject *a_obj, f32 a_d)
845         {
846                 obj = a_obj;
847                 d = a_d;
848         }
849         
850         MapBlockObject *obj;
851         f32 d;
852
853         bool operator < (DistanceSortedObject &other)
854         {
855                 return d < other.d;
856         }
857 };
858
859 class MapBlockObjectList
860 {
861 public:
862         MapBlockObjectList(MapBlock *block);
863         ~MapBlockObjectList();
864
865         // Writes the count, id, the type id and the parameters of all objects
866         void serialize(std::ostream &os, u8 version);
867
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,
872                         u32 daynight_ratio);
873
874         // Finds a new unique id
875         s16 getFreeId() throw(ContainerFullException);
876         /*
877                 Adds an object.
878                 Set id to -1 to have this set it to a suitable one.
879                 The block pointer member is set to this block.
880         */
881         void add(MapBlockObject *object)
882                         throw(ContainerFullException, AlreadyExistsException);
883
884         // Deletes and removes all objects
885         void clear();
886
887         /*
888                 Removes an object.
889                 Ignores inexistent objects
890         */
891         void remove(s16 id);
892         /*
893                 References an object.
894                 The object will not be valid after step() or of course if
895                 it is removed.
896                 Grabbing the lock is recommended while processing.
897         */
898         MapBlockObject * get(s16 id);
899
900         // You'll want to grab this in a SharedPtr
901         JMutexAutoLock * getLock()
902         {
903                 return new JMutexAutoLock(m_mutex);
904         }
905
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);
909
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);
913         
914         // origin is relative to block
915         void getObjects(v3f origin, f32 max_d,
916                         core::array<DistanceSortedObject> &dest);
917         
918         // Number of objects
919         s32 getCount()
920         {
921                 return m_objects.size();
922         }
923
924 private:
925         JMutex m_mutex;
926         // Key is id
927         core::map<s16, MapBlockObject*> m_objects;
928         MapBlock *m_block;
929
930         u32 m_last_update_daynight_ratio;
931 };
932
933
934 #endif
935