From 19026c057b76c3f72efb70f660cae4bfe69d43af Mon Sep 17 00:00:00 2001 From: Tropical <42101043+tropicaaal@users.noreply.github.com> Date: Sat, 21 Mar 2026 17:26:42 -0500 Subject: [PATCH] TU19: merge Minecraft.World/Player --- Minecraft.World/Player/Abilities.cpp | 4 +- Minecraft.World/Player/FoodData.cpp | 30 +- Minecraft.World/Player/Player.cpp | 853 ++++++++++-------- Minecraft.World/Player/Player.h | 172 ++-- .../Player/PlayerEnderChestContainer.cpp | 12 +- .../Player/PlayerEnderChestContainer.h | 3 + 6 files changed, 620 insertions(+), 454 deletions(-) diff --git a/Minecraft.World/Player/Abilities.cpp b/Minecraft.World/Player/Abilities.cpp index 5c3b67448..d5e1b913f 100644 --- a/Minecraft.World/Player/Abilities.cpp +++ b/Minecraft.World/Player/Abilities.cpp @@ -51,8 +51,8 @@ void Abilities::loadSaveData(CompoundTag* parentTag) { float Abilities::getFlyingSpeed() { return flyingSpeed; } -void Abilities::setFlyingSpeed(float value) { this->flyingSpeed = value; } +void Abilities::setFlyingSpeed(float value) { flyingSpeed = value; } float Abilities::getWalkingSpeed() { return walkingSpeed; } -void Abilities::setWalkingSpeed(float value) { this->walkingSpeed = value; } \ No newline at end of file +void Abilities::setWalkingSpeed(float value) { walkingSpeed = value; } \ No newline at end of file diff --git a/Minecraft.World/Player/FoodData.cpp b/Minecraft.World/Player/FoodData.cpp index 17a1fa02e..cdbc25d93 100644 --- a/Minecraft.World/Player/FoodData.cpp +++ b/Minecraft.World/Player/FoodData.cpp @@ -12,9 +12,9 @@ FoodData::FoodData() { exhaustionLevel = 0; tickTimer = 0; - this->foodLevel = FoodConstants::MAX_FOOD; - this->lastFoodLevel = FoodConstants::MAX_FOOD; - this->saturationLevel = FoodConstants::START_SATURATION; + foodLevel = FoodConstants::MAX_FOOD; + lastFoodLevel = FoodConstants::MAX_FOOD; + saturationLevel = FoodConstants::START_SATURATION; } void FoodData::eat(int food, float saturationModifier) { @@ -43,9 +43,12 @@ void FoodData::tick(std::shared_ptr player) { } } - // 4J Added - Allow host to disable using hunger. We don't deplete the - // hunger bar due to exhaustion but I think we should deplete it to heal - if (player->isAllowedToIgnoreExhaustion()) { + // 4J: Added - Allow host to disable using hunger. We don't deplete the + // hunger bar due to exhaustion but I think we should deplete it to heal. + // Don't heal if natural regen is disabled + if (player->isAllowedToIgnoreExhaustion() && + player->level->getGameRules()->getBoolean( + GameRules::RULE_NATURAL_REGENERATION)) { if (foodLevel > 0 && player->isHurt()) { tickTimer++; if (tickTimer >= FoodConstants::HEALTH_TICK_COUNT) { @@ -54,10 +57,13 @@ void FoodData::tick(std::shared_ptr player) { tickTimer = 0; } } - } else if (foodLevel >= FoodConstants::HEAL_LEVEL && player->isHurt()) { + } else if (player->level->getGameRules()->getBoolean( + GameRules::RULE_NATURAL_REGENERATION) && + foodLevel >= FoodConstants::HEAL_LEVEL && player->isHurt()) { tickTimer++; if (tickTimer >= FoodConstants::HEALTH_TICK_COUNT) { player->heal(1); + addExhaustion(FoodConstants::EXHAUSTION_HEAL); tickTimer = 0; } } else if (foodLevel <= FoodConstants::STARVE_LEVEL) { @@ -105,12 +111,8 @@ float FoodData::getExhaustionLevel() { return exhaustionLevel; } float FoodData::getSaturationLevel() { return saturationLevel; } -void FoodData::setFoodLevel(int food) { this->foodLevel = food; } +void FoodData::setFoodLevel(int food) { foodLevel = food; } -void FoodData::setSaturation(float saturation) { - this->saturationLevel = saturation; -} +void FoodData::setSaturation(float saturation) { saturationLevel = saturation; } -void FoodData::setExhaustion(float exhaustion) { - this->exhaustionLevel = exhaustion; -} \ No newline at end of file +void FoodData::setExhaustion(float exhaustion) { exhaustionLevel = exhaustion; } \ No newline at end of file diff --git a/Minecraft.World/Player/Player.cpp b/Minecraft.World/Player/Player.cpp index a6bc411f9..f7b8e9b85 100644 --- a/Minecraft.World/Player/Player.cpp +++ b/Minecraft.World/Player/Player.cpp @@ -16,7 +16,9 @@ #include "../Headers/net.minecraft.world.level.chunk.h" #include "../Headers/net.minecraft.world.phys.h" #include "../Headers/net.minecraft.world.entity.h" +#include "../Headers/net.minecraft.world.entity.ai.attributes.h" #include "../Headers/net.minecraft.world.entity.animal.h" +#include "../Headers/net.minecraft.world.entity.boss.h" #include "../Headers/net.minecraft.world.entity.monster.h" #include "../Headers/net.minecraft.world.entity.item.h" #include "../Headers/net.minecraft.world.item.h" @@ -25,6 +27,8 @@ #include "../Headers/net.minecraft.world.level.material.h" #include "../Headers/net.minecraft.world.level.tile.h" #include "../Headers/net.minecraft.world.level.tile.entity.h" +#include "../Headers/net.minecraft.world.scores.h" +#include "../Headers/net.minecraft.world.scores.criteria.h" #include "../Headers/net.minecraft.world.entity.projectile.h" #include "../Headers/net.minecraft.world.inventory.h" #include "../Headers/net.minecraft.world.damagesource.h" @@ -42,23 +46,21 @@ #include "../Util/SoundTypes.h" void Player::_init() { + registerAttributes(); + setHealth(getMaxHealth()); + inventory = std::shared_ptr(new Inventory(this)); userType = 0; - score = 0; oBob = bob = 0.0f; - swinging = false; - swingTime = 0; - - // string name; - dimension = 0; - // string cloakTexture; xCloakO = yCloakO = zCloakO = 0.0; xCloak = yCloak = zCloak = 0.0; m_isSleeping = false; + customTextureUrl = L""; + customTextureUrl2 = L""; m_uiPlayerCurrentSkin = 0; bedPosition = NULL; @@ -70,16 +72,9 @@ void Player::_init() { stats = NULL; respawnPosition = NULL; + respawnForced = false; minecartAchievementPos = NULL; - changingDimensionDelay = 20; - - isInsidePortal = false; - - portalTime = oPortalTime = 0.0f; - - dmgSpill = 0; - fishing = nullptr; distanceWalk = distanceSwim = distanceFall = distanceClimb = @@ -98,6 +93,8 @@ void Player::_init() { defaultWalkSpeed = 0.1f; defaultFlySpeed = 0.02f; + lastLevelUpTime = 0; + m_uiGamePrivileges = 0; m_ppAdditionalModelParts = NULL; @@ -114,14 +111,12 @@ void Player::_init() { m_bAwardedOnARail = false; } -Player::Player(Level* level) : Mob(level) { +Player::Player(Level* level, const std::wstring& name) : LivingEntity(level) { // 4J Stu - This function call had to be moved here from the Entity ctor to // ensure that the derived version of the function is called this->defineSynchedData(); - // 4J Stu - This function call had to be moved here from the Entity ctor to - // ensure that the derived version of the function is called - health = getMaxHealth(); + this->name = name; _init(); MemSect(11); @@ -132,14 +127,12 @@ Player::Player(Level* level) : Mob(level) { heightOffset = 1.62f; Pos* spawnPos = level->getSharedSpawnPos(); - this->moveTo(spawnPos->x + 0.5, spawnPos->y + 1, spawnPos->z + 0.5, 0, 0); + moveTo(spawnPos->x + 0.5, spawnPos->y + 1, spawnPos->z + 0.5, 0, 0); delete spawnPos; - modelName = L"humanoid"; rotOffs = 180; flameTime = 20; - textureIdx = TN_MOB_CHAR; // 4J - was L"/mob/char.png"; m_skinIndex = eDefaultSkins_Skin0; m_playerIndex = 0; m_dwSkinId = 0; @@ -152,7 +145,12 @@ Player::Player(Level* level) : Mob(level) { setShowOnMaps( app.GetGameHostOption(eGameHostOption_Gamertags) != 0 ? true : false); m_bIsGuest = false; - m_UUID = L""; + +#ifndef _XBOX_ONE + // 4J: Set UUID to name on none-XB1 consoles, may change in future but for + // now ownership of animals on these consoles is done by name + setUUID(name); +#endif } Player::~Player() { @@ -167,13 +165,20 @@ Player::~Player() { // if( containerMenu != inventoryMenu ) delete containerMenu; } -int Player::getMaxHealth() { return MAX_HEALTH; } +void Player::registerAttributes() { + LivingEntity::registerAttributes(); + + getAttributes() + ->registerAttribute(SharedMonsterAttributes::ATTACK_DAMAGE) + ->setBaseValue(1); +} void Player::defineSynchedData() { - this->Mob::defineSynchedData(); + LivingEntity::defineSynchedData(); - entityData->define(DATA_PLAYER_FLAGS_ID, (std::uint8_t)0); - entityData->define(DATA_PLAYER_RUNNING_ID, (std::uint8_t)0); + entityData->define(DATA_PLAYER_FLAGS_ID, (uint8_t)0); + entityData->define(DATA_PLAYER_ABSORPTION_ID, (float)0); + entityData->define(DATA_SCORE_ID, (int)0); } std::shared_ptr Player::getUseItem() { return useItem; } @@ -217,7 +222,9 @@ bool Player::isBlocking() { Item::items[useItem->id]->getUseAnimation(useItem) == UseAnim_block; } -void Player::tick() { +// 4J Stu - Added for things that should only be ticked once per simulation +// frame +void Player::updateFrameTick() { if (useItem != NULL) { std::shared_ptr item = inventory->getSelected(); // 4J Stu - Fix for #45508 - TU5: Gameplay: Eating one piece of food @@ -269,7 +276,16 @@ void Player::tick() { deathFadeCounter = DEATHFADE_DURATION; } } - this->Mob::tick(); +} + +void Player::tick() { + if (level->isClientSide) { + // 4J Stu - Server player calls this differently so that it only happens + // once per simulation tick + updateFrameTick(); + } + + LivingEntity::tick(); if (!level->isClientSide) { if (containerMenu != NULL && @@ -332,11 +348,11 @@ void Player::tick() { #ifdef __PS3__ // #ifdef _DEBUG // // Drop some items so we have them in inventory to play with - // this->drop( std::shared_ptr( new ItemInstance(Tile::recordPlayer) ) ); - // this->drop( std::shared_ptr( new ItemInstance(Item::map) ) ); - // this->drop( std::shared_ptr( new ItemInstance(Item::record_01) ) ); - // this->drop( std::shared_ptr( new ItemInstance(Item::record_02) ) ); - // this->drop( std::shared_ptr(new ItemInstance( Item::pickAxe_diamond, 1 )) ); + // this->drop( shared_ptr( new ItemInstance(Tile::recordPlayer) ) ); + // this->drop( shared_ptr( new ItemInstance(Item::map) ) ); + // this->drop( shared_ptr( new ItemInstance(Item::record_01) ) ); + // this->drop( shared_ptr( new ItemInstance(Item::record_02) ) ); + // this->drop( shared_ptr(new ItemInstance( Item::pickAxe_diamond, 1 )) ); // #endif #endif @@ -353,49 +369,49 @@ void Player::tick() { // this->drop( new ItemInstance( Item::pickAxe_diamond, 1 ) ); // this->drop( new ItemInstance( Tile::workBench, 1 ) ); // this->drop( new ItemInstance( Tile::treeTrunk, 8 ) ); - // this->drop( std::shared_ptr( new ItemInstance( - // Item::milk, 3 ) ) ); this->drop( std::shared_ptr( - // new ItemInstance( Item::sugar, 2 ) ) ); this->drop( new - // ItemInstance( Tile::stoneBrick, 8 ) ); this->drop( - // std::shared_ptr( new ItemInstance( Item::wheat, 3 ) - // ) ); this->drop( std::shared_ptr( new ItemInstance( - // Item::egg, 1 ) ) ); this->drop( new ItemInstance( Item::bow, 1 ) - // ); this->drop( new ItemInstance( Item::arrow, 10 ) ); this->drop( - // std::shared_ptr( new ItemInstance( Item::saddle, 10 - // ) ) ); this->drop( std::shared_ptr( new + // this->drop( shared_ptr( new ItemInstance( + // Item::milk, 3 ) ) ); this->drop( shared_ptr( new + // ItemInstance( Item::sugar, 2 ) ) ); this->drop( new ItemInstance( + // Tile::stoneBrick, 8 ) ); this->drop( shared_ptr( + // new ItemInstance( Item::wheat, 3 ) ) ); this->drop( + // shared_ptr( new ItemInstance( Item::egg, 1 ) ) ); + // this->drop( new ItemInstance( Item::bow, 1 ) ); + // this->drop( new ItemInstance( Item::arrow, 10 ) ); + // this->drop( shared_ptr( new ItemInstance( + // Item::saddle, 10 ) ) ); this->drop( shared_ptr( new // ItemInstance( Tile::fence, 64 ) ) ); this->drop( - // std::shared_ptr( new ItemInstance( Tile::fence, 64 - // ) ) ); this->drop( std::shared_ptr( new - // ItemInstance( Tile::fence, 64 ) ) ); + // shared_ptr( new ItemInstance( Tile::fence, 64 ) ) + // ); this->drop( shared_ptr( new ItemInstance( + // Tile::fence, 64 ) ) ); - // std::shared_ptr mob = + // shared_ptr mob = // std::dynamic_pointer_cast(Pig::_class->newInstance( level // )); mob->moveTo(x+1, y, z+1, level->random->nextFloat() * 360, // 0); level->addEntity(mob); // 4J : WESTY : Spawn some wolves to befriend! /* - std::shared_ptr mob1 = + shared_ptr mob1 = std::dynamic_pointer_cast(Wolf::_class->newInstance( level )); mob1->moveTo(x+1, y, z+1, level->random->nextFloat() * 360, 0); level->addEntity(mob1); - std::shared_ptr mob2 = + shared_ptr mob2 = std::dynamic_pointer_cast(Wolf::_class->newInstance( level )); mob2->moveTo(x+2, y, z+1, level->random->nextFloat() * 360, 0); level->addEntity(mob2); - std::shared_ptr mob3 = + shared_ptr mob3 = std::dynamic_pointer_cast(Wolf::_class->newInstance( level )); mob3->moveTo(x+1, y, z+2, level->random->nextFloat() * 360, 0); level->addEntity(mob3); - std::shared_ptr mob4 = + shared_ptr mob4 = std::dynamic_pointer_cast(Wolf::_class->newInstance( level )); mob4->moveTo(x+3, y, z+1, level->random->nextFloat() * 360, 0); level->addEntity(mob4); - std::shared_ptr mob5 = + shared_ptr mob5 = std::dynamic_pointer_cast(Wolf::_class->newInstance( level )); mob5->moveTo(x+1, y, z+3, level->random->nextFloat() * 360, 0); level->addEntity(mob5); @@ -424,62 +440,61 @@ void Player::tick() { this->drop( std::shared_ptr( new ItemInstance( Tile::goldenRail, 10 ) ) ); this->drop( std::shared_ptr( new ItemInstance( Tile::lever, 10 ) ) ); - level->setTime( 0 ); int poweredCount = 0; for(int i = 10; i < 2800; ++i) { - level->setTile(x+i,y-1,z-2,Tile::quartzBlock_Id); - level->setTile(x+i,y,z-2,Tile::quartzBlock_Id); - level->setTile(x+i,y+1,z-2,Tile::quartzBlock_Id); - level->setTile(x+i,y+2,z-2,Tile::lightGem_Id); - level->setTile(x+i,y+3,z-2,Tile::quartzBlock_Id); + level->setTileAndData(x+i,y-1,z-2,Tile::quartzBlock_Id,0,Tile::UPDATE_CLIENTS); + level->setTileAndData(x+i,y,z-2,Tile::quartzBlock_Id,0,Tile::UPDATE_CLIENTS); + level->setTileAndData(x+i,y+1,z-2,Tile::quartzBlock_Id,0,Tile::UPDATE_CLIENTS); + level->setTileAndData(x+i,y+2,z-2,Tile::glowstone_Id,0,Tile::UPDATE_CLIENTS); + level->setTileAndData(x+i,y+3,z-2,Tile::quartzBlock_Id,0,Tile::UPDATE_CLIENTS); - level->setTile(x+i,y-1,z-1,Tile::stoneBrick_Id); + level->setTileAndData(x+i,y-1,z-1,Tile::stoneBrick_Id,0,Tile::UPDATE_CLIENTS); if(i%20 == 0) { - level->setTile(x+i,y,z-1,Tile::notGate_on_Id); + level->setTileAndData(x+i,y,z-1,Tile::redstoneTorch_on_Id,0,Tile::UPDATE_CLIENTS); poweredCount = 4; } else { - level->setTile(x+i,y,z-1,0); + level->setTileAndData(x+i,y,z-1,0,0,Tile::UPDATE_CLIENTS); } - level->setTile(x+i,y+1,z-1,0); - level->setTile(x+i,y+2,z-1,0); - level->setTile(x+i,y+3,z-1,0); + level->setTileAndData(x+i,y+1,z-1,0,0,Tile::UPDATE_CLIENTS); + level->setTileAndData(x+i,y+2,z-1,0,0,Tile::UPDATE_CLIENTS); + level->setTileAndData(x+i,y+3,z-1,0,0,Tile::UPDATE_CLIENTS); - level->setTile(x+i,y-1,z,Tile::stoneBrick_Id); + level->setTileAndData(x+i,y-1,z,Tile::stoneBrick_Id,0,Tile::UPDATE_CLIENTS); if(poweredCount>0) { - level->setTile(x+i,y,z,Tile::goldenRail_Id); + level->setTileAndData(x+i,y,z,Tile::goldenRail_Id,0,Tile::UPDATE_CLIENTS); --poweredCount; } else { - level->setTile(x+i,y,z,Tile::rail_Id); + level->setTileAndData(x+i,y,z,Tile::rail_Id,0,Tile::UPDATE_CLIENTS); } - level->setTile(x+i,y+1,z,0); - level->setTile(x+i,y+2,z,0); - level->setTile(x+i,y+3,z,0); + level->setTileAndData(x+i,y+1,z,0,0,Tile::UPDATE_CLIENTS); + level->setTileAndData(x+i,y+2,z,0,0,Tile::UPDATE_CLIENTS); + level->setTileAndData(x+i,y+3,z,0,0,Tile::UPDATE_CLIENTS); - level->setTile(x+i,y-1,z+1,Tile::stoneBrick_Id); + level->setTileAndData(x+i,y-1,z+1,Tile::stoneBrick_Id,0,Tile::UPDATE_CLIENTS); if((i+5)%20 == 0) { - level->setTile(x+i,y,z+1,Tile::torch_Id); + level->setTileAndData(x+i,y,z+1,Tile::torch_Id,0,Tile::UPDATE_CLIENTS); } else { - level->setTile(x+i,y,z+1,0); + level->setTileAndData(x+i,y,z+1,0,0,Tile::UPDATE_CLIENTS); } - level->setTile(x+i,y+1,z+1,0); - level->setTile(x+i,y+2,z+1,0); - level->setTile(x+i,y+3,z+1,0); + level->setTileAndData(x+i,y+1,z+1,0,0,Tile::UPDATE_CLIENTS); + level->setTileAndData(x+i,y+2,z+1,0,0,Tile::UPDATE_CLIENTS); + level->setTileAndData(x+i,y+3,z+1,0,0,Tile::UPDATE_CLIENTS); - level->setTile(x+i,y-1,z+2,Tile::quartzBlock_Id); - level->setTile(x+i,y,z+2,Tile::quartzBlock_Id); - level->setTile(x+i,y+1,z+2,Tile::quartzBlock_Id); - level->setTile(x+i,y+2,z+2,Tile::lightGem_Id); - level->setTile(x+i,y+3,z+2,Tile::quartzBlock_Id); + level->setTileAndData(x+i,y-1,z+2,Tile::quartzBlock_Id,0,Tile::UPDATE_CLIENTS); + level->setTileAndData(x+i,y,z+2,Tile::quartzBlock_Id,0,Tile::UPDATE_CLIENTS); + level->setTileAndData(x+i,y+1,z+2,Tile::quartzBlock_Id,0,Tile::UPDATE_CLIENTS); + level->setTileAndData(x+i,y+2,z+2,Tile::glowstone_Id,0,Tile::UPDATE_CLIENTS); + level->setTileAndData(x+i,y+3,z+2,Tile::quartzBlock_Id,0,Tile::UPDATE_CLIENTS); } madeTrack = true; } @@ -488,11 +503,27 @@ void Player::tick() { // End 4J sTU } +int Player::getPortalWaitTime() { + return abilities.invulnerable ? 0 : SharedConstants::TICKS_PER_SECOND * 4; +} + +int Player::getDimensionChangingDelay() { + return SharedConstants::TICKS_PER_SECOND / 2; +} + +void Player::playSound(int iSound, float volume, float pitch) { + // this sound method will play locally for the local player, and + // broadcast to remote players + level->playPlayerSound( + std::dynamic_pointer_cast(shared_from_this()), iSound, volume, + pitch); +} + void Player::spawnEatParticles(std::shared_ptr useItem, int count) { if (useItem->getUseAnimation() == UseAnim_drink) { - level->playSound(shared_from_this(), eSoundType_RANDOM_DRINK, 0.5f, - level->random->nextFloat() * 0.1f + 0.9f); + playSound(eSoundType_RANDOM_DRINK, 0.5f, + level->random->nextFloat() * 0.1f + 0.9f); } if (useItem->getUseAnimation() == UseAnim_eat) { for (int i = 0; i < count; i++) { @@ -513,10 +544,8 @@ void Player::spawnEatParticles(std::shared_ptr useItem, } // 4J Stu - Was L"mob.eat" which doesnt exist - level->playSound( - shared_from_this(), eSoundType_RANDOM_EAT, - 0.5f + 0.5f * random->nextInt(2), - (random->nextFloat() - random->nextFloat()) * 0.2f + 1.0f); + playSound(eSoundType_RANDOM_EAT, 0.5f + 0.5f * random->nextInt(2), + (random->nextFloat() - random->nextFloat()) * 0.2f + 1.0f); } } @@ -538,11 +567,11 @@ void Player::completeUsingItem() { } } -void Player::handleEntityEvent(std::uint8_t id) { +void Player::handleEntityEvent(uint8_t id) { if (id == EntityEvent::USE_ITEM_COMPLETE) { completeUsingItem(); } else { - Mob::handleEntityEvent(id); + LivingEntity::handleEntityEvent(id); } } @@ -561,7 +590,7 @@ void Player::ride(std::shared_ptr e) { return; } - Mob::ride(e); + LivingEntity::ride(e); } void Player::setPlayerDefaultSkin(EDefaultSkins skin) { @@ -605,8 +634,7 @@ void Player::setCustomSkin(std::uint32_t skinId) { this->customTextureUrl = app.getSkinPathFromId(skinId); // set the new player additional boxes - /*std::vector - *pvModelParts=app.GetAdditionalModelParts(m_dwSkinId); + /*vector *pvModelParts=app.GetAdditionalModelParts(m_dwSkinId); if(pvModelParts==NULL) { @@ -821,12 +849,11 @@ void Player::prepareCustomTextures() { //{ // if(app.DefaultCapeExists()) // { - // this->customTextureUrl2= - //std::wstring(L"Default_Cape.png"); + // this->customTextureUrl2= wstring(L"Default_Cape.png"); // } // else // { - // this->customTextureUrl2= std::wstring(L""); + // this->customTextureUrl2= wstring(L""); // } //} @@ -835,25 +862,31 @@ void Player::prepareCustomTextures() { // if there is a custom default cloak, then set it here // if(app.DefaultCapeExists()) //{ - // this->customTextureUrl2= std::wstring(L"Default_Cape.png"); + // this->customTextureUrl2= wstring(L"Default_Cape.png"); //} // else //{ - // this->customTextureUrl2 =std::wstring(L""); + // this->customTextureUrl2 =wstring(L""); //} } /*cloakTexture = - * std::wstring(L"http://s3.amazonaws.com/MinecraftCloaks/").append( name + * wstring(L"http://s3.amazonaws.com/MinecraftCloaks/").append( name * ).append( L".png" );*/ // this->customTextureUrl2 = cloakTexture; } void Player::rideTick() { + if (!level->isClientSide && isSneaking()) { + ride(nullptr); + setSneaking(false); + return; + } + double preX = x, preY = y, preZ = z; float preYRot = yRot, preXRot = xRot; - this->Mob::rideTick(); + LivingEntity::rideTick(); oBob = bob; bob = 0; @@ -877,57 +910,40 @@ void Player::rideTick() { void Player::resetPos() { heightOffset = 1.62f; setSize(0.6f, 1.8f); - this->Mob::resetPos(); + LivingEntity::resetPos(); setHealth(getMaxHealth()); deathTime = 0; } -int Player::getCurrentSwingDuration() { - if (hasEffect(MobEffect::digSpeed)) { - return SWING_DURATION - - (1 + getEffect(MobEffect::digSpeed)->getAmplifier()) * 1; - } - if (hasEffect(MobEffect::digSlowdown)) { - return SWING_DURATION + - (1 + getEffect(MobEffect::digSlowdown)->getAmplifier()) * 2; - } - return SWING_DURATION; -} - void Player::serverAiStep() { - int currentSwingDuration = getCurrentSwingDuration(); - if (swinging) { - swingTime++; - if (swingTime >= currentSwingDuration) { - swingTime = 0; - swinging = false; - } - } else { - swingTime = 0; - } - - attackAnim = swingTime / (float)currentSwingDuration; + LivingEntity::serverAiStep(); + updateSwingTime(); } void Player::aiStep() { if (jumpTriggerTime > 0) jumpTriggerTime--; if (level->difficulty == Difficulty::PEACEFUL && - getHealth() < getMaxHealth()) { + getHealth() < getMaxHealth() && + level->getGameRules()->getBoolean( + GameRules::RULE_NATURAL_REGENERATION)) { if (tickCount % 20 * 12 == 0) heal(1); } inventory->tick(); oBob = bob; - this->Mob::aiStep(); + LivingEntity::aiStep(); - this->walkingSpeed = abilities.getWalkingSpeed(); - this->flyingSpeed = defaultFlySpeed; + AttributeInstance* speed = + getAttribute(SharedMonsterAttributes::MOVEMENT_SPEED); + if (!level->isClientSide) speed->setBaseValue(abilities.getWalkingSpeed()); + flyingSpeed = defaultFlySpeed; if (isSprinting()) { - walkingSpeed += abilities.getWalkingSpeed() * 0.3f; flyingSpeed += defaultFlySpeed * 0.3f; } + setSpeed((float)speed->getValue()); + float tBob = (float)sqrt(xd * xd + zd * zd); // 4J added - we were getting a NaN with zero xd & zd @@ -945,8 +961,17 @@ void Player::aiStep() { tilt += (tTilt - tilt) * 0.8f; if (getHealth() > 0) { + AABB* pickupArea = NULL; + if (riding != NULL && !riding->removed) { + // if the player is riding, also touch entities under the + // pig/horse + pickupArea = bb->minmax(riding->bb)->grow(1, 0, 1); + } else { + pickupArea = bb->grow(1, .5, 1); + } + std::vector >* entities = - level->getEntities(shared_from_this(), bb->grow(1, 0, 1)); + level->getEntities(shared_from_this(), pickupArea); if (entities != NULL) { AUTO_VAR(itEnd, entities->end()); for (AUTO_VAR(it, entities->begin()); it != itEnd; it++) { @@ -963,18 +988,18 @@ void Player::touch(std::shared_ptr entity) { entity->playerTouch(std::dynamic_pointer_cast(shared_from_this())); } -// 4J - Removed 1.0.1 -// bool Player::addResource(int resource) -//{ -// return inventory->add(std::shared_ptr( new -//ItemInstance(resource, 1, 0) ) ); -//} +int Player::getScore() { return entityData->getInteger(DATA_SCORE_ID); } -int Player::getScore() { return score; } +void Player::setScore(int value) { entityData->set(DATA_SCORE_ID, value); } + +void Player::increaseScore(int amount) { + int score = getScore(); + entityData->set(DATA_SCORE_ID, score + amount); +} void Player::die(DamageSource* source) { - this->Mob::die(source); - this->setSize(0.2f, 0.2f); + LivingEntity::die(source); + setSize(0.2f, 0.2f); setPos(x, y, z); yd = 0.1f; @@ -983,7 +1008,9 @@ void Player::die(DamageSource* source) { drop(std::shared_ptr(new ItemInstance(Item::apple, 1)), true); } - inventory->dropAll(); + if (!level->getGameRules()->getBoolean(GameRules::RULE_KEEPINVENTORY)) { + inventory->dropAll(); + } if (source != NULL) { xd = -Mth::cos((hurtDir + yRot) * PI / 180) * 0.1f; @@ -991,30 +1018,44 @@ void Player::die(DamageSource* source) { } else { xd = zd = 0; } - this->heightOffset = 0.1f; + heightOffset = 0.1f; } -void Player::awardKillScore(std::shared_ptr victim, int score) { - this->score += score; -} +void Player::awardKillScore(std::shared_ptr victim, int awardPoints) { + increaseScore(awardPoints); + std::vector* objectives = + getScoreboard()->findObjectiveFor(ObjectiveCriteria::KILL_COUNT_ALL); -int Player::decreaseAirSupply(int currentSupply) { - int oxygenBonus = EnchantmentHelper::getOxygenBonus(inventory); - if (oxygenBonus > 0) { - if (random->nextInt(oxygenBonus + 1) > 0) { - // the oxygen bonus prevents us from drowning - return currentSupply; + // if (victim instanceof Player) + //{ + // awardStat(Stats::playerKills, 1); + // objectives.addAll(getScoreboard().findObjectiveFor(ObjectiveCriteria::KILL_COUNT_PLAYERS)); + // } + // else + //{ + // awardStat(Stats::mobKills, 1); + // } + + if (objectives) { + for (AUTO_VAR(it, objectives->begin()); it != objectives->end(); ++it) { + Objective* objective = *it; + Score* score = + getScoreboard()->getPlayerScore(getAName(), objective); + score->increment(); } } - return Mob::decreaseAirSupply(currentSupply); } bool Player::isShootable() { return true; } bool Player::isCreativeModeAllowed() { return true; } -std::shared_ptr Player::drop() { - return drop(inventory->removeItem(inventory->selected, 1), false); +std::shared_ptr Player::drop(bool all) { + return drop(inventory->removeItem(inventory->selected, + all && inventory->getSelected() != NULL + ? inventory->getSelected()->count + : 1), + false); } std::shared_ptr Player::drop(std::shared_ptr item) { @@ -1024,6 +1065,7 @@ std::shared_ptr Player::drop(std::shared_ptr item) { std::shared_ptr Player::drop(std::shared_ptr item, bool randomly) { if (item == NULL) return nullptr; + if (item->count == 0) return nullptr; std::shared_ptr thrownItem = std::shared_ptr( new ItemEntity(level, x, y - 0.3f + getHeadHeight(), z, item)); @@ -1062,12 +1104,23 @@ void Player::reallyDrop(std::shared_ptr thrownItem) { level->addEntity(thrownItem); } -float Player::getDestroySpeed(Tile* tile) { +float Player::getDestroySpeed(Tile* tile, bool hasProperTool) { float speed = inventory->getDestroySpeed(tile); - int efficiency = EnchantmentHelper::getDiggingBonus(inventory); - if (efficiency > 0 && inventory->canDestroy(tile)) { - speed += (efficiency * efficiency + 1); + if (speed > 1) { + int efficiency = EnchantmentHelper::getDiggingBonus( + std::dynamic_pointer_cast(shared_from_this())); + std::shared_ptr item = inventory->getSelected(); + + if (efficiency > 0 && item != NULL) { + float boost = efficiency * efficiency + 1; + + if (item->canDestroySpecial(tile) || speed > 1) { + speed += boost; + } else { + speed += boost * 0.08f; + } + } } if (hasEffect(MobEffect::digSpeed)) { @@ -1080,7 +1133,8 @@ float Player::getDestroySpeed(Tile* tile) { } if (isUnderLiquid(Material::water) && - !EnchantmentHelper::hasWaterWorkerBonus(inventory)) + !EnchantmentHelper::hasWaterWorkerBonus( + std::dynamic_pointer_cast(shared_from_this()))) speed /= 5; // 4J Stu - onGround is set to true on the client when we are flying, which @@ -1094,17 +1148,18 @@ float Player::getDestroySpeed(Tile* tile) { bool Player::canDestroy(Tile* tile) { return inventory->canDestroy(tile); } void Player::readAdditionalSaveData(CompoundTag* entityTag) { - Mob::readAdditionalSaveData(entityTag); + LivingEntity::readAdditionalSaveData(entityTag); ListTag* inventoryList = (ListTag*)entityTag->getList(L"Inventory"); inventory->load(inventoryList); - dimension = entityTag->getInt(L"Dimension"); + inventory->selected = entityTag->getInt(L"SelectedItemSlot"); m_isSleeping = entityTag->getBoolean(L"Sleeping"); sleepCounter = entityTag->getShort(L"SleepTimer"); experienceProgress = entityTag->getFloat(L"XpP"); experienceLevel = entityTag->getInt(L"XpLevel"); totalExperience = entityTag->getInt(L"XpTotal"); + setScore(entityTag->getInt(L"Score")); if (m_isSleeping) { bedPosition = new Pos(Mth::floor(x), Mth::floor(y), Mth::floor(z)); @@ -1116,6 +1171,7 @@ void Player::readAdditionalSaveData(CompoundTag* entityTag) { respawnPosition = new Pos(entityTag->getInt(L"SpawnX"), entityTag->getInt(L"SpawnY"), entityTag->getInt(L"SpawnZ")); + respawnForced = entityTag->getBoolean(L"SpawnForced"); } foodData.readAdditionalSaveData(entityTag); @@ -1132,20 +1188,22 @@ void Player::readAdditionalSaveData(CompoundTag* entityTag) { } void Player::addAdditonalSaveData(CompoundTag* entityTag) { - Mob::addAdditonalSaveData(entityTag); + LivingEntity::addAdditonalSaveData(entityTag); entityTag->put(L"Inventory", inventory->save(new ListTag())); - entityTag->putInt(L"Dimension", dimension); + entityTag->putInt(L"SelectedItemSlot", inventory->selected); entityTag->putBoolean(L"Sleeping", m_isSleeping); entityTag->putShort(L"SleepTimer", (short)sleepCounter); entityTag->putFloat(L"XpP", experienceProgress); entityTag->putInt(L"XpLevel", experienceLevel); entityTag->putInt(L"XpTotal", totalExperience); + entityTag->putInt(L"Score", getScore()); if (respawnPosition != NULL) { entityTag->putInt(L"SpawnX", respawnPosition->x); entityTag->putInt(L"SpawnY", respawnPosition->y); entityTag->putInt(L"SpawnZ", respawnPosition->z); + entityTag->putBoolean(L"SpawnForced", respawnForced); } foodData.addAdditonalSaveData(entityTag); @@ -1157,33 +1215,39 @@ void Player::addAdditonalSaveData(CompoundTag* entityTag) { entityTag->putInt(L"GamePrivileges", m_uiGamePrivileges); } -Pos* Player::getRespawnPosition(Level* level, CompoundTag* entityTag) { - if (entityTag->contains(L"SpawnX") && entityTag->contains(L"SpawnY") && - entityTag->contains(L"SpawnZ")) { - return new Pos(entityTag->getInt(L"SpawnX"), - entityTag->getInt(L"SpawnY"), - entityTag->getInt(L"SpawnZ")); - } - return level->getSharedSpawnPos(); -} - bool Player::openContainer(std::shared_ptr container) { return true; } -bool Player::startEnchanting(int x, int y, int z) { return true; } +bool Player::openHopper(std::shared_ptr container) { + return true; +} + +bool Player::openHopper(std::shared_ptr container) { + return true; +} + +bool Player::openHorseInventory(std::shared_ptr horse, + std::shared_ptr container) { + return true; +} + +bool Player::startEnchanting(int x, int y, int z, const std::wstring& name) { + return true; +} bool Player::startRepairing(int x, int y, int z) { return true; } bool Player::startCrafting(int x, int y, int z) { return true; } -void Player::take(std::shared_ptr e, int orgCount) {} +bool Player::openFireworks(int x, int y, int z) { return true; } float Player::getHeadHeight() { return 0.12f; } void Player::setDefaultHeadHeight() { heightOffset = 1.62f; } -bool Player::hurt(DamageSource* source, int dmg) { +bool Player::hurt(DamageSource* source, float dmg) { + if (isInvulnerable()) return false; if (hasInvulnerablePrivilege() || (abilities.invulnerable && !source->isBypassInvul())) return false; @@ -1209,86 +1273,33 @@ bool Player::hurt(DamageSource* source, int dmg) { if (dmg == 0) return false; std::shared_ptr attacker = source->getEntity(); - if (std::dynamic_pointer_cast(attacker) != NULL) { - if ((std::dynamic_pointer_cast(attacker))->owner != NULL) { - attacker = (std::dynamic_pointer_cast(attacker))->owner; + if (attacker != NULL && attacker->instanceof(eTYPE_ARROW)) { + std::shared_ptr arrow = + std::dynamic_pointer_cast(attacker); + if (arrow->owner != NULL) { + attacker = arrow->owner; } } - if (std::dynamic_pointer_cast(attacker) != NULL) { - // aggreviate all pet wolves nearby - directAllTameWolvesOnTarget(std::dynamic_pointer_cast(attacker), - false); - } - return this->Mob::hurt(source, dmg); + return LivingEntity::hurt(source, dmg); } -int Player::getDamageAfterMagicAbsorb(DamageSource* damageSource, int damage) { - int remainingDamage = Mob::getDamageAfterMagicAbsorb(damageSource, damage); - if (remainingDamage <= 0) { - return 0; - } +bool Player::canHarmPlayer(std::shared_ptr target) { + Team* team = getTeam(); + Team* otherTeam = target->getTeam(); - int enchantmentArmor = - EnchantmentHelper::getDamageProtection(inventory, damageSource); - if (enchantmentArmor > 20) { - enchantmentArmor = 20; + if (team == NULL) { + return true; } - if (enchantmentArmor > 0 && enchantmentArmor <= 20) { - int absorb = 25 - enchantmentArmor; - int v = remainingDamage * absorb + dmgSpill; - remainingDamage = v / 25; - dmgSpill = v % 25; + if (!team->isAlliedTo(otherTeam)) { + return true; } - - return remainingDamage; + return team->isAllowFriendlyFire(); } -bool Player::isPlayerVersusPlayer() { return false; } +bool Player::canHarmPlayer(std::wstring targetName) { return true; } -void Player::directAllTameWolvesOnTarget(std::shared_ptr target, - bool skipSitting) { - // filter un-attackable mobs - if ((std::dynamic_pointer_cast(target) != NULL) || - (std::dynamic_pointer_cast(target) != NULL)) { - return; - } - // never target wolves that has this player as owner - if (std::dynamic_pointer_cast(target) != NULL) { - std::shared_ptr wolfTarget = - std::dynamic_pointer_cast(target); - if (wolfTarget->isTame() && - m_UUID.compare(wolfTarget->getOwnerUUID()) == 0) { - return; - } - } - if ((std::dynamic_pointer_cast(target) != NULL) && - !isPlayerVersusPlayer()) { - // pvp is off - return; - } - - // TODO: Optimize this? Most of the time players wont have pets: - std::vector >* nearbyWolves = - level->getEntitiesOfClass( - typeid(Wolf), - AABB::newTemp(x, y, z, x + 1, y + 1, z + 1)->grow(16, 4, 16)); - AUTO_VAR(itEnd, nearbyWolves->end()); - for (AUTO_VAR(it, nearbyWolves->begin()); it != itEnd; it++) { - std::shared_ptr wolf = std::dynamic_pointer_cast(*it); - ; - if (wolf->isTame() && wolf->getAttackTarget() == NULL && - m_UUID.compare(wolf->getOwnerUUID()) == 0) { - if (!skipSitting || !wolf->isSitting()) { - wolf->setSitting(false); - wolf->setAttackTarget(target); - } - } - } - delete nearbyWolves; -} - -void Player::hurtArmor(int damage) { inventory->hurtArmor(damage); } +void Player::hurtArmor(float damage) { inventory->hurtArmor(damage); } int Player::getArmorValue() { return inventory->getArmorValue(); } @@ -1302,15 +1313,23 @@ float Player::getArmorCoverPercentage() { return (float)count / (float)inventory->armor.length; } -void Player::actuallyHurt(DamageSource* source, int dmg) { - if (!source->isBypassArmor() && isBlocking()) { - dmg = (1 + dmg) >> 1; +void Player::actuallyHurt(DamageSource* source, float dmg) { + if (isInvulnerable()) return; + if (!source->isBypassArmor() && isBlocking() && dmg > 0) { + dmg = (1 + dmg) * .5f; } dmg = getDamageAfterArmorAbsorb(source, dmg); dmg = getDamageAfterMagicAbsorb(source, dmg); + + float originalDamage = dmg; + dmg = std::max(dmg - getAbsorptionAmount(), 0.0f); + setAbsorptionAmount(getAbsorptionAmount() - (originalDamage - dmg)); + if (dmg == 0) return; + causeFoodExhaustion(source->getFoodExhaustion()); - // this->Mob::actuallyHurt(source, dmg); - health -= dmg; + float oldHealth = getHealth(); + setHealth(getHealth() - dmg); + getCombatTracker()->recordDamage(source, oldHealth, dmg); } bool Player::openFurnace(std::shared_ptr container) { @@ -1321,14 +1340,19 @@ bool Player::openTrap(std::shared_ptr container) { return true; } -void Player::openTextEdit(std::shared_ptr sign) {} +void Player::openTextEdit(std::shared_ptr sign) {} bool Player::openBrewingStand( std::shared_ptr brewingStand) { return true; } -bool Player::openTrading(std::shared_ptr traderTarget) { +bool Player::openBeacon(std::shared_ptr beacon) { + return true; +} + +bool Player::openTrading(std::shared_ptr traderTarget, + const std::wstring& name) { return true; } @@ -1340,20 +1364,37 @@ bool Player::openTrading(std::shared_ptr traderTarget) { void Player::openItemInstanceGui(std::shared_ptr itemInstance) {} bool Player::interact(std::shared_ptr entity) { - if (entity->interact(std::dynamic_pointer_cast(shared_from_this()))) - return true; + std::shared_ptr thisPlayer = + std::dynamic_pointer_cast(shared_from_this()); + std::shared_ptr item = getSelectedItem(); - if (item != NULL && std::dynamic_pointer_cast(entity) != NULL) { + std::shared_ptr itemClone = + (item != NULL) ? item->copy() : nullptr; + if (entity->interact(thisPlayer)) { + // [EB]: Added rude check to see if we're still talking about the + // same item; this code caused bucket->milkbucket to be deleted because + // the milkbuckets' stack got decremented to 0. + if (item != NULL && item == getSelectedItem()) { + if (item->count <= 0 && !abilities.instabuild) { + removeSelectedItem(); + } else if (item->count < itemClone->count && abilities.instabuild) { + item->count = itemClone->count; + } + } + return true; + } + + if ((item != NULL) && entity->instanceof(eTYPE_LIVINGENTITY)) { // 4J - PC Comments // Hack to prevent item stacks from decrementing if the player has // the ability to instabuild - if (this->abilities.instabuild) item = item->copy(); - if (item->interactEnemy(std::dynamic_pointer_cast(entity))) { + if (this->abilities.instabuild) item = itemClone; + if (item->interactEnemy( + thisPlayer, std::dynamic_pointer_cast(entity))) { // 4J - PC Comments // Don't remove the item in hand if the player has the ability - // to - // instabuild - if (item->count <= 0 && !this->abilities.instabuild) { + // to instabuild + if ((item->count <= 0) && !abilities.instabuild) { removeSelectedItem(); } return true; @@ -1372,34 +1413,28 @@ void Player::removeSelectedItem() { double Player::getRidingHeight() { return heightOffset - 0.5f; } -void Player::swing() { - if (!swinging || swingTime >= getCurrentSwingDuration() / 2 || - swingTime < 0) { - swingTime = -1; - swinging = true; - } -} - void Player::attack(std::shared_ptr entity) { if (!entity->isAttackable()) { return; } - int dmg = inventory->getAttackDamage(entity); + if (entity->skipAttackInteraction(shared_from_this())) { + return; + } - if (hasEffect(MobEffect::damageBoost)) { - dmg += (3 << getEffect(MobEffect::damageBoost)->getAmplifier()); - } - if (hasEffect(MobEffect::weakness)) { - dmg -= (2 << getEffect(MobEffect::weakness)->getAmplifier()); - } + float dmg = + (float)getAttribute(SharedMonsterAttributes::ATTACK_DAMAGE)->getValue(); int knockback = 0; - int magicBoost = 0; - std::shared_ptr mob = std::dynamic_pointer_cast(entity); - if (mob != NULL) { - magicBoost = EnchantmentHelper::getDamageBonus(inventory, mob); - knockback += EnchantmentHelper::getKnockbackBonus(inventory, mob); + float magicBoost = 0; + + if (entity->instanceof(eTYPE_LIVINGENTITY)) { + std::shared_ptr thisPlayer = + std::dynamic_pointer_cast(shared_from_this()); + std::shared_ptr mob = + std::dynamic_pointer_cast(entity); + magicBoost = EnchantmentHelper::getDamageBonus(thisPlayer, mob); + knockback += EnchantmentHelper::getKnockbackBonus(thisPlayer, mob); } if (isSprinting()) { knockback += 1; @@ -1408,9 +1443,9 @@ void Player::attack(std::shared_ptr entity) { if (dmg > 0 || magicBoost > 0) { bool bCrit = fallDistance > 0 && !onGround && !onLadder() && !isInWater() && !hasEffect(MobEffect::blindness) && - riding == NULL && mob != NULL; - if (bCrit) { - dmg += random->nextInt(dmg / 2 + 2); + (riding == NULL) && entity->instanceof(eTYPE_LIVINGENTITY); + if (bCrit && dmg > 0) { + dmg *= 1.5f; } dmg += magicBoost; @@ -1418,8 +1453,8 @@ void Player::attack(std::shared_ptr entity) { // fire-enchanted weapon bool setOnFireTemporatily = false; int fireAspect = EnchantmentHelper::getFireAspect( - std::dynamic_pointer_cast(shared_from_this())); - if (std::dynamic_pointer_cast(entity) && fireAspect > 0 && + std::dynamic_pointer_cast(shared_from_this())); + if (entity->instanceof(eTYPE_MOB) && fireAspect > 0 && !entity->isOnFire()) { setOnFireTemporatily = true; entity->setOnFire(1); @@ -1451,29 +1486,37 @@ void Player::attack(std::shared_ptr entity) { } setLastHurtMob(entity); - std::shared_ptr mob = std::dynamic_pointer_cast(entity); - if (mob) { + if (entity->instanceof(eTYPE_LIVINGENTITY)) { + std::shared_ptr mob = + std::dynamic_pointer_cast(entity); ThornsEnchantment::doThornsAfterAttack(shared_from_this(), mob, random); } } std::shared_ptr item = getSelectedItem(); - if (item != NULL && std::dynamic_pointer_cast(entity) != NULL) { + std::shared_ptr hurtTarget = entity; + if (entity->instanceof(eTYPE_MULTIENTITY_MOB_PART)) { + std::shared_ptr multiMob = + std::dynamic_pointer_cast( + (std::dynamic_pointer_cast(entity)) + ->parentMob.lock()); + if ((multiMob != NULL) && + multiMob->instanceof(eTYPE_LIVINGENTITY)) { + hurtTarget = std::dynamic_pointer_cast(multiMob); + } + } + if ((item != NULL) && hurtTarget->instanceof(eTYPE_LIVINGENTITY)) { item->hurtEnemy( - std::dynamic_pointer_cast(entity), + std::dynamic_pointer_cast(hurtTarget), std::dynamic_pointer_cast(shared_from_this())); if (item->count <= 0) { removeSelectedItem(); } } - if (std::dynamic_pointer_cast(entity) != NULL) { - if (entity->isAlive()) { - directAllTameWolvesOnTarget( - std::dynamic_pointer_cast(entity), true); - } - // 4J Stu - Brought forward wasHurt check to Fix 66140 - Bug: Fire - // Aspect bypasses "Player v Player" being Disabled + if (entity->instanceof(eTYPE_LIVINGENTITY)) { + // awardStat(Stats.damageDealt, (int) Math.round(dmg * 10)); + if (fireAspect > 0 && wasHurt) { entity->setOnFire(fireAspect * 4); } else if (setOnFireTemporatily) { @@ -1483,6 +1526,12 @@ void Player::attack(std::shared_ptr entity) { causeFoodExhaustion(FoodConstants::EXHAUSTION_ATTACK); } + + // if (SharedConstants::INGAME_DEBUG_OUTPUT) + // { + // //sendMessage(ChatMessageComponent.forPlainText("DMG " + dmg + + // ", " + magicBoost + ", " + knockback)); + // } } void Player::crit(std::shared_ptr entity) {} @@ -1506,7 +1555,7 @@ void Player::animateRespawn(std::shared_ptr player, Level* level) { Slot* Player::getInventorySlot(int slotId) { return NULL; } void Player::remove() { - this->Mob::remove(); + LivingEntity::remove(); inventoryMenu->removed( std::dynamic_pointer_cast(shared_from_this())); if (containerMenu != NULL) { @@ -1515,7 +1564,7 @@ void Player::remove() { } } -bool Player::isInWall() { return !m_isSleeping && this->Mob::isInWall(); } +bool Player::isInWall() { return !m_isSleeping && LivingEntity::isInWall(); } bool Player::isLocalPlayer() { return false; } @@ -1553,6 +1602,7 @@ Player::BedSleepingResult Player::startSleepInBed(int x, int y, int z, AABB::newTemp(x - hRange, y - vRange, z - hRange, x + hRange, y + vRange, z + hRange)); if (!monsters->empty()) { + delete monsters; return NOT_SAFE; } delete monsters; @@ -1572,9 +1622,9 @@ Player::BedSleepingResult Player::startSleepInBed(int x, int y, int z, return OK; } - // 4J Stu - You can use a bed from within a minecart, and this causes all - // sorts of problems. - ride(nullptr); + if (isRiding()) { + ride(nullptr); + } setSize(0.2f, 0.2f); heightOffset = .2f; @@ -1676,7 +1726,7 @@ void Player::stopSleepInBed(bool forcefulWakeUp, bool updateLevelList, sleepCounter = SLEEP_DURATION; } if (saveRespawnPoint) { - setRespawnPosition(bedPosition); + setRespawnPosition(bedPosition, false); } } @@ -1685,7 +1735,7 @@ bool Player::checkBed() { Tile::bed_Id); } -Pos* Player::checkBedValidRespawnPosition(Level* level, Pos* pos) { +Pos* Player::checkBedValidRespawnPosition(Level* level, Pos* pos, bool forced) { // make sure the chunks around the bed exist ChunkSource* chunkSource = level->getChunkSource(); chunkSource->create((pos->x - 3) >> 4, (pos->z - 3) >> 4); @@ -1695,6 +1745,15 @@ Pos* Player::checkBedValidRespawnPosition(Level* level, Pos* pos) { // make sure the bed is still standing if (level->getTile(pos->x, pos->y, pos->z) != Tile::bed_Id) { + Material* bottomMaterial = level->getMaterial(pos->x, pos->y, pos->z); + Material* topMaterial = level->getMaterial(pos->x, pos->y + 1, pos->z); + bool freeFeet = + !bottomMaterial->isSolid() && !bottomMaterial->isLiquid(); + bool freeHead = !topMaterial->isSolid() && !topMaterial->isLiquid(); + + if (forced && freeFeet && freeHead) { + return pos; + } return NULL; } // make sure the bed still has a stand-up position @@ -1739,13 +1798,13 @@ bool Player::getPlayerFlag(int flag) { } void Player::setPlayerFlag(int flag, bool value) { - std::uint8_t currentValue = entityData->getByte(DATA_PLAYER_FLAGS_ID); + uint8_t currentValue = entityData->getByte(DATA_PLAYER_FLAGS_ID); if (value) { entityData->set(DATA_PLAYER_FLAGS_ID, - (std::uint8_t)(currentValue | (1 << flag))); + (uint8_t)(currentValue | (1 << flag))); } else { entityData->set(DATA_PLAYER_FLAGS_ID, - (std::uint8_t)(currentValue & ~(1 << flag))); + (uint8_t)(currentValue & ~(1 << flag))); } } @@ -1758,11 +1817,15 @@ void Player::displayClientMessage(int messageId) {} Pos* Player::getRespawnPosition() { return respawnPosition; } -void Player::setRespawnPosition(Pos* respawnPosition) { +bool Player::isRespawnForced() { return respawnForced; } + +void Player::setRespawnPosition(Pos* respawnPosition, bool forced) { if (respawnPosition != NULL) { this->respawnPosition = new Pos(*respawnPosition); + respawnForced = forced; } else { this->respawnPosition = NULL; + respawnForced = false; } } @@ -1773,7 +1836,7 @@ void Player::awardStat(Stat* stat, byteArray paramBlob) { } void Player::jumpFromGround() { - this->Mob::jumpFromGround(); + LivingEntity::jumpFromGround(); // 4J Stu - This seems to have been missed from 1.7.3, but do we care? // awardStat(Stats::jump, 1); @@ -1789,19 +1852,24 @@ void Player::travel(float xa, float ya) { double preX = x, preY = y, preZ = z; if (abilities.flying && riding == NULL) { - double ydo = this->yd; + double ydo = yd; float ofs = flyingSpeed; flyingSpeed = abilities.getFlyingSpeed(); - this->Mob::travel(xa, ya); - this->yd = ydo * 0.6; + LivingEntity::travel(xa, ya); + yd = ydo * 0.6; flyingSpeed = ofs; } else { - this->Mob::travel(xa, ya); + LivingEntity::travel(xa, ya); } checkMovementStatistiscs(x - preX, y - preY, z - preZ); } +float Player::getSpeed() { + return (float)getAttribute(SharedMonsterAttributes::MOVEMENT_SPEED) + ->getValue(); +} + void Player::checkMovementStatistiscs(double dx, double dy, double dz) { if (riding != NULL) { return; @@ -1865,7 +1933,7 @@ void Player::checkRidingStatistiscs(double dx, double dy, double dz) { int distance = (int)Math::round(sqrt(dx * dx + dy * dy + dz * dz) * 100.0f); if (distance > 0) { - if (std::dynamic_pointer_cast(riding)) { + if (riding->instanceof(eTYPE_MINECART)) { distanceMinecart += distance; if (distanceMinecart >= 100) { int newDistance = @@ -1911,7 +1979,7 @@ void Player::checkRidingStatistiscs(double dx, double dy, double dz) { #endif } - } else if (std::dynamic_pointer_cast(riding) != NULL) { + } else if (riding->instanceof(eTYPE_BOAT)) { distanceBoat += distance; if (distanceBoat >= 100) { int newDistance = distanceBoat - (distanceBoat % 100); @@ -1919,7 +1987,7 @@ void Player::checkRidingStatistiscs(double dx, double dy, double dz) { awardStat(GenericStats::boatOneM(), GenericStats::param_boat(newDistance / 100)); } - } else if (std::dynamic_pointer_cast(riding) != NULL) { + } else if (riding->instanceof(eTYPE_PIG)) { distancePig += distance; if (distancePig >= 100) { int newDistance = distancePig - (distancePig % 100); @@ -1944,16 +2012,15 @@ void Player::causeFallDamage(float distance) { GenericStats::param_fall(newDistance / 100)); } } - this->Mob::causeFallDamage(distance); + LivingEntity::causeFallDamage(distance); } -void Player::killed(std::shared_ptr mob) { +void Player::killed(std::shared_ptr mob) { // 4J-PB - added the lavaslime enemy - fix for #64007 - TU7: Code: // Achievements: TCR#073: Killing Magma Cubes doesn't unlock "Monster // Hunter" Achievement. - if (std::dynamic_pointer_cast(mob) != NULL || - mob->GetType() == eTYPE_GHAST || mob->GetType() == eTYPE_SLIME || - mob->GetType() == eTYPE_LAVASLIME || + if (mob->instanceof(eTYPE_ENEMY) || mob->GetType() == eTYPE_GHAST || + mob->GetType() == eTYPE_SLIME || mob->GetType() == eTYPE_LAVASLIME || mob->GetType() == eTYPE_ENDERDRAGON) { awardStat(GenericStats::killEnemy(), GenericStats::param_noArgs()); @@ -2011,8 +2078,12 @@ void Player::killed(std::shared_ptr mob) { } } +void Player::makeStuckInWeb() { + if (!abilities.flying) LivingEntity::makeStuckInWeb(); +} + Icon* Player::getItemInHandIcon(std::shared_ptr item, int layer) { - Icon* icon = Mob::getItemInHandIcon(item, layer); + Icon* icon = LivingEntity::getItemInHandIcon(item, layer); if (item->id == Item::fishingRod->id && fishing != NULL) { icon = Item::fishingRod->getEmptyIcon(); } else if (item->getItem()->hasMultipleSpriteLayers()) { @@ -2036,18 +2107,8 @@ std::shared_ptr Player::getArmor(int pos) { return inventory->getArmor(pos); } -void Player::handleInsidePortal() { - if (changingDimensionDelay > 0) { - changingDimensionDelay = 10; - return; - } - - isInsidePortal = true; -} - void Player::increaseXp(int i) { - // Update xp calculations from 1.3 - score += i; + increaseScore(i); int max = INT_MAX - totalExperience; if (i > max) { i = max; @@ -2057,15 +2118,26 @@ void Player::increaseXp(int i) { while (experienceProgress >= 1) { experienceProgress = (experienceProgress - 1) * getXpNeededForNextLevel(); - levelUp(); + giveExperienceLevels(1); experienceProgress /= getXpNeededForNextLevel(); } } -void Player::withdrawExperienceLevels(int amount) { - experienceLevel -= amount; +void Player::giveExperienceLevels(int amount) { + experienceLevel += amount; if (experienceLevel < 0) { experienceLevel = 0; + experienceProgress = 0; + totalExperience = 0; + } + + if (amount > 0 && experienceLevel % 5 == 0 && + lastLevelUpTime < + tickCount - SharedConstants::TICKS_PER_SECOND * 5.0f) { + float vol = experienceLevel > 30 ? 1 : experienceLevel / 30.0f; + level->playEntitySound(shared_from_this(), eSoundType_RANDOM_LEVELUP, + vol * 0.75f, 1); + lastLevelUpTime = tickCount; } } @@ -2080,8 +2152,6 @@ int Player::getXpNeededForNextLevel() { return 17; } -void Player::levelUp() { experienceLevel++; } - /** * This method adds on to the player's exhaustion, which may decrease the * player's food level. @@ -2140,9 +2210,42 @@ void Player::startUsingItem(std::shared_ptr instance, #endif } -bool Player::mayBuild(int x, int y, int z) { return abilities.mayBuild; } +bool Player::mayDestroyBlockAt(int x, int y, int z) { + if (abilities.mayBuild) { + return true; + } + int t = level->getTile(x, y, z); + if (t > 0) { + Tile* tile = Tile::tiles[t]; + + if (tile->material->isDestroyedByHand()) { + return true; + } else if (getSelectedItem() != NULL) { + std::shared_ptr carried = getSelectedItem(); + + if (carried->canDestroySpecial(tile) || + carried->getDestroySpeed(tile) > 1) { + return true; + } + } + } + return false; +} + +bool Player::mayUseItemAt(int x, int y, int z, int face, + std::shared_ptr item) { + if (abilities.mayBuild) { + return true; + } + if (item != NULL) { + return item->mayBePlacedInAdventureMode(); + } + return false; +} int Player::getExperienceReward(std::shared_ptr killedBy) { + if (level->getGameRules()->getBoolean(GameRules::RULE_KEEPINVENTORY)) + return 0; int reward = experienceLevel * 7; if (reward > 100) { return 100; @@ -2157,27 +2260,29 @@ bool Player::isAlwaysExperienceDropper() { std::wstring Player::getAName() { return name; } -void Player::changeDimension(int i) {} +bool Player::shouldShowName() { return true; } void Player::restoreFrom(std::shared_ptr oldPlayer, bool restoreAll) { if (restoreAll) { inventory->replaceWith(oldPlayer->inventory); - health = oldPlayer->health; + setHealth(oldPlayer->getHealth()); foodData = oldPlayer->foodData; experienceLevel = oldPlayer->experienceLevel; totalExperience = oldPlayer->totalExperience; experienceProgress = oldPlayer->experienceProgress; - score = oldPlayer->score; + setScore(oldPlayer->getScore()); + portalEntranceDir = oldPlayer->portalEntranceDir; + } else if (level->getGameRules()->getBoolean( + GameRules::RULE_KEEPINVENTORY)) { + inventory->replaceWith(oldPlayer->inventory); - for (AUTO_VAR(it, oldPlayer->activeEffects.begin()); - it != oldPlayer->activeEffects.end(); ++it) { - MobEffectInstance* instance = it->second; - addEffectNoUpdate(instance); - } - oldPlayer->activeEffects.clear(); + experienceLevel = oldPlayer->experienceLevel; + totalExperience = oldPlayer->totalExperience; + experienceProgress = oldPlayer->experienceProgress; + setScore(oldPlayer->getScore()); } enderChestInventory = oldPlayer->enderChestInventory; } @@ -2190,24 +2295,60 @@ void Player::setGameMode(GameType* mode) {} std::wstring Player::getName() { return name; } -std::wstring Player::getDisplayName() { return displayName; } +std::wstring Player::getDisplayName() { + // PlayerTeam.formatNameForTeam(getTeam(), name); -// Language getLanguage() { return Language.getInstance(); } -// String localize(String key, Object... args) { return -// getLanguage().getElement(key, args); } + // If player display name is not set, return name + return m_displayName.size() > 0 ? m_displayName : name; +} + +std::wstring Player::getNetworkName() { + // 4J: We can only transmit gamertag in network packets + return name; +} + +Level* Player::getCommandSenderWorld() { return level; } std::shared_ptr Player::getEnderChestInventory() { return enderChestInventory; } +std::shared_ptr Player::getCarried(int slot) { + if (slot == 0) return inventory->getSelected(); + return inventory->armor[slot - 1]; +} + std::shared_ptr Player::getCarriedItem() { return inventory->getSelected(); } +void Player::setEquippedSlot(int slot, std::shared_ptr item) { + inventory->armor[slot] = item; +} + bool Player::isInvisibleTo(std::shared_ptr player) { return isInvisible(); } +ItemInstanceArray Player::getEquipmentSlots() { return inventory->armor; } + +bool Player::isCapeHidden() { return getPlayerFlag(FLAG_HIDE_CAPE); } + +bool Player::isPushedByWater() { return !abilities.flying; } + +Scoreboard* Player::getScoreboard() { return level->getScoreboard(); } + +Team* Player::getTeam() { return getScoreboard()->getPlayersTeam(name); } + +void Player::setAbsorptionAmount(float absorptionAmount) { + if (absorptionAmount < 0) absorptionAmount = 0; + getEntityData()->set(DATA_PLAYER_ABSORPTION_ID, absorptionAmount); +} + +float Player::getAbsorptionAmount() { + return getEntityData()->getFloat(DATA_PLAYER_ABSORPTION_ID); +} + int Player::getTexture() { switch (m_skinIndex) { case eDefaultSkins_Skin0: @@ -2233,9 +2374,10 @@ int Player::getTexture() { } int Player::hash_fnct(const std::shared_ptr k) { - // Hashing the player's name based on platform + // TODO 4J Stu - Should we just be using the pointers and hashing them? #ifdef __PS3__ - return (int)boost::hash_value(k->name); + return (int)boost::hash_value( + k->name); // 4J Stu - Names are completely unique? #else return (int)std::hash()(k->name); #endif // __PS3__ @@ -2451,12 +2593,13 @@ bool Player::isAllowedToUse(std::shared_ptr item) { bool Player::isAllowedToInteract(std::shared_ptr target) { bool allowed = true; if (app.GetGameHostOption(eGameHostOption_TrustPlayers) == 0) { - if (target->GetType() == eTYPE_MINECART) { + if (target->instanceof(eTYPE_MINECART)) { if (getPlayerGamePrivilege( Player::ePlayerGamePrivilege_CanUseContainers) == 0) { std::shared_ptr minecart = std::dynamic_pointer_cast(target); - if (minecart->type == Minecart::CHEST) allowed = false; + if (minecart->getType() == Minecart::TYPE_CHEST) + allowed = false; } } else { diff --git a/Minecraft.World/Player/Player.h b/Minecraft.World/Player/Player.h index 06897b9df..8d3d3194c 100644 --- a/Minecraft.World/Player/Player.h +++ b/Minecraft.World/Player/Player.h @@ -2,25 +2,29 @@ #include -#include "../Entities/Mob.h" +#include "../Entities/LivingEntity.h" #include "../Util/Definitions.h" #include "Abilities.h" #include "FoodData.h" #include "PlayerEnderChestContainer.h" #include "../Commands/CommandSender.h" +#include "../Scores/ScoreHolder.h" class AbstractContainerMenu; class Stats; class FishingHook; - +class EntityHorse; class ItemEntity; class Slot; class Pos; - +class TileEntity; +class BeaconTileEntity; class FurnaceTileEntity; class DispenserTileEntity; class SignTileEntity; class BrewingStandTileEntity; +class HopperTileEntity; +class MinecartHopper; class Inventory; class Container; class FoodData; @@ -28,12 +32,12 @@ class DamageSource; class Merchant; class PlayerEnderChestContainer; class GameType; +class Scoreboard; -class Player : public Mob, public CommandSender { +class Player : public LivingEntity, public CommandSender, public ScoreHolder { public: static const int MAX_NAME_LENGTH = 16 + 4; static const int MAX_HEALTH = 20; - static const int SWING_DURATION = 6; static const int SLEEP_DURATION = 100; static const int WAKE_UP_DURATION = 10; @@ -48,7 +52,11 @@ private: static const int FLY_ACHIEVEMENT_SPEED = 25; static const int DATA_PLAYER_FLAGS_ID = 16; - static const int DATA_PLAYER_RUNNING_ID = 17; + static const int DATA_PLAYER_ABSORPTION_ID = 17; + static const int DATA_SCORE_ID = 18; + +protected: + static const int FLAG_HIDE_CAPE = 1; public: std::shared_ptr inventory; @@ -66,27 +74,25 @@ protected: public: std::uint8_t userType; - int score; float oBob, bob; - bool swinging; - int swingTime; std::wstring name; - int dimension; int takeXpDelay; // 4J-PB - track custom skin + std::wstring customTextureUrl; + std::wstring customTextureUrl2; unsigned int m_uiPlayerCurrentSkin; void ChangePlayerSkin(); - // 4J-PB - not needed, since cutomtextureurl2 is the same thing std::wstring + // 4J-PB - not needed, since cutomtextureurl2 is the same thing wstring // cloakTexture; double xCloakO, yCloakO, zCloakO; double xCloak, yCloak, zCloak; - // 4J-HEG - store display name, added for Xbox One - std::wstring displayName; + // 4J-HG: store display name, added for Xbox One "game display name" + std::wstring m_displayName; protected: // player sleeping in bed? @@ -105,6 +111,7 @@ public: private: Pos* respawnPosition; + bool respawnForced; Pos* minecartAchievementPos; // 4J Gordon: These are in cms, every time they go > 1m they are entered @@ -113,14 +120,6 @@ private: distanceMinecart, distanceBoat, distancePig; public: - int changingDimensionDelay; - -protected: - bool isInsidePortal; - -public: - float portalTime, oPortalTime; - Abilities abilities; int experienceLevel, totalExperience; @@ -136,18 +135,20 @@ protected: float defaultWalkSpeed; float defaultFlySpeed; +private: + int lastLevelUpTime; + public: eINSTANCEOF GetType() { return eTYPE_PLAYER; } // 4J Added to default init void _init(); - Player(Level* level); + Player(Level* level, const std::wstring& name); virtual ~Player(); - virtual int getMaxHealth(); - protected: + virtual void registerAttributes(); virtual void defineSynchedData(); public: @@ -159,7 +160,14 @@ public: void stopUsingItem(); virtual bool isBlocking(); + // 4J Stu - Added for things that should only be ticked once per simulation + // frame + virtual void updateFrameTick(); + virtual void tick(); + virtual int getPortalWaitTime(); + virtual int getDimensionChangingDelay(); + virtual void playSound(int iSound, float volume, float pitch); protected: void spawnEatParticles(std::shared_ptr useItem, int count); @@ -178,9 +186,6 @@ public: virtual void rideTick(); virtual void resetPos(); -private: - int getCurrentSwingDuration(); - protected: virtual void serverAiStep(); @@ -191,18 +196,15 @@ private: virtual void touch(std::shared_ptr entity); public: - // bool addResource(int resource); // 4J - Removed 1.0.1 - int getScore(); + virtual int getScore(); + virtual void setScore(int value); + virtual void increaseScore(int amount); virtual void die(DamageSource* source); - void awardKillScore(std::shared_ptr victim, int score); - -protected: - virtual int decreaseAirSupply(int currentSupply); - -public: + virtual void awardKillScore(std::shared_ptr victim, + int awardPoints); virtual bool isShootable(); bool isCreativeModeAllowed(); - virtual std::shared_ptr drop(); + virtual std::shared_ptr drop(bool all); std::shared_ptr drop(std::shared_ptr item); std::shared_ptr drop(std::shared_ptr item, bool randomly); @@ -211,18 +213,22 @@ protected: virtual void reallyDrop(std::shared_ptr thrownItem); public: - float getDestroySpeed(Tile* tile); + float getDestroySpeed(Tile* tile, bool hasProperTool); bool canDestroy(Tile* tile); virtual void readAdditionalSaveData(CompoundTag* entityTag); virtual void addAdditonalSaveData(CompoundTag* entityTag); - static Pos* getRespawnPosition(Level* level, CompoundTag* entityTag); virtual bool openContainer( std::shared_ptr container); // 4J - added bool return - virtual bool startEnchanting(int x, int y, - int z); // 4J - added bool return + virtual bool openHopper(std::shared_ptr container); + virtual bool openHopper(std::shared_ptr container); + virtual bool openHorseInventory(std::shared_ptr horse, + std::shared_ptr container); + virtual bool startEnchanting( + int x, int y, int z, + const std::wstring& name); // 4J - added bool return virtual bool startRepairing(int x, int y, int z); // 4J - added bool return - virtual bool startCrafting(int x, int y, int z); // 4J - added boo return - virtual void take(std::shared_ptr e, int orgCount); + virtual bool startCrafting(int x, int y, int z); // 4J - added bool return + virtual bool openFireworks(int x, int y, int z); // 4J - added virtual float getHeadHeight(); // 4J-PB - added to keep the code happy with the change to make the third @@ -236,22 +242,21 @@ protected: public: std::shared_ptr fishing; - virtual bool hurt(DamageSource* source, int dmg); + virtual bool hurt(DamageSource* source, float dmg); + virtual bool canHarmPlayer(std::shared_ptr target); + virtual bool canHarmPlayer( + std::wstring targetName); // 4J: Added for ServerPlayer when only + // player name is provided protected: - virtual int getDamageAfterMagicAbsorb(DamageSource* damageSource, - int damage); - virtual bool isPlayerVersusPlayer(); - void directAllTameWolvesOnTarget(std::shared_ptr target, - bool skipSitting); - virtual void hurtArmor(int damage); + virtual void hurtArmor(float damage); public: virtual int getArmorValue(); - float getArmorCoverPercentage(); + virtual float getArmorCoverPercentage(); protected: - virtual void actuallyHurt(DamageSource* source, int dmg); + virtual void actuallyHurt(DamageSource* source, float dmg); public: using Entity::interact; @@ -260,18 +265,19 @@ public: container); // 4J - added bool return virtual bool openTrap(std::shared_ptr container); // 4J - added bool return - virtual void openTextEdit(std::shared_ptr sign); + virtual void openTextEdit(std::shared_ptr sign); virtual bool openBrewingStand(std::shared_ptr brewingStand); // 4J - added bool return + virtual bool openBeacon(std::shared_ptr beacon); virtual bool openTrading( - std::shared_ptr traderTarget); // 4J - added bool return + std::shared_ptr traderTarget, + const std::wstring& name); // 4J - added bool return virtual void openItemInstanceGui( std::shared_ptr itemInstance); virtual bool interact(std::shared_ptr entity); virtual std::shared_ptr getSelectedItem(); void removeSelectedItem(); virtual double getRidingHeight(); - virtual void swing(); virtual void attack(std::shared_ptr entity); virtual void crit(std::shared_ptr entity); virtual void magicCrit(std::shared_ptr entity); @@ -321,7 +327,8 @@ private: bool checkBed(); public: - static Pos* checkBedValidRespawnPosition(Level* level, Pos* pos); + static Pos* checkBedValidRespawnPosition(Level* level, Pos* pos, + bool forced); float getSleepRotation(); bool isSleeping(); bool isSleepingLongEnough(); @@ -339,16 +346,18 @@ public: * client. */ virtual void displayClientMessage(int messageId); - Pos* getRespawnPosition(); - void setRespawnPosition(Pos* respawnPosition); + virtual Pos* getRespawnPosition(); + virtual bool isRespawnForced(); + virtual void setRespawnPosition(Pos* respawnPosition, bool forced); virtual void awardStat(Stat* stat, byteArray param); protected: void jumpFromGround(); public: - void travel(float xa, float ya); - void checkMovementStatistiscs(double dx, double dy, double dz); + virtual void travel(float xa, float ya); + virtual float getSpeed(); + virtual void checkMovementStatistiscs(double dx, double dy, double dz); private: void checkRidingStatistiscs(double dx, double dy, double dz); @@ -359,27 +368,23 @@ protected: virtual void causeFallDamage(float distance); public: - virtual void killed(std::shared_ptr mob); + virtual void killed(std::shared_ptr mob); + virtual void makeStuckInWeb(); virtual Icon* getItemInHandIcon(std::shared_ptr item, int layer); virtual std::shared_ptr getArmor(int pos); - virtual void handleInsidePortal(); - - void increaseXp(int i); - virtual void withdrawExperienceLevels(int amount); + virtual void increaseXp(int i); + virtual void giveExperienceLevels(int amount); int getXpNeededForNextLevel(); - -private: - void levelUp(); - -public: void causeFoodExhaustion(float amount); FoodData* getFoodData(); bool canEat(bool magicalItem); bool isHurt(); virtual void startUsingItem(std::shared_ptr instance, int duration); - bool mayBuild(int x, int y, int z); + virtual bool mayDestroyBlockAt(int x, int y, int z); + virtual bool mayUseItemAt(int x, int y, int z, int face, + std::shared_ptr item); protected: virtual int getExperienceReward(std::shared_ptr killedBy); @@ -387,8 +392,7 @@ protected: public: virtual std::wstring getAName(); - - virtual void changeDimension(int i); + virtual bool shouldShowName(); virtual void restoreFrom(std::shared_ptr oldPlayer, bool restoreAll); @@ -399,18 +403,26 @@ public: void onUpdateAbilities(); void setGameMode(GameType* mode); std::wstring getName(); - std::wstring getDisplayName(); // 4J added + virtual std::wstring getDisplayName(); + virtual std::wstring getNetworkName(); // 4J: Added - // Language getLanguage() { return Language.getInstance(); } - // String localize(String key, Object... args) { return - // getLanguage().getElement(key, args); } + virtual Level* getCommandSenderWorld(); std::shared_ptr getEnderChestInventory(); -public: + virtual std::shared_ptr getCarried(int slot); virtual std::shared_ptr getCarriedItem(); - + virtual void setEquippedSlot(int slot, std::shared_ptr item); virtual bool isInvisibleTo(std::shared_ptr player); + virtual ItemInstanceArray getEquipmentSlots(); + virtual bool isCapeHidden(); + virtual bool isPushedByWater(); + virtual Scoreboard* getScoreboard(); + virtual Team* getTeam(); + virtual void setAbsorptionAmount(float absorptionAmount); + virtual float getAbsorptionAmount(); + + //////// 4J ///////////////// static int hash_fnct(const std::shared_ptr k); static bool eq_test(const std::shared_ptr x, @@ -438,8 +450,6 @@ public: PlayerUID getXuid() { return m_xuid; } void setOnlineXuid(PlayerUID xuid) { m_OnlineXuid = xuid; } PlayerUID getOnlineXuid() { return m_OnlineXuid; } - void setUUID(const std::wstring& UUID) { m_UUID = UUID; } - std::wstring getUUID() { return m_UUID; } void setPlayerIndex(std::uint8_t index) { m_playerIndex = index; } std::uint8_t getPlayerIndex() { return m_playerIndex; } @@ -463,8 +473,6 @@ private: PlayerUID m_OnlineXuid; protected: - std::wstring m_UUID; // 4J Added - bool m_bShownOnMaps; bool m_bIsGuest; diff --git a/Minecraft.World/Player/PlayerEnderChestContainer.cpp b/Minecraft.World/Player/PlayerEnderChestContainer.cpp index 4f3eabf2d..9fe66f554 100644 --- a/Minecraft.World/Player/PlayerEnderChestContainer.cpp +++ b/Minecraft.World/Player/PlayerEnderChestContainer.cpp @@ -1,12 +1,17 @@ #include "../Platform/stdafx.h" #include "../Headers/net.minecraft.world.level.tile.entity.h" +#include "../Network/Packets/ContainerOpenPacket.h" #include "PlayerEnderChestContainer.h" PlayerEnderChestContainer::PlayerEnderChestContainer() - : SimpleContainer(IDS_TILE_ENDERCHEST, 9 * 3) { + : SimpleContainer(IDS_TILE_ENDERCHEST, L"", false, 9 * 3) { activeChest = nullptr; } +int PlayerEnderChestContainer::getContainerType() { + return ContainerOpenPacket::ENDER_CHEST; +} + void PlayerEnderChestContainer::setActiveChest( std::shared_ptr activeChest) { this->activeChest = activeChest; @@ -60,3 +65,8 @@ void PlayerEnderChestContainer::stopOpen() { SimpleContainer::stopOpen(); activeChest = nullptr; } + +bool PlayerEnderChestContainer::canPlaceItem( + int slot, std::shared_ptr item) { + return true; +} \ No newline at end of file diff --git a/Minecraft.World/Player/PlayerEnderChestContainer.h b/Minecraft.World/Player/PlayerEnderChestContainer.h index 2c156cc6f..a3ff584c4 100644 --- a/Minecraft.World/Player/PlayerEnderChestContainer.h +++ b/Minecraft.World/Player/PlayerEnderChestContainer.h @@ -11,10 +11,13 @@ private: public: PlayerEnderChestContainer(); + virtual int getContainerType(); + void setActiveChest(std::shared_ptr activeChest); void setItemsByTag(ListTag* enderItemsList); ListTag* createTag(); bool stillValid(std::shared_ptr player); void startOpen(); void stopOpen(); + bool canPlaceItem(int slot, std::shared_ptr item); }; \ No newline at end of file