Entity.cpp 14 KB

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