#include "Player.h" #include "Game.h" #include "PlayerHand.h" #include "ItemFilter.h" Player::Player( Framework::Vec3 location, int dimensionId, int entityId ) : Entity( PlayerEntityType::INSTANCE, location, dimensionId, entityId ) { for( int i = 0; i < 9; i++ ) { ItemSlot* slot = new ItemSlot( 50, 0, i, 0, ANY_DIRECTION, 0 ); itemBar.add( slot ); addSlot( slot ); } leftHandPosition = 0; maxHP = 10; currentHP = 10; stamina = 10; maxStamina = 10; hunger = 10; maxHunger = 10; thirst = 10; maxThirst = 10; keyState = 0; jumping = 0; faceOffset = { 0.f, 0.f, 1.5f }; targetDistanceLimit = 4; } void Player::afterPullStack( ItemSlot* zSlot, Direction dir, const Item* zItem, int count ) { for( auto slot : itemBar ) { if( slot == zSlot ) { needUpdate = 1; return; } } } void Player::afterPushStack( ItemSlot* zSlot, Direction dir, const Item* zItem, int count ) { for( auto slot : itemBar ) { if( slot == zSlot ) { needUpdate = 1; return; } } } void Player::useItemSlot( ItemSlot* zSlot ) { if( zSlot->zStack() ) { ItemStack* stack = takeItemsOut( zSlot, 1, NO_DIRECTION ); if( stack ) { Item* item = stack->extractFromStack(); Entity::useItem( item->zItemType(), item ); if( item->getDurability() > 0 && item->getDamage() < item->getMaxDamage() ) { // put used item back stack->addToStack( item ); // TODO: use inventory wrapper to update the cache of the inventory if( !zSlot->numberOfAddableItems( stack, NO_DIRECTION ) ) { // move other items to other space ItemStack* oldItems = zSlot->takeItemsOut( zSlot->zStack()->getSize(), NO_DIRECTION ); zSlot->addItems( stack, NO_DIRECTION ); addItems( oldItems, NO_DIRECTION ); if( oldItems->getSize() > 0 ) { // TODO: drop remaining items } } else zSlot->addItems( stack, NO_DIRECTION ); } else { // item is broken // move other items of the same type to the slot Array< ItemSlot*> fromSlots; for( ItemSlot* slot : itemBar ) { if( slot != zSlot ) fromSlots.add( slot ); } Array targetSlots; targetSlots.add( zSlot ); TypeItemFilter filter( item->zItemType() ); localTransaction( &fromSlots, &targetSlots, &filter, zSlot->getFreeSpace() ); // 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 ); if( stack->getSize() > 0 ) { // TODO: drop remaining items } } } item->release(); } stack->release(); } } else Entity::useItem( PlayerHandItemType::INSTANCE, 0 ); // hand usage } void Player::setName( Framework::Text name ) { this->name = name; } const char* Player::getName() const { return name; } void Player::tick( const Dimension* zDimension ) { speed = { 0, 0, speed.z }; if( (keyState | Key::MOVE_FRONT) == keyState ) speed += {faceDir.x, faceDir.y, 0}; if( (keyState | Key::MOVE_BACK) == keyState ) speed += {-faceDir.x, -faceDir.y, 0}; if( (keyState | Key::MOVE_RIGHT) == keyState ) { Vec2 norm = { faceDir.x, faceDir.y }; norm.CW90().normalize(); speed += {norm.x, norm.y, 0}; } if( (keyState | Key::MOVE_LEFT) == keyState ) { Vec2 norm = { faceDir.x, faceDir.y }; norm.CCW90().normalize(); speed += {norm.x, norm.y, 0}; } Vec2 norm = { speed.x, speed.y }; if( norm.getLengthSq() != 0 ) { norm.normalize(); speed.x = norm.x * 4.f; // 4 blocks per second movement speed speed.y = norm.y * 4.f; } if( (keyState | Key::MOVE_DOWN) == keyState && gravityMultiplier == 0.f ) speed.z = -4.f; if( (keyState | Key::LEFT_HAND_ACTION) == keyState ) useItemSlot( itemBar.z( leftHandPosition ) ); if( (keyState | Key::RIGHT_HAND_ACTION) == keyState ) useItemSlot( itemBar.z( (leftHandPosition + 1) % itemBar.getEintragAnzahl() ) ); return Entity::tick( zDimension ); } void Player::api( Framework::StreamReader* zRequest, NetworkResponse* zResponse ) { char byte; zRequest->lese( &byte, 1 ); switch( byte ) { case 0: zRequest->lese( &byte, 1 ); switch( byte ) { case 0: keyState = keyState & ~Key::MOVE_FRONT; break; case 1: keyState = keyState & ~Key::MOVE_LEFT; break; case 2: keyState = keyState & ~Key::MOVE_BACK; break; case 3: keyState = keyState & ~Key::MOVE_RIGHT; break; case 4: if( gravityMultiplier == 0.f ) speed.z = 0; keyState = keyState & ~Key::MOVE_DOWN; break; case 5: keyState = keyState & ~Key::ROTATE_LEFT; break; case 6: keyState = keyState & ~Key::ROTATE_RIGHT; break; case 7: if( gravityMultiplier == 0.f ) speed.z = 0; keyState = keyState & ~Key::MOVE_UP; break; case 8: keyState = keyState & ~Key::LEFT_HAND_ACTION; break; case 9: keyState = keyState & ~Key::RIGHT_HAND_ACTION; break; } break; case 1: zRequest->lese( &byte, 1 ); switch( byte ) { case 0: keyState = keyState | Key::MOVE_FRONT; break; case 1: keyState = keyState | Key::MOVE_LEFT; break; case 2: keyState = keyState | Key::MOVE_BACK; break; case 3: keyState = keyState | Key::MOVE_RIGHT; break; case 4: keyState = keyState | Key::MOVE_DOWN; break; case 5: keyState = keyState | Key::ROTATE_LEFT; break; case 6: keyState = keyState | Key::ROTATE_RIGHT; break; case 7: if( (keyState | Key::MOVE_UP) != keyState ) { if( gravityMultiplier > 0 ) { if( jumping ) { // TODO: check if flight is enabled gravityMultiplier = 0; jumping = 0; speed.z = 1.5f; } else { jumping = 1; speed.z = 5.f; } } else speed.z = 1.5f; } keyState = keyState | Key::MOVE_UP; break; case 8: keyState = keyState | Key::LEFT_HAND_ACTION; break; case 9: keyState = keyState | Key::RIGHT_HAND_ACTION; break; } break; case 2: zRequest->lese( (char*)&faceDir.x, 4 ); zRequest->lese( (char*)&faceDir.y, 4 ); zRequest->lese( (char*)&faceDir.z, 4 ); case 3: zRequest->lese( (char*)&leftHandPosition, 4 ); leftHandPosition = leftHandPosition % itemBar.getEintragAnzahl(); needUpdate = 1; } } void Player::onFall( float collisionSpeed ) { Entity::onFall( collisionSpeed ); gravityMultiplier = 1.f; jumping = 0; } PlayerEntityType::PlayerEntityType() : EntityType( ID ) {} 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 ); 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 ); EntityType::saveSuperEntity( zEntity, zWriter ); } Entity* PlayerEntityType::createEntity( Framework::Vec3 position, int dimensionId, int entityId ) const { return new Player( position, dimensionId, entityId ); }