Entity.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708
  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. || blockSide == NO_DIRECTION);
  23. }
  24. bool ActionTarget::isEntity(int entityId) const
  25. {
  26. return this->entityId == entityId;
  27. }
  28. void ActionTarget::applyItemSkillOnTarget(
  29. Entity* zActor, ItemSkill* zItemSkill, Item* zUsedItem)
  30. {
  31. if (entityId >= 0)
  32. {
  33. // TODO: get entity from game and apply skill
  34. }
  35. else
  36. {
  37. Block* block = Game::INSTANCE->zRealBlockInstance(
  38. blockPos, zActor->getCurrentDimensionId());
  39. if (block) zItemSkill->use(zActor, zUsedItem, block);
  40. }
  41. }
  42. void ActionTarget::placeBlock(Entity* zActor, Item* zItem)
  43. {
  44. // TODO: check stamina of actor
  45. auto zB = Game::INSTANCE->zBlockAt(blockPos + getDirection(targetBlockSide),
  46. zActor->getCurrentDimensionId());
  47. if ((zB.isA() && zB.getA()->zBlockType()->getId() == BlockTypeEnum::AIR)
  48. || (zB.isB() && zB.isB() == BlockTypeEnum::AIR))
  49. {
  50. Block* block = zItem->zPlacedBlockType()->createBlockAt(
  51. blockPos + getDirection(targetBlockSide), zItem);
  52. if (block)
  53. {
  54. Game::INSTANCE->zDimension(zActor->getCurrentDimensionId())
  55. ->placeBlock(block->getPos(), block);
  56. zItem->onPlaced();
  57. // TODO: decrese stamina of actor
  58. }
  59. }
  60. }
  61. void ActionTarget::toMessage(
  62. const ActionTarget* zTarget, int dimensionId, NetworkMessage* zMsg)
  63. {
  64. if (zTarget)
  65. {
  66. if (zTarget->entityId >= 0)
  67. {
  68. char* message = new char[6];
  69. message[0] = 3;
  70. message[1] = 1;
  71. *(int*)(message + 2) = zTarget->entityId;
  72. zMsg->setMessage(message, 6);
  73. }
  74. else
  75. {
  76. Framework::Text targetUIML = "";
  77. auto block
  78. = Game::INSTANCE->zBlockAt(zTarget->blockPos, dimensionId);
  79. if (block.isA())
  80. {
  81. targetUIML = block.getA()->getTargetUIML();
  82. }
  83. else if (block.isB())
  84. {
  85. targetUIML = StaticRegistry<BlockType>::INSTANCE
  86. .zElement(block.getB())
  87. ->getTargetUIML();
  88. }
  89. char* message = new char[18 + targetUIML.getLength() + 2];
  90. message[0] = 3;
  91. message[1] = 2;
  92. *(int*)(message + 2) = zTarget->blockPos.x;
  93. *(int*)(message + 6) = zTarget->blockPos.y;
  94. *(int*)(message + 10) = zTarget->blockPos.z;
  95. *(int*)(message + 14) = zTarget->targetBlockSide;
  96. short len = (short)targetUIML.getLength();
  97. *(short*)(message + 18) = len;
  98. memcpy(message + 20, targetUIML.getText(), len);
  99. zMsg->setMessage(message, 18 + len + 2);
  100. }
  101. }
  102. else
  103. {
  104. char* message = new char[2];
  105. message[0] = 3;
  106. message[1] = 0;
  107. zMsg->setMessage(message, 2);
  108. }
  109. }
  110. void ActionTarget::save(ActionTarget* zTarget, Framework::StreamWriter* zWriter)
  111. {
  112. if (zTarget)
  113. {
  114. if (zTarget->entityId >= 0)
  115. {
  116. char b = 1;
  117. zWriter->schreibe(&b, 1);
  118. zWriter->schreibe((char*)&zTarget->entityId, 4);
  119. }
  120. else
  121. {
  122. char b = 2;
  123. zWriter->schreibe(&b, 1);
  124. zWriter->schreibe((char*)&zTarget->blockPos.x, 4);
  125. zWriter->schreibe((char*)&zTarget->blockPos.y, 4);
  126. zWriter->schreibe((char*)&zTarget->blockPos.z, 4);
  127. zWriter->schreibe((char*)&zTarget->targetBlockSide, 4);
  128. }
  129. }
  130. else
  131. {
  132. char b = 0;
  133. zWriter->schreibe(&b, 1);
  134. }
  135. }
  136. ActionTarget* ActionTarget::load(Framework::StreamReader* zReader)
  137. {
  138. char b;
  139. zReader->lese(&b, 1);
  140. if (b == 1)
  141. {
  142. int id;
  143. zReader->lese((char*)&id, 4);
  144. return new ActionTarget(id);
  145. }
  146. else if (b == 2)
  147. {
  148. Framework::Vec3<int> pos;
  149. Direction side;
  150. zReader->lese((char*)&pos.x, 4);
  151. zReader->lese((char*)&pos.y, 4);
  152. zReader->lese((char*)&pos.z, 4);
  153. zReader->lese((char*)&side, 4);
  154. return new ActionTarget(pos, side);
  155. }
  156. return 0;
  157. }
  158. Entity::Entity(
  159. int typeId, Framework::Vec3<float> location, int dimensionId, int entityId)
  160. : Inventory(location, true),
  161. speed(0, 0, 0),
  162. faceDir(1, 0, 0),
  163. target(0),
  164. typeId(typeId),
  165. currentDimensionId(dimensionId),
  166. removed(0),
  167. gravityMultiplier(1.f),
  168. id(entityId),
  169. placeBlockCooldown(0)
  170. {}
  171. void Entity::onDeath()
  172. {
  173. removed = 1;
  174. Game::INSTANCE->requestWorldUpdate(
  175. new EntityRemovedUpdate(id, currentDimensionId, location));
  176. }
  177. void Entity::useItem(int typeId, Item* zItem)
  178. {
  179. if (zItem && zItem->isEatable())
  180. { // TODO: eat item
  181. zItem->applyFoodEffects(this);
  182. }
  183. else if (zItem && zItem->isPlaceable())
  184. { // TODO: place item
  185. if (placeBlockCooldown <= 0)
  186. {
  187. cs.lock();
  188. if (target)
  189. {
  190. target->placeBlock(this, zItem);
  191. placeBlockCooldown = 15;
  192. }
  193. cs.unlock();
  194. }
  195. }
  196. else if (!zItem || zItem->isUsable())
  197. { // use item skill
  198. cs.lock();
  199. if (target)
  200. {
  201. ItemSkill* selected = 0;
  202. for (ItemSkill* skill : skills)
  203. {
  204. if (skill->getTypeId() == typeId)
  205. {
  206. selected = skill;
  207. break;
  208. }
  209. }
  210. if (!selected)
  211. {
  212. selected = StaticRegistry<ItemType>::INSTANCE.zElement(typeId)
  213. ->createDefaultItemSkill();
  214. skills.add(selected);
  215. }
  216. target->applyItemSkillOnTarget(this, selected, zItem);
  217. }
  218. cs.unlock();
  219. }
  220. }
  221. void Entity::onTargetChange() {}
  222. void Entity::addMovementFrame(MovementFrame& frame)
  223. {
  224. cs.lock();
  225. movements.add(frame);
  226. cs.unlock();
  227. NetworkMessage* message = new NetworkMessage();
  228. message->addressEntity(this);
  229. char* msg = new char[37];
  230. msg[0] = 0;
  231. *(float*)(msg + 1) = frame.direction.x;
  232. *(float*)(msg + 5) = frame.direction.y;
  233. *(float*)(msg + 9) = frame.direction.z;
  234. *(float*)(msg + 13) = frame.targetPosition.x;
  235. *(float*)(msg + 17) = frame.targetPosition.y;
  236. *(float*)(msg + 21) = frame.targetPosition.z;
  237. *(int*)(msg + 25) = frame.movementFlags;
  238. *(double*)(msg + 29) = frame.duration;
  239. message->setMessage(msg, 37);
  240. Game::INSTANCE->broadcastMessage(message);
  241. faceDir = frame.direction;
  242. // TODO implement subscription system to notify only interested clients
  243. }
  244. void Entity::calculateTarget(
  245. Framework::Vec3<float> basePos, Framework::Vec3<float> direction)
  246. {
  247. Vec3<float> headPosition = basePos + faceOffset;
  248. int px = (int)floor(headPosition.x);
  249. int py = (int)floor(headPosition.y);
  250. int pz = (int)floor(headPosition.z);
  251. direction.normalize();
  252. Direction dir = BOTTOM;
  253. while (true)
  254. {
  255. if (getDefaultBlock(Game::INSTANCE->zBlockAt(
  256. Vec3<int>{px, py, pz}, currentDimensionId))
  257. ->isInteractable())
  258. {
  259. if (!target || !target->isBlock({px, py, pz}, dir))
  260. {
  261. cs.lock();
  262. delete target;
  263. target = new ActionTarget({px, py, pz}, dir);
  264. cs.unlock();
  265. onTargetChange();
  266. }
  267. break;
  268. }
  269. // collision to neighbor of current block
  270. if (direction.x > 0)
  271. {
  272. float xt = ((float)px + 1.f - headPosition.x) / direction.x;
  273. Vec3<float> tmp = headPosition + direction * xt;
  274. if (xt <= targetDistanceLimit && tmp.y >= (float)py
  275. && tmp.y < (float)py + 1.f && tmp.z >= (float)pz
  276. && tmp.z < (float)pz + 1.f)
  277. {
  278. dir = WEST;
  279. px++;
  280. continue;
  281. }
  282. }
  283. if (direction.x < 0)
  284. {
  285. float xt = ((float)px - headPosition.x) / direction.x;
  286. Vec3<float> tmp = headPosition + direction * xt;
  287. if (xt <= targetDistanceLimit && tmp.y >= (float)py
  288. && tmp.y < (float)py + 1.f && tmp.z >= (float)pz
  289. && tmp.z < (float)pz + 1.f)
  290. {
  291. dir = EAST;
  292. px--;
  293. continue;
  294. }
  295. }
  296. if (direction.y > 0)
  297. {
  298. float yt = ((float)py + 1.f - headPosition.y) / direction.y;
  299. Vec3<float> tmp = headPosition + direction * yt;
  300. if (yt <= targetDistanceLimit && tmp.x >= (float)px
  301. && tmp.x < (float)px + 1.f && tmp.z >= (float)pz
  302. && tmp.z < (float)pz + 1.f)
  303. {
  304. dir = NORTH;
  305. py++;
  306. continue;
  307. }
  308. }
  309. if (direction.y < 0)
  310. {
  311. float yt = ((float)py - headPosition.y) / direction.y;
  312. Vec3<float> tmp = headPosition + direction * yt;
  313. if (yt <= targetDistanceLimit && tmp.x >= (float)px
  314. && tmp.x < (float)px + 1.f && tmp.z >= (float)pz
  315. && tmp.z < (float)pz + 1.f)
  316. {
  317. dir = SOUTH;
  318. py--;
  319. continue;
  320. }
  321. }
  322. if (direction.z > 0)
  323. {
  324. float zt = ((float)pz + 1.f - headPosition.z) / direction.z;
  325. Vec3<float> tmp = headPosition + direction * zt;
  326. if (zt <= targetDistanceLimit && tmp.x >= (float)px
  327. && tmp.x < (float)px + 1.f && tmp.y >= (float)py
  328. && tmp.y < (float)py + 1.f)
  329. {
  330. dir = BOTTOM;
  331. pz++;
  332. continue;
  333. }
  334. }
  335. if (direction.z < 0)
  336. {
  337. float zt = ((float)pz - headPosition.z) / direction.z;
  338. Vec3<float> tmp = headPosition + direction * zt;
  339. if (zt <= targetDistanceLimit && tmp.x >= (float)px
  340. && tmp.x < (float)px + 1.f && tmp.y >= (float)py
  341. && tmp.y < (float)py + 1)
  342. {
  343. dir = TOP;
  344. pz--;
  345. continue;
  346. }
  347. }
  348. if (target)
  349. {
  350. cs.lock();
  351. delete target;
  352. target = 0;
  353. cs.unlock();
  354. onTargetChange();
  355. }
  356. break;
  357. }
  358. }
  359. void Entity::removeStatusBarObserver(Entity* zSource, Framework::Text id)
  360. {
  361. cs.lock();
  362. int index = 0;
  363. for (auto observer : statusBarObservers)
  364. {
  365. if (observer.getFirst() == zSource->getId()
  366. && observer.getSecond().istGleich(id))
  367. {
  368. statusBarObservers.remove(index);
  369. break;
  370. }
  371. index++;
  372. }
  373. cs.unlock();
  374. }
  375. void Entity::addStatusBarObserver(Entity* zSource, Framework::Text id)
  376. {
  377. cs.lock();
  378. for (auto observer : statusBarObservers)
  379. {
  380. if (observer.getFirst() == zSource->getId()
  381. && observer.getSecond().istGleich(id))
  382. {
  383. cs.unlock();
  384. return;
  385. }
  386. }
  387. statusBarObservers.add(ImmutablePair<int, Text>(zSource->getId(), id));
  388. cs.unlock();
  389. }
  390. void Entity::notifyStatusBarObservers(NetworkMessage* msg)
  391. {
  392. cs.lock();
  393. int index = 0;
  394. Array<int> toDelete;
  395. for (auto observer : statusBarObservers)
  396. {
  397. Entity* e = Game::INSTANCE->zEntity(observer.getFirst());
  398. if (e)
  399. {
  400. msg->addressGui(observer.getSecond());
  401. Game::INSTANCE->sendMessage(msg->clone(), e);
  402. }
  403. else
  404. toDelete.add(index, 0);
  405. index++;
  406. }
  407. for (int i : toDelete)
  408. statusBarObservers.remove(i);
  409. cs.unlock();
  410. msg->release();
  411. }
  412. void Entity::prepareTick(const Dimension* zDimension) {}
  413. void Entity::tick(const Dimension* zDimension)
  414. {
  415. if (placeBlockCooldown > 0)
  416. {
  417. placeBlockCooldown--;
  418. }
  419. placeBlockCooldown--;
  420. if (time.isMeasuring())
  421. {
  422. time.messungEnde();
  423. if (movements.getEintragAnzahl() > 0)
  424. {
  425. MovementFrame currentFrame = movements.get(0);
  426. double seconds = time.getSekunden();
  427. while (seconds > 0)
  428. {
  429. if (currentFrame.duration <= 0)
  430. {
  431. cs.lock();
  432. movements.remove(0);
  433. cs.unlock();
  434. if (movements.getEintragAnzahl() > 0)
  435. currentFrame = movements.get(0);
  436. else
  437. break;
  438. }
  439. double t = MIN(currentFrame.duration, seconds);
  440. // TODO: add collisin detection to reduce cheating capability
  441. location += (currentFrame.targetPosition - location)
  442. * (float)(t / currentFrame.duration);
  443. currentFrame.duration -= t;
  444. seconds -= t;
  445. if (currentFrame.duration <= 0)
  446. {
  447. location = currentFrame.targetPosition;
  448. }
  449. }
  450. if (currentFrame.duration > 0) movements.set(currentFrame, 0);
  451. if (getStamina() <= getMaxStamina() - 0.0025f)
  452. {
  453. if (getThirst() > 0 && getHunger() > 0)
  454. {
  455. setStamina(getStamina() + 0.0025f);
  456. setHunger(getHunger() - 0.0005f);
  457. setThirst(getThirst() - 0.0015f);
  458. }
  459. }
  460. }
  461. else
  462. {
  463. if (getStamina() <= getMaxStamina() - 0.005f)
  464. {
  465. if (getThirst() > 0 && getHunger() > 0)
  466. {
  467. setStamina(getStamina() + 0.005f);
  468. setHunger(getHunger() - 0.001f);
  469. setThirst(getThirst() - 0.003f);
  470. }
  471. }
  472. }
  473. }
  474. time.messungStart();
  475. }
  476. void Entity::api(Framework::StreamReader* zRequest,
  477. NetworkMessage* zResponse,
  478. Entity* zSource)
  479. {
  480. char type;
  481. zRequest->lese(&type, 1);
  482. switch (type)
  483. {
  484. case 0: // request status bar state
  485. {
  486. char len;
  487. zRequest->lese(&len, 1);
  488. char* guiId = new char[(int)len + 1];
  489. zRequest->lese(guiId, len);
  490. guiId[(int)len] = 0;
  491. zResponse->addressGui(guiId);
  492. addStatusBarObserver(zSource, guiId);
  493. char* msg = new char[33];
  494. msg[0] = 0;
  495. *(float*)(msg + 1) = getMaxHP();
  496. *(float*)(msg + 5) = getCurrentHP();
  497. *(float*)(msg + 9) = getMaxStamina();
  498. *(float*)(msg + 13) = getStamina();
  499. *(float*)(msg + 17) = getMaxHunger();
  500. *(float*)(msg + 21) = getHunger();
  501. *(float*)(msg + 25) = getMaxThirst();
  502. *(float*)(msg + 29) = getThirst();
  503. zResponse->setMessage(msg, 33);
  504. delete[] guiId;
  505. break;
  506. }
  507. case 1: // remove status bar observer
  508. {
  509. char len;
  510. zRequest->lese(&len, 1);
  511. char* guiId = new char[(int)len + 1];
  512. zRequest->lese(guiId, len);
  513. guiId[(int)len] = 0;
  514. removeStatusBarObserver(zSource, guiId);
  515. delete[] guiId;
  516. break;
  517. }
  518. }
  519. }
  520. void Entity::onFall(float collisionSpeed)
  521. {
  522. if (collisionSpeed > 5)
  523. {
  524. // TODO: take damage
  525. }
  526. }
  527. void Entity::setPosition(Framework::Vec3<float> pos)
  528. {
  529. location = pos;
  530. }
  531. void Entity::setHP(float hp)
  532. {
  533. currentHP = MIN(MAX(hp, 0), maxHP);
  534. NetworkMessage* msg = new NetworkMessage();
  535. char* message = new char[9];
  536. message[0] = 1;
  537. *(float*)(message + 1) = getMaxHP();
  538. *(float*)(message + 5) = getCurrentHP();
  539. msg->setMessage(message, 9);
  540. notifyStatusBarObservers(msg);
  541. }
  542. void Entity::setStamina(float stamina)
  543. {
  544. this->stamina = MIN(MAX(stamina, 0), maxStamina);
  545. NetworkMessage* msg = new NetworkMessage();
  546. char* message = new char[9];
  547. message[0] = 2;
  548. *(float*)(message + 1) = getMaxStamina();
  549. *(float*)(message + 5) = getStamina();
  550. msg->setMessage(message, 9);
  551. notifyStatusBarObservers(msg);
  552. }
  553. void Entity::setHunger(float hunger)
  554. {
  555. this->hunger = MIN(MAX(hunger, 0), maxHunger);
  556. NetworkMessage* msg = new NetworkMessage();
  557. char* message = new char[9];
  558. message[0] = 3;
  559. *(float*)(message + 1) = getMaxHunger();
  560. *(float*)(message + 5) = getHunger();
  561. msg->setMessage(message, 9);
  562. notifyStatusBarObservers(msg);
  563. }
  564. void Entity::setThirst(float thirst)
  565. {
  566. this->thirst = MIN(MAX(thirst, 0), maxThirst);
  567. NetworkMessage* msg = new NetworkMessage();
  568. char* message = new char[9];
  569. message[0] = 4;
  570. *(float*)(message + 1) = getMaxThirst();
  571. *(float*)(message + 5) = getThirst();
  572. msg->setMessage(message, 9);
  573. notifyStatusBarObservers(msg);
  574. }
  575. float Entity::getMaxHP() const
  576. {
  577. return maxHP;
  578. }
  579. float Entity::getCurrentHP() const
  580. {
  581. return currentHP;
  582. }
  583. float Entity::getStamina() const
  584. {
  585. return stamina;
  586. }
  587. float Entity::getMaxStamina() const
  588. {
  589. return maxStamina;
  590. }
  591. float Entity::getHunger() const
  592. {
  593. return hunger;
  594. }
  595. float Entity::getMaxHunger() const
  596. {
  597. return maxHunger;
  598. }
  599. float Entity::getThirst() const
  600. {
  601. return thirst;
  602. }
  603. float Entity::getMaxThirst() const
  604. {
  605. return maxThirst;
  606. }
  607. Framework::Vec3<float> Entity::getSpeed() const
  608. {
  609. return speed;
  610. }
  611. Framework::Vec3<float> Entity::getFaceDir() const
  612. {
  613. return faceDir;
  614. }
  615. Framework::Vec3<float> Entity::getPosition() const
  616. {
  617. return location;
  618. }
  619. float Entity::getGravityMultiplier() const
  620. {
  621. return gravityMultiplier;
  622. }
  623. int Entity::getCurrentDimensionId() const
  624. {
  625. return currentDimensionId;
  626. }
  627. bool Entity::isRemoved() const
  628. {
  629. return removed;
  630. }
  631. const EntityType* Entity::zType() const
  632. {
  633. return StaticRegistry<EntityType>::INSTANCE.zElement(typeId);
  634. }
  635. const ActionTarget* Entity::zTarget() const
  636. {
  637. return target;
  638. }
  639. int Entity::getId() const
  640. {
  641. return id;
  642. }
  643. bool Entity::hasDefaultModel() const
  644. {
  645. return 1;
  646. }
  647. ModelInfo Entity::getSpecialModel() const
  648. {
  649. return ModelInfo("", "", 0);
  650. }
  651. float Entity::getMaxSpeed() const
  652. {
  653. return maxMovementSpeed;
  654. }
  655. bool Entity::isMoving() const
  656. {
  657. return movements.getEintragAnzahl() > 0;
  658. }