Entity.cpp 12 KB

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