Some progress on transitioning from MapBlockObject to ActiveObject.
[oweals/minetest.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
26 core::map<u16, ClientActiveObject::Factory> ClientActiveObject::m_types;
27
28 ClientActiveObject::ClientActiveObject(u16 id):
29         ActiveObject(id)
30 {
31 }
32
33 ClientActiveObject::~ClientActiveObject()
34 {
35         removeFromScene();
36 }
37
38 ClientActiveObject* ClientActiveObject::create(u8 type)
39 {
40         // Find factory function
41         core::map<u16, Factory>::Node *n;
42         n = m_types.find(type);
43         if(n == NULL)
44         {
45                 // If factory is not found, just return.
46                 dstream<<"WARNING: ClientActiveObject: No factory for type="
47                                 <<type<<std::endl;
48                 return NULL;
49         }
50
51         Factory f = n->getValue();
52         ClientActiveObject *object = (*f)();
53         return object;
54 }
55
56 void ClientActiveObject::registerType(u16 type, Factory f)
57 {
58         core::map<u16, Factory>::Node *n;
59         n = m_types.find(type);
60         if(n)
61                 return;
62         m_types.insert(type, f);
63 }
64
65 /*
66         TestCAO
67 */
68
69 // Prototype
70 TestCAO proto_TestCAO;
71
72 TestCAO::TestCAO():
73         ClientActiveObject(0),
74         m_node(NULL),
75         m_position(v3f(0,10*BS,0))
76 {
77         ClientActiveObject::registerType(getType(), create);
78 }
79
80 TestCAO::~TestCAO()
81 {
82 }
83
84 ClientActiveObject* TestCAO::create()
85 {
86         return new TestCAO();
87 }
88
89 void TestCAO::addToScene(scene::ISceneManager *smgr)
90 {
91         if(m_node != NULL)
92                 return;
93         
94         video::IVideoDriver* driver = smgr->getVideoDriver();
95         
96         scene::SMesh *mesh = new scene::SMesh();
97         scene::IMeshBuffer *buf = new scene::SMeshBuffer();
98         video::SColor c(255,255,255,255);
99         video::S3DVertex vertices[4] =
100         {
101                 video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1),
102                 video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1),
103                 video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0),
104                 video::S3DVertex(-BS/2,BS/4,0, 0,0,0, c, 0,0),
105         };
106         u16 indices[] = {0,1,2,2,3,0};
107         buf->append(vertices, 4, indices, 6);
108         // Set material
109         buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
110         buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
111         buf->getMaterial().setTexture
112                         (0, driver->getTexture(porting::getDataPath("rat.png").c_str()));
113         buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
114         buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
115         buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
116         // Add to mesh
117         mesh->addMeshBuffer(buf);
118         buf->drop();
119         m_node = smgr->addMeshSceneNode(mesh, NULL);
120         mesh->drop();
121         updateNodePos();
122 }
123
124 void TestCAO::removeFromScene()
125 {
126         if(m_node == NULL)
127                 return;
128
129         m_node->remove();
130         m_node = NULL;
131 }
132
133 void TestCAO::updateLight(u8 light_at_pos)
134 {
135 }
136
137 v3s16 TestCAO::getLightPosition()
138 {
139         return floatToInt(m_position, BS);
140 }
141
142 void TestCAO::updateNodePos()
143 {
144         if(m_node == NULL)
145                 return;
146
147         m_node->setPosition(m_position);
148         //m_node->setRotation(v3f(0, 45, 0));
149 }
150
151 void TestCAO::step(float dtime)
152 {
153         if(m_node)
154         {
155                 v3f rot = m_node->getRotation();
156                 //dstream<<"dtime="<<dtime<<", rot.Y="<<rot.Y<<std::endl;
157                 rot.Y += dtime * 180;
158                 m_node->setRotation(rot);
159         }
160 }
161
162 void TestCAO::processMessage(const std::string &data)
163 {
164         dstream<<"TestCAO: Got data: "<<data<<std::endl;
165         std::istringstream is(data, std::ios::binary);
166         u16 cmd;
167         is>>cmd;
168         if(cmd == 0)
169         {
170                 v3f newpos;
171                 is>>newpos.X;
172                 is>>newpos.Y;
173                 is>>newpos.Z;
174                 m_position = newpos;
175                 updateNodePos();
176         }
177 }
178
179 /*
180         ItemCAO
181 */
182
183 #include "inventory.h"
184
185 // Prototype
186 ItemCAO proto_ItemCAO;
187
188 ItemCAO::ItemCAO():
189         ClientActiveObject(0),
190         m_selection_box(-BS*0.4,0.0,-BS*0.4, BS*0.4,BS*0.8,BS*0.4),
191         m_node(NULL),
192         m_position(v3f(0,10*BS,0))
193 {
194         ClientActiveObject::registerType(getType(), create);
195 }
196
197 ItemCAO::~ItemCAO()
198 {
199 }
200
201 ClientActiveObject* ItemCAO::create()
202 {
203         return new ItemCAO();
204 }
205
206 void ItemCAO::addToScene(scene::ISceneManager *smgr)
207 {
208         if(m_node != NULL)
209                 return;
210         
211         video::IVideoDriver* driver = smgr->getVideoDriver();
212         
213         scene::SMesh *mesh = new scene::SMesh();
214         scene::IMeshBuffer *buf = new scene::SMeshBuffer();
215         video::SColor c(255,255,255,255);
216         video::S3DVertex vertices[4] =
217         {
218                 /*video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1),
219                 video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1),
220                 video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0),
221                 video::S3DVertex(-BS/2,BS/4,0, 0,0,0, c, 0,0),*/
222                 video::S3DVertex(BS/3,0,0, 0,0,0, c, 0,1),
223                 video::S3DVertex(-BS/3,0,0, 0,0,0, c, 1,1),
224                 video::S3DVertex(-BS/3,0+BS*2/3,0, 0,0,0, c, 1,0),
225                 video::S3DVertex(BS/3,0+BS*2/3,0, 0,0,0, c, 0,0),
226         };
227         u16 indices[] = {0,1,2,2,3,0};
228         buf->append(vertices, 4, indices, 6);
229         // Set material
230         buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
231         buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
232         //buf->getMaterial().setTexture(0, NULL);
233         buf->getMaterial().setTexture
234                         (0, driver->getTexture(porting::getDataPath("rat.png").c_str()));
235         buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
236         buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
237         buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
238         // Add to mesh
239         mesh->addMeshBuffer(buf);
240         buf->drop();
241         m_node = smgr->addMeshSceneNode(mesh, NULL);
242         mesh->drop();
243         // Set it to use the materials of the meshbuffers directly.
244         // This is needed for changing the texture in the future
245         m_node->setReadOnlyMaterials(true);
246         updateNodePos();
247 }
248
249 void ItemCAO::removeFromScene()
250 {
251         if(m_node == NULL)
252                 return;
253
254         m_node->remove();
255         m_node = NULL;
256 }
257
258 void ItemCAO::updateLight(u8 light_at_pos)
259 {
260 }
261
262 v3s16 ItemCAO::getLightPosition()
263 {
264         return floatToInt(m_position, BS);
265 }
266
267 void ItemCAO::updateNodePos()
268 {
269         if(m_node == NULL)
270                 return;
271
272         m_node->setPosition(m_position);
273 }
274
275 void ItemCAO::step(float dtime)
276 {
277         if(m_node)
278         {
279                 v3f rot = m_node->getRotation();
280                 rot.Y += dtime * 120;
281                 m_node->setRotation(rot);
282         }
283 }
284
285 void ItemCAO::processMessage(const std::string &data)
286 {
287         dstream<<"ItemCAO: Got data: "<<data<<std::endl;
288         std::istringstream is(data, std::ios::binary);
289         u16 cmd;
290         is>>cmd;
291         if(cmd == 0)
292         {
293                 v3f newpos;
294                 is>>newpos.X;
295                 is>>newpos.Y;
296                 is>>newpos.Z;
297                 m_position = newpos;
298                 updateNodePos();
299         }
300 }
301
302 void ItemCAO::initialize(const std::string &data)
303 {
304         dstream<<"ItemCAO: Got init data: "<<data<<std::endl;
305         
306         Strfnd fn(data);
307
308         v3f newpos;
309         newpos.X = stoi(fn.next(","));
310         newpos.Y = stoi(fn.next(","));
311         newpos.Z = stoi(fn.next(":"));
312         m_position = newpos;
313         updateNodePos();
314
315         m_inventorystring = fn.next("");
316
317         if(m_node == NULL)
318                 return;
319
320         scene::IMesh *mesh = m_node->getMesh();
321
322         if(mesh == NULL)
323                 return;
324         
325         scene::IMeshBuffer *buf = mesh->getMeshBuffer(0);
326
327         if(buf == NULL)
328                 return;
329
330         /*
331                 Create an inventory item to see what is its image
332         */
333         std::istringstream is(m_inventorystring, std::ios_base::binary);
334         video::ITexture *texture = NULL;
335         try{
336                 InventoryItem *item = NULL;
337                 item = InventoryItem::deSerialize(is);
338                 dstream<<__FUNCTION_NAME<<": m_inventorystring=\""
339                                 <<m_inventorystring<<"\" -> item="<<item
340                                 <<std::endl;
341                 if(item)
342                 {
343                         texture = item->getImage();
344                         delete item;
345                 }
346         }
347         catch(SerializationError &e)
348         {
349                 dstream<<"WARNING: "<<__FUNCTION_NAME
350                                 <<": error deSerializing inventorystring \""
351                                 <<m_inventorystring<<"\""<<std::endl;
352         }
353         
354         // Set meshbuffer texture
355         buf->getMaterial().setTexture(0, texture);
356         
357 }
358
359