Net Object.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. namespace EE{
  4. namespace Net{
  5. /******************************************************************************/
  6. #define CC4_NOBJ CC4('N','O','B','J')
  7. #define NEIGHBOR_UPDATE_DISTANCE 3.0 // travel distance after which neighbors are updated
  8. /******************************************************************************/
  9. static Bool AreNeighbors(C Vec &a, C Vec &b, World *world)
  10. {
  11. return Dist2(a.xz(), b.xz())<=world->_neighbor_dist2;
  12. }
  13. /******************************************************************************/
  14. Obj::Obj()
  15. {
  16. _pos.zero(); _old_pos.zero(); _area=null; _world=null;
  17. }
  18. /******************************************************************************/
  19. // GET / SET
  20. /******************************************************************************/
  21. Obj& Obj::pos(C Vec &pos)
  22. {
  23. T._pos=pos;
  24. if(inGame())
  25. {
  26. VecI2 xy=_world->worldToArea(pos);
  27. if(_area->xy()!=xy)putToArea(*_world->grid.get(xy).data());
  28. if(Dist2(_old_pos.xz(), pos.xz())>=Sqr(NEIGHBOR_UPDATE_DISTANCE)) // after moving NEIGHBOR_UPDATE_DISTANCE meters
  29. {
  30. _old_pos=pos;
  31. updateNeighbors();
  32. }
  33. }else
  34. {
  35. _old_pos=pos;
  36. }
  37. return T;
  38. }
  39. /******************************************************************************/
  40. void Obj::setWorld(World *world, C Vec &pos)
  41. {
  42. leaveGame();
  43. T._world=world;
  44. T.pos(pos);
  45. }
  46. /******************************************************************************/
  47. // OPERATIONS
  48. /******************************************************************************/
  49. void Obj::enterGame()
  50. {
  51. if(!inGame() && _world)
  52. {
  53. putToArea(*_world->grid.get(_world->worldToArea(pos())).data());
  54. updateNeighbors();
  55. }
  56. }
  57. void Obj::leaveGame()
  58. {
  59. removeFromArea ();
  60. removeNeighbors();
  61. }
  62. /******************************************************************************/
  63. void Obj::removeFromArea()
  64. {
  65. if(_area)
  66. {
  67. _area->_objs.exclude(this);
  68. _area=null;
  69. }
  70. }
  71. void Obj::putToArea(Area &area)
  72. {
  73. removeFromArea();
  74. T._area=&area;
  75. T._area->_objs.include(this);
  76. }
  77. /******************************************************************************/
  78. static void Connect(Obj &a, Obj &b)
  79. {
  80. if(&a!=&b)
  81. {
  82. REP(a.neighbors())if(&a.neighbor(i).obj()==&b)return; // already are neighbors
  83. // first add to containers
  84. a._neighbors.New()._obj=&b;
  85. b._neighbors.New()._obj=&a;
  86. // then run callbacks
  87. a.connected(b);
  88. b.connected(a);
  89. }
  90. }
  91. static void Disconnect(Obj &a, Obj &b)
  92. {
  93. if(&a!=&b)REP(a.neighbors())if(&a.neighbor(i).obj()==&b)
  94. {
  95. // first remove from containers
  96. a._neighbors.remove(i);
  97. REP(b.neighbors())if(&b.neighbor(i).obj()==&a)b._neighbors.remove(i);
  98. // then run callbacks
  99. a.disconnected(b);
  100. b.disconnected(a);
  101. break;
  102. }
  103. }
  104. static void DetectNeighbors(Cell<Area> &cell, Obj &obj)
  105. {
  106. Area &area=cell();
  107. REP( area.objs())if(InRange(i, area.objs())) // InRange in case 'connect' will somehow modify the 'area.objs'
  108. {
  109. Obj &test=area.obj(i);
  110. if(AreNeighbors(test.pos(), obj.pos(), obj.world()))Connect(obj, test);
  111. }
  112. }
  113. void Obj::updateNeighbors()
  114. {
  115. // update existing neighbors
  116. REP(neighbors())
  117. if(InRange(i, neighbors())) // InRange in case 'disconnect' will somehow modify the 'neighbors' container
  118. if(!AreNeighbors(pos(), neighbor(i).obj().pos(), world()))
  119. Disconnect(T, neighbor(i).obj());
  120. // add new neighbors
  121. if(world())world()->grid.func(world()->worldToArea(Rect_C(pos().xz(), world()->neighborDist())), DetectNeighbors, T);
  122. }
  123. void Obj::removeNeighbors()
  124. {
  125. REP(neighbors())
  126. if(InRange(i, neighbors())) // InRange in case 'disconnect' will somehow modify the 'neighbors' container
  127. Disconnect(T, neighbor(i).obj());
  128. }
  129. /******************************************************************************/
  130. // NETWORK
  131. /******************************************************************************/
  132. void Obj::compress(File &f, C StrLibrary *worlds)
  133. {
  134. if(worlds)worlds->putStr(f, Worlds.name(world()));else f.putStr(Worlds.name(world()));
  135. f<<pos();
  136. }
  137. void Obj::decompress(File &f, C StrLibrary *worlds)
  138. {
  139. if(worlds)_world=Worlds(worlds->getStr(f));else _world=Worlds(f.getStr());
  140. f>>_pos;
  141. }
  142. /******************************************************************************/
  143. // IO
  144. /******************************************************************************/
  145. Bool Obj::save(File &f)
  146. {
  147. f.cmpUIntV(0); // version
  148. f.putAsset(Worlds.name(world())); // operate on Str instead of ID in case user uses a custom world name
  149. f<<pos();
  150. return f.ok();
  151. }
  152. Bool Obj::load(File &f)
  153. {
  154. switch(f.decUIntV()) // version
  155. {
  156. case 0:
  157. {
  158. _world=Worlds(f.getAsset()); // operate on Str instead of ID in case user uses a custom world name
  159. f>>_pos;
  160. if(f.ok())return true;
  161. }break;
  162. }
  163. return false;
  164. }
  165. /******************************************************************************/
  166. }}
  167. /******************************************************************************/