]> git.lizzy.rs Git - dragonfireclient.git/blob - src/clientobject.cpp
updated menu a bit, and some other small fixes
[dragonfireclient.git] / src / clientobject.cpp
1 /*
2 Minetest-c55
3 Copyright (C) 2010-2011 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 #include "clientobject.h"
21 #include "debug.h"
22 #include "porting.h"
23 #include "constants.h"
24 #include "utility.h"
25 #include "environment.h"
26
27 /*
28         ClientActiveObject
29 */
30
31 core::map<u16, ClientActiveObject::Factory> ClientActiveObject::m_types;
32
33 ClientActiveObject::ClientActiveObject(u16 id):
34         ActiveObject(id)
35 {
36 }
37
38 ClientActiveObject::~ClientActiveObject()
39 {
40         removeFromScene();
41 }
42
43 ClientActiveObject* ClientActiveObject::create(u8 type)
44 {
45         // Find factory function
46         core::map<u16, Factory>::Node *n;
47         n = m_types.find(type);
48         if(n == NULL)
49         {
50                 // If factory is not found, just return.
51                 dstream<<"WARNING: ClientActiveObject: No factory for type="
52                                 <<type<<std::endl;
53                 return NULL;
54         }
55
56         Factory f = n->getValue();
57         ClientActiveObject *object = (*f)();
58         return object;
59 }
60
61 void ClientActiveObject::registerType(u16 type, Factory f)
62 {
63         core::map<u16, Factory>::Node *n;
64         n = m_types.find(type);
65         if(n)
66                 return;
67         m_types.insert(type, f);
68 }
69
70 /*
71         TestCAO
72 */
73
74 // Prototype
75 TestCAO proto_TestCAO;
76
77 TestCAO::TestCAO():
78         ClientActiveObject(0),
79         m_node(NULL),
80         m_position(v3f(0,10*BS,0))
81 {
82         ClientActiveObject::registerType(getType(), create);
83 }
84
85 TestCAO::~TestCAO()
86 {
87 }
88
89 ClientActiveObject* TestCAO::create()
90 {
91         return new TestCAO();
92 }
93
94 void TestCAO::addToScene(scene::ISceneManager *smgr)
95 {
96         if(m_node != NULL)
97                 return;
98         
99         video::IVideoDriver* driver = smgr->getVideoDriver();
100         
101         scene::SMesh *mesh = new scene::SMesh();
102         scene::IMeshBuffer *buf = new scene::SMeshBuffer();
103         video::SColor c(255,255,255,255);
104         video::S3DVertex vertices[4] =
105         {
106                 video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1),
107                 video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1),
108                 video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0),
109                 video::S3DVertex(-BS/2,BS/4,0, 0,0,0, c, 0,0),
110         };
111         u16 indices[] = {0,1,2,2,3,0};
112         buf->append(vertices, 4, indices, 6);
113         // Set material
114         buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
115         buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
116         buf->getMaterial().setTexture
117                         (0, driver->getTexture(porting::getDataPath("rat.png").c_str()));
118         buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
119         buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
120         buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
121         // Add to mesh
122         mesh->addMeshBuffer(buf);
123         buf->drop();
124         m_node = smgr->addMeshSceneNode(mesh, NULL);
125         mesh->drop();
126         updateNodePos();
127 }
128
129 void TestCAO::removeFromScene()
130 {
131         if(m_node == NULL)
132                 return;
133
134         m_node->remove();
135         m_node = NULL;
136 }
137
138 void TestCAO::updateLight(u8 light_at_pos)
139 {
140 }
141
142 v3s16 TestCAO::getLightPosition()
143 {
144         return floatToInt(m_position, BS);
145 }
146
147 void TestCAO::updateNodePos()
148 {
149         if(m_node == NULL)
150                 return;
151
152         m_node->setPosition(m_position);
153         //m_node->setRotation(v3f(0, 45, 0));
154 }
155
156 void TestCAO::step(float dtime, ClientEnvironment *env)
157 {
158         if(m_node)
159         {
160                 v3f rot = m_node->getRotation();
161                 //dstream<<"dtime="<<dtime<<", rot.Y="<<rot.Y<<std::endl;
162                 rot.Y += dtime * 180;
163                 m_node->setRotation(rot);
164         }
165 }
166
167 void TestCAO::processMessage(const std::string &data)
168 {
169         dstream<<"TestCAO: Got data: "<<data<<std::endl;
170         std::istringstream is(data, std::ios::binary);
171         u16 cmd;
172         is>>cmd;
173         if(cmd == 0)
174         {
175                 v3f newpos;
176                 is>>newpos.X;
177                 is>>newpos.Y;
178                 is>>newpos.Z;
179                 m_position = newpos;
180                 updateNodePos();
181         }
182 }
183
184 /*
185         ItemCAO
186 */
187
188 #include "inventory.h"
189
190 // Prototype
191 ItemCAO proto_ItemCAO;
192
193 ItemCAO::ItemCAO():
194         ClientActiveObject(0),
195         m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.),
196         m_node(NULL),
197         m_position(v3f(0,10*BS,0))
198 {
199         ClientActiveObject::registerType(getType(), create);
200 }
201
202 ItemCAO::~ItemCAO()
203 {
204 }
205
206 ClientActiveObject* ItemCAO::create()
207 {
208         return new ItemCAO();
209 }
210
211 void ItemCAO::addToScene(scene::ISceneManager *smgr)
212 {
213         if(m_node != NULL)
214                 return;
215         
216         video::IVideoDriver* driver = smgr->getVideoDriver();
217         
218         scene::SMesh *mesh = new scene::SMesh();
219         scene::IMeshBuffer *buf = new scene::SMeshBuffer();
220         video::SColor c(255,255,255,255);
221         video::S3DVertex vertices[4] =
222         {
223                 /*video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1),
224                 video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1),
225                 video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0),
226                 video::S3DVertex(-BS/2,BS/4,0, 0,0,0, c, 0,0),*/
227                 video::S3DVertex(BS/3.,0,0, 0,0,0, c, 0,1),
228                 video::S3DVertex(-BS/3.,0,0, 0,0,0, c, 1,1),
229                 video::S3DVertex(-BS/3.,0+BS*2./3.,0, 0,0,0, c, 1,0),
230                 video::S3DVertex(BS/3.,0+BS*2./3.,0, 0,0,0, c, 0,0),
231         };
232         u16 indices[] = {0,1,2,2,3,0};
233         buf->append(vertices, 4, indices, 6);
234         // Set material
235         buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
236         buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
237         //buf->getMaterial().setTexture(0, NULL);
238         // Initialize with the stick texture
239         buf->getMaterial().setTexture
240                         (0, driver->getTexture(porting::getDataPath("stick.png").c_str()));
241         buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
242         buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
243         buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
244         // Add to mesh
245         mesh->addMeshBuffer(buf);
246         buf->drop();
247         m_node = smgr->addMeshSceneNode(mesh, NULL);
248         mesh->drop();
249         // Set it to use the materials of the meshbuffers directly.
250         // This is needed for changing the texture in the future
251         m_node->setReadOnlyMaterials(true);
252         updateNodePos();
253 }
254
255 void ItemCAO::removeFromScene()
256 {
257         if(m_node == NULL)
258                 return;
259
260         m_node->remove();
261         m_node = NULL;
262 }
263
264 void ItemCAO::updateLight(u8 light_at_pos)
265 {
266         if(m_node == NULL)
267                 return;
268
269         u8 li = decode_light(light_at_pos);
270         video::SColor color(255,li,li,li);
271
272         scene::IMesh *mesh = m_node->getMesh();
273         if(mesh == NULL)
274                 return;
275         
276         u16 mc = mesh->getMeshBufferCount();
277         for(u16 j=0; j<mc; j++)
278         {
279                 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
280                 video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
281                 u16 vc = buf->getVertexCount();
282                 for(u16 i=0; i<vc; i++)
283                 {
284                         vertices[i].Color = color;
285                 }
286         }
287 }
288
289 v3s16 ItemCAO::getLightPosition()
290 {
291         return floatToInt(m_position, BS);
292 }
293
294 void ItemCAO::updateNodePos()
295 {
296         if(m_node == NULL)
297                 return;
298
299         m_node->setPosition(m_position);
300 }
301
302 void ItemCAO::step(float dtime, ClientEnvironment *env)
303 {
304         if(m_node)
305         {
306                 /*v3f rot = m_node->getRotation();
307                 rot.Y += dtime * 120;
308                 m_node->setRotation(rot);*/
309                 LocalPlayer *player = env->getLocalPlayer();
310                 assert(player);
311                 v3f rot = m_node->getRotation();
312                 rot.Y = 180.0 - (player->getYaw());
313                 m_node->setRotation(rot);
314         }
315 }
316
317 void ItemCAO::processMessage(const std::string &data)
318 {
319         dstream<<"ItemCAO: Got message"<<std::endl;
320         std::istringstream is(data, std::ios::binary);
321         // command
322         u8 cmd = readU8(is);
323         if(cmd == 0)
324         {
325                 // pos
326                 m_position = readV3F1000(is);
327                 updateNodePos();
328         }
329 }
330
331 void ItemCAO::initialize(const std::string &data)
332 {
333         dstream<<"ItemCAO: Got init data"<<std::endl;
334         
335         {
336                 std::istringstream is(data, std::ios::binary);
337                 // version
338                 u8 version = readU8(is);
339                 // check version
340                 if(version != 0)
341                         return;
342                 // pos
343                 m_position = readV3F1000(is);
344                 // inventorystring
345                 m_inventorystring = deSerializeString(is);
346         }
347         
348         updateNodePos();
349
350         /*
351                 Update image of node
352         */
353
354         if(m_node == NULL)
355                 return;
356
357         scene::IMesh *mesh = m_node->getMesh();
358
359         if(mesh == NULL)
360                 return;
361         
362         scene::IMeshBuffer *buf = mesh->getMeshBuffer(0);
363
364         if(buf == NULL)
365                 return;
366
367         // Create an inventory item to see what is its image
368         std::istringstream is(m_inventorystring, std::ios_base::binary);
369         video::ITexture *texture = NULL;
370         try{
371                 InventoryItem *item = NULL;
372                 item = InventoryItem::deSerialize(is);
373                 dstream<<__FUNCTION_NAME<<": m_inventorystring=\""
374                                 <<m_inventorystring<<"\" -> item="<<item
375                                 <<std::endl;
376                 if(item)
377                 {
378                         texture = item->getImage();
379                         delete item;
380                 }
381         }
382         catch(SerializationError &e)
383         {
384                 dstream<<"WARNING: "<<__FUNCTION_NAME
385                                 <<": error deSerializing inventorystring \""
386                                 <<m_inventorystring<<"\""<<std::endl;
387         }
388         
389         // Set meshbuffer texture
390         buf->getMaterial().setTexture(0, texture);
391         
392 }
393
394 /*
395         RatCAO
396 */
397
398 #include "inventory.h"
399
400 // Prototype
401 RatCAO proto_RatCAO;
402
403 RatCAO::RatCAO():
404         ClientActiveObject(0),
405         m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.),
406         m_node(NULL),
407         m_position(v3f(0,10*BS,0)),
408         m_yaw(0)
409 {
410         ClientActiveObject::registerType(getType(), create);
411 }
412
413 RatCAO::~RatCAO()
414 {
415 }
416
417 ClientActiveObject* RatCAO::create()
418 {
419         return new RatCAO();
420 }
421
422 void RatCAO::addToScene(scene::ISceneManager *smgr)
423 {
424         if(m_node != NULL)
425                 return;
426         
427         video::IVideoDriver* driver = smgr->getVideoDriver();
428         
429         scene::SMesh *mesh = new scene::SMesh();
430         scene::IMeshBuffer *buf = new scene::SMeshBuffer();
431         video::SColor c(255,255,255,255);
432         video::S3DVertex vertices[4] =
433         {
434                 video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
435                 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
436                 video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0),
437                 video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 0,0),
438         };
439         u16 indices[] = {0,1,2,2,3,0};
440         buf->append(vertices, 4, indices, 6);
441         // Set material
442         buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
443         buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
444         //buf->getMaterial().setTexture(0, NULL);
445         buf->getMaterial().setTexture
446                         (0, driver->getTexture(porting::getDataPath("rat.png").c_str()));
447         buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
448         buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
449         buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
450         // Add to mesh
451         mesh->addMeshBuffer(buf);
452         buf->drop();
453         m_node = smgr->addMeshSceneNode(mesh, NULL);
454         mesh->drop();
455         // Set it to use the materials of the meshbuffers directly.
456         // This is needed for changing the texture in the future
457         m_node->setReadOnlyMaterials(true);
458         updateNodePos();
459 }
460
461 void RatCAO::removeFromScene()
462 {
463         if(m_node == NULL)
464                 return;
465
466         m_node->remove();
467         m_node = NULL;
468 }
469
470 void RatCAO::updateLight(u8 light_at_pos)
471 {
472         if(m_node == NULL)
473                 return;
474
475         u8 li = decode_light(light_at_pos);
476         video::SColor color(255,li,li,li);
477
478         scene::IMesh *mesh = m_node->getMesh();
479         if(mesh == NULL)
480                 return;
481         
482         u16 mc = mesh->getMeshBufferCount();
483         for(u16 j=0; j<mc; j++)
484         {
485                 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
486                 video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
487                 u16 vc = buf->getVertexCount();
488                 for(u16 i=0; i<vc; i++)
489                 {
490                         vertices[i].Color = color;
491                 }
492         }
493 }
494
495 v3s16 RatCAO::getLightPosition()
496 {
497         return floatToInt(m_position+v3f(0,BS*0.5,0), BS);
498 }
499
500 void RatCAO::updateNodePos()
501 {
502         if(m_node == NULL)
503                 return;
504
505         //m_node->setPosition(m_position);
506         m_node->setPosition(pos_translator.vect_show);
507
508         v3f rot = m_node->getRotation();
509         rot.Y = 180.0 - m_yaw;
510         m_node->setRotation(rot);
511 }
512
513 void RatCAO::step(float dtime, ClientEnvironment *env)
514 {
515         pos_translator.translate(dtime);
516         updateNodePos();
517 }
518
519 void RatCAO::processMessage(const std::string &data)
520 {
521         //dstream<<"RatCAO: Got message"<<std::endl;
522         std::istringstream is(data, std::ios::binary);
523         // command
524         u8 cmd = readU8(is);
525         if(cmd == 0)
526         {
527                 // pos
528                 m_position = readV3F1000(is);
529                 pos_translator.update(m_position);
530                 // yaw
531                 m_yaw = readF1000(is);
532                 updateNodePos();
533         }
534 }
535
536 void RatCAO::initialize(const std::string &data)
537 {
538         //dstream<<"RatCAO: Got init data"<<std::endl;
539         
540         {
541                 std::istringstream is(data, std::ios::binary);
542                 // version
543                 u8 version = readU8(is);
544                 // check version
545                 if(version != 0)
546                         return;
547                 // pos
548                 m_position = readV3F1000(is);
549                 pos_translator.init(m_position);
550         }
551         
552         updateNodePos();
553 }
554
555 /*
556         Oerkki1CAO
557 */
558
559 #include "inventory.h"
560
561 // Prototype
562 Oerkki1CAO proto_Oerkki1CAO;
563
564 Oerkki1CAO::Oerkki1CAO():
565         ClientActiveObject(0),
566         m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2.,BS/3.),
567         m_node(NULL),
568         m_position(v3f(0,10*BS,0)),
569         m_yaw(0)
570 {
571         ClientActiveObject::registerType(getType(), create);
572 }
573
574 Oerkki1CAO::~Oerkki1CAO()
575 {
576 }
577
578 ClientActiveObject* Oerkki1CAO::create()
579 {
580         return new Oerkki1CAO();
581 }
582
583 void Oerkki1CAO::addToScene(scene::ISceneManager *smgr)
584 {
585         if(m_node != NULL)
586                 return;
587         
588         video::IVideoDriver* driver = smgr->getVideoDriver();
589         
590         scene::SMesh *mesh = new scene::SMesh();
591         scene::IMeshBuffer *buf = new scene::SMeshBuffer();
592         video::SColor c(255,255,255,255);
593         video::S3DVertex vertices[4] =
594         {
595                 video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
596                 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
597                 video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0),
598                 video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0),
599         };
600         u16 indices[] = {0,1,2,2,3,0};
601         buf->append(vertices, 4, indices, 6);
602         // Set material
603         buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
604         buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
605         //buf->getMaterial().setTexture(0, NULL);
606         buf->getMaterial().setTexture
607                         (0, driver->getTexture(porting::getDataPath("oerkki1.png").c_str()));
608         buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
609         buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
610         buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
611         // Add to mesh
612         mesh->addMeshBuffer(buf);
613         buf->drop();
614         m_node = smgr->addMeshSceneNode(mesh, NULL);
615         mesh->drop();
616         // Set it to use the materials of the meshbuffers directly.
617         // This is needed for changing the texture in the future
618         m_node->setReadOnlyMaterials(true);
619         updateNodePos();
620 }
621
622 void Oerkki1CAO::removeFromScene()
623 {
624         if(m_node == NULL)
625                 return;
626
627         m_node->remove();
628         m_node = NULL;
629 }
630
631 void Oerkki1CAO::updateLight(u8 light_at_pos)
632 {
633         if(m_node == NULL)
634                 return;
635
636         u8 li = decode_light(light_at_pos);
637         video::SColor color(255,li,li,li);
638
639         scene::IMesh *mesh = m_node->getMesh();
640         if(mesh == NULL)
641                 return;
642         
643         u16 mc = mesh->getMeshBufferCount();
644         for(u16 j=0; j<mc; j++)
645         {
646                 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
647                 video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
648                 u16 vc = buf->getVertexCount();
649                 for(u16 i=0; i<vc; i++)
650                 {
651                         vertices[i].Color = color;
652                 }
653         }
654 }
655
656 v3s16 Oerkki1CAO::getLightPosition()
657 {
658         return floatToInt(m_position+v3f(0,BS*1.5,0), BS);
659 }
660
661 void Oerkki1CAO::updateNodePos()
662 {
663         if(m_node == NULL)
664                 return;
665
666         //m_node->setPosition(m_position);
667         m_node->setPosition(pos_translator.vect_show);
668
669         v3f rot = m_node->getRotation();
670         rot.Y = 180.0 - m_yaw + 90.0;
671         m_node->setRotation(rot);
672 }
673
674 void Oerkki1CAO::step(float dtime, ClientEnvironment *env)
675 {
676         pos_translator.translate(dtime);
677         updateNodePos();
678
679         LocalPlayer *player = env->getLocalPlayer();
680         assert(player);
681         
682         v3f playerpos = player->getPosition();
683         v2f playerpos_2d(playerpos.X,playerpos.Z);
684         v2f objectpos_2d(m_position.X,m_position.Z);
685
686         if(fabs(m_position.Y - playerpos.Y) < 3.0*BS &&
687                         objectpos_2d.getDistanceFrom(playerpos_2d) < 1.0*BS)
688         {
689                 if(m_attack_interval.step(dtime, 0.5))
690                 {
691                         env->damageLocalPlayer(2);
692                 }
693         }
694 }
695
696 void Oerkki1CAO::processMessage(const std::string &data)
697 {
698         //dstream<<"Oerkki1CAO: Got message"<<std::endl;
699         std::istringstream is(data, std::ios::binary);
700         // command
701         u8 cmd = readU8(is);
702         if(cmd == 0)
703         {
704                 // pos
705                 m_position = readV3F1000(is);
706                 pos_translator.update(m_position);
707                 // yaw
708                 m_yaw = readF1000(is);
709                 updateNodePos();
710         }
711 }
712
713 void Oerkki1CAO::initialize(const std::string &data)
714 {
715         //dstream<<"Oerkki1CAO: Got init data"<<std::endl;
716         
717         {
718                 std::istringstream is(data, std::ios::binary);
719                 // version
720                 u8 version = readU8(is);
721                 // check version
722                 if(version != 0)
723                         return;
724                 // pos
725                 m_position = readV3F1000(is);
726                 pos_translator.init(m_position);
727         }
728         
729         updateNodePos();
730 }
731
732