Changed the Heal Amount of Apples from 6 to 2
[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(getTexturePath("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(getTexturePath("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_yaw = 0;
568                 m_counter1 = 0;
569                 m_counter2 = 0;
570                 m_age = 0;
571         }
572         virtual ~RatObject()
573         {
574                 delete m_collision_box;
575                 delete m_selection_box;
576         }
577         
578         /*
579                 Implementation interface
580         */
581         virtual u16 getTypeId() const
582         {
583                 return MAPBLOCKOBJECT_TYPE_RAT;
584         }
585         virtual void serialize(std::ostream &os, u8 version)
586         {
587                 MovingObject::serialize(os, version);
588                 u8 buf[2];
589
590                 // Write yaw * 10
591                 writeS16(buf, m_yaw * 10);
592                 os.write((char*)buf, 2);
593
594         }
595         virtual void update(std::istream &is, u8 version)
596         {
597                 MovingObject::update(is, version);
598                 u8 buf[2];
599                 
600                 // Read yaw * 10
601                 is.read((char*)buf, 2);
602                 s16 yaw_i = readS16(buf);
603                 m_yaw = (f32)yaw_i / 10;
604
605                 updateNodePos();
606         }
607
608         virtual bool serverStep(float dtime, u32 daynight_ratio)
609         {
610                 m_age += dtime;
611                 if(m_age > 60)
612                         // Die
613                         return true;
614
615                 v3f dir(cos(m_yaw/180*PI),0,sin(m_yaw/180*PI));
616
617                 f32 speed = 2*BS;
618
619                 m_speed.X = speed * dir.X;
620                 m_speed.Z = speed * dir.Z;
621
622                 if(m_touching_ground && (m_oldpos - m_pos).getLength() < dtime*speed/2)
623                 {
624                         m_counter1 -= dtime;
625                         if(m_counter1 < 0.0)
626                         {
627                                 m_counter1 += 1.0;
628                                 m_speed.Y = 5.0*BS;
629                         }
630                 }
631
632                 {
633                         m_counter2 -= dtime;
634                         if(m_counter2 < 0.0)
635                         {
636                                 m_counter2 += (float)(myrand()%100)/100*3.0;
637                                 m_yaw += ((float)(myrand()%200)-100)/100*180;
638                                 m_yaw = wrapDegrees(m_yaw);
639                         }
640                 }
641
642                 m_oldpos = m_pos;
643
644                 //m_yaw += dtime*90;
645
646                 move(dtime, v3f(0, -9.81*BS, 0));
647
648                 //updateNodePos();
649
650                 return false;
651         }
652 #ifndef SERVER
653         virtual void clientStep(float dtime)
654         {
655                 //m_pos += m_speed * dtime;
656                 MovingObject::simpleMove(dtime);
657
658                 updateNodePos();
659         }
660         
661         virtual void addToScene(scene::ISceneManager *smgr);
662
663         virtual void removeFromScene()
664         {
665                 if(m_node == NULL)
666                         return;
667
668                 m_node->remove();
669                 m_node = NULL;
670         }
671
672         virtual void updateLight(u8 light_at_pos)
673         {
674                 if(m_node == NULL)
675                         return;
676
677                 u8 li = decode_light(light_at_pos);
678                 video::SColor color(255,li,li,li);
679
680                 scene::IMesh *mesh = m_node->getMesh();
681                 
682                 u16 mc = mesh->getMeshBufferCount();
683                 for(u16 j=0; j<mc; j++)
684                 {
685                         scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
686                         video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
687                         u16 vc = buf->getVertexCount();
688                         for(u16 i=0; i<vc; i++)
689                         {
690                                 vertices[i].Color = color;
691                         }
692                 }
693         }
694         
695 #endif
696
697         virtual std::string getInventoryString()
698         {
699                 // There must be a space after the name
700                 // Or does there?
701                 return std::string("Rat ");
702         }
703
704         /*
705                 Special methods
706         */
707         
708         void updateNodePos()
709         {
710                 if(m_node == NULL)
711                         return;
712
713                 m_node->setPosition(getAbsoluteShowPos());
714                 m_node->setRotation(v3f(0, -m_yaw+180, 0));
715         }
716         
717 protected:
718         scene::IMeshSceneNode *m_node;
719         float m_yaw;
720
721         float m_counter1;
722         float m_counter2;
723         float m_age;
724 };
725
726 /*
727         An object on the map that represents an inventory item
728 */
729
730 class InventoryItem;
731
732 class ItemObject : public MapBlockObject
733 {
734 public:
735         // The constructor of every MapBlockObject should be like this
736         ItemObject(MapBlock *block, s16 id, v3f pos):
737                 MapBlockObject(block, id, pos),
738                 m_node(NULL)
739         {
740                 /*m_selection_box = new core::aabbox3d<f32>
741                                 (-BS*0.4,-BS*0.5,-BS*0.4, BS*0.4,BS*0.5,BS*0.4);*/
742                 m_selection_box = new core::aabbox3d<f32>
743                                 (-BS/3,-BS/2,-BS/3, BS/3,-BS/2+BS*2/3,BS/3);
744                 m_yaw = 0.0;
745         }
746         virtual ~ItemObject()
747         {
748                 delete m_selection_box;
749         }
750         
751         /*
752                 Implementation interface
753         */
754         virtual u16 getTypeId() const
755         {
756                 return MAPBLOCKOBJECT_TYPE_ITEM;
757         }
758         virtual void serialize(std::ostream &os, u8 version)
759         {
760                 serializeBase(os, version);
761                 u8 buf[2];
762
763                 // Write text length
764                 writeU16(buf, m_itemstring.size());
765                 os.write((char*)buf, 2);
766                 
767                 // Write text
768                 os.write(m_itemstring.c_str(), m_itemstring.size());
769         }
770         virtual void update(std::istream &is, u8 version)
771         {
772                 u8 buf[2];
773
774                 // Read text length
775                 is.read((char*)buf, 2);
776                 u16 size = readU16(buf);
777
778                 // Read text
779                 std::string old_itemstring = m_itemstring;
780                 m_itemstring.clear();
781                 for(u16 i=0; i<size; i++)
782                 {
783                         is.read((char*)buf, 1);
784                         m_itemstring += buf[0];
785                 }
786                 
787 #ifndef SERVER
788                 if(m_itemstring != old_itemstring && m_node)
789                 {
790                         /*
791                                 Update texture
792                         */
793                         video::ITexture *texture = getItemImage();
794                         scene::IMesh *mesh = m_node->getMesh();
795                         if(mesh->getMeshBufferCount() >= 1)
796                         {
797                                 scene::IMeshBuffer *buf = mesh->getMeshBuffer(0);
798                                 //dstream<<"Setting texture "<<texture<<std::endl;
799                                 buf->getMaterial().setTexture(0, texture);
800                         }
801                 }
802                 
803                 updateSceneNode();
804 #endif
805         }
806
807         virtual bool serverStep(float dtime, u32 daynight_ratio)
808         {
809                 return false;
810         }
811
812 #ifndef SERVER
813         virtual void clientStep(float dtime)
814         {
815                 m_yaw += dtime * 60;
816                 if(m_yaw >= 360.)
817                         m_yaw -= 360.;
818
819                 updateSceneNode();
820         }
821         
822         virtual void addToScene(scene::ISceneManager *smgr);
823         
824         virtual void removeFromScene()
825         {
826                 if(m_node != NULL)
827                 {
828                         m_node->remove();
829                         m_node = NULL;
830                 }
831         }
832         virtual void updateLight(u8 light_at_pos)
833         {
834                 if(m_node == NULL)
835                         return;
836
837                 u8 li = decode_light(light_at_pos);
838                 video::SColor color(255,li,li,li);
839
840                 scene::IMesh *mesh = m_node->getMesh();
841                 
842                 u16 mc = mesh->getMeshBufferCount();
843                 for(u16 j=0; j<mc; j++)
844                 {
845                         scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
846                         video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
847                         u16 vc = buf->getVertexCount();
848                         for(u16 i=0; i<vc; i++)
849                         {
850                                 vertices[i].Color = color;
851                         }
852                 }
853         }
854 #endif
855
856         virtual std::string infoText()
857         {
858                 return std::string("\"") + m_itemstring + "\"";
859         }
860
861         virtual std::string getInventoryString()
862         {
863                 return std::string("ItemObj ")+m_itemstring;
864         }
865
866         /*
867                 Special methods
868         */
869
870         InventoryItem * createInventoryItem();
871         
872 #ifndef SERVER
873         video::ITexture * getItemImage();
874
875         void updateSceneNode()
876         {
877                 if(m_node != NULL)
878                 {
879                         m_node->setPosition(getAbsolutePos());
880                         m_node->setRotation(v3f(0, m_yaw, 0));
881                 }
882         }
883 #endif
884
885         void setItemString(std::string inventorystring)
886         {
887                 m_itemstring = inventorystring;
888                 setBlockChanged();
889         }
890
891         std::string getItemString()
892         {
893                 return m_itemstring;
894         }
895
896 protected:
897         scene::IMeshSceneNode *m_node;
898         std::string m_itemstring;
899         f32 m_yaw;
900 };
901
902 /*
903         NOTE: Not used.
904 */
905 class PlayerObject : public MovingObject
906 {
907 public:
908         PlayerObject(MapBlock *block, s16 id, v3f pos):
909                 MovingObject(block, id, pos),
910                 m_node(NULL),
911                 m_yaw(0)
912         {
913                 m_collision_box = new core::aabbox3d<f32>
914                                 (-BS*0.3,-BS*.25,-BS*0.3, BS*0.3,BS*0.25,BS*0.3);
915                 /*m_selection_box = new core::aabbox3d<f32>
916                                 (-BS*0.3,-BS*.25,-BS*0.3, BS*0.3,BS*0.25,BS*0.3);*/
917         }
918         virtual ~PlayerObject()
919         {
920                 if(m_collision_box)
921                         delete m_collision_box;
922                 if(m_selection_box)
923                         delete m_selection_box;
924         }
925         
926         /*
927                 Implementation interface
928         */
929         virtual u16 getTypeId() const
930         {
931                 return MAPBLOCKOBJECT_TYPE_PLAYER;
932         }
933         virtual void serialize(std::ostream &os, u8 version)
934         {
935                 // Object data is generated from actual player
936         }
937         virtual void update(std::istream &is, u8 version)
938         {
939                 MovingObject::update(is, version);
940                 u8 buf[2];
941                 
942                 // Read yaw * 10
943                 is.read((char*)buf, 2);
944                 s16 yaw_i = readS16(buf);
945                 m_yaw = (f32)yaw_i / 10;
946
947                 updateNodePos();
948         }
949
950         virtual bool serverStep(float dtime, u32 daynight_ratio)
951         {
952                 // Player is handled elsewhere.
953                 // Die.
954                 //return true;
955                 // Actually, fail very loudly:
956                 assert(0);
957         }
958
959 #ifndef SERVER
960         virtual void clientStep(float dtime)
961         {
962                 MovingObject::simpleMove(dtime);
963
964                 updateNodePos();
965         }
966         
967         virtual void addToScene(scene::ISceneManager *smgr);
968
969         virtual void removeFromScene()
970         {
971                 if(m_node == NULL)
972                         return;
973
974                 m_node->remove();
975                 m_node = NULL;
976         }
977
978         virtual void updateLight(u8 light_at_pos)
979         {
980                 if(m_node == NULL)
981                         return;
982
983                 u8 li = decode_light(light_at_pos);
984                 video::SColor color(255,li,li,li);
985
986                 scene::IMesh *mesh = m_node->getMesh();
987                 
988                 u16 mc = mesh->getMeshBufferCount();
989                 for(u16 j=0; j<mc; j++)
990                 {
991                         scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
992                         video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
993                         u16 vc = buf->getVertexCount();
994                         for(u16 i=0; i<vc; i++)
995                         {
996                                 vertices[i].Color = color;
997                         }
998                 }
999         }
1000         
1001 #endif
1002
1003         /*
1004                 Special methods
1005         */
1006         
1007         void updateNodePos()
1008         {
1009                 if(m_node == NULL)
1010                         return;
1011
1012                 m_node->setPosition(getAbsoluteShowPos());
1013                 m_node->setRotation(v3f(0, -m_yaw+180, 0));
1014         }
1015         
1016 protected:
1017         scene::IMeshSceneNode *m_node;
1018         float m_yaw;
1019
1020         v3f m_oldpos;
1021 };
1022
1023 struct DistanceSortedObject
1024 {
1025         DistanceSortedObject(MapBlockObject *a_obj, f32 a_d)
1026         {
1027                 obj = a_obj;
1028                 d = a_d;
1029         }
1030         
1031         MapBlockObject *obj;
1032         f32 d;
1033
1034         bool operator < (DistanceSortedObject &other)
1035         {
1036                 return d < other.d;
1037         }
1038 };
1039
1040 class MapBlockObjectList
1041 {
1042 public:
1043         MapBlockObjectList(MapBlock *block);
1044         ~MapBlockObjectList();
1045
1046         // Writes the count, id, the type id and the parameters of all objects
1047         void serialize(std::ostream &os, u8 version);
1048
1049         // Reads ids, type_ids and parameters.
1050         // Creates, updates and deletes objects.
1051         // If smgr!=NULL, new objects are added to the scene
1052         void update(std::istream &is, u8 version, scene::ISceneManager *smgr,
1053                         u32 daynight_ratio);
1054
1055         // Finds a new unique id
1056         s16 getFreeId() throw(ContainerFullException);
1057         /*
1058                 Adds an object.
1059                 Set id to -1 to have this set it to a suitable one.
1060                 The block pointer member is set to this block.
1061         */
1062         void add(MapBlockObject *object)
1063                         throw(ContainerFullException, AlreadyExistsException);
1064
1065         // Deletes and removes all objects
1066         void clear();
1067
1068         /*
1069                 Removes an object.
1070                 Ignores inexistent objects
1071         */
1072         void remove(s16 id);
1073         /*
1074                 References an object.
1075                 The object will not be valid after step() or of course if
1076                 it is removed.
1077                 Grabbing the lock is recommended while processing.
1078         */
1079         MapBlockObject * get(s16 id);
1080
1081         // You'll want to grab this in a SharedPtr
1082         JMutexAutoLock * getLock()
1083         {
1084                 return new JMutexAutoLock(m_mutex);
1085         }
1086
1087         // Steps all objects and if server==true, removes those that
1088         // want to be removed
1089         void step(float dtime, bool server, u32 daynight_ratio);
1090
1091         // Wraps an object that wants to move onto this block from an another
1092         // Returns true if wrapping was impossible
1093         bool wrapObject(MapBlockObject *object);
1094         
1095         // origin is relative to block
1096         void getObjects(v3f origin, f32 max_d,
1097                         core::array<DistanceSortedObject> &dest);
1098         
1099         // Number of objects
1100         s32 getCount()
1101         {
1102                 return m_objects.size();
1103         }
1104
1105 private:
1106         JMutex m_mutex;
1107         // Key is id
1108         core::map<s16, MapBlockObject*> m_objects;
1109         MapBlock *m_block;
1110
1111         u32 m_last_update_daynight_ratio;
1112 };
1113
1114
1115 #endif
1116