Entity.cpp 19 KB

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