#include "Player.h" #include "Game.h" #include "ItemFilter.h" #include "PlayerHand.h" Player::Player(Framework::Vec3 location, int dimensionId, int entityId) : Entity(EntityTypeEnum::PLAYER, location, dimensionId, entityId), BasicShapedCrafter(3, 3, this, "inventory") { for (int i = 0; i < 10; i++) { ItemSlot* slot = new ItemSlot("ItemBar", 50, 0, i, 0, ANY_DIRECTION, 0); itemBar.add(slot); addSlot(slot); } for (int i = 0; i < 30; i++) { ItemSlot* slot = new ItemSlot("Inventory", 50, 0, i + 10, 0, ANY_DIRECTION, 0); addSlot(slot); } leftHandPosition = 0; maxHP = 10; maxStamina = 10; maxHunger = 10; maxThirst = 10; setHP(10); setStamina(10); setHunger(10); setThirst(10); keyState = 0; jumping = 0; faceOffset = {0.f, 0.f, 1.5f}; targetDistanceLimit = 4; maxMovementSpeed = 4; } void Player::onTargetChange() { NetworkMessage* msg = new NetworkMessage(); ActionTarget::toMessage(zTarget(), dimensionId, msg); Game::INSTANCE->sendMessage(msg, this); } Framework::Text Player::getInventoryUIML() { Framework::Text result = ""; result.append() << "" << "" << "" << ""; return result; } Framework::Text Player::getPlayerGUI() { Framework::Text result = ""; result.append() << "" << "" << ""; return result; } void Player::useItemSlot(ItemSlot* zSlot, bool left) { if (zSlot->zStack()) { ItemStack* stack = takeItemsOut(zSlot, 1, NO_DIRECTION); if (stack) { Item* item = stack->extractFromStack(); Entity::useItem(item->getTypeId(), item, left); if (item->getHp() > 0) { if (item->getDurability() > 0) { // put used item back stack->addToStack(item); if (!zSlot->numberOfAddableItems(stack, NO_DIRECTION)) { // move other items to other space ItemStack* oldItems = takeItemsOut( zSlot, zSlot->zStack()->getSize(), NO_DIRECTION); addItems(zSlot, stack, NO_DIRECTION); addItems(oldItems, NO_DIRECTION, 0); if (oldItems->getSize() > 0) { Game::INSTANCE->spawnItem( getLocation(), getDimensionId(), oldItems); } else { oldItems->release(); } } else addItems(zSlot, stack, NO_DIRECTION); } else { // item is broken // move other items of the same type to the slot Array fromSlots; for (ItemSlot* slot : *this) { if (slot != zSlot) fromSlots.add(slot); } Array targetSlots; targetSlots.add(zSlot); TypeItemFilter filter(item->zItemType()); localTransaction(&fromSlots, &targetSlots, &filter, zSlot->getFreeSpace(), NO_DIRECTION, NO_DIRECTION); // place broken item in inventory const ItemType* brokenType = item->zItemType()->zBrokenItemType(); if (brokenType) { Item* broken = item->zItemType()->breakItem(item); if (broken) { stack->addToStack(broken); addItems(stack, NO_DIRECTION, 0); if (stack->getSize() > 0) { Game::INSTANCE->spawnItem(getLocation(), getDimensionId(), dynamic_cast(stack->getThis())); } } } item->release(); } } else item->release(); stack->release(); } } else Entity::useItem(ItemTypeEnum::PLAYER_HAND, 0, left); // hand usage } void Player::setName(Framework::Text name) { this->name = name; } const char* Player::getName() const { return name; } void Player::tick(const Dimension* zDimension) { if ((keyState | Key::LEFT_HAND_ACTION) == keyState) useItemSlot(itemBar.get(leftHandPosition), true); if ((keyState | Key::RIGHT_HAND_ACTION) == keyState) useItemSlot(itemBar.get(leftHandPosition), false); return Entity::tick(zDimension); } void Player::playerApi( Framework::StreamReader* zRequest, NetworkMessage* zResponse) { char byte; zRequest->lese(&byte, 1); switch (byte) { case 0: // stop action zRequest->lese(&byte, 1); switch (byte) { case 8: keyState = keyState & ~Key::LEFT_HAND_ACTION; break; case 9: keyState = keyState & ~Key::RIGHT_HAND_ACTION; break; } break; case 1: // begin action zRequest->lese(&byte, 1); switch (byte) { case 8: keyState = keyState | Key::LEFT_HAND_ACTION; break; case 9: keyState = keyState | Key::RIGHT_HAND_ACTION; break; } break; case 2: // set movement { MovementFrame frame; zRequest->lese((char*)&frame.direction.x, 4); zRequest->lese((char*)&frame.direction.y, 4); zRequest->lese((char*)&frame.direction.z, 4); zRequest->lese((char*)&frame.targetPosition.x, 4); zRequest->lese((char*)&frame.targetPosition.y, 4); zRequest->lese((char*)&frame.targetPosition.z, 4); zRequest->lese((char*)&frame.movementFlags, 4); zRequest->lese((char*)&frame.duration, 8); addMovementFrame(frame); calculateTarget(frame.targetPosition, frame.direction, !itemBar.get(leftHandPosition)->isEmpty() ? itemBar.get(leftHandPosition)->zStack()->zItem() : 0); break; } case 3: { // switch item bar position zRequest->lese((char*)&leftHandPosition, 4); leftHandPosition = leftHandPosition % itemBar.getEintragAnzahl(); NetworkMessage* msg = new NetworkMessage(); msg->addressGui("gui_item_bar"); char* message = new char[5]; message[0] = 3; // set selected slot *(int*)(message + 1) = leftHandPosition; msg->setMessage(message, 5); Game::INSTANCE->sendMessage(msg, this); break; } case 4: { // open inventory zResponse->openDialog("player_inventory"); Text uiml = getInventoryUIML(); int msgSize = 4 + uiml.getLength(); char* msg = new char[msgSize]; *(int*)msg = uiml.getLength(); memcpy(msg + 4, uiml.getText(), uiml.getLength()); zResponse->setMessage(msg, msgSize); Game::INSTANCE->zQuestManager()->processEvent( new QuestEventOpenDialog( dynamic_cast(getThis()), "player_inventory")); break; } case 5: { // request gui Text uiml = getPlayerGUI(); int msgSize = 6 + uiml.getLength(); char* msg = new char[msgSize]; msg[0] = 2; // gui message msg[1] = 2; // set gui *(int*)(msg + 2) = uiml.getLength(); memcpy(msg + 6, uiml.getText(), uiml.getLength()); zResponse->setMessage(msg, msgSize); break; } case 6: { // inventory transaction bool isEntity; zRequest->lese((char*)&isEntity, 1); Inventory* source; if (isEntity) { int id; zRequest->lese((char*)&id, 4); source = Game::INSTANCE->zEntity(id, dimensionId); } else { int dim; Framework::Vec3 pos; zRequest->lese((char*)&dim, 4); zRequest->lese((char*)&pos.x, 4); zRequest->lese((char*)&pos.y, 4); zRequest->lese((char*)&pos.z, 4); source = Game::INSTANCE->zBlockAt(pos, dim); } int sourceSlotId; zRequest->lese((char*)&sourceSlotId, 4); zRequest->lese((char*)&isEntity, 1); Inventory* target; if (isEntity) { int id; zRequest->lese((char*)&id, 4); target = Game::INSTANCE->zEntity(id, dimensionId); } else { int dim; Framework::Vec3 pos; zRequest->lese((char*)&dim, 4); zRequest->lese((char*)&pos.x, 4); zRequest->lese((char*)&pos.y, 4); zRequest->lese((char*)&pos.z, 4); target = Game::INSTANCE->zBlockAt(pos, dim); } if (source && target) { int targetSlotId; zRequest->lese((char*)&targetSlotId, 4); SpecificSlotFilter filter(sourceSlotId, targetSlotId); source->interactWith(target, Direction::NO_DIRECTION) .pushItems(source->zSlot(sourceSlotId)->getNumberOfItems(), &filter); } break; } case 7: // craft action { bool isEntity; zRequest->lese((char*)&isEntity, 1); BasicShapedCrafter* target; if (isEntity) { int id; zRequest->lese((char*)&id, 4); target = dynamic_cast( Game::INSTANCE->zEntity(id, dimensionId)); } else { int dim; Framework::Vec3 pos; zRequest->lese((char*)&dim, 4); zRequest->lese((char*)&pos.x, 4); zRequest->lese((char*)&pos.y, 4); zRequest->lese((char*)&pos.z, 4); target = dynamic_cast( Game::INSTANCE->zRealBlockInstance(pos, dim)); } if (target) target->applyCurrentRecipie(); break; } case 8: // request left hand position { NetworkMessage* msg = new NetworkMessage(); msg->addressGui("gui_item_bar"); char* message = new char[5]; message[0] = 3; // set selected slot *(int*)(message + 1) = leftHandPosition; msg->setMessage(message, 5); Game::INSTANCE->sendMessage(msg, this); break; } case 9: // open quest dialog { // TODO: open quest dialog } } } void Player::onFall(float collisionSpeed) { Entity::onFall(collisionSpeed); gravityMultiplier = 1.f; jumping = 0; } PlayerEntityType::PlayerEntityType() : EntityType(EntityTypeEnum::PLAYER, ModelInfo("player", "player.ltdb/player.png", 6)) {} void PlayerEntityType::loadSuperEntity( Entity* zEntity, Framework::StreamReader* zReader) const { Player* zPlayer = dynamic_cast(zEntity); if (!zPlayer) throw "PlayerEntityType::loadSuperEntity was called with an entity " "witch is not an instance of Player"; zReader->lese((char*)&zPlayer->leftHandPosition, 4); char len; zReader->lese(&len, 1); char* name = new char[(int)len + 1]; zReader->lese(name, (int)len); name[(int)len] = 0; zPlayer->name = name; delete[] name; EntityType::loadSuperEntity(zPlayer, zReader); } void PlayerEntityType::saveSuperEntity( Entity* zEntity, Framework::StreamWriter* zWriter) const { Player* zPlayer = dynamic_cast(zEntity); if (!zPlayer) throw "PlayerEntityType::saveSuperEntity was called with an entity " "witch is not an instance of Player"; zWriter->schreibe((char*)&zPlayer->leftHandPosition, 4); char len = (char)textLength(zPlayer->getName()); zWriter->schreibe(&len, 1); zWriter->schreibe(zPlayer->getName(), (int)len); EntityType::saveSuperEntity(zEntity, zWriter); } Entity* PlayerEntityType::createEntity( Framework::Vec3 position, int dimensionId, int entityId) const { return new Player(position, dimensionId, entityId); }