3 Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
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.
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.
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.
20 #include "mapblockobject.h"
22 // Only for ::getNodeBox, TODO: Get rid of this
24 #include "inventory.h"
25 #include "irrlichtwrapper.h"
31 // This is here because it uses the MapBlock
32 v3f MapBlockObject::getAbsolutePos()
37 // getPosRelative gets nodepos relative to map origin
38 v3f blockpos = intToFloat(m_block->getPosRelative());
39 return blockpos + m_pos;
42 void MapBlockObject::setBlockChanged()
45 m_block->setChangedFlag();
52 v3f MovingObject::getAbsoluteShowPos()
57 // getPosRelative gets nodepos relative to map origin
58 v3f blockpos = intToFloat(m_block->getPosRelative());
59 return blockpos + m_showpos;
62 void MovingObject::move(float dtime, v3f acceleration)
64 DSTACK("%s: typeid=%i, pos=(%f,%f,%f), speed=(%f,%f,%f)"
65 ", dtime=%f, acc=(%f,%f,%f)",
68 m_pos.X, m_pos.Y, m_pos.Z,
69 m_speed.X, m_speed.Y, m_speed.Z,
71 acceleration.X, acceleration.Y, acceleration.Z
74 v3s16 oldpos_i = floatToInt(m_pos);
76 if(m_block->isValidPosition(oldpos_i) == false)
78 // Should have wrapped, cancelling further movement.
82 // No collisions if there is no collision box
83 if(m_collision_box == NULL)
85 m_speed += dtime * acceleration;
86 m_pos += m_speed * dtime;
90 // Set insane speed to zero
91 // Otherwise there will be divides by zero and other silly stuff
92 if(m_speed.getLength() > 1000.0*BS)
95 // Limit speed to a reasonable value
96 float speed_limit = 20.0*BS;
97 if(m_speed.getLength() > speed_limit)
98 m_speed = m_speed * (speed_limit / m_speed.getLength());
100 v3f position = m_pos;
101 v3f oldpos = position;
103 /*std::cout<<"oldpos_i=("<<oldpos_i.X<<","<<oldpos_i.Y<<","
104 <<oldpos_i.Z<<")"<<std::endl;*/
106 // Maximum time increment (for collision detection etc)
107 // Allow 0.1 blocks per increment
108 // time = distance / speed
109 // NOTE: In the loop below collisions are detected at 0.15*BS radius
110 float speedlength = m_speed.getLength();
111 f32 dtime_max_increment;
112 if(fabs(speedlength) > 0.001)
113 dtime_max_increment = 0.05*BS / speedlength;
115 dtime_max_increment = 0.5;
117 m_touching_ground = false;
125 if(dtime > dtime_max_increment)
126 dtime_part = dtime_max_increment;
131 // Begin of dtime limited code
133 m_speed += acceleration * dtime_part;
134 position += m_speed * dtime_part;
140 v3s16 pos_i = floatToInt(position);
142 // The loop length is limited to the object moving a distance
143 f32 d = (float)BS * 0.15;
145 core::aabbox3d<f32> objectbox(
146 m_collision_box->MinEdge + position,
147 m_collision_box->MaxEdge + position
150 core::aabbox3d<f32> objectbox_old(
151 m_collision_box->MinEdge + oldpos,
152 m_collision_box->MaxEdge + oldpos
155 //TODO: Get these ranges from somewhere
156 for(s16 y = oldpos_i.Y - 1; y <= oldpos_i.Y + 2; y++)
157 for(s16 z = oldpos_i.Z - 1; z <= oldpos_i.Z + 1; z++)
158 for(s16 x = oldpos_i.X - 1; x <= oldpos_i.X + 1; x++)
161 if(content_walkable(m_block->getNodeParent(v3s16(x,y,z)).d)
165 catch(InvalidPositionException &e)
167 // Doing nothing here will block the object from
168 // walking over map borders
171 core::aabbox3d<f32> nodebox = Map::getNodeBox(
174 // See if the object is touching ground
176 fabs(nodebox.MaxEdge.Y-objectbox.MinEdge.Y) < d
177 && nodebox.MaxEdge.X-d > objectbox.MinEdge.X
178 && nodebox.MinEdge.X+d < objectbox.MaxEdge.X
179 && nodebox.MaxEdge.Z-d > objectbox.MinEdge.Z
180 && nodebox.MinEdge.Z+d < objectbox.MaxEdge.Z
182 m_touching_ground = true;
185 if(objectbox.intersectsWithBox(nodebox))
193 for(u16 i=0; i<3; i++)
195 f32 nodemax = nodebox.MaxEdge.dotProduct(dirs[i]);
196 f32 nodemin = nodebox.MinEdge.dotProduct(dirs[i]);
197 f32 playermax = objectbox.MaxEdge.dotProduct(dirs[i]);
198 f32 playermin = objectbox.MinEdge.dotProduct(dirs[i]);
199 f32 playermax_old = objectbox_old.MaxEdge.dotProduct(dirs[i]);
200 f32 playermin_old = objectbox_old.MinEdge.dotProduct(dirs[i]);
202 bool main_edge_collides =
203 ((nodemax > playermin && nodemax <= playermin_old + d
204 && m_speed.dotProduct(dirs[i]) < 0)
206 (nodemin < playermax && nodemin >= playermax_old - d
207 && m_speed.dotProduct(dirs[i]) > 0));
209 bool other_edges_collide = true;
210 for(u16 j=0; j<3; j++)
214 f32 nodemax = nodebox.MaxEdge.dotProduct(dirs[j]);
215 f32 nodemin = nodebox.MinEdge.dotProduct(dirs[j]);
216 f32 playermax = objectbox.MaxEdge.dotProduct(dirs[j]);
217 f32 playermin = objectbox.MinEdge.dotProduct(dirs[j]);
218 if(!(nodemax - d > playermin && nodemin + d < playermax))
220 other_edges_collide = false;
225 if(main_edge_collides && other_edges_collide)
227 m_speed -= m_speed.dotProduct(dirs[i]) * dirs[i];
228 position -= position.dotProduct(dirs[i]) * dirs[i];
229 position += oldpos.dotProduct(dirs[i]) * dirs[i];
234 } // if(objectbox.intersectsWithBox(nodebox))
237 } // End of dtime limited loop
238 while(dtime > 0.001);
243 void MovingObject::simpleMove(float dtime)
245 m_pos_animation_time_counter += dtime;
246 m_pos_animation_counter += dtime;
247 v3f movevector = m_pos - m_oldpos;
249 if(m_pos_animation_time < 0.001)
252 moveratio = m_pos_animation_counter / m_pos_animation_time;
255 m_showpos = m_oldpos + movevector * moveratio;
262 void RatObject::addToScene(scene::ISceneManager *smgr)
267 video::IVideoDriver* driver = smgr->getVideoDriver();
269 scene::SMesh *mesh = new scene::SMesh();
270 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
271 video::SColor c(255,255,255,255);
272 video::S3DVertex vertices[4] =
274 video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1),
275 video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1),
276 video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0),
277 video::S3DVertex(-BS/2,BS/4,0, 0,0,0, c, 0,0),
279 u16 indices[] = {0,1,2,2,3,0};
280 buf->append(vertices, 4, indices, 6);
282 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
283 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
284 buf->getMaterial().setTexture
285 (0, driver->getTexture(porting::getDataPath("rat.png").c_str()));
286 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
287 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
288 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
290 mesh->addMeshBuffer(buf);
292 m_node = smgr->addMeshSceneNode(mesh, NULL);
302 void ItemObject::addToScene(scene::ISceneManager *smgr)
307 //video::IVideoDriver* driver = smgr->getVideoDriver();
309 // Get image of item for showing
310 video::ITexture *texture = getItemImage();
316 scene::SMesh *mesh = new scene::SMesh();
318 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
319 video::SColor c(255,255,255,255);
320 video::S3DVertex vertices[4] =
322 /*video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c, 0,1),
323 video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c, 1,1),
324 video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 1,0),
325 video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 0,0),*/
326 video::S3DVertex(BS/3,-BS/2,0, 0,0,0, c, 0,1),
327 video::S3DVertex(-BS/3,-BS/2,0, 0,0,0, c, 1,1),
328 video::S3DVertex(-BS/3,-BS/2+BS*2/3,0, 0,0,0, c, 1,0),
329 video::S3DVertex(BS/3,-BS/2+BS*2/3,0, 0,0,0, c, 0,0),
331 u16 indices[] = {0,1,2,2,3,0};
332 buf->append(vertices, 4, indices, 6);
334 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
335 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
336 buf->getMaterial().setTexture(0, texture);
337 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
338 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
339 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
341 mesh->addMeshBuffer(buf);
344 m_node = smgr->addMeshSceneNode(mesh, NULL);
345 // Set it to use the materials of the meshbuffers directly.
346 // This is needed for changing the texture in the future
347 ((scene::IMeshSceneNode*)m_node)->setReadOnlyMaterials(true);
353 video::ITexture * ItemObject::getItemImage()
356 Create an inventory item to see what is its image
358 video::ITexture *texture = NULL;
359 InventoryItem *item = createInventoryItem();
361 texture = item->getImage();
363 texture = g_irrlicht->getTexture(porting::getDataPath("cloud.png").c_str());*/
371 InventoryItem * ItemObject::createInventoryItem()
374 std::istringstream is(m_itemstring, std::ios_base::binary);
375 InventoryItem *item = InventoryItem::deSerialize(is);
376 dstream<<__FUNCTION_NAME<<": m_itemstring=\""
377 <<m_itemstring<<"\" -> item="<<item
381 catch(SerializationError &e)
383 dstream<<__FUNCTION_NAME<<": serialization error: "
384 <<"m_itemstring=\""<<m_itemstring<<"\""<<std::endl;
393 void PlayerObject::addToScene(scene::ISceneManager *smgr)
398 video::IVideoDriver* driver = smgr->getVideoDriver();
400 // Attach a simple mesh to the player for showing an image
401 scene::SMesh *mesh = new scene::SMesh();
403 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
404 video::SColor c(255,255,255,255);
405 video::S3DVertex vertices[4] =
407 video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
408 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
409 video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0),
410 video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0),
412 u16 indices[] = {0,1,2,2,3,0};
413 buf->append(vertices, 4, indices, 6);
415 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
416 //buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
417 buf->getMaterial().setTexture(0, driver->getTexture(porting::getDataPath("player.png").c_str()));
418 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
419 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
420 //buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
421 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
423 mesh->addMeshBuffer(buf);
427 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
428 video::SColor c(255,255,255,255);
429 video::S3DVertex vertices[4] =
431 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
432 video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
433 video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0),
434 video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0),
436 u16 indices[] = {0,1,2,2,3,0};
437 buf->append(vertices, 4, indices, 6);
439 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
440 //buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
441 buf->getMaterial().setTexture(0, driver->getTexture(porting::getDataPath("player_back.png").c_str()));
442 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
443 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
444 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
446 mesh->addMeshBuffer(buf);
450 m_node = smgr->addMeshSceneNode(mesh, NULL);
460 MapBlockObjectList::MapBlockObjectList(MapBlock *block):
466 MapBlockObjectList::~MapBlockObjectList()
472 The serialization format:
473 [0] u16 number of entries
474 [2] entries (id, typeId, parameters)
477 void MapBlockObjectList::serialize(std::ostream &os, u8 version)
479 JMutexAutoLock lock(m_mutex);
482 writeU16(buf, m_objects.size());
483 os.write((char*)buf, 2);
485 for(core::map<s16, MapBlockObject*>::Iterator
486 i = m_objects.getIterator();
487 i.atEnd() == false; i++)
489 i.getNode()->getValue()->serialize(os, version);
493 void MapBlockObjectList::update(std::istream &is, u8 version,
494 scene::ISceneManager *smgr, u32 daynight_ratio)
496 JMutexAutoLock lock(m_mutex);
499 Collect all existing ids to a set.
501 As things are updated, they are removed from this.
503 All remaining ones are deleted.
505 core::map<s16, bool> ids_to_delete;
506 for(core::map<s16, MapBlockObject*>::Iterator
507 i = m_objects.getIterator();
508 i.atEnd() == false; i++)
510 ids_to_delete.insert(i.getNode()->getKey(), true);
515 is.read((char*)buf, 2);
516 u16 count = readU16(buf);
518 for(u16 i=0; i<count; i++)
521 is.read((char*)buf, 2);
522 s16 id = readS16(buf);
525 // stored as x1000/BS v3s16
526 is.read((char*)buf, 6);
527 v3s16 pos_i = readV3S16(buf);
528 v3f pos((f32)pos_i.X/1000*BS,
529 (f32)pos_i.Y/1000*BS,
530 (f32)pos_i.Z/1000*BS);
533 is.read((char*)buf, 2);
534 u16 type_id = readU16(buf);
536 bool create_new = false;
538 // Find an object with the id
539 core::map<s16, MapBlockObject*>::Node *n;
540 n = m_objects.find(id);
541 // If no entry is found for id
544 // Insert dummy pointer node
545 m_objects.insert(id, NULL);
547 n = m_objects.find(id);
548 // A new object will be created at this node
551 // If type_id differs
552 else if(n->getValue()->getTypeId() != type_id)
555 delete n->getValue();
556 // A new object will be created at this node
560 MapBlockObject *obj = NULL;
564 /*dstream<<"MapBlockObjectList adding new object"
568 if(type_id == MAPBLOCKOBJECT_TYPE_SIGN)
570 obj = new SignObject(m_block, id, pos);
572 else if(type_id == MAPBLOCKOBJECT_TYPE_RAT)
574 obj = new RatObject(m_block, id, pos);
576 else if(type_id == MAPBLOCKOBJECT_TYPE_ITEM)
578 obj = new ItemObject(m_block, id, pos);
582 // This is fatal because we cannot know the length
583 // of the object's data
584 throw SerializationError
585 ("MapBlockObjectList::update(): Unknown MapBlockObject type");
589 //obj->addToScene(smgr, daynight_ratio);
590 obj->addToScene(smgr);
598 /*if(daynight_ratio != m_last_update_daynight_ratio)
600 obj->removeFromScene();
601 obj->addToScene(smgr, daynight_ratio);
605 // Now there is an object in obj.
608 obj->update(is, version);
611 Update light on client
615 u8 light = LIGHT_MAX;
617 v3s16 relpos_i = floatToInt(obj->m_pos);
618 MapNode n = m_block->getNodeParent(relpos_i);
619 light = n.getLightBlend(daynight_ratio);
621 catch(InvalidPositionException &e) {}
622 obj->updateLight(light);
625 // Remove from deletion list
626 if(ids_to_delete.find(id) != NULL)
627 ids_to_delete.remove(id);
630 // Delete all objects whose ids_to_delete remain in ids_to_delete
631 for(core::map<s16, bool>::Iterator
632 i = ids_to_delete.getIterator();
633 i.atEnd() == false; i++)
635 s16 id = i.getNode()->getKey();
637 /*dstream<<"MapBlockObjectList deleting object"
641 MapBlockObject *obj = m_objects[id];
642 obj->removeFromScene();
644 m_objects.remove(id);
647 m_last_update_daynight_ratio = daynight_ratio;
650 s16 MapBlockObjectList::getFreeId() throw(ContainerFullException)
655 if(m_objects.find(id) == NULL)
658 throw ContainerFullException
659 ("MapBlockObjectList doesn't fit more objects");
664 void MapBlockObjectList::add(MapBlockObject *object)
665 throw(ContainerFullException, AlreadyExistsException)
669 dstream<<"MapBlockObjectList::add(): NULL object"<<std::endl;
673 JMutexAutoLock lock(m_mutex);
675 // Create unique id if id==-1
676 if(object->m_id == -1)
678 object->m_id = getFreeId();
681 if(m_objects.find(object->m_id) != NULL)
683 dstream<<"MapBlockObjectList::add(): "
684 "object with same id already exists"<<std::endl;
685 throw AlreadyExistsException
686 ("MapBlockObjectList already has given id");
689 object->m_block = m_block;
691 /*v3f p = object->m_pos;
692 dstream<<"MapBlockObjectList::add(): "
693 <<"m_block->getPos()=("
694 <<m_block->getPos().X<<","
695 <<m_block->getPos().Y<<","
696 <<m_block->getPos().Z<<")"
697 <<" inserting object with id="<<object->m_id
699 <<"("<<p.X<<","<<p.Y<<","<<p.Z<<")"
702 m_objects.insert(object->m_id, object);
705 void MapBlockObjectList::clear()
707 JMutexAutoLock lock(m_mutex);
709 for(core::map<s16, MapBlockObject*>::Iterator
710 i = m_objects.getIterator();
711 i.atEnd() == false; i++)
713 MapBlockObject *obj = i.getNode()->getValue();
714 //FIXME: This really shouldn't be NULL at any time,
715 // but this condition was added because it was.
718 obj->removeFromScene();
726 void MapBlockObjectList::remove(s16 id)
728 JMutexAutoLock lock(m_mutex);
730 core::map<s16, MapBlockObject*>::Node *n;
731 n = m_objects.find(id);
735 n->getValue()->removeFromScene();
736 delete n->getValue();
737 m_objects.remove(id);
740 MapBlockObject * MapBlockObjectList::get(s16 id)
742 core::map<s16, MapBlockObject*>::Node *n;
743 n = m_objects.find(id);
747 return n->getValue();
750 void MapBlockObjectList::step(float dtime, bool server, u32 daynight_ratio)
752 DSTACK(__FUNCTION_NAME);
754 JMutexAutoLock lock(m_mutex);
756 core::map<s16, bool> ids_to_delete;
759 DSTACK("%s: stepping objects", __FUNCTION_NAME);
761 for(core::map<s16, MapBlockObject*>::Iterator
762 i = m_objects.getIterator();
763 i.atEnd() == false; i++)
765 MapBlockObject *obj = i.getNode()->getValue();
767 DSTACK("%s: stepping object type %i", __FUNCTION_NAME,
773 u8 light = LIGHT_MAX;
775 v3s16 relpos_i = floatToInt(obj->m_pos);
776 MapNode n = m_block->getNodeParent(relpos_i);
777 light = n.getLightBlend(daynight_ratio);
779 catch(InvalidPositionException &e) {}
780 obj->updateLight(light);
782 bool to_delete = obj->serverStep(dtime, daynight_ratio);
785 ids_to_delete.insert(obj->m_id, true);
789 obj->clientStep(dtime);
795 DSTACK("%s: deleting objects", __FUNCTION_NAME);
797 // Delete objects in delete queue
798 for(core::map<s16, bool>::Iterator
799 i = ids_to_delete.getIterator();
800 i.atEnd() == false; i++)
802 s16 id = i.getNode()->getKey();
804 MapBlockObject *obj = m_objects[id];
805 obj->removeFromScene();
807 m_objects.remove(id);
812 Wrap objects on server
819 DSTACK("%s: object wrap loop", __FUNCTION_NAME);
821 for(core::map<s16, MapBlockObject*>::Iterator
822 i = m_objects.getIterator();
823 i.atEnd() == false; i++)
825 MapBlockObject *obj = i.getNode()->getValue();
827 v3s16 pos_i = floatToInt(obj->m_pos);
829 if(m_block->isValidPosition(pos_i))
835 bool impossible = wrapObject(obj);
844 i = m_objects.getIterator();
849 bool MapBlockObjectList::wrapObject(MapBlockObject *object)
851 DSTACK(__FUNCTION_NAME);
853 // No lock here; this is called so that the lock is already locked.
854 //JMutexAutoLock lock(m_mutex);
856 assert(object->m_block == m_block);
857 assert(m_objects.find(object->m_id) != NULL);
858 assert(m_objects[object->m_id] == object);
860 NodeContainer *parentcontainer = m_block->getParent();
861 // This will only work if the parent is the map
862 if(parentcontainer->nodeContainerId() != NODECONTAINER_ID_MAP)
864 dstream<<"WARNING: Wrapping object not possible: "
865 "MapBlock's parent is not map"<<std::endl;
868 // OK, we have the map!
869 Map *map = (Map*)parentcontainer;
871 // Calculate blockpos on map
872 v3s16 oldblock_pos_i_on_map = m_block->getPosRelative();
873 v3f pos_f_on_oldblock = object->m_pos;
874 v3s16 pos_i_on_oldblock = floatToInt(pos_f_on_oldblock);
875 v3s16 pos_i_on_map = pos_i_on_oldblock + oldblock_pos_i_on_map;
876 v3s16 pos_blocks_on_map = getNodeBlockPos(pos_i_on_map);
881 newblock = map->getBlockNoCreate(pos_blocks_on_map);
883 catch(InvalidPositionException &e)
885 // Couldn't find block -> not wrapping
886 /*dstream<<"WARNING: Wrapping object not possible: "
887 <<"could not find new block"
888 <<"("<<pos_blocks_on_map.X
889 <<","<<pos_blocks_on_map.Y
890 <<","<<pos_blocks_on_map.Z
892 /*dstream<<"pos_f_on_oldblock=("
893 <<pos_f_on_oldblock.X<<","
894 <<pos_f_on_oldblock.Y<<","
895 <<pos_f_on_oldblock.Z<<")"
900 if(newblock == m_block)
902 dstream<<"WARNING: Wrapping object not possible: "
903 "newblock == oldblock"<<std::endl;
907 // Calculate position on new block
908 v3f oldblock_pos_f_on_map = intToFloat(oldblock_pos_i_on_map);
909 v3s16 newblock_pos_i_on_map = newblock->getPosRelative();
910 v3f newblock_pos_f_on_map = intToFloat(newblock_pos_i_on_map);
911 v3f pos_f_on_newblock = pos_f_on_oldblock
912 - newblock_pos_f_on_map + oldblock_pos_f_on_map;
914 // Remove object from this block
915 m_objects.remove(object->m_id);
917 // Add object to new block
918 object->m_pos = pos_f_on_newblock;
920 object->m_block = NULL;
921 newblock->addObject(object);
923 //dstream<<"NOTE: Wrapped object"<<std::endl;
928 void MapBlockObjectList::getObjects(v3f origin, f32 max_d,
929 core::array<DistanceSortedObject> &dest)
931 for(core::map<s16, MapBlockObject*>::Iterator
932 i = m_objects.getIterator();
933 i.atEnd() == false; i++)
935 MapBlockObject *obj = i.getNode()->getValue();
937 f32 d = (obj->getRelativeShowPos() - origin).getLength();
942 DistanceSortedObject dso(obj, d);