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