Entity.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  1. #include "Entity.h"
  2. #include "Dimension.h"
  3. #include "Game.h"
  4. #include "BlockType.h"
  5. #include "ItemSkill.h"
  6. #include "EntityRemovedUpdate.h"
  7. ActionTarget::ActionTarget(Vec3<int> blockPos, Direction blockSide)
  8. : blockPos(blockPos),
  9. targetBlockSide(blockSide),
  10. entityId(-1)
  11. {}
  12. ActionTarget::ActionTarget(int entityId)
  13. : entityId(entityId)
  14. {}
  15. bool ActionTarget::isBlock(Framework::Vec3<int> blockPos, Direction blockSide) const
  16. {
  17. return this->entityId == -1 && this->blockPos == blockPos && this->targetBlockSide == targetBlockSide;
  18. }
  19. bool ActionTarget::isEntity(int entityId) const
  20. {
  21. return this->entityId == entityId;
  22. }
  23. void ActionTarget::applyItemSkillOnTarget(Entity* zActor, ItemSkill* zItemSkill, Item* zUsedItem)
  24. {
  25. if (entityId >= 0)
  26. {
  27. // TODO: get entity from game and apply skill
  28. }
  29. else
  30. {
  31. Block* block = Game::INSTANCE->zRealBlockInstance(blockPos, zActor->getCurrentDimensionId());
  32. if (block)
  33. zItemSkill->use(zActor, zUsedItem, block);
  34. }
  35. }
  36. void ActionTarget::placeBlock(Entity* zActor, Item* zItem)
  37. {
  38. // TODO: check stamina of actor
  39. Block* block = zItem->zPlacedBlockType()->createBlockAt(blockPos + getDirection(targetBlockSide), zItem);
  40. if (block)
  41. {
  42. Game::INSTANCE->zDimension(zActor->getCurrentDimensionId())->placeBlock(block->getPos(), block);
  43. zItem->onPlaced();
  44. // TODO: decrese stamina of actor
  45. }
  46. }
  47. void ActionTarget::toMessage(const ActionTarget* zTarget, NetworkMessage& msg)
  48. {
  49. if (zTarget)
  50. {
  51. if (zTarget->entityId >= 0)
  52. {
  53. char* message = new char[6];
  54. message[0] = 3;
  55. message[1] = 1;
  56. *(int*)(message + 2) = zTarget->entityId;
  57. msg.setMessage(message, 6, 1);
  58. }
  59. else
  60. {
  61. char* message = new char[18];
  62. message[0] = 3;
  63. message[1] = 2;
  64. *(int*)(message + 2) = zTarget->blockPos.x;
  65. *(int*)(message + 6) = zTarget->blockPos.y;
  66. *(int*)(message + 10) = zTarget->blockPos.z;
  67. *(int*)(message + 14) = zTarget->targetBlockSide;
  68. msg.setMessage(message, 18, 1);
  69. }
  70. }
  71. else
  72. {
  73. char* message = new char[2];
  74. message[0] = 3;
  75. message[1] = 0;
  76. msg.setMessage(message, 2, 1);
  77. }
  78. }
  79. void ActionTarget::save(ActionTarget* zTarget, Framework::StreamWriter* zWriter)
  80. {
  81. if (zTarget)
  82. {
  83. if (zTarget->entityId >= 0)
  84. {
  85. char b = 1;
  86. zWriter->schreibe(&b, 1);
  87. zWriter->schreibe((char*)&zTarget->entityId, 4);
  88. }
  89. else
  90. {
  91. char b = 2;
  92. zWriter->schreibe(&b, 1);
  93. zWriter->schreibe((char*)&zTarget->blockPos.x, 4);
  94. zWriter->schreibe((char*)&zTarget->blockPos.y, 4);
  95. zWriter->schreibe((char*)&zTarget->blockPos.z, 4);
  96. zWriter->schreibe((char*)&zTarget->targetBlockSide, 4);
  97. }
  98. }
  99. else
  100. {
  101. char b = 0;
  102. zWriter->schreibe(&b, 1);
  103. }
  104. }
  105. ActionTarget* ActionTarget::load(Framework::StreamReader* zReader)
  106. {
  107. char b;
  108. zReader->lese(&b, 1);
  109. if (b == 1)
  110. {
  111. int id;
  112. zReader->lese((char*)&id, 4);
  113. return new ActionTarget(id);
  114. }
  115. else if (b == 2)
  116. {
  117. Framework::Vec3<int> pos;
  118. Direction side;
  119. zReader->lese((char*)&pos.x, 4);
  120. zReader->lese((char*)&pos.y, 4);
  121. zReader->lese((char*)&pos.z, 4);
  122. zReader->lese((char*)&side, 4);
  123. return new ActionTarget(pos, side);
  124. }
  125. return 0;
  126. }
  127. Entity::Entity(const EntityType* zType, Framework::Vec3<float> location, int dimensionId, int entityId)
  128. : Inventory(location, true),
  129. speed(0, 0, 0),
  130. faceDir(1, 0, 0),
  131. target(0),
  132. zEntityType(zType),
  133. currentDimensionId(dimensionId),
  134. removed(0),
  135. gravityMultiplier(1.f),
  136. id(entityId)
  137. {}
  138. void Entity::onDeath()
  139. {
  140. removed = 1;
  141. Game::INSTANCE->requestWorldUpdate(new EntityRemovedUpdate(id, currentDimensionId, location));
  142. }
  143. void Entity::useItem(const ItemType* zType, Item* zItem)
  144. {
  145. if (zItem && zItem->isEatable())
  146. { // TODO: eat item
  147. zItem->applyFoodEffects(this);
  148. }
  149. else if (zItem && zItem->isPlaceable())
  150. { // TODO: place item
  151. cs.lock();
  152. if (target)
  153. target->placeBlock(this, zItem);
  154. cs.unlock();
  155. }
  156. else if (!zItem || zItem->isUsable())
  157. { // use item skill
  158. cs.lock();
  159. if (target)
  160. {
  161. ItemSkill* selected = 0;
  162. for (ItemSkill* skill : skills)
  163. {
  164. if (skill->zSkillType() == zType)
  165. {
  166. selected = skill;
  167. break;
  168. }
  169. }
  170. if (!selected)
  171. {
  172. selected = zType->createDefaultItemSkill();
  173. skills.add(selected);
  174. }
  175. target->applyItemSkillOnTarget(this, selected, zItem);
  176. }
  177. cs.unlock();
  178. }
  179. }
  180. void Entity::onTargetChange()
  181. {}
  182. void Entity::addMovementFrame(MovementFrame& frame)
  183. {
  184. cs.lock();
  185. movements.add(frame);
  186. cs.unlock();
  187. NetworkMessage message;
  188. message.addressEntity(this);
  189. char msg[37];
  190. msg[0] = 0;
  191. *(float*)(msg + 1) = frame.direction.x;
  192. *(float*)(msg + 5) = frame.direction.y;
  193. *(float*)(msg + 9) = frame.direction.z;
  194. *(float*)(msg + 13) = frame.targetPosition.x;
  195. *(float*)(msg + 17) = frame.targetPosition.y;
  196. *(float*)(msg + 21) = frame.targetPosition.z;
  197. *(int*)(msg + 25) = frame.movementFlags;
  198. *(double*)(msg + 29) = frame.duration;
  199. message.setMessage(msg, 37, 0);
  200. Game::INSTANCE->broadcastMessage(&message);
  201. // TODO: implement movement on server
  202. setPosition(frame.targetPosition);
  203. faceDir = frame.direction;
  204. // TODO implement subscription system to notify only interested clients
  205. }
  206. void Entity::calculateTarget(Framework::Vec3<float> basePos, Framework::Vec3<float> direction)
  207. {
  208. Vec3<float> headPosition = basePos + faceOffset;
  209. int px = (int)floor(headPosition.x);
  210. int py = (int)floor(headPosition.y);
  211. int pz = (int)floor(headPosition.z);
  212. direction.normalize();
  213. Direction dir = BOTTOM;
  214. while (true)
  215. {
  216. if (getDefaultBlock(Game::INSTANCE->zBlockAt(Vec3<int>{ px, py, pz }, currentDimensionId))->isInteractable())
  217. {
  218. if (!target || !target->isBlock({ px, py, pz }, dir))
  219. {
  220. cs.lock();
  221. delete target;
  222. target = new ActionTarget({ px, py, pz }, dir);
  223. cs.unlock();
  224. onTargetChange();
  225. }
  226. break;
  227. }
  228. // collision to neighbor of current block
  229. if (direction.x > 0)
  230. {
  231. float xt = ((float)px + 1.f - headPosition.x) / direction.x;
  232. Vec3<float> tmp = headPosition + direction * xt;
  233. if (xt <= targetDistanceLimit && tmp.y >= (float)py && tmp.y < (float)py + 1.f && tmp.z >= (float)pz && tmp.z < (float)pz + 1.f)
  234. {
  235. dir = WEST;
  236. px++;
  237. continue;
  238. }
  239. }
  240. if (direction.x < 0)
  241. {
  242. float xt = ((float)px - headPosition.x) / direction.x;
  243. Vec3<float> tmp = headPosition + direction * xt;
  244. if (xt <= targetDistanceLimit && tmp.y >= (float)py && tmp.y < (float)py + 1.f && tmp.z >= (float)pz && tmp.z < (float)pz + 1.f)
  245. {
  246. dir = EAST;
  247. px--;
  248. continue;
  249. }
  250. }
  251. if (direction.y > 0)
  252. {
  253. float yt = ((float)py + 1.f - headPosition.y) / direction.y;
  254. Vec3<float> tmp = headPosition + direction * yt;
  255. if (yt <= targetDistanceLimit && tmp.x >= (float)px && tmp.x < (float)px + 1.f && tmp.z >= (float)pz && tmp.z < (float)pz + 1.f)
  256. {
  257. dir = NORTH;
  258. py++;
  259. continue;
  260. }
  261. }
  262. if (direction.y < 0)
  263. {
  264. float yt = ((float)py - headPosition.y) / direction.y;
  265. Vec3<float> tmp = headPosition + direction * yt;
  266. if (yt <= targetDistanceLimit && tmp.x >= (float)px && tmp.x < (float)px + 1.f && tmp.z >= (float)pz && tmp.z < (float)pz + 1.f)
  267. {
  268. dir = SOUTH;
  269. py--;
  270. continue;
  271. }
  272. }
  273. if (direction.z > 0)
  274. {
  275. float zt = ((float)pz + 1.f - headPosition.z) / direction.z;
  276. Vec3<float> tmp = headPosition + direction * zt;
  277. if (zt <= targetDistanceLimit && tmp.x >= (float)px && tmp.x < (float)px + 1.f && tmp.y >= (float)py && tmp.y < (float)py + 1.f)
  278. {
  279. dir = BOTTOM;
  280. pz++;
  281. continue;
  282. }
  283. }
  284. if (direction.z < 0)
  285. {
  286. float zt = ((float)pz - headPosition.z) / direction.z;
  287. Vec3<float> tmp = headPosition + direction * zt;
  288. if (zt <= targetDistanceLimit && tmp.x >= (float)px && tmp.x < (float)px + 1.f && tmp.y >= (float)py && tmp.y < (float)py + 1)
  289. {
  290. dir = TOP;
  291. pz--;
  292. continue;
  293. }
  294. }
  295. if (target)
  296. {
  297. cs.lock();
  298. delete target;
  299. target = 0;
  300. cs.unlock();
  301. onTargetChange();
  302. }
  303. break;
  304. }
  305. }
  306. void Entity::prepareTick(const Dimension* zDimension)
  307. {}
  308. void Entity::tick(const Dimension* zDimension)
  309. {
  310. if (time.isMeasuring())
  311. {
  312. time.messungEnde();
  313. if (movements.getEintragAnzahl() > 0)
  314. {
  315. MovementFrame currentFrame = movements.get(0);
  316. double seconds = time.getSekunden();
  317. while (seconds > 0)
  318. {
  319. if (currentFrame.duration <= 0)
  320. {
  321. cs.lock();
  322. movements.remove(0);
  323. cs.unlock();
  324. if (movements.getEintragAnzahl() > 0)
  325. currentFrame = movements.get(0);
  326. else
  327. break;
  328. }
  329. double t = MIN(currentFrame.duration, seconds);
  330. // TODO: add collisin detection to reduce cheating capability
  331. location += (currentFrame.targetPosition - location) * (float)(t / currentFrame.duration);
  332. currentFrame.duration -= t;
  333. seconds -= t;
  334. if (currentFrame.duration <= 0)
  335. {
  336. location = currentFrame.targetPosition;
  337. }
  338. }
  339. if (currentFrame.duration > 0)
  340. movements.set(currentFrame, 0);
  341. }
  342. }
  343. time.messungStart();
  344. }
  345. void Entity::api(Framework::StreamReader* zRequest, NetworkMessage* zResponse)
  346. {}
  347. void Entity::onFall(float collisionSpeed)
  348. {
  349. if (collisionSpeed > 5)
  350. {
  351. // TODO: take damage
  352. }
  353. }
  354. void Entity::setPosition(Framework::Vec3<float> pos)
  355. {
  356. location = pos;
  357. }
  358. float Entity::getMaxHP() const
  359. {
  360. return maxHP;
  361. }
  362. float Entity::getCurrentHP() const
  363. {
  364. return currentHP;
  365. }
  366. float Entity::getStamina() const
  367. {
  368. return stamina;
  369. }
  370. float Entity::getMaxStamina() const
  371. {
  372. return maxStamina;
  373. }
  374. float Entity::getHunger() const
  375. {
  376. return hunger;
  377. }
  378. float Entity::getMaxHunger() const
  379. {
  380. return maxHunger;
  381. }
  382. float Entity::getThirst() const
  383. {
  384. return thirst;
  385. }
  386. float Entity::getMaxThirst() const
  387. {
  388. return maxThirst;
  389. }
  390. Framework::Vec3<float> Entity::getSpeed() const
  391. {
  392. return speed;
  393. }
  394. Framework::Vec3<float> Entity::getFaceDir() const
  395. {
  396. return faceDir;
  397. }
  398. Framework::Vec3<float> Entity::getPosition() const
  399. {
  400. return location;
  401. }
  402. float Entity::getGravityMultiplier() const
  403. {
  404. return gravityMultiplier;
  405. }
  406. int Entity::getCurrentDimensionId() const
  407. {
  408. return currentDimensionId;
  409. }
  410. bool Entity::isRemoved() const
  411. {
  412. return removed;
  413. }
  414. const EntityType* Entity::zType() const
  415. {
  416. return zEntityType;
  417. }
  418. const ActionTarget* Entity::zTarget() const
  419. {
  420. return target;
  421. }
  422. int Entity::getId() const
  423. {
  424. return id;
  425. }
  426. bool Entity::hasDefaultModel() const
  427. {
  428. return 1;
  429. }
  430. ModelInfo Entity::getSpecialModel() const
  431. {
  432. return ModelInfo("", "", 0);
  433. }
  434. float Entity::getMaxSpeed() const
  435. {
  436. return maxMovementSpeed;
  437. }