Entity.cpp 13 KB

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