Player.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. #include "Player.h"
  2. #include "ArrayUtils.h"
  3. #include "Game.h"
  4. #include "ItemFilter.h"
  5. #include "PlayerHand.h"
  6. #include "QuestDialog.h"
  7. Player::Player(Framework::Vec3<float> location, int dimensionId, int entityId)
  8. : Entity(EntityTypeEnum::PLAYER, location, dimensionId, entityId),
  9. BasicShapedCrafter(3, 3, this, "inventory")
  10. {
  11. for (int i = 0; i < 10; i++)
  12. {
  13. ItemSlot* slot = new ItemSlot("ItemBar", 50, 0, i, 0, ANY_DIRECTION, 0);
  14. itemBar.add(slot);
  15. addSlot(slot);
  16. }
  17. for (int i = 0; i < 30; i++)
  18. {
  19. ItemSlot* slot
  20. = new ItemSlot("Inventory", 50, 0, i + 10, 0, ANY_DIRECTION, 0);
  21. addSlot(slot);
  22. }
  23. leftHandPosition = 0;
  24. maxHP = 10;
  25. maxStamina = 10;
  26. maxHunger = 10;
  27. maxThirst = 10;
  28. setHP(10);
  29. setStamina(10);
  30. setHunger(10);
  31. setThirst(10);
  32. keyState = 0;
  33. jumping = 0;
  34. faceOffset = {0.f, 0.f, 1.5f};
  35. targetDistanceLimit = 4;
  36. maxMovementSpeed = 4;
  37. }
  38. void Player::onTargetChange()
  39. {
  40. NetworkMessage* msg = new NetworkMessage();
  41. ActionTarget::toMessage(zTarget(), dimensionId, msg);
  42. Game::INSTANCE->sendMessage(msg, this);
  43. }
  44. Framework::Text Player::getInventoryUIML()
  45. {
  46. Framework::Text result
  47. = "<dialog id=\"player_inventory\" title=\"Inventory\" width=\"610\" "
  48. "height=\"450\">";
  49. result.append()
  50. << "<craftingGrid id=\"crafting\" margin-top=\"9\" "
  51. "align-top=\"start\" align-left=\"start\" margin-left=\"9\" "
  52. "width=\"282\" height=\"172\" rowSize=\"3\" colSize=\"3\" "
  53. "numOutputSlots=\"1\" target=\""
  54. << getId() << "\"/>"
  55. << "<inventory id=\"inventory\" margin-bottom=\"18\" "
  56. "align-bottom=\"item_bar\" align-left=\"start\" "
  57. "margin-left=\"9\" width=\"592\" height=\"172\" rowSize=\"10\" "
  58. "numSlots=\"30\" slotNameFilter=\"Inventory\" target=\""
  59. << getId() << "\"/>"
  60. << "<inventory id=\"item_bar\" margin-bottom=\"9\" "
  61. "align-bottom=\"end\" align-left=\"start\" margin-left=\"9\" "
  62. "width=\"592\" height=\"52\" rowSize=\"10\" numSlots=\"10\" "
  63. "slotNameFilter=\"ItemBar\" target=\""
  64. << getId() << "\"/>"
  65. << "</dialog>";
  66. return result;
  67. }
  68. Framework::Text Player::getPlayerGUI()
  69. {
  70. Framework::Text result = "<gui id=\"player_gui\">";
  71. result.append()
  72. << "<itemBar id=\"gui_item_bar\" margin-bottom=\"9\" "
  73. "align-bottom=\"end\" align-left=\"center\" width=\"592\" "
  74. "height=\"52\" rowSize=\"10\" slotNameFilter=\"ItemBar\" target=\""
  75. << getId() << "\"/>"
  76. << "<statusBars id=\"gui_status_bars\" margin-bottom=\"9\" "
  77. "align-bottom=\"gui_item_bar\" align-left=\"center\" target=\""
  78. << getId() << "\"/>"
  79. << "</gui>";
  80. return result;
  81. }
  82. void Player::useItemSlot(ItemSlot* zSlot, bool left)
  83. {
  84. if (Entity::useItem(zSlot->zStack() && zSlot->zStack()->zItem()
  85. ? zSlot->zStack()->zItem()->getTypeId()
  86. : ItemTypeEnum::PLAYER_HAND,
  87. (ItemStack*)zSlot->zStack(),
  88. left))
  89. {
  90. zSlot->update();
  91. if (zSlot->zStack())
  92. {
  93. if (zSlot->zStack()->zItem()->getDurability() <= 0)
  94. {
  95. ItemStack* stack = zSlot->takeItemsOut(
  96. zSlot->getNumberOfItems(), NO_DIRECTION);
  97. Item* broken
  98. = stack->zItem()->zItemType()->breakItem(stack->zItem());
  99. if (broken)
  100. {
  101. ItemStack* newStack
  102. = new ItemStack(broken, stack->getSize());
  103. zSlot->addItems(newStack, NO_DIRECTION);
  104. if (newStack->getSize() > 0)
  105. {
  106. Game::INSTANCE->spawnItem(
  107. getLocation(), getDimensionId(), newStack);
  108. }
  109. else
  110. {
  111. newStack->release();
  112. }
  113. }
  114. stack->release();
  115. }
  116. else if (zSlot->zStack()->zItem()->getHp() <= 0)
  117. {
  118. ItemStack* stack = zSlot->takeItemsOut(
  119. zSlot->getNumberOfItems(), NO_DIRECTION);
  120. Array<ItemSlot*> fromSlots;
  121. for (ItemSlot* slot : *this)
  122. {
  123. if (slot != zSlot) fromSlots.add(slot);
  124. }
  125. Array<ItemSlot*> targetSlots;
  126. targetSlots.add(zSlot);
  127. TypeItemFilter filter(stack->zItem()->zItemType());
  128. localTransaction(&fromSlots,
  129. &targetSlots,
  130. &filter,
  131. zSlot->getFreeSpace(),
  132. NO_DIRECTION,
  133. NO_DIRECTION);
  134. stack->release();
  135. }
  136. }
  137. updateSlot(zSlot);
  138. }
  139. }
  140. void Player::setName(Framework::Text name)
  141. {
  142. this->name = name;
  143. }
  144. const char* Player::getName() const
  145. {
  146. return name;
  147. }
  148. void Player::tick(const Dimension* zDimension)
  149. {
  150. if ((keyState | Key::LEFT_HAND_ACTION) == keyState)
  151. useItemSlot(itemBar.get(leftHandPosition), true);
  152. if ((keyState | Key::RIGHT_HAND_ACTION) == keyState)
  153. useItemSlot(itemBar.get(leftHandPosition), false);
  154. return Entity::tick(zDimension);
  155. }
  156. void Player::playerApi(
  157. Framework::StreamReader* zRequest, NetworkMessage* zResponse)
  158. {
  159. char byte;
  160. zRequest->lese(&byte, 1);
  161. switch (byte)
  162. {
  163. case 0:
  164. // stop action
  165. zRequest->lese(&byte, 1);
  166. switch (byte)
  167. {
  168. case 8:
  169. keyState = keyState & ~Key::LEFT_HAND_ACTION;
  170. break;
  171. case 9:
  172. keyState = keyState & ~Key::RIGHT_HAND_ACTION;
  173. break;
  174. }
  175. break;
  176. case 1:
  177. // begin action
  178. zRequest->lese(&byte, 1);
  179. switch (byte)
  180. {
  181. case 8:
  182. keyState = keyState | Key::LEFT_HAND_ACTION;
  183. break;
  184. case 9:
  185. keyState = keyState | Key::RIGHT_HAND_ACTION;
  186. break;
  187. }
  188. break;
  189. case 2:
  190. // set movement
  191. {
  192. MovementFrame frame;
  193. zRequest->lese((char*)&frame.direction.x, 4);
  194. zRequest->lese((char*)&frame.direction.y, 4);
  195. zRequest->lese((char*)&frame.direction.z, 4);
  196. zRequest->lese((char*)&frame.targetPosition.x, 4);
  197. zRequest->lese((char*)&frame.targetPosition.y, 4);
  198. zRequest->lese((char*)&frame.targetPosition.z, 4);
  199. zRequest->lese((char*)&frame.movementFlags, 4);
  200. zRequest->lese((char*)&frame.duration, 8);
  201. addMovementFrame(frame);
  202. calculateTarget(frame.targetPosition,
  203. frame.direction,
  204. !itemBar.get(leftHandPosition)->isEmpty()
  205. ? itemBar.get(leftHandPosition)->zStack()->zItem()
  206. : 0);
  207. break;
  208. }
  209. case 3:
  210. { // switch item bar position
  211. zRequest->lese((char*)&leftHandPosition, 4);
  212. leftHandPosition = leftHandPosition % itemBar.getEintragAnzahl();
  213. NetworkMessage* msg = new NetworkMessage();
  214. msg->addressUIElement("gui_item_bar");
  215. char* message = new char[5];
  216. message[0] = 3; // set selected slot
  217. *(int*)(message + 1) = leftHandPosition;
  218. msg->setMessage(message, 5);
  219. Game::INSTANCE->sendMessage(msg, this);
  220. break;
  221. }
  222. case 4:
  223. {
  224. Game::INSTANCE->zUIController()->addDialog(
  225. new UIDialog("player_inventory",
  226. getId(),
  227. new Framework::XML::Element(getInventoryUIML())));
  228. break;
  229. }
  230. case 5:
  231. {
  232. // request gui
  233. Text uiml = getPlayerGUI();
  234. int msgSize = 6 + uiml.getLength();
  235. char* msg = new char[msgSize];
  236. msg[0] = 2; // gui message
  237. msg[1] = 2; // set gui
  238. *(int*)(msg + 2) = uiml.getLength();
  239. memcpy(msg + 6, uiml.getText(), uiml.getLength());
  240. zResponse->setMessage(msg, msgSize);
  241. break;
  242. }
  243. case 6:
  244. { // inventory transaction
  245. bool isEntity;
  246. zRequest->lese((char*)&isEntity, 1);
  247. Inventory* source;
  248. if (isEntity)
  249. {
  250. int id;
  251. zRequest->lese((char*)&id, 4);
  252. source = Game::INSTANCE->zEntity(id, dimensionId);
  253. }
  254. else
  255. {
  256. int dim;
  257. Framework::Vec3<int> pos;
  258. zRequest->lese((char*)&dim, 4);
  259. zRequest->lese((char*)&pos.x, 4);
  260. zRequest->lese((char*)&pos.y, 4);
  261. zRequest->lese((char*)&pos.z, 4);
  262. source = Game::INSTANCE->zBlockAt(pos, dim);
  263. }
  264. int sourceSlotId;
  265. zRequest->lese((char*)&sourceSlotId, 4);
  266. zRequest->lese((char*)&isEntity, 1);
  267. Inventory* target;
  268. if (isEntity)
  269. {
  270. int id;
  271. zRequest->lese((char*)&id, 4);
  272. target = Game::INSTANCE->zEntity(id, dimensionId);
  273. }
  274. else
  275. {
  276. int dim;
  277. Framework::Vec3<int> pos;
  278. zRequest->lese((char*)&dim, 4);
  279. zRequest->lese((char*)&pos.x, 4);
  280. zRequest->lese((char*)&pos.y, 4);
  281. zRequest->lese((char*)&pos.z, 4);
  282. target = Game::INSTANCE->zBlockAt(pos, dim);
  283. }
  284. if (source && target)
  285. {
  286. int targetSlotId;
  287. zRequest->lese((char*)&targetSlotId, 4);
  288. SpecificSlotFilter filter(sourceSlotId, targetSlotId);
  289. source->interactWith(target, Direction::NO_DIRECTION)
  290. .pushItems(source->zSlot(sourceSlotId)->getNumberOfItems(),
  291. &filter);
  292. }
  293. break;
  294. }
  295. case 7: // craft action
  296. {
  297. bool isEntity;
  298. zRequest->lese((char*)&isEntity, 1);
  299. BasicShapedCrafter* target;
  300. if (isEntity)
  301. {
  302. int id;
  303. zRequest->lese((char*)&id, 4);
  304. target = dynamic_cast<BasicShapedCrafter*>(
  305. Game::INSTANCE->zEntity(id, dimensionId));
  306. }
  307. else
  308. {
  309. int dim;
  310. Framework::Vec3<int> pos;
  311. zRequest->lese((char*)&dim, 4);
  312. zRequest->lese((char*)&pos.x, 4);
  313. zRequest->lese((char*)&pos.y, 4);
  314. zRequest->lese((char*)&pos.z, 4);
  315. target = dynamic_cast<BasicShapedCrafter*>(
  316. Game::INSTANCE->zRealBlockInstance(pos, dim));
  317. }
  318. if (target) target->applyCurrentRecipie();
  319. break;
  320. }
  321. case 8: // request left hand position
  322. {
  323. NetworkMessage* msg = new NetworkMessage();
  324. msg->addressUIElement("gui_item_bar");
  325. char* message = new char[5];
  326. message[0] = 3; // set selected slot
  327. *(int*)(message + 1) = leftHandPosition;
  328. msg->setMessage(message, 5);
  329. Game::INSTANCE->sendMessage(msg, this);
  330. break;
  331. }
  332. case 9: // open quest dialog
  333. {
  334. Game::INSTANCE->zUIController()->addDialog(
  335. new QuestDialog(getId()));
  336. break;
  337. }
  338. case 10: // request quest graph
  339. {
  340. /*
  341. unsigned char length;
  342. zRequest->lese((char*)&length, 1);
  343. char* collectionName = new char[length + 1];
  344. zRequest->lese(collectionName, length);
  345. collectionName[length] = 0;
  346. Framework::Text uiml
  347. = Game::INSTANCE->zQuestManager()->getQuestGraphUIML(
  348. this, collectionName);
  349. delete[] collectionName;
  350. zRequest->lese((char*)&length, 1);
  351. char* guiId = new char[(int)length + 1];
  352. zRequest->lese(guiId, length);
  353. guiId[(int)length] = 0;
  354. zResponse->addressGui(guiId);
  355. delete[] guiId;
  356. int msgSize = 4 + uiml.getLength();
  357. char* msg = new char[msgSize];
  358. *(int*)msg = uiml.getLength();
  359. memcpy(msg + 4, uiml.getText(), uiml.getLength());
  360. zResponse->setMessage(msg, msgSize);*/
  361. break;
  362. }
  363. case 11: // request quest view
  364. {
  365. /* unsigned char length;
  366. zRequest->lese((char*)&length, 1);
  367. char* questName = new char[length + 1];
  368. zRequest->lese(questName, length);
  369. questName[length] = 0;
  370. Framework::Text uiml
  371. = Game::INSTANCE->zQuestManager()->getQuestViewUIML(
  372. this, questName);
  373. delete[] questName;
  374. zRequest->lese((char*)&length, 1);
  375. char* guiId = new char[(int)length + 1];
  376. zRequest->lese(guiId, length);
  377. guiId[(int)length] = 0;
  378. zResponse->addressGui(guiId);
  379. delete[] guiId;
  380. int msgSize = 4 + uiml.getLength();
  381. char* msg = new char[msgSize];
  382. *(int*)msg = uiml.getLength();
  383. memcpy(msg + 4, uiml.getText(), uiml.getLength());
  384. zResponse->setMessage(msg, msgSize);*/
  385. break;
  386. }
  387. }
  388. }
  389. void Player::onFall(float collisionSpeed)
  390. {
  391. Entity::onFall(collisionSpeed);
  392. gravityMultiplier = 1.f;
  393. jumping = 0;
  394. }
  395. PlayerEntityType::PlayerEntityType()
  396. : EntityType(
  397. "Player",
  398. new ModelInfo("player", toArray("player.ltdb/player.png", 6), 0, 1.f))
  399. {}
  400. void PlayerEntityType::loadSuperEntity(
  401. Entity* zEntity, Framework::StreamReader* zReader) const
  402. {
  403. Player* zPlayer = dynamic_cast<Player*>(zEntity);
  404. if (!zPlayer)
  405. throw "PlayerEntityType::loadSuperEntity was called with an entity "
  406. "witch is not an instance of Player";
  407. zReader->lese((char*)&zPlayer->leftHandPosition, 4);
  408. char len;
  409. zReader->lese(&len, 1);
  410. char* name = new char[(int)len + 1];
  411. zReader->lese(name, (int)len);
  412. name[(int)len] = 0;
  413. zPlayer->name = name;
  414. delete[] name;
  415. EntityType::loadSuperEntity(zPlayer, zReader);
  416. }
  417. void PlayerEntityType::saveSuperEntity(
  418. Entity* zEntity, Framework::StreamWriter* zWriter) const
  419. {
  420. Player* zPlayer = dynamic_cast<Player*>(zEntity);
  421. if (!zPlayer)
  422. throw "PlayerEntityType::saveSuperEntity was called with an entity "
  423. "witch is not an instance of Player";
  424. zWriter->schreibe((char*)&zPlayer->leftHandPosition, 4);
  425. char len = (char)textLength(zPlayer->getName());
  426. zWriter->schreibe(&len, 1);
  427. zWriter->schreibe(zPlayer->getName(), (int)len);
  428. EntityType::saveSuperEntity(zEntity, zWriter);
  429. }
  430. Entity* PlayerEntityType::createEntity(
  431. Framework::Vec3<float> position, int dimensionId, int entityId) const
  432. {
  433. return new Player(position, dimensionId, entityId);
  434. }