]> git.lizzy.rs Git - minetest.git/blob - src/mapblockobject.h
Lock mutex when accessing m_env in Server::~Server
[minetest.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 // This file contains the DEPRECATED MapBlockObject system
21
22 #ifndef MAPBLOCKOBJECT_HEADER
23 #define MAPBLOCKOBJECT_HEADER
24
25 #include "common_irrlicht.h"
26 #include <math.h>
27 #include <string>
28 #include "serialization.h"
29 #include "mapnode.h"
30 #include "constants.h"
31 #include "debug.h"
32
33 #define MAPBLOCKOBJECT_TYPE_PLAYER 0
34 #define MAPBLOCKOBJECT_TYPE_SIGN 2
35 #define MAPBLOCKOBJECT_TYPE_RAT 3
36 #define MAPBLOCKOBJECT_TYPE_ITEM 4
37 // Used for handling selecting special stuff
38 //#define MAPBLOCKOBJECT_TYPE_PSEUDO 1000
39
40 class MapBlock;
41
42 class MapBlockObject
43 {
44 public:
45         MapBlockObject(MapBlock *block, s16 id, v3f pos):
46                 m_collision_box(NULL),
47                 m_selection_box(NULL),
48                 m_block(block),
49                 m_id(id),
50                 m_pos(pos)
51         {
52         }
53         virtual ~MapBlockObject()
54         {
55         }
56
57         s16 getId()
58         {
59                 return m_id;
60         }
61         MapBlock* getBlock()
62         {
63                 return m_block;
64         }
65         
66         // Writes id, pos and typeId
67         void serializeBase(std::ostream &os, u8 version)
68         {
69                 u8 buf[6];
70
71                 // id
72                 writeS16(buf, m_id);
73                 os.write((char*)buf, 2);
74                 
75                 // position
76                 // stored as x1000/BS v3s16
77                 v3s16 pos_i(m_pos.X*1000/BS, m_pos.Y*1000/BS, m_pos.Z*1000/BS);
78                 writeV3S16(buf, pos_i);
79                 os.write((char*)buf, 6);
80
81                 // typeId
82                 writeU16(buf, getTypeId());
83                 os.write((char*)buf, 2);
84         }
85         
86         // Position where the object is drawn relative to block
87         virtual v3f getRelativeShowPos()
88         {
89                 return m_pos;
90         }
91         // Get floating point position on map
92         v3f getAbsolutePos();
93
94         void setBlockChanged();
95
96         // Shootline is relative to block
97         bool isSelected(core::line3d<f32> shootline)
98         {
99                 if(m_selection_box == NULL)
100                         return false;
101
102                 core::aabbox3d<f32> offsetted_box(
103                                 m_selection_box->MinEdge + m_pos,
104                                 m_selection_box->MaxEdge + m_pos
105                 );
106
107                 return offsetted_box.intersectsWithLine(shootline);
108         }
109
110         core::aabbox3d<f32> getSelectionBoxOnMap()
111         {
112                 v3f absolute_pos = getAbsolutePos();
113
114                 core::aabbox3d<f32> box(
115                                 m_selection_box->MinEdge + absolute_pos,
116                                 m_selection_box->MaxEdge + absolute_pos
117                 );
118
119                 return box;
120         }
121         
122         /*
123                 Implementation interface
124         */
125
126         virtual u16 getTypeId() const = 0;
127         // Shall call serializeBase and then write the parameters
128         virtual void serialize(std::ostream &os, u8 version) = 0;
129         // Shall read parameters from stream
130         virtual void update(std::istream &is, u8 version) = 0;
131
132         virtual std::string getInventoryString() { return "None"; }
133         
134         // Reimplementation shall call this.
135         virtual void updatePos(v3f pos)
136         {
137                 m_pos = pos;
138         }
139         
140         // Shall move the object around, modify it and possibly delete it.
141         // Typical dtimes are 0.2 and 10000.
142         // A return value of true requests deletion of the object by the caller.
143         // NOTE: Only server calls this.
144         virtual bool serverStep(float dtime, u32 daynight_ratio)
145         { return false; };
146
147 #ifdef SERVER
148         void clientStep(float dtime) {};
149         void addToScene(void *smgr) {};
150         void removeFromScene() {};
151         void updateLight(u8 light_at_pos) {};
152 #else
153         // This should do slight animations only or so
154         virtual void clientStep(float dtime) {};
155
156         // NOTE: These functions should do nothing if the asked state is
157         //       same as the current state
158         // Shall add and remove relevant scene nodes for rendering the
159         // object in the game world
160         virtual void addToScene(scene::ISceneManager *smgr) = 0;
161         // Shall remove stuff from the scene
162         // Should return silently if there is nothing to remove
163         // NOTE: This has to be called before calling destructor
164         virtual void removeFromScene() = 0;
165         
166         // 0 <= light_at_pos <= LIGHT_SUN
167         virtual void updateLight(u8 light_at_pos) {};
168 #endif
169
170         virtual std::string infoText() { return ""; }
171         
172         // Shall be left NULL if doesn't collide
173         // Position is relative to m_pos in block
174         core::aabbox3d<f32> * m_collision_box;
175         
176         // Shall be left NULL if can't be selected
177         core::aabbox3d<f32> * m_selection_box;
178
179 protected:
180         MapBlock *m_block;
181         // This differentiates the instance of the object
182         // Not same as typeId.
183         s16 m_id;
184         // Position of the object inside the block
185         // Units is node coordinates * BS
186         v3f m_pos;
187
188         friend class MapBlockObjectList;
189 };
190
191 #if 0
192 /*
193         Used for handling selections of special stuff
194 */
195 class PseudoMBObject : public MapBlockObject
196 {
197 public:
198         // The constructor of every MapBlockObject should be like this
199         PseudoMBObject(MapBlock *block, s16 id, v3f pos):
200                 MapBlockObject(block, id, pos)
201         {
202         }
203         virtual ~PseudoMBObject()
204         {
205                 if(m_selection_box)
206                         delete m_selection_box;
207         }
208         
209         /*
210                 Implementation interface
211         */
212         virtual u16 getTypeId() const
213         {
214                 return MAPBLOCKOBJECT_TYPE_PSEUDO;
215         }
216         virtual void serialize(std::ostream &os, u8 version)
217         {
218                 assert(0);
219         }
220         virtual void update(std::istream &is, u8 version)
221         {
222                 assert(0);
223         }
224         virtual bool serverStep(float dtime, u32 daynight_ratio)
225         {
226                 assert(0);
227         }
228
229         /*
230                 Special methods
231         */
232         
233         void setSelectionBox(core::aabbox3d<f32> box)
234         {
235                 m_selection_box = new core::aabbox3d<f32>(box);
236         }
237         
238 protected:
239 };
240 #endif
241
242 class MovingObject : public MapBlockObject
243 {
244 public:
245         // The constructor of every MapBlockObject should be like this
246         MovingObject(MapBlock *block, s16 id, v3f pos):
247                 MapBlockObject(block, id, pos),
248                 m_speed(0,0,0),
249                 m_oldpos(pos),
250                 m_pos_animation_time(0),
251                 m_showpos(pos)
252         {
253                 m_touching_ground = false;
254         }
255         virtual ~MovingObject()
256         {
257         }
258         
259         /*
260                 Implementation interface
261         */
262         
263         virtual u16 getTypeId() const = 0;
264
265         virtual void serialize(std::ostream &os, u8 version)
266         {
267                 serializeBase(os, version);
268
269                 u8 buf[6];
270
271                 // Write speed
272                 // stored as x100/BS v3s16
273                 v3s16 speed_i(m_speed.X*100/BS, m_speed.Y*100/BS, m_speed.Z*100/BS);
274                 writeV3S16(buf, speed_i);
275                 os.write((char*)buf, 6);
276         }
277         virtual void update(std::istream &is, u8 version)
278         {
279                 u8 buf[6];
280                 
281                 // Read speed
282                 // stored as x100/BS v3s16
283                 is.read((char*)buf, 6);
284                 v3s16 speed_i = readV3S16(buf);
285                 v3f speed((f32)speed_i.X/100*BS,
286                                 (f32)speed_i.Y/100*BS,
287                                 (f32)speed_i.Z/100*BS);
288
289                 m_speed = speed;
290         }
291         
292         // Reimplementation shall call this.
293         virtual void updatePos(v3f pos)
294         {
295                 m_oldpos = m_showpos;
296                 m_pos = pos;
297                 
298                 if(m_pos_animation_time < 0.001 || m_pos_animation_time > 1.0)
299                         m_pos_animation_time = m_pos_animation_time_counter;
300                 else
301                         m_pos_animation_time = m_pos_animation_time * 0.9
302                                         + m_pos_animation_time_counter * 0.1;
303                 m_pos_animation_time_counter = 0;
304                 m_pos_animation_counter = 0;
305         }
306         
307         // Position where the object is drawn relative to block
308         virtual v3f getRelativeShowPos()
309         {
310                 return m_showpos;
311         }
312         // Returns m_showpos relative to whole map
313         v3f getAbsoluteShowPos();
314
315         virtual bool serverStep(float dtime, u32 daynight_ratio)
316         { return false; };
317         virtual void clientStep(float dtime)
318         {};
319         
320         /*virtual void addToScene(scene::ISceneManager *smgr) = 0;
321         virtual void removeFromScene() = 0;*/
322
323         /*
324                 Special methods
325         */
326         
327         // Move with collision detection, server side
328         void move(float dtime, v3f acceleration);
329
330         // Move from old position to new position, client side
331         void simpleMove(float dtime);
332         
333 protected:
334         v3f m_speed;
335         bool m_touching_ground;
336         // Client-side moving
337         v3f m_oldpos;
338         f32 m_pos_animation_counter;
339         f32 m_pos_animation_time;
340         f32 m_pos_animation_time_counter;
341         v3f m_showpos;
342 };
343
344 class SignObject : public MapBlockObject
345 {
346 public:
347         // The constructor of every MapBlockObject should be like this
348         SignObject(MapBlock *block, s16 id, v3f pos):
349                 MapBlockObject(block, id, pos)
350 #ifndef SERVER
351                 ,m_node(NULL)
352 #endif
353         {
354                 m_selection_box = new core::aabbox3d<f32>
355                                 (-BS*0.4,-BS*0.5,-BS*0.4, BS*0.4,BS*0.5,BS*0.4);
356         }
357         virtual ~SignObject()
358         {
359                 delete m_selection_box;
360         }
361         
362         /*
363                 Implementation interface
364         */
365         virtual u16 getTypeId() const
366         {
367                 return MAPBLOCKOBJECT_TYPE_SIGN;
368         }
369         virtual void serialize(std::ostream &os, u8 version)
370         {
371                 serializeBase(os, version);
372                 u8 buf[2];
373
374                 // Write yaw * 10
375                 writeS16(buf, m_yaw * 10);
376                 os.write((char*)buf, 2);
377
378                 // Write text length
379                 writeU16(buf, m_text.size());
380                 os.write((char*)buf, 2);
381                 
382                 // Write text
383                 os.write(m_text.c_str(), m_text.size());
384         }
385         virtual void update(std::istream &is, u8 version)
386         {
387                 u8 buf[2];
388
389                 // Read yaw * 10
390                 is.read((char*)buf, 2);
391                 s16 yaw_i = readS16(buf);
392                 m_yaw = (f32)yaw_i / 10;
393
394                 // Read text length
395                 is.read((char*)buf, 2);
396                 u16 size = readU16(buf);
397
398                 // Read text
399                 m_text.clear();
400                 for(u16 i=0; i<size; i++)
401                 {
402                         is.read((char*)buf, 1);
403                         m_text += buf[0];
404                 }
405
406                 updateSceneNode();
407         }
408         virtual bool serverStep(float dtime, u32 daynight_ratio)
409         {
410                 return false;
411         }
412 #ifndef SERVER
413         virtual void addToScene(scene::ISceneManager *smgr)
414         {
415                 if(m_node != NULL)
416                         return;
417                 
418                 video::IVideoDriver* driver = smgr->getVideoDriver();
419                 
420                 scene::SMesh *mesh = new scene::SMesh();
421                 { // Front
422                 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
423                 video::SColor c(255,255,255,255);
424                 video::S3DVertex vertices[4] =
425                 {
426                         video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c, 0,1),
427                         video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c, 1,1),
428                         video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 1,0),
429                         video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 0,0),
430                 };
431                 u16 indices[] = {0,1,2,2,3,0};
432                 buf->append(vertices, 4, indices, 6);
433                 // Set material
434                 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
435                 //buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
436                 buf->getMaterial().setTexture
437                                 (0, driver->getTexture(getTexturePath("sign.png").c_str()));
438                 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
439                 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
440                 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
441                 // Add to mesh
442                 mesh->addMeshBuffer(buf);
443                 buf->drop();
444                 }
445                 { // Back
446                 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
447                 video::SColor c(255,255,255,255);
448                 video::S3DVertex vertices[4] =
449                 {
450                         video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c, 0,1),
451                         video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c, 1,1),
452                         video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0),
453                         video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 0,0),
454                 };
455                 u16 indices[] = {0,1,2,2,3,0};
456                 buf->append(vertices, 4, indices, 6);
457                 // Set material
458                 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
459                 //buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
460                 buf->getMaterial().setTexture
461                                 (0, driver->getTexture(getTexturePath("sign_back.png").c_str()));
462                 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
463                 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
464                 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
465                 // Add to mesh
466                 mesh->addMeshBuffer(buf);
467                 buf->drop();
468                 }
469                 m_node = smgr->addMeshSceneNode(mesh, NULL);
470                 mesh->drop();
471
472                 updateSceneNode();
473         }
474         virtual void removeFromScene()
475         {
476                 if(m_node != NULL)
477                 {
478                         m_node->remove();
479                         m_node = NULL;
480                 }
481         }
482         virtual void updateLight(u8 light_at_pos)
483         {
484                 if(m_node == NULL)
485                         return;
486
487                 u8 li = decode_light(light_at_pos);
488                 video::SColor color(255,li,li,li);
489                 setMeshVerticesColor(m_node->getMesh(), color);
490         }
491 #endif
492
493         virtual std::string infoText()
494         {
495                 return std::string("\"") + m_text + "\"";
496         }
497
498         virtual std::string getInventoryString()
499         {
500                 return std::string("Sign ")+m_text;
501         }
502
503         /*
504                 Special methods
505         */
506         void updateSceneNode()
507         {
508 #ifndef SERVER
509                 if(m_node != NULL)
510                 {
511                         m_node->setPosition(getAbsolutePos());
512                         m_node->setRotation(v3f(0, m_yaw, 0));
513                 }
514 #endif
515         }
516
517         void setText(std::string text)
518         {
519                 if(text.size() > SIGN_TEXT_MAX_LENGTH)
520                         text = text.substr(0, SIGN_TEXT_MAX_LENGTH);
521                 m_text = text;
522
523                 setBlockChanged();
524         }
525
526         std::string getText()
527         {
528                 return m_text;
529         }
530
531         void setYaw(f32 yaw)
532         {
533                 m_yaw = yaw;
534
535                 setBlockChanged();
536         }
537         
538 protected:
539 #ifndef SERVER
540         scene::IMeshSceneNode *m_node;
541 #endif
542         std::string m_text;
543         f32 m_yaw;
544 };
545
546 class RatObject : public MovingObject
547 {
548 public:
549         RatObject(MapBlock *block, s16 id, v3f pos):
550                 MovingObject(block, id, pos)
551 #ifndef SERVER
552                 ,m_node(NULL)
553 #endif
554         {
555                 m_collision_box = new core::aabbox3d<f32>
556                                 (-BS*0.3,-BS*.25,-BS*0.3, BS*0.3,BS*0.25,BS*0.3);
557                 m_selection_box = new core::aabbox3d<f32>
558                                 (-BS*0.3,-BS*.25,-BS*0.3, BS*0.3,BS*0.25,BS*0.3);
559                 
560                 m_yaw = 0;
561                 m_counter1 = 0;
562                 m_counter2 = 0;
563                 m_age = 0;
564         }
565         virtual ~RatObject()
566         {
567                 delete m_collision_box;
568                 delete m_selection_box;
569         }
570         
571         /*
572                 Implementation interface
573         */
574         virtual u16 getTypeId() const
575         {
576                 return MAPBLOCKOBJECT_TYPE_RAT;
577         }
578         virtual void serialize(std::ostream &os, u8 version)
579         {
580                 MovingObject::serialize(os, version);
581                 u8 buf[2];
582
583                 // Write yaw * 10
584                 writeS16(buf, m_yaw * 10);
585                 os.write((char*)buf, 2);
586
587         }
588         virtual void update(std::istream &is, u8 version)
589         {
590                 MovingObject::update(is, version);
591                 u8 buf[2];
592                 
593                 // Read yaw * 10
594                 is.read((char*)buf, 2);
595                 s16 yaw_i = readS16(buf);
596                 m_yaw = (f32)yaw_i / 10;
597
598                 updateNodePos();
599         }
600
601         virtual bool serverStep(float dtime, u32 daynight_ratio)
602         {
603                 m_age += dtime;
604                 if(m_age > 60)
605                         // Die
606                         return true;
607
608                 v3f dir(cos(m_yaw/180*PI),0,sin(m_yaw/180*PI));
609
610                 f32 speed = 2*BS;
611
612                 m_speed.X = speed * dir.X;
613                 m_speed.Z = speed * dir.Z;
614
615                 if(m_touching_ground && (m_oldpos - m_pos).getLength() < dtime*speed/2)
616                 {
617                         m_counter1 -= dtime;
618                         if(m_counter1 < 0.0)
619                         {
620                                 m_counter1 += 1.0;
621                                 m_speed.Y = 5.0*BS;
622                         }
623                 }
624
625                 {
626                         m_counter2 -= dtime;
627                         if(m_counter2 < 0.0)
628                         {
629                                 m_counter2 += (float)(myrand()%100)/100*3.0;
630                                 m_yaw += ((float)(myrand()%200)-100)/100*180;
631                                 m_yaw = wrapDegrees(m_yaw);
632                         }
633                 }
634
635                 m_oldpos = m_pos;
636
637                 //m_yaw += dtime*90;
638
639                 move(dtime, v3f(0, -9.81*BS, 0));
640
641                 //updateNodePos();
642
643                 return false;
644         }
645 #ifndef SERVER
646         virtual void clientStep(float dtime)
647         {
648                 //m_pos += m_speed * dtime;
649                 MovingObject::simpleMove(dtime);
650
651                 updateNodePos();
652         }
653         
654         virtual void addToScene(scene::ISceneManager *smgr);
655
656         virtual void removeFromScene()
657         {
658                 if(m_node == NULL)
659                         return;
660
661                 m_node->remove();
662                 m_node = NULL;
663         }
664
665         virtual void updateLight(u8 light_at_pos)
666         {
667                 if(m_node == NULL)
668                         return;
669
670                 u8 li = decode_light(light_at_pos);
671                 video::SColor color(255,li,li,li);
672                 setMeshVerticesColor(m_node->getMesh(), color);
673         }
674         
675 #endif
676
677         virtual std::string getInventoryString()
678         {
679                 // There must be a space after the name
680                 // Or does there?
681                 return std::string("Rat ");
682         }
683
684         /*
685                 Special methods
686         */
687         
688         void updateNodePos()
689         {
690 #ifndef SERVER
691                 if(m_node == NULL)
692                         return;
693
694                 m_node->setPosition(getAbsoluteShowPos());
695                 m_node->setRotation(v3f(0, -m_yaw+180, 0));
696 #endif
697         }
698         
699 protected:
700 #ifndef SERVER
701         scene::IMeshSceneNode *m_node;
702 #endif
703         float m_yaw;
704
705         float m_counter1;
706         float m_counter2;
707         float m_age;
708 };
709
710 /*
711         An object on the map that represents an inventory item
712 */
713
714 class InventoryItem;
715
716 class ItemObject : public MapBlockObject
717 {
718 public:
719         // The constructor of every MapBlockObject should be like this
720         ItemObject(MapBlock *block, s16 id, v3f pos):
721                 MapBlockObject(block, id, pos)
722 #ifndef SERVER
723                 ,m_node(NULL)
724 #endif
725         {
726                 /*m_selection_box = new core::aabbox3d<f32>
727                                 (-BS*0.4,-BS*0.5,-BS*0.4, BS*0.4,BS*0.5,BS*0.4);*/
728                 m_selection_box = new core::aabbox3d<f32>
729                                 (-BS/3,-BS/2,-BS/3, BS/3,-BS/2+BS*2/3,BS/3);
730                 m_yaw = 0.0;
731         }
732         virtual ~ItemObject()
733         {
734                 delete m_selection_box;
735         }
736         
737         /*
738                 Implementation interface
739         */
740         virtual u16 getTypeId() const
741         {
742                 return MAPBLOCKOBJECT_TYPE_ITEM;
743         }
744         virtual void serialize(std::ostream &os, u8 version)
745         {
746                 serializeBase(os, version);
747                 u8 buf[2];
748
749                 // Write text length
750                 writeU16(buf, m_itemstring.size());
751                 os.write((char*)buf, 2);
752                 
753                 // Write text
754                 os.write(m_itemstring.c_str(), m_itemstring.size());
755         }
756         virtual void update(std::istream &is, u8 version)
757         {
758                 u8 buf[2];
759
760                 // Read text length
761                 is.read((char*)buf, 2);
762                 u16 size = readU16(buf);
763
764                 // Read text
765                 std::string old_itemstring = m_itemstring;
766                 m_itemstring.clear();
767                 for(u16 i=0; i<size; i++)
768                 {
769                         is.read((char*)buf, 1);
770                         m_itemstring += buf[0];
771                 }
772                 
773 #ifndef SERVER
774                 if(m_itemstring != old_itemstring && m_node)
775                 {
776                         /*
777                                 Update texture
778                         */
779                         video::ITexture *texture = getItemImage();
780                         scene::IMesh *mesh = m_node->getMesh();
781                         if(mesh->getMeshBufferCount() >= 1)
782                         {
783                                 scene::IMeshBuffer *buf = mesh->getMeshBuffer(0);
784                                 //dstream<<"Setting texture "<<texture<<std::endl;
785                                 buf->getMaterial().setTexture(0, texture);
786                         }
787                 }
788                 
789                 updateSceneNode();
790 #endif
791         }
792
793         virtual bool serverStep(float dtime, u32 daynight_ratio)
794         {
795                 return false;
796         }
797
798 #ifndef SERVER
799         virtual void clientStep(float dtime)
800         {
801                 m_yaw += dtime * 60;
802                 if(m_yaw >= 360.)
803                         m_yaw -= 360.;
804
805                 updateSceneNode();
806         }
807         
808         virtual void addToScene(scene::ISceneManager *smgr);
809         
810         virtual void removeFromScene()
811         {
812                 if(m_node != NULL)
813                 {
814                         m_node->remove();
815                         m_node = NULL;
816                 }
817         }
818         virtual void updateLight(u8 light_at_pos)
819         {
820                 if(m_node == NULL)
821                         return;
822
823                 u8 li = decode_light(light_at_pos);
824                 video::SColor color(255,li,li,li);
825                 setMeshVerticesColor(m_node->getMesh(), color);
826         }
827 #endif
828
829         virtual std::string infoText()
830         {
831                 return std::string("\"") + m_itemstring + "\"";
832         }
833
834         virtual std::string getInventoryString()
835         {
836                 return std::string("ItemObj ")+m_itemstring;
837         }
838
839         /*
840                 Special methods
841         */
842
843         InventoryItem * createInventoryItem();
844         
845 #ifndef SERVER
846         video::ITexture * getItemImage();
847
848         void updateSceneNode()
849         {
850                 if(m_node != NULL)
851                 {
852                         m_node->setPosition(getAbsolutePos());
853                         m_node->setRotation(v3f(0, m_yaw, 0));
854                 }
855         }
856 #endif
857
858         void setItemString(std::string inventorystring)
859         {
860                 m_itemstring = inventorystring;
861                 setBlockChanged();
862         }
863
864         std::string getItemString()
865         {
866                 return m_itemstring;
867         }
868
869 protected:
870 #ifndef SERVER
871         scene::IMeshSceneNode *m_node;
872 #endif
873         std::string m_itemstring;
874         f32 m_yaw;
875 };
876
877 /*
878         NOTE: Not used.
879 */
880 class PlayerObject : public MovingObject
881 {
882 public:
883         PlayerObject(MapBlock *block, s16 id, v3f pos):
884                 MovingObject(block, id, pos),
885 #ifndef SERVER
886                 m_node(NULL),
887 #endif
888                 m_yaw(0)
889         {
890                 m_collision_box = new core::aabbox3d<f32>
891                                 (-BS*0.3,-BS*.25,-BS*0.3, BS*0.3,BS*0.25,BS*0.3);
892                 /*m_selection_box = new core::aabbox3d<f32>
893                                 (-BS*0.3,-BS*.25,-BS*0.3, BS*0.3,BS*0.25,BS*0.3);*/
894         }
895         virtual ~PlayerObject()
896         {
897                 if(m_collision_box)
898                         delete m_collision_box;
899                 if(m_selection_box)
900                         delete m_selection_box;
901         }
902         
903         /*
904                 Implementation interface
905         */
906         virtual u16 getTypeId() const
907         {
908                 return MAPBLOCKOBJECT_TYPE_PLAYER;
909         }
910         virtual void serialize(std::ostream &os, u8 version)
911         {
912                 // Object data is generated from actual player
913         }
914         virtual void update(std::istream &is, u8 version)
915         {
916                 MovingObject::update(is, version);
917                 u8 buf[2];
918                 
919                 // Read yaw * 10
920                 is.read((char*)buf, 2);
921                 s16 yaw_i = readS16(buf);
922                 m_yaw = (f32)yaw_i / 10;
923
924                 updateNodePos();
925         }
926
927         virtual bool serverStep(float dtime, u32 daynight_ratio)
928         {
929                 // Player is handled elsewhere.
930                 // Die.
931                 //return true;
932                 // Actually, fail very loudly:
933                 assert(0);
934         }
935
936 #ifndef SERVER
937         virtual void clientStep(float dtime)
938         {
939                 MovingObject::simpleMove(dtime);
940
941                 updateNodePos();
942         }
943         
944         virtual void addToScene(scene::ISceneManager *smgr);
945
946         virtual void removeFromScene()
947         {
948                 if(m_node == NULL)
949                         return;
950
951                 m_node->remove();
952                 m_node = NULL;
953         }
954
955         virtual void updateLight(u8 light_at_pos)
956         {
957                 if(m_node == NULL)
958                         return;
959
960                 u8 li = decode_light(light_at_pos);
961                 video::SColor color(255,li,li,li);
962                 setMeshVerticesColor(m_node->getMesh(), color);
963         }
964         
965 #endif
966
967         /*
968                 Special methods
969         */
970         
971         void updateNodePos()
972         {
973 #ifndef SERVER
974                 if(m_node == NULL)
975                         return;
976
977                 m_node->setPosition(getAbsoluteShowPos());
978                 m_node->setRotation(v3f(0, -m_yaw+180, 0));
979 #endif
980         }
981         
982 protected:
983 #ifndef SERVER
984         scene::IMeshSceneNode *m_node;
985 #endif
986         float m_yaw;
987
988         v3f m_oldpos;
989 };
990
991 struct DistanceSortedObject
992 {
993         DistanceSortedObject(MapBlockObject *a_obj, f32 a_d)
994         {
995                 obj = a_obj;
996                 d = a_d;
997         }
998         
999         MapBlockObject *obj;
1000         f32 d;
1001
1002         bool operator < (DistanceSortedObject &other)
1003         {
1004                 return d < other.d;
1005         }
1006 };
1007
1008 namespace irr{
1009 namespace scene{
1010         class ISceneManager;
1011 }
1012 }
1013 using namespace irr;
1014
1015 class MapBlockObjectList
1016 {
1017 public:
1018         MapBlockObjectList(MapBlock *block);
1019         ~MapBlockObjectList();
1020
1021         // Writes the count, id, the type id and the parameters of all objects
1022         void serialize(std::ostream &os, u8 version);
1023
1024         // Reads ids, type_ids and parameters.
1025         // Creates, updates and deletes objects.
1026         // If smgr!=NULL, new objects are added to the scene
1027         void update(std::istream &is, u8 version, scene::ISceneManager *smgr,
1028                         u32 daynight_ratio);
1029
1030         // Finds a new unique id
1031         s16 getFreeId() throw(ContainerFullException);
1032         /*
1033                 Adds an object.
1034                 Set id to -1 to have this set it to a suitable one.
1035                 The block pointer member is set to this block.
1036         */
1037         void add(MapBlockObject *object)
1038                         throw(ContainerFullException, AlreadyExistsException);
1039
1040         // Deletes and removes all objects
1041         void clear();
1042
1043         /*
1044                 Removes an object.
1045                 Ignores inexistent objects
1046         */
1047         void remove(s16 id);
1048         /*
1049                 References an object.
1050                 The object will not be valid after step() or of course if
1051                 it is removed.
1052                 Grabbing the lock is recommended while processing.
1053         */
1054         MapBlockObject * get(s16 id);
1055
1056         // You'll want to grab this in a SharedPtr
1057         JMutexAutoLock * getLock()
1058         {
1059                 return new JMutexAutoLock(m_mutex);
1060         }
1061
1062         // Steps all objects and if server==true, removes those that
1063         // want to be removed
1064         void step(float dtime, bool server, u32 daynight_ratio);
1065
1066         // Wraps an object that wants to move onto this block from an another
1067         // Returns true if wrapping was impossible
1068         bool wrapObject(MapBlockObject *object);
1069         
1070         // origin is relative to block
1071         void getObjects(v3f origin, f32 max_d,
1072                         core::array<DistanceSortedObject> &dest);
1073         
1074         // Number of objects
1075         s32 getCount()
1076         {
1077                 return m_objects.size();
1078         }
1079
1080 private:
1081         JMutex m_mutex;
1082         // Key is id
1083         core::map<s16, MapBlockObject*> m_objects;
1084         MapBlock *m_block;
1085
1086         u32 m_last_update_daynight_ratio;
1087 };
1088
1089
1090 #endif
1091