6a0c36d9cbf765084949f4bb1f8bdfec1cdf4fc2
[oweals/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                 m_node(NULL)
351         {
352                 m_selection_box = new core::aabbox3d<f32>
353                                 (-BS*0.4,-BS*0.5,-BS*0.4, BS*0.4,BS*0.5,BS*0.4);
354         }
355         virtual ~SignObject()
356         {
357                 delete m_selection_box;
358         }
359         
360         /*
361                 Implementation interface
362         */
363         virtual u16 getTypeId() const
364         {
365                 return MAPBLOCKOBJECT_TYPE_SIGN;
366         }
367         virtual void serialize(std::ostream &os, u8 version)
368         {
369                 serializeBase(os, version);
370                 u8 buf[2];
371
372                 // Write yaw * 10
373                 writeS16(buf, m_yaw * 10);
374                 os.write((char*)buf, 2);
375
376                 // Write text length
377                 writeU16(buf, m_text.size());
378                 os.write((char*)buf, 2);
379                 
380                 // Write text
381                 os.write(m_text.c_str(), m_text.size());
382         }
383         virtual void update(std::istream &is, u8 version)
384         {
385                 u8 buf[2];
386
387                 // Read yaw * 10
388                 is.read((char*)buf, 2);
389                 s16 yaw_i = readS16(buf);
390                 m_yaw = (f32)yaw_i / 10;
391
392                 // Read text length
393                 is.read((char*)buf, 2);
394                 u16 size = readU16(buf);
395
396                 // Read text
397                 m_text.clear();
398                 for(u16 i=0; i<size; i++)
399                 {
400                         is.read((char*)buf, 1);
401                         m_text += buf[0];
402                 }
403
404                 updateSceneNode();
405         }
406         virtual bool serverStep(float dtime, u32 daynight_ratio)
407         {
408                 return false;
409         }
410 #ifndef SERVER
411         virtual void addToScene(scene::ISceneManager *smgr)
412         {
413                 if(m_node != NULL)
414                         return;
415                 
416                 video::IVideoDriver* driver = smgr->getVideoDriver();
417                 
418                 scene::SMesh *mesh = new scene::SMesh();
419                 { // Front
420                 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
421                 video::SColor c(255,255,255,255);
422                 video::S3DVertex vertices[4] =
423                 {
424                         video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c, 0,1),
425                         video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c, 1,1),
426                         video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 1,0),
427                         video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 0,0),
428                 };
429                 u16 indices[] = {0,1,2,2,3,0};
430                 buf->append(vertices, 4, indices, 6);
431                 // Set material
432                 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
433                 //buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
434                 buf->getMaterial().setTexture
435                                 (0, driver->getTexture(porting::getDataPath("sign.png").c_str()));
436                 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
437                 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
438                 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
439                 // Add to mesh
440                 mesh->addMeshBuffer(buf);
441                 buf->drop();
442                 }
443                 { // Back
444                 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
445                 video::SColor c(255,255,255,255);
446                 video::S3DVertex vertices[4] =
447                 {
448                         video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c, 0,1),
449                         video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c, 1,1),
450                         video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0),
451                         video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 0,0),
452                 };
453                 u16 indices[] = {0,1,2,2,3,0};
454                 buf->append(vertices, 4, indices, 6);
455                 // Set material
456                 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
457                 //buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
458                 buf->getMaterial().setTexture
459                                 (0, driver->getTexture(porting::getDataPath("sign_back.png").c_str()));
460                 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
461                 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
462                 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
463                 // Add to mesh
464                 mesh->addMeshBuffer(buf);
465                 buf->drop();
466                 }
467                 m_node = smgr->addMeshSceneNode(mesh, NULL);
468                 mesh->drop();
469
470                 updateSceneNode();
471         }
472         virtual void removeFromScene()
473         {
474                 if(m_node != NULL)
475                 {
476                         m_node->remove();
477                         m_node = NULL;
478                 }
479         }
480         virtual void updateLight(u8 light_at_pos)
481         {
482                 if(m_node == NULL)
483                         return;
484
485                 u8 li = decode_light(light_at_pos);
486                 video::SColor color(255,li,li,li);
487
488                 scene::IMesh *mesh = m_node->getMesh();
489                 
490                 u16 mc = mesh->getMeshBufferCount();
491                 for(u16 j=0; j<mc; j++)
492                 {
493                         scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
494                         video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
495                         u16 vc = buf->getVertexCount();
496                         for(u16 i=0; i<vc; i++)
497                         {
498                                 vertices[i].Color = color;
499                         }
500                 }
501         }
502 #endif
503
504         virtual std::string infoText()
505         {
506                 return std::string("\"") + m_text + "\"";
507         }
508
509         virtual std::string getInventoryString()
510         {
511                 return std::string("Sign ")+m_text;
512         }
513
514         /*
515                 Special methods
516         */
517         void updateSceneNode()
518         {
519 #ifndef SERVER
520                 if(m_node != NULL)
521                 {
522                         m_node->setPosition(getAbsolutePos());
523                         m_node->setRotation(v3f(0, m_yaw, 0));
524                 }
525 #endif
526         }
527
528         void setText(std::string text)
529         {
530                 if(text.size() > SIGN_TEXT_MAX_LENGTH)
531                         text = text.substr(0, SIGN_TEXT_MAX_LENGTH);
532                 m_text = text;
533
534                 setBlockChanged();
535         }
536
537         std::string getText()
538         {
539                 return m_text;
540         }
541
542         void setYaw(f32 yaw)
543         {
544                 m_yaw = yaw;
545
546                 setBlockChanged();
547         }
548         
549 protected:
550         scene::IMeshSceneNode *m_node;
551         std::string m_text;
552         f32 m_yaw;
553 };
554
555 class RatObject : public MovingObject
556 {
557 public:
558         RatObject(MapBlock *block, s16 id, v3f pos):
559                 MovingObject(block, id, pos),
560                 m_node(NULL)
561         {
562                 m_collision_box = new core::aabbox3d<f32>
563                                 (-BS*0.3,-BS*.25,-BS*0.3, BS*0.3,BS*0.25,BS*0.3);
564                 m_selection_box = new core::aabbox3d<f32>
565                                 (-BS*0.3,-BS*.25,-BS*0.3, BS*0.3,BS*0.25,BS*0.3);
566
567                 m_counter1 = 0;
568                 m_counter2 = 0;
569                 m_age = 0;
570         }
571         virtual ~RatObject()
572         {
573                 delete m_collision_box;
574                 delete m_selection_box;
575         }
576         
577         /*
578                 Implementation interface
579         */
580         virtual u16 getTypeId() const
581         {
582                 return MAPBLOCKOBJECT_TYPE_RAT;
583         }
584         virtual void serialize(std::ostream &os, u8 version)
585         {
586                 MovingObject::serialize(os, version);
587                 u8 buf[2];
588
589                 // Write yaw * 10
590                 writeS16(buf, m_yaw * 10);
591                 os.write((char*)buf, 2);
592
593         }
594         virtual void update(std::istream &is, u8 version)
595         {
596                 MovingObject::update(is, version);
597                 u8 buf[2];
598                 
599                 // Read yaw * 10
600                 is.read((char*)buf, 2);
601                 s16 yaw_i = readS16(buf);
602                 m_yaw = (f32)yaw_i / 10;
603
604                 updateNodePos();
605         }
606
607         virtual bool serverStep(float dtime, u32 daynight_ratio)
608         {
609                 m_age += dtime;
610                 if(m_age > 60)
611                         // Die
612                         return true;
613
614                 v3f dir(cos(m_yaw/180*PI),0,sin(m_yaw/180*PI));
615
616                 f32 speed = 2*BS;
617
618                 m_speed.X = speed * dir.X;
619                 m_speed.Z = speed * dir.Z;
620
621                 if(m_touching_ground && (m_oldpos - m_pos).getLength() < dtime*speed/2)
622                 {
623                         m_counter1 -= dtime;
624                         if(m_counter1 < 0.0)
625                         {
626                                 m_counter1 += 1.0;
627                                 m_speed.Y = 5.0*BS;
628                         }
629                 }
630
631                 {
632                         m_counter2 -= dtime;
633                         if(m_counter2 < 0.0)
634                         {
635                                 m_counter2 += (float)(myrand()%100)/100*3.0;
636                                 m_yaw += ((float)(myrand()%200)-100)/100*180;
637                                 m_yaw = wrapDegrees(m_yaw);
638                         }
639                 }
640
641                 m_oldpos = m_pos;
642
643                 //m_yaw += dtime*90;
644
645                 move(dtime, v3f(0, -9.81*BS, 0));
646
647                 //updateNodePos();
648
649                 return false;
650         }
651 #ifndef SERVER
652         virtual void clientStep(float dtime)
653         {
654                 //m_pos += m_speed * dtime;
655                 MovingObject::simpleMove(dtime);
656
657                 updateNodePos();
658         }
659         
660         virtual void addToScene(scene::ISceneManager *smgr);
661
662         virtual void removeFromScene()
663         {
664                 if(m_node == NULL)
665                         return;
666
667                 m_node->remove();
668                 m_node = NULL;
669         }
670
671         virtual void updateLight(u8 light_at_pos)
672         {
673                 if(m_node == NULL)
674                         return;
675
676                 u8 li = decode_light(light_at_pos);
677                 video::SColor color(255,li,li,li);
678
679                 scene::IMesh *mesh = m_node->getMesh();
680                 
681                 u16 mc = mesh->getMeshBufferCount();
682                 for(u16 j=0; j<mc; j++)
683                 {
684                         scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
685                         video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
686                         u16 vc = buf->getVertexCount();
687                         for(u16 i=0; i<vc; i++)
688                         {
689                                 vertices[i].Color = color;
690                         }
691                 }
692         }
693         
694 #endif
695
696         virtual std::string getInventoryString()
697         {
698                 // There must be a space after the name
699                 // Or does there?
700                 return std::string("Rat ");
701         }
702
703         /*
704                 Special methods
705         */
706         
707         void updateNodePos()
708         {
709                 if(m_node == NULL)
710                         return;
711
712                 m_node->setPosition(getAbsoluteShowPos());
713                 m_node->setRotation(v3f(0, -m_yaw+180, 0));
714         }
715         
716 protected:
717         scene::IMeshSceneNode *m_node;
718         float m_yaw;
719
720         float m_counter1;
721         float m_counter2;
722         float m_age;
723 };
724
725 /*
726         An object on the map that represents an inventory item
727 */
728
729 class InventoryItem;
730
731 class ItemObject : public MapBlockObject
732 {
733 public:
734         // The constructor of every MapBlockObject should be like this
735         ItemObject(MapBlock *block, s16 id, v3f pos):
736                 MapBlockObject(block, id, pos),
737                 m_node(NULL)
738         {
739                 /*m_selection_box = new core::aabbox3d<f32>
740                                 (-BS*0.4,-BS*0.5,-BS*0.4, BS*0.4,BS*0.5,BS*0.4);*/
741                 m_selection_box = new core::aabbox3d<f32>
742                                 (-BS/3,-BS/2,-BS/3, BS/3,-BS/2+BS*2/3,BS/3);
743                 m_yaw = 0.0;
744         }
745         virtual ~ItemObject()
746         {
747                 delete m_selection_box;
748         }
749         
750         /*
751                 Implementation interface
752         */
753         virtual u16 getTypeId() const
754         {
755                 return MAPBLOCKOBJECT_TYPE_ITEM;
756         }
757         virtual void serialize(std::ostream &os, u8 version)
758         {
759                 serializeBase(os, version);
760                 u8 buf[2];
761
762                 // Write text length
763                 writeU16(buf, m_itemstring.size());
764                 os.write((char*)buf, 2);
765                 
766                 // Write text
767                 os.write(m_itemstring.c_str(), m_itemstring.size());
768         }
769         virtual void update(std::istream &is, u8 version)
770         {
771                 u8 buf[2];
772
773                 // Read text length
774                 is.read((char*)buf, 2);
775                 u16 size = readU16(buf);
776
777                 // Read text
778                 std::string old_itemstring = m_itemstring;
779                 m_itemstring.clear();
780                 for(u16 i=0; i<size; i++)
781                 {
782                         is.read((char*)buf, 1);
783                         m_itemstring += buf[0];
784                 }
785                 
786 #ifndef SERVER
787                 if(m_itemstring != old_itemstring && m_node)
788                 {
789                         /*
790                                 Update texture
791                         */
792                         video::ITexture *texture = getItemImage();
793                         scene::IMesh *mesh = m_node->getMesh();
794                         if(mesh->getMeshBufferCount() >= 1)
795                         {
796                                 scene::IMeshBuffer *buf = mesh->getMeshBuffer(0);
797                                 //dstream<<"Setting texture "<<texture<<std::endl;
798                                 buf->getMaterial().setTexture(0, texture);
799                         }
800                 }
801                 
802                 updateSceneNode();
803 #endif
804         }
805
806         virtual bool serverStep(float dtime, u32 daynight_ratio)
807         {
808                 return false;
809         }
810
811 #ifndef SERVER
812         virtual void clientStep(float dtime)
813         {
814                 m_yaw += dtime * 60;
815                 if(m_yaw >= 360.)
816                         m_yaw -= 360.;
817
818                 updateSceneNode();
819         }
820         
821         virtual void addToScene(scene::ISceneManager *smgr);
822         
823         virtual void removeFromScene()
824         {
825                 if(m_node != NULL)
826                 {
827                         m_node->remove();
828                         m_node = NULL;
829                 }
830         }
831         virtual void updateLight(u8 light_at_pos)
832         {
833                 if(m_node == NULL)
834                         return;
835
836                 u8 li = decode_light(light_at_pos);
837                 video::SColor color(255,li,li,li);
838
839                 scene::IMesh *mesh = m_node->getMesh();
840                 
841                 u16 mc = mesh->getMeshBufferCount();
842                 for(u16 j=0; j<mc; j++)
843                 {
844                         scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
845                         video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
846                         u16 vc = buf->getVertexCount();
847                         for(u16 i=0; i<vc; i++)
848                         {
849                                 vertices[i].Color = color;
850                         }
851                 }
852         }
853 #endif
854
855         virtual std::string infoText()
856         {
857                 return std::string("\"") + m_itemstring + "\"";
858         }
859
860         virtual std::string getInventoryString()
861         {
862                 return std::string("ItemObj ")+m_itemstring;
863         }
864
865         /*
866                 Special methods
867         */
868
869         InventoryItem * createInventoryItem();
870         
871 #ifndef SERVER
872         video::ITexture * getItemImage();
873
874         void updateSceneNode()
875         {
876                 if(m_node != NULL)
877                 {
878                         m_node->setPosition(getAbsolutePos());
879                         m_node->setRotation(v3f(0, m_yaw, 0));
880                 }
881         }
882 #endif
883
884         void setItemString(std::string inventorystring)
885         {
886                 m_itemstring = inventorystring;
887                 setBlockChanged();
888         }
889
890         std::string getItemString()
891         {
892                 return m_itemstring;
893         }
894
895 protected:
896         scene::IMeshSceneNode *m_node;
897         std::string m_itemstring;
898         f32 m_yaw;
899 };
900
901 /*
902         NOTE: Not used.
903 */
904 class PlayerObject : public MovingObject
905 {
906 public:
907         PlayerObject(MapBlock *block, s16 id, v3f pos):
908                 MovingObject(block, id, pos),
909                 m_node(NULL)
910         {
911                 m_collision_box = new core::aabbox3d<f32>
912                                 (-BS*0.3,-BS*.25,-BS*0.3, BS*0.3,BS*0.25,BS*0.3);
913                 /*m_selection_box = new core::aabbox3d<f32>
914                                 (-BS*0.3,-BS*.25,-BS*0.3, BS*0.3,BS*0.25,BS*0.3);*/
915         }
916         virtual ~PlayerObject()
917         {
918                 if(m_collision_box)
919                         delete m_collision_box;
920                 if(m_selection_box)
921                         delete m_selection_box;
922         }
923         
924         /*
925                 Implementation interface
926         */
927         virtual u16 getTypeId() const
928         {
929                 return MAPBLOCKOBJECT_TYPE_PLAYER;
930         }
931         virtual void serialize(std::ostream &os, u8 version)
932         {
933                 // Object data is generated from actual player
934         }
935         virtual void update(std::istream &is, u8 version)
936         {
937                 MovingObject::update(is, version);
938                 u8 buf[2];
939                 
940                 // Read yaw * 10
941                 is.read((char*)buf, 2);
942                 s16 yaw_i = readS16(buf);
943                 m_yaw = (f32)yaw_i / 10;
944
945                 updateNodePos();
946         }
947
948         virtual bool serverStep(float dtime, u32 daynight_ratio)
949         {
950                 // Player is handled elsewhere.
951                 // Die.
952                 //return true;
953                 // Actually, fail very loudly:
954                 assert(0);
955         }
956
957 #ifndef SERVER
958         virtual void clientStep(float dtime)
959         {
960                 MovingObject::simpleMove(dtime);
961
962                 updateNodePos();
963         }
964         
965         virtual void addToScene(scene::ISceneManager *smgr);
966
967         virtual void removeFromScene()
968         {
969                 if(m_node == NULL)
970                         return;
971
972                 m_node->remove();
973                 m_node = NULL;
974         }
975
976         virtual void updateLight(u8 light_at_pos)
977         {
978                 if(m_node == NULL)
979                         return;
980
981                 u8 li = decode_light(light_at_pos);
982                 video::SColor color(255,li,li,li);
983
984                 scene::IMesh *mesh = m_node->getMesh();
985                 
986                 u16 mc = mesh->getMeshBufferCount();
987                 for(u16 j=0; j<mc; j++)
988                 {
989                         scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
990                         video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
991                         u16 vc = buf->getVertexCount();
992                         for(u16 i=0; i<vc; i++)
993                         {
994                                 vertices[i].Color = color;
995                         }
996                 }
997         }
998         
999 #endif
1000
1001         /*
1002                 Special methods
1003         */
1004         
1005         void updateNodePos()
1006         {
1007                 if(m_node == NULL)
1008                         return;
1009
1010                 m_node->setPosition(getAbsoluteShowPos());
1011                 m_node->setRotation(v3f(0, -m_yaw+180, 0));
1012         }
1013         
1014 protected:
1015         scene::IMeshSceneNode *m_node;
1016         float m_yaw;
1017
1018         v3f m_oldpos;
1019 };
1020
1021 struct DistanceSortedObject
1022 {
1023         DistanceSortedObject(MapBlockObject *a_obj, f32 a_d)
1024         {
1025                 obj = a_obj;
1026                 d = a_d;
1027         }
1028         
1029         MapBlockObject *obj;
1030         f32 d;
1031
1032         bool operator < (DistanceSortedObject &other)
1033         {
1034                 return d < other.d;
1035         }
1036 };
1037
1038 class MapBlockObjectList
1039 {
1040 public:
1041         MapBlockObjectList(MapBlock *block);
1042         ~MapBlockObjectList();
1043
1044         // Writes the count, id, the type id and the parameters of all objects
1045         void serialize(std::ostream &os, u8 version);
1046
1047         // Reads ids, type_ids and parameters.
1048         // Creates, updates and deletes objects.
1049         // If smgr!=NULL, new objects are added to the scene
1050         void update(std::istream &is, u8 version, scene::ISceneManager *smgr,
1051                         u32 daynight_ratio);
1052
1053         // Finds a new unique id
1054         s16 getFreeId() throw(ContainerFullException);
1055         /*
1056                 Adds an object.
1057                 Set id to -1 to have this set it to a suitable one.
1058                 The block pointer member is set to this block.
1059         */
1060         void add(MapBlockObject *object)
1061                         throw(ContainerFullException, AlreadyExistsException);
1062
1063         // Deletes and removes all objects
1064         void clear();
1065
1066         /*
1067                 Removes an object.
1068                 Ignores inexistent objects
1069         */
1070         void remove(s16 id);
1071         /*
1072                 References an object.
1073                 The object will not be valid after step() or of course if
1074                 it is removed.
1075                 Grabbing the lock is recommended while processing.
1076         */
1077         MapBlockObject * get(s16 id);
1078
1079         // You'll want to grab this in a SharedPtr
1080         JMutexAutoLock * getLock()
1081         {
1082                 return new JMutexAutoLock(m_mutex);
1083         }
1084
1085         // Steps all objects and if server==true, removes those that
1086         // want to be removed
1087         void step(float dtime, bool server, u32 daynight_ratio);
1088
1089         // Wraps an object that wants to move onto this block from an another
1090         // Returns true if wrapping was impossible
1091         bool wrapObject(MapBlockObject *object);
1092         
1093         // origin is relative to block
1094         void getObjects(v3f origin, f32 max_d,
1095                         core::array<DistanceSortedObject> &dest);
1096         
1097         // Number of objects
1098         s32 getCount()
1099         {
1100                 return m_objects.size();
1101         }
1102
1103 private:
1104         JMutex m_mutex;
1105         // Key is id
1106         core::map<s16, MapBlockObject*> m_objects;
1107         MapBlock *m_block;
1108
1109         u32 m_last_update_daynight_ratio;
1110 };
1111
1112
1113 #endif
1114