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