#include "Player.h" #include "ArrayUtils.h" #include "Block.h" #include "Chat.h" #include "Game.h" #include "ItemFilter.h" #include "ItemStack.h" #include "PlayerHand.h" #include "QuestDialog.h" #include "UIController.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); setJumpSpeed(5.f); 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 (Entity::useItem(zSlot->zStack() && zSlot->zStack()->zItem() ? zSlot->zStack()->zItem()->getTypeId() : ItemTypeEnum::PLAYER_HAND, (ItemStack*)zSlot->zStack(), left)) { zSlot->update(); if (zSlot->zStack()) { if (zSlot->zStack()->zItem()->getDurability() <= 0) { ItemStack* stack = zSlot->takeItemsOut( zSlot->getNumberOfItems(), NO_DIRECTION); Item* broken = stack->zItem()->zItemType()->breakItem(stack->zItem()); if (broken) { ItemStack* newStack = new ItemStack(broken, stack->getSize()); zSlot->addItems(newStack, NO_DIRECTION); if (newStack->getSize() > 0) { Game::INSTANCE->spawnItem( getLocation(), getDimensionId(), newStack); } else { newStack->release(); } } stack->release(); } else if (zSlot->zStack()->zItem()->getHp() <= 0) { ItemStack* stack = zSlot->takeItemsOut( zSlot->getNumberOfItems(), NO_DIRECTION); Framework::Array fromSlots; for (ItemSlot* slot : *this) { if (slot != zSlot) fromSlots.add(slot); } Framework::Array targetSlots; targetSlots.add(zSlot); TypeItemFilter filter; filter.setType(stack->zItem()->zItemType()); localTransaction(&fromSlots, &targetSlots, &filter, zSlot->getFreeSpace(), NO_DIRECTION, NO_DIRECTION); stack->release(); } } updateSlot(zSlot); } } 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->addressUIElement("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: { Game::INSTANCE->zUIController()->addDialog( new UIDialog("player_inventory", getId(), new Framework::XML::Element(getInventoryUIML()))); break; } case 5: { // request gui Framework::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, 0); } 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, 0); } 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->addressUIElement("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 { Game::INSTANCE->zUIController()->addDialog( new QuestDialog(getId())); break; } case 10: // fall damage { float speed = 0.f; zRequest->lese((char*)&speed, 4); onFall(speed); break; } } } void Player::onFall(float collisionSpeed) { Entity::onFall(collisionSpeed); // TODO: check validity } void Player::onDeath() { this->setHP(this->getMaxHP()); Game::INSTANCE->zChat()->broadcastMessage( name + " died!", Chat::CHANNEL_INFO); // TODO: respown } PlayerEntityType::PlayerEntityType() : EntityType("Player", new ModelInfo("entities.m3/player", toArray("entities.ltdb/player.png", 6), 0, 1.f)) {} 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)Framework::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); }