Entity.cpp 10 KB

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