the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 1742 lines 50 kB view raw
1#include "stdafx.h" 2#include "LocalPlayer.h" 3#include "User.h" 4#include "Input.h" 5#include "StatsCounter.h" 6#include "ParticleEngine.h" 7#include "TakeAnimationParticle.h" 8#include "Options.h" 9#include "TextEditScreen.h" 10#include "ContainerScreen.h" 11#include "CraftingScreen.h" 12#include "FurnaceScreen.h" 13#include "TrapScreen.h" 14 15#include "MultiPlayerLocalPlayer.h" 16#include "CreativeMode.h" 17#include "GameRenderer.h" 18#include "ItemInHandRenderer.h" 19#include "..\Minecraft.World\AttributeInstance.h" 20#include "..\Minecraft.World\LevelData.h" 21#include "..\Minecraft.World\net.minecraft.world.damagesource.h" 22#include "..\Minecraft.World\net.minecraft.world.item.h" 23#include "..\Minecraft.World\net.minecraft.world.food.h" 24#include "..\Minecraft.World\net.minecraft.world.effect.h" 25#include "..\Minecraft.World\net.minecraft.world.entity.player.h" 26#include "..\Minecraft.World\net.minecraft.world.entity.monster.h" 27#include "..\Minecraft.World\ItemEntity.h" 28#include "..\Minecraft.World\net.minecraft.world.level.h" 29#include "..\Minecraft.World\net.minecraft.world.level.tile.entity.h" 30#include "..\Minecraft.World\net.minecraft.world.phys.h" 31#include "..\Minecraft.World\net.minecraft.stats.h" 32#include "..\Minecraft.World\com.mojang.nbt.h" 33#include "..\Minecraft.World\Random.h" 34#include "..\Minecraft.World\TileEntity.h" 35#include "..\Minecraft.World\Mth.h" 36#include "AchievementPopup.h" 37#include "CritParticle.h" 38 39// 4J : WESTY : Added for new achievements. 40#include "..\Minecraft.World\item.h" 41#include "..\Minecraft.World\mapitem.h" 42#include "..\Minecraft.World\tile.h" 43 44// 4J Stu - Added for tutorial callbacks 45#include "Minecraft.h" 46 47#include "..\Minecraft.World\Minecart.h" 48#include "..\Minecraft.World\Boat.h" 49#include "..\Minecraft.World\Pig.h" 50 51#include "..\Minecraft.World\StringHelpers.h" 52 53#include "Options.h" 54#include "..\Minecraft.World\Dimension.h" 55 56#ifndef _DURANGO 57#include "..\Minecraft.World\CommonStats.h" 58#endif 59 60 61 62LocalPlayer::LocalPlayer(Minecraft *minecraft, Level *level, User *user, int dimension) : Player(level, user->name) 63{ 64 flyX = flyY = flyZ = 0.0f; // 4J added 65 m_awardedThisSession = 0; 66 67 sprintTriggerTime = 0; 68 sprintTriggerRegisteredReturn = false; 69 twoJumpsRegistered = false; 70 sprintTime = 0; 71 m_uiInactiveTicks=0; 72 portalTime = 0.0f; 73 oPortalTime = 0.0f; 74 jumpRidingTicks = 0; 75 jumpRidingScale = 0.0f; 76 77 yBob = xBob = yBobO = xBobO = 0.0f; 78 79 this->minecraft = minecraft; 80 this->dimension = dimension; 81 82 if (user != NULL && user->name.length() > 0) 83 { 84 customTextureUrl = L"http://s3.amazonaws.com/MinecraftSkins/" + user->name + L".png"; 85 } 86 if( user != NULL ) 87 { 88 this->name = user->name; 89 //wprintf(L"Created LocalPlayer with name %ls\n", name.c_str() ); 90 // check to see if this player's xuid is in the list of special players 91 MOJANG_DATA *pMojangData=app.GetMojangDataForXuid(getOnlineXuid()); 92 if(pMojangData) 93 { 94 customTextureUrl=pMojangData->wchSkin; 95 } 96 97 } 98 input = NULL; 99 m_iPad = -1; 100 m_iScreenSection=C4JRender::VIEWPORT_TYPE_FULLSCREEN; // assume singleplayer default 101 m_bPlayerRespawned=false; 102 ullButtonsPressed=0LL; 103 ullDpad_last = ullDpad_this = ullDpad_filtered = 0; 104 105 // 4J-PB - moved in from the minecraft structure 106 //ticks=0; 107 missTime=0; 108 lastClickTick[0] = 0; 109 lastClickTick[1] = 0; 110 isRaining=false; 111 112 m_bIsIdle = false; 113 m_iThirdPersonView=0; 114 115 // 4J Stu - Added for telemetry 116 SetSessionTimerStart(); 117 118 // 4J - added for auto repeat in creative mode 119 lastClickState = lastClick_invalid; 120 lastClickTolerance = 0.0f; 121 122 m_bHasAwardedStayinFrosty = false; 123} 124 125LocalPlayer::~LocalPlayer() 126{ 127 if( this->input != NULL ) 128 delete input; 129} 130 131void LocalPlayer::calculateFlight(float xa, float ya, float za) 132{ 133 xa = xa * minecraft->options->flySpeed; 134 ya = 0; 135 za = za * minecraft->options->flySpeed; 136 137 flyX = smoothFlyX.getNewDeltaValue(xa, .35f * minecraft->options->sensitivity); 138 flyY = smoothFlyY.getNewDeltaValue(ya, .35f * minecraft->options->sensitivity); 139 flyZ = smoothFlyZ.getNewDeltaValue(za, .35f * minecraft->options->sensitivity); 140} 141 142void LocalPlayer::serverAiStep() 143{ 144 Player::serverAiStep(); 145 146 if( abilities.flying && abilities.mayfly ) 147 { 148 // snap y rotation for flying to nearest 90 degrees in world space 149 float fMag = sqrtf(input->xa * input->xa + input->ya * input->ya); 150 // Don't bother for tiny inputs 151 if( fMag >= 0.1f ) 152 { 153 // Get angle (in player rotated space) of input controls 154 float yRotInput = atan2f(input->ya, input->xa) * (180.0f / PI); 155 // Now get in world space 156 float yRotFinal = yRotInput + yRot; 157 // Snap this to nearest 90 degrees 158 float yRotSnapped = floorf((yRotFinal / 45.0f) + 0.5f) * 45.0f; 159 // Find out how much we had to move to do this snap 160 float yRotDiff = yRotSnapped - yRotFinal; 161 // Apply the same difference to the player rotated space angle 162 float yRotInputAdjust = yRotInput + yRotDiff; 163 164 // Calculate final x/y player-space movement required 165 this->xxa = cos(yRotInputAdjust * ( PI / 180.0f) ) * fMag; 166 this->yya = sin(yRotInputAdjust * ( PI / 180.0f) ) * fMag; 167 } 168 else 169 { 170 this->xxa = input->xa; 171 this->yya = input->ya; 172 } 173 } 174 else 175 { 176 this->xxa = input->xa; 177 this->yya = input->ya; 178 } 179 this->jumping = input->jumping; 180 181 yBobO = yBob; 182 xBobO = xBob; 183 xBob += (xRot - xBob) * 0.5; 184 yBob += (yRot - yBob) * 0.5; 185 186 // TODO 4J - Remove 187 //if (input->jumping) 188 // mapPlayerChunk(8); 189} 190 191bool LocalPlayer::isEffectiveAi() 192{ 193 return true; 194} 195 196void LocalPlayer::aiStep() 197{ 198 if (sprintTime > 0) 199 { 200 sprintTime--; 201 if (sprintTime == 0) 202 { 203 setSprinting(false); 204 } 205 } 206 if (sprintTriggerTime > 0) sprintTriggerTime--; 207 if (minecraft->gameMode->isCutScene()) 208 { 209 x = z = 0.5; 210 x = 0; 211 z = 0; 212 yRot = tickCount / 12.0f; 213 xRot = 10; 214 y = 68.5; 215 return; 216 } 217 oPortalTime = portalTime; 218 if (isInsidePortal) 219 { 220 if (!level->isClientSide) 221 { 222 if (riding != NULL) this->ride(nullptr); 223 } 224 if (minecraft->screen != NULL) minecraft->setScreen(NULL); 225 226 if (portalTime == 0) 227 { 228 minecraft->soundEngine->playUI(eSoundType_PORTAL_TRIGGER, 1, random->nextFloat() * 0.4f + 0.8f); 229 } 230 portalTime += 1 / 80.0f; 231 if (portalTime >= 1) 232 { 233 portalTime = 1; 234 } 235 isInsidePortal = false; 236 } 237 else if (hasEffect(MobEffect::confusion) && getEffect(MobEffect::confusion)->getDuration() > (SharedConstants::TICKS_PER_SECOND * 3)) 238 { 239 portalTime += 1 / 150.0f; 240 if (portalTime > 1) 241 { 242 portalTime = 1; 243 } 244 } 245 else 246 { 247 if (portalTime > 0) portalTime -= 1 / 20.0f; 248 if (portalTime < 0) portalTime = 0; 249 } 250 251 if (changingDimensionDelay > 0) changingDimensionDelay--; 252 bool wasJumping = input->jumping; 253 float runTreshold = 0.8f; 254 float sprintForward = input->sprintForward; 255 256 bool wasRunning = sprintForward >= runTreshold; 257 //input->tick( dynamic_pointer_cast<Player>( shared_from_this() ) ); 258 // 4J-PB - make it a localplayer 259 input->tick( this ); 260 sprintForward = input->sprintForward; 261 if (isUsingItem() && !isRiding()) 262 { 263 input->xa *= 0.2f; 264 input->ya *= 0.2f; 265 sprintTriggerTime = 0; 266 } 267 // this.heightOffset = input.sneaking?1.30f:1.62f; // 4J - this was already commented out 268 if (input->sneaking) // 4J - removed - TODO replace 269 { 270 if (ySlideOffset < 0.2f) ySlideOffset = 0.2f; 271 } 272 273 checkInTile(x - bbWidth * 0.35, bb->y0 + 0.5, z + bbWidth * 0.35); 274 checkInTile(x - bbWidth * 0.35, bb->y0 + 0.5, z - bbWidth * 0.35); 275 checkInTile(x + bbWidth * 0.35, bb->y0 + 0.5, z - bbWidth * 0.35); 276 checkInTile(x + bbWidth * 0.35, bb->y0 + 0.5, z + bbWidth * 0.35); 277 278 bool enoughFoodToSprint = getFoodData()->getFoodLevel() > FoodConstants::MAX_FOOD * FoodConstants::FOOD_SATURATION_LOW; 279 280 // 4J Stu - If we can fly, then we should be able to sprint without requiring food. This is particularly a problem for people who save a survival 281 // world with low food, then reload it in creative. 282 if(abilities.mayfly || isAllowedToFly() ) enoughFoodToSprint = true; 283 284 bool forwardEnoughToTriggerSprint = sprintForward >= runTreshold; 285 bool forwardReturnedToDeadzone = sprintForward == 0.0f; 286 bool forwardEnoughToContinueSprint = sprintForward >= runTreshold; 287 288#ifdef _WINDOWS64 289 if (GetXboxPad() == 0 && input->usingKeyboardMovement) 290 { 291 forwardEnoughToContinueSprint = sprintForward > 0.0f; 292 } 293#endif 294 295#ifdef _WINDOWS64 296 // Keyboard sprint: Ctrl held while moving forward 297 if (GetXboxPad() == 0 && input->usingKeyboardMovement && KMInput.IsKeyDown(VK_CONTROL) && sprintForward > 0.0f && 298 enoughFoodToSprint && !isUsingItem() && !hasEffect(MobEffect::blindness) && onGround) 299 { 300 if (!isSprinting()) setSprinting(true); 301 } 302#endif 303 304 // 4J - altered this slightly to make sure that the joypad returns to below returnTreshold in between registering two movements up to runThreshold 305 if (onGround && !isSprinting() && enoughFoodToSprint && !isUsingItem() && !hasEffect(MobEffect::blindness)) 306 { 307 if( !wasRunning && forwardEnoughToTriggerSprint ) 308 { 309 if (sprintTriggerTime == 0) 310 { 311 sprintTriggerTime = 7; 312 sprintTriggerRegisteredReturn = false; 313 } 314 else 315 { 316 if( sprintTriggerRegisteredReturn ) 317 { 318 setSprinting(true); 319 sprintTriggerTime = 0; 320 sprintTriggerRegisteredReturn = false; 321 } 322 } 323 } 324 else if( ( sprintTriggerTime > 0 ) && forwardReturnedToDeadzone ) // zero sprintForward here signifies that we have returned to the deadzone 325 { 326 sprintTriggerRegisteredReturn = true; 327 } 328 } 329 if (isSneaking()) sprintTriggerTime = 0; 330 // 4J-PB - try not stopping sprint on collision 331 //if (isSprinting() && (input->ya < runTreshold || horizontalCollision || !enoughFoodToSprint)) 332 if (isSprinting() && (!forwardEnoughToContinueSprint || !enoughFoodToSprint || isSneaking() || isUsingItem())) 333 { 334 setSprinting(false); 335 } 336 337 // 4J Stu - Fix for #52705 - Customer Encountered: Player can fly in bed while being in Creative mode. 338 if (!isSleeping() && (abilities.mayfly || isAllowedToFly() )) 339 { 340 // 4J altered to require jump button to released after being tapped twice to trigger move between flying / not flying 341 if (!wasJumping && input->jumping) 342 { 343 if (jumpTriggerTime == 0) 344 { 345 jumpTriggerTime = 7; // the 4J team changed it to 10 because of additional requirements to initiate flight 346 twoJumpsRegistered = false; 347 } 348 else 349 { 350 twoJumpsRegistered = true; 351 } 352 } 353 else if(jumpTriggerTime > 0 && twoJumpsRegistered) //the 4J team checked if the player was NOT jumping after the two jumps, aka had let go of the jump button 354 { 355#ifndef _CONTENT_PACKAGE 356 printf("flying was %s\n", abilities.flying ? "on" : "off"); 357#endif 358 abilities.flying = !abilities.flying; 359#ifndef _CONTENT_PACKAGE 360 printf("flying is %s\n", abilities.flying ? "on" : "off"); 361#endif 362 jumpTriggerTime = 0; 363 twoJumpsRegistered = false; 364 if( abilities.flying ) input->sneaking = false; // 4J added - would we ever intentially want to go into flying mode whilst sneaking? 365 } 366 } 367 else if(abilities.flying) 368 { 369#ifdef _DEBUG_MENUS_ENABLED 370 if(!abilities.debugflying) 371#endif 372 { 373 abilities.flying = false; 374 } 375 } 376 377 378 if (abilities.flying) 379 { 380 // yd = 0; 381 // 4J - note that the 0.42 added for going down is to make it match with what happens when you jump - jumping itself adds 0.42 to yd in Mob::jumpFromGround 382 if (ullButtonsPressed & (1LL<<MINECRAFT_ACTION_SNEAK_TOGGLE) ) yd -= ( 0.15 + 0.42 ); // 4J - for flying mode, MINECRAFT_ACTION_SNEAK_TOGGLE isn't a toggle but just indicates that this button is down 383 if (input->jumping) 384 { 385 noJumpDelay = 0; 386 yd += 0.15; 387 } 388 389 // snap y rotation to nearest 90 degree axis aligned value 390 float yRotSnapped = floorf((yRot / 90.0f) + 0.5f) * 90.0f; 391 392 if(InputManager.GetJoypadMapVal(m_iPad) == 0) 393 { 394 if( ullDpad_filtered & (1LL<<MINECRAFT_ACTION_DPAD_RIGHT)) 395 { 396 xd = -0.15 * cos(yRotSnapped * PI / 180); 397 zd = -0.15 * sin(yRotSnapped * PI / 180); 398 } 399 else if( ullDpad_filtered & (1LL<<MINECRAFT_ACTION_DPAD_LEFT)) 400 { 401 xd = 0.15 * cos(yRotSnapped * PI / 180); 402 zd = 0.15 * sin(yRotSnapped * PI / 180); 403 } 404 } 405 } 406 407 if (isRidingJumpable()) 408 { 409 if (jumpRidingTicks < 0) 410 { 411 jumpRidingTicks++; 412 if (jumpRidingTicks == 0) 413 { 414 // reset scale (for gui) 415 jumpRidingScale = 0; 416 } 417 } 418 if (wasJumping && !input->jumping) 419 { 420 // jump release 421 jumpRidingTicks = -10; 422 sendRidingJump(); 423 } 424 else if (!wasJumping && input->jumping) 425 { 426 // jump press 427 jumpRidingTicks = 0; 428 jumpRidingScale = 0; 429 } 430 else if (wasJumping) 431 { 432 // calc jump scale 433 jumpRidingTicks++; 434 if (jumpRidingTicks < 10) 435 { 436 jumpRidingScale = (float) jumpRidingTicks * .1f; 437 } 438 else 439 { 440 jumpRidingScale = .8f + (2.f / ((float) (jumpRidingTicks - 9))) * .1f; 441 } 442 } 443 } 444 else 445 { 446 jumpRidingScale = 0; 447 } 448 449 Player::aiStep(); 450 451 // 4J-PB - If we're in Creative Mode, allow flying on ground 452 if(!abilities.mayfly && !isAllowedToFly() ) 453 { 454 if (onGround && abilities.flying) 455 { 456#ifdef _DEBUG_MENUS_ENABLED 457 if(!abilities.debugflying) 458#endif 459 { 460 abilities.flying = false; 461 } 462 } 463 } 464 465 if( abilities.flying )//minecraft->options->isFlying ) 466 { 467 Vec3* viewVector = getViewVector(1.0f); 468 469 // 4J-PB - To let the player build easily while flying, we need to change this 470 471#ifdef _DEBUG_MENUS_ENABLED 472 if(abilities.debugflying) 473 { 474 flyX = (float)viewVector->x * input->ya; 475 flyY = (float)viewVector->y * input->ya; 476 flyZ = (float)viewVector->z * input->ya; 477 } 478 else 479#endif 480 { 481 if( isSprinting() ) 482 { 483 // Accelrate up to full speed if we are sprinting, moving in the direction of the view vector 484 flyX = (float)viewVector->x * input->ya; 485 flyY = (float)viewVector->y * input->ya; 486 flyZ = (float)viewVector->z * input->ya; 487 488 float scale = ((float)(SPRINT_DURATION - sprintTime))/10.0f; 489 scale = scale * scale; 490 if ( scale > 1.0f ) scale = 1.0f; 491 flyX *= scale; 492 flyY *= scale; 493 flyZ *= scale; 494 } 495 else 496 { 497 flyX = 0.0f; 498 flyY = 0.0f; 499 flyZ = 0.0f; 500 if( ullDpad_filtered & (1LL<<MINECRAFT_ACTION_DPAD_UP)) 501 { 502 flyY = 0.1f; 503 } 504 if( ullDpad_filtered & (1LL<<MINECRAFT_ACTION_DPAD_DOWN)) 505 { 506 flyY = -0.1f; 507 } 508 } 509 } 510 511 Player::move(flyX, flyY, flyZ); 512 513 fallDistance = 0.0f; 514 yd = 0.0f; 515 onGround = true; 516 } 517 518 // Check if the player is idle and the rich presence needs updated 519 if( !m_bIsIdle && InputManager.GetIdleSeconds( m_iPad ) > PLAYER_IDLE_TIME ) 520 { 521 ProfileManager.SetCurrentGameActivity(m_iPad,CONTEXT_PRESENCE_IDLE,false); 522 m_bIsIdle = true; 523 } 524 else if ( m_bIsIdle && InputManager.GetIdleSeconds( m_iPad ) < PLAYER_IDLE_TIME ) 525 { 526 // Are we offline or online, and how many players are there 527 if(g_NetworkManager.GetPlayerCount()>1) 528 { 529 // only do it for this player here - each player will run this code 530 if(g_NetworkManager.IsLocalGame()) 531 { 532 ProfileManager.SetCurrentGameActivity(m_iPad,CONTEXT_PRESENCE_MULTIPLAYEROFFLINE,false); 533 } 534 else 535 { 536 ProfileManager.SetCurrentGameActivity(m_iPad,CONTEXT_PRESENCE_MULTIPLAYER,false); 537 } 538 } 539 else 540 { 541 if(g_NetworkManager.IsLocalGame()) 542 { 543 ProfileManager.SetCurrentGameActivity(m_iPad,CONTEXT_PRESENCE_MULTIPLAYER_1POFFLINE,false); 544 } 545 else 546 { 547 ProfileManager.SetCurrentGameActivity(m_iPad,CONTEXT_PRESENCE_MULTIPLAYER_1P,false); 548 } 549 } 550 updateRichPresence(); 551 m_bIsIdle = false; 552 } 553} 554 555void LocalPlayer::changeDimension(int i) 556{ 557 if (!level->isClientSide) 558 { 559 if (dimension == 1 && i == 1) 560 { 561 awardStat(GenericStats::winGame(), GenericStats::param_noArgs()); 562 //minecraft.setScreen(new WinScreen()); 563#ifndef _CONTENT_PACKAGE 564 app.DebugPrintf("LocalPlayer::changeDimension from 1 to 1 but WinScreen has not been implemented.\n"); 565 __debugbreak(); 566#endif 567 } 568 else 569 { 570 awardStat(GenericStats::theEnd(), GenericStats::param_theEnd()); 571 572 minecraft->soundEngine->playUI(eSoundType_PORTAL_TRAVEL, 1, random->nextFloat() * 0.4f + 0.8f); 573 } 574 } 575} 576 577float LocalPlayer::getFieldOfViewModifier() 578{ 579 float targetFov = 1.0f; 580 581 // modify for movement 582 if (abilities.flying) targetFov *= 1.1f; 583 584 AttributeInstance *speed = getAttribute(SharedMonsterAttributes::MOVEMENT_SPEED); 585 targetFov *= (speed->getValue() / abilities.getWalkingSpeed() + 1) / 2; 586 587 // modify for bow =) 588 if (isUsingItem() && getUseItem()->id == Item::bow->id) 589 { 590 int ticksHeld = getTicksUsingItem(); 591 float scale = (float) ticksHeld / BowItem::MAX_DRAW_DURATION; 592 if (scale > 1) 593 { 594 scale = 1; 595 } 596 else 597 { 598 scale *= scale; 599 } 600 targetFov *= 1.0f - scale * .15f; 601 } 602 603 return targetFov; 604} 605 606void LocalPlayer::addAdditonalSaveData(CompoundTag *entityTag) 607{ 608 Player::addAdditonalSaveData(entityTag); 609 //entityTag->putInt(L"Score", score); 610} 611 612void LocalPlayer::readAdditionalSaveData(CompoundTag *entityTag) 613{ 614 Player::readAdditionalSaveData(entityTag); 615 //score = entityTag->getInt(L"Score"); 616} 617 618void LocalPlayer::closeContainer() 619{ 620 Player::closeContainer(); 621 minecraft->setScreen(NULL); 622 623 // 4J - Close any xui here 624 // Fix for #9164 - CRASH: MP: Title crashes upon opening a chest and having another user destroy it. 625 ui.PlayUISFX(eSFX_Back); 626 ui.CloseUIScenes( m_iPad ); 627} 628 629void LocalPlayer::openTextEdit(shared_ptr<TileEntity> tileEntity) 630{ 631 bool success; 632 633 if (tileEntity->GetType() == eTYPE_SIGNTILEENTITY) 634 { 635 success = app.LoadSignEntryMenu(GetXboxPad(), dynamic_pointer_cast<SignTileEntity>(tileEntity)); 636 } 637 else if (tileEntity->GetType() == eTYPE_COMMANDBLOCKTILEENTITY) 638 { 639 success = app.LoadCommandBlockMenu(GetXboxPad(), dynamic_pointer_cast<CommandBlockEntity>(tileEntity)); 640 } 641 642 if( success ) ui.PlayUISFX(eSFX_Press); 643 //minecraft->setScreen(new TextEditScreen(sign)); 644} 645 646bool LocalPlayer::openContainer(shared_ptr<Container> container) 647{ 648 bool success = app.LoadContainerMenu(GetXboxPad(), inventory, container ); 649 if( success ) ui.PlayUISFX(eSFX_Press); 650 //minecraft->setScreen(new ContainerScreen(inventory, container)); 651 return success; 652} 653 654bool LocalPlayer::openHopper(shared_ptr<HopperTileEntity> container) 655{ 656 //minecraft->setScreen(new HopperScreen(inventory, container)); 657 bool success = app.LoadHopperMenu(GetXboxPad(), inventory, container ); 658 if( success ) ui.PlayUISFX(eSFX_Press); 659 return success; 660} 661 662bool LocalPlayer::openHopper(shared_ptr<MinecartHopper> container) 663{ 664 //minecraft->setScreen(new HopperScreen(inventory, container)); 665 bool success = app.LoadHopperMenu(GetXboxPad(), inventory, container ); 666 if( success ) ui.PlayUISFX(eSFX_Press); 667 return success; 668} 669 670bool LocalPlayer::openHorseInventory(shared_ptr<EntityHorse> horse, shared_ptr<Container> container) 671{ 672 //minecraft->setScreen(new HorseInventoryScreen(inventory, container, horse)); 673 bool success = app.LoadHorseMenu(GetXboxPad(), inventory, container, horse); 674 if( success ) ui.PlayUISFX(eSFX_Press); 675 return success; 676} 677 678bool LocalPlayer::startCrafting(int x, int y, int z) 679{ 680 bool success = app.LoadCrafting3x3Menu(GetXboxPad(), dynamic_pointer_cast<LocalPlayer>( shared_from_this() ), x, y, z ); 681 if( success ) ui.PlayUISFX(eSFX_Press); 682 //app.LoadXuiCraftMenu(0,inventory, level, x, y, z); 683 //minecraft->setScreen(new CraftingScreen(inventory, level, x, y, z)); 684 return success; 685} 686 687bool LocalPlayer::openFireworks(int x, int y, int z) 688{ 689 bool success = app.LoadFireworksMenu(GetXboxPad(), dynamic_pointer_cast<LocalPlayer>( shared_from_this() ), x, y, z ); 690 if( success ) ui.PlayUISFX(eSFX_Press); 691 return success; 692} 693 694bool LocalPlayer::startEnchanting(int x, int y, int z, const wstring &name) 695{ 696 bool success = app.LoadEnchantingMenu(GetXboxPad(), inventory, x, y, z, level, name); 697 if( success ) ui.PlayUISFX(eSFX_Press); 698 //minecraft.setScreen(new EnchantmentScreen(inventory, level, x, y, z)); 699 return success; 700} 701 702bool LocalPlayer::startRepairing(int x, int y, int z) 703{ 704 bool success = app.LoadRepairingMenu(GetXboxPad(), inventory, level, x, y, z ); 705 if( success ) ui.PlayUISFX(eSFX_Press); 706 //minecraft.setScreen(new RepairScreen(inventory, level, x, y, z)); 707 return success; 708} 709 710bool LocalPlayer::openFurnace(shared_ptr<FurnaceTileEntity> furnace) 711{ 712 bool success = app.LoadFurnaceMenu(GetXboxPad(),inventory, furnace); 713 if( success ) ui.PlayUISFX(eSFX_Press); 714 //minecraft->setScreen(new FurnaceScreen(inventory, furnace)); 715 return success; 716} 717 718bool LocalPlayer::openBrewingStand(shared_ptr<BrewingStandTileEntity> brewingStand) 719{ 720 bool success = app.LoadBrewingStandMenu(GetXboxPad(),inventory, brewingStand); 721 if( success ) ui.PlayUISFX(eSFX_Press); 722 //minecraft.setScreen(new BrewingStandScreen(inventory, brewingStand)); 723 return success; 724} 725 726bool LocalPlayer::openBeacon(shared_ptr<BeaconTileEntity> beacon) 727{ 728 //minecraft->setScreen(new BeaconScreen(inventory, beacon)); 729 bool success = app.LoadBeaconMenu(GetXboxPad(), inventory, beacon); 730 if( success ) ui.PlayUISFX(eSFX_Press); 731 return success; 732} 733 734bool LocalPlayer::openTrap(shared_ptr<DispenserTileEntity> trap) 735{ 736 bool success = app.LoadTrapMenu(GetXboxPad(),inventory, trap); 737 if( success ) ui.PlayUISFX(eSFX_Press); 738 //minecraft->setScreen(new TrapScreen(inventory, trap)); 739 return success; 740} 741 742bool LocalPlayer::openTrading(shared_ptr<Merchant> traderTarget, const wstring &name) 743{ 744 bool success = app.LoadTradingMenu(GetXboxPad(),inventory, traderTarget, level, name); 745 if( success ) ui.PlayUISFX(eSFX_Press); 746 //minecraft.setScreen(new MerchantScreen(inventory, traderTarget, level)); 747 return success; 748} 749 750void LocalPlayer::crit(shared_ptr<Entity> e) 751{ 752 shared_ptr<CritParticle> critParticle = shared_ptr<CritParticle>( new CritParticle((Level *)minecraft->level, e) ); 753 critParticle->CritParticlePostConstructor(); 754 minecraft->particleEngine->add(critParticle); 755} 756 757void LocalPlayer::magicCrit(shared_ptr<Entity> e) 758{ 759 shared_ptr<CritParticle> critParticle = shared_ptr<CritParticle>( new CritParticle((Level *)minecraft->level, e, eParticleType_magicCrit) ); 760 critParticle->CritParticlePostConstructor(); 761 minecraft->particleEngine->add(critParticle); 762} 763 764void LocalPlayer::take(shared_ptr<Entity> e, int orgCount) 765{ 766 minecraft->particleEngine->add( shared_ptr<TakeAnimationParticle>( new TakeAnimationParticle((Level *)minecraft->level, e, shared_from_this(), -0.5f) ) ); 767} 768 769void LocalPlayer::chat(const wstring& message) 770{ 771} 772 773bool LocalPlayer::isSneaking() 774{ 775 return input->sneaking && !m_isSleeping; 776} 777 778void LocalPlayer::hurtTo(float newHealth, ETelemetryChallenges damageSource) 779{ 780 float dmg = getHealth() - newHealth; 781 if (dmg <= 0) 782 { 783 setHealth(newHealth); 784 if (dmg < 0) 785 { 786 invulnerableTime = invulnerableDuration / 2; 787 } 788 } 789 else 790 { 791 lastHurt = dmg; 792 setHealth(getHealth()); 793 invulnerableTime = invulnerableDuration; 794 actuallyHurt(DamageSource::genericSource,dmg); 795 hurtTime = hurtDuration = 10; 796 } 797 798 799 if( this->getHealth() <= 0) 800 { 801 int deathTime = (int)(level->getGameTime() % Level::TICKS_PER_DAY)/1000; 802 int carriedId = inventory->getSelected() == NULL ? 0 : inventory->getSelected()->id; 803 TelemetryManager->RecordPlayerDiedOrFailed(GetXboxPad(), 0, y, 0, 0, carriedId, 0, damageSource); 804 805 // if there are any xuiscenes up for this player, close them 806 if(ui.GetMenuDisplayed(GetXboxPad())) 807 { 808 ui.CloseUIScenes(GetXboxPad()); 809 } 810 } 811 812} 813 814void LocalPlayer::respawn() 815{ 816 // Select the right payer to respawn 817 minecraft->respawnPlayer(GetXboxPad(), 0, 0); 818} 819 820void LocalPlayer::animateRespawn() 821{ 822// Player.animateRespawn(this, level); 823} 824 825void LocalPlayer::displayClientMessage(int messageId) 826{ 827 minecraft->gui->displayClientMessage(messageId, GetXboxPad()); 828} 829 830void LocalPlayer::awardStat(Stat *stat, byteArray param) 831{ 832#ifdef _DURANGO 833 // 4J-JEV: Maybe we want to fine tune this later? #TODO 834 if ( !ProfileManager.IsGuest(GetXboxPad()) 835 && app.CanRecordStatsAndAchievements() 836 && ProfileManager.IsFullVersion() 837 ) 838 { 839 stat->handleParamBlob(dynamic_pointer_cast<LocalPlayer>(shared_from_this()), param); 840 } 841 delete [] param.data; 842#else 843 int count = CommonStats::readParam(param); 844 delete [] param.data; 845 846 if (!app.CanRecordStatsAndAchievements()) return; 847 if (stat == NULL) return; 848 849 if (stat->isAchievement()) 850 { 851 Achievement *ach = (Achievement *) stat; 852 // 4J-PB - changed to attempt to award everytime - the award may need a storage device, so needs a primary player, and the player may not have been a primary player when they first 'got' the award 853 // so let the award manager figure it out 854 //if (!minecraft->stats[m_iPad]->hasTaken(ach)) 855 { 856 // 4J-PB - Don't display the java popup 857 //minecraft->achievementPopup->popup(ach); 858 859 // 4J Stu - Added this function in the libraries as some achievements don't get awarded to all players 860 // e.g. Splitscreen players cannot get theme/avatar/gamerpic and Trial players cannot get any 861 // This causes some extreme flooding of some awards 862 if(ProfileManager.CanBeAwarded(m_iPad, ach->getAchievementID() ) ) 863 { 864 // 4J Stu - We don't (currently) care about the gamerscore, so setting to a default of 0 points 865 TelemetryManager->RecordAchievementUnlocked(m_iPad,ach->getAchievementID(),0); 866 867 // 4J Stu - Some awards cause a menu to popup. This can be bad, especially if you are surrounded by mobs! 868 // We cannot pause the game unless in offline single player, but lets at least do it then 869 if( g_NetworkManager.IsLocalGame() && g_NetworkManager.GetPlayerCount() == 1 && ProfileManager.GetAwardType(ach->getAchievementID() ) != eAwardType_Achievement ) 870 { 871 ui.CloseUIScenes(m_iPad); 872 ui.NavigateToScene(m_iPad,eUIScene_PauseMenu); 873 } 874 } 875 876 // 4J-JEV: To stop spamming trophies. 877 unsigned long long achBit = ((unsigned long long)1) << ach->getAchievementID(); 878 if ( !(achBit & m_awardedThisSession) ) 879 { 880 ProfileManager.Award(m_iPad, ach->getAchievementID()); 881 if (ProfileManager.IsFullVersion()) 882 m_awardedThisSession |= achBit; 883 } 884 } 885 minecraft->stats[m_iPad]->award(stat, level->difficulty, count); 886 } 887 else 888 { 889 // 4J : WESTY : Added for new achievements. 890 StatsCounter* pStats = minecraft->stats[m_iPad]; 891 pStats->award(stat, level->difficulty, count); 892 893 // 4J-JEV: Check achievements for unlocks. 894 895 // LEADER OF THE PACK 896 if ( stat == GenericStats::tamedEntity(eTYPE_WOLF) ) 897 { 898 // Check to see if we have befriended 5 wolves! Is this really the best place to do this??!! 899 if ( pStats->getTotalValue(GenericStats::tamedEntity(eTYPE_WOLF)) >= 5 ) 900 { 901 awardStat(GenericStats::leaderOfThePack(), GenericStats::param_noArgs()); 902 } 903 } 904 905 // MOAR TOOLS 906 { 907 Stat *toolStats[4][5]; 908 toolStats[0][0] = GenericStats::itemsCrafted(Item::shovel_wood->id); 909 toolStats[0][1] = GenericStats::itemsCrafted(Item::shovel_stone->id); 910 toolStats[0][2] = GenericStats::itemsCrafted(Item::shovel_iron->id); 911 toolStats[0][3] = GenericStats::itemsCrafted(Item::shovel_diamond->id); 912 toolStats[0][4] = GenericStats::itemsCrafted(Item::shovel_gold->id); 913 toolStats[1][0] = GenericStats::itemsCrafted(Item::pickAxe_wood->id); 914 toolStats[1][1] = GenericStats::itemsCrafted(Item::pickAxe_stone->id); 915 toolStats[1][2] = GenericStats::itemsCrafted(Item::pickAxe_iron->id); 916 toolStats[1][3] = GenericStats::itemsCrafted(Item::pickAxe_diamond->id); 917 toolStats[1][4] = GenericStats::itemsCrafted(Item::pickAxe_gold->id); 918 toolStats[2][0] = GenericStats::itemsCrafted(Item::hatchet_wood->id); 919 toolStats[2][1] = GenericStats::itemsCrafted(Item::hatchet_stone->id); 920 toolStats[2][2] = GenericStats::itemsCrafted(Item::hatchet_iron->id); 921 toolStats[2][3] = GenericStats::itemsCrafted(Item::hatchet_diamond->id); 922 toolStats[2][4] = GenericStats::itemsCrafted(Item::hatchet_gold->id); 923 toolStats[3][0] = GenericStats::itemsCrafted(Item::hoe_wood->id); 924 toolStats[3][1] = GenericStats::itemsCrafted(Item::hoe_stone->id); 925 toolStats[3][2] = GenericStats::itemsCrafted(Item::hoe_iron->id); 926 toolStats[3][3] = GenericStats::itemsCrafted(Item::hoe_diamond->id); 927 toolStats[3][4] = GenericStats::itemsCrafted(Item::hoe_gold->id); 928 929 bool justCraftedTool = false; 930 for (int i=0; i<4; i++) 931 { 932 for (int j=0; j<5; j++) 933 { 934 if ( stat == toolStats[i][j] ) 935 { 936 justCraftedTool = true; 937 break; 938 } 939 } 940 } 941 942 if (justCraftedTool) 943 { 944 bool awardNow = true; 945 for (int i=0; i<4; i++) 946 { 947 bool craftedThisTool = false; 948 for (int j=0; j<5; j++) 949 { 950 if ( pStats->getTotalValue(toolStats[i][j]) > 0 ) 951 craftedThisTool = true; 952 } 953 954 if (!craftedThisTool) 955 { 956 awardNow = false; 957 break; 958 } 959 } 960 961 if (awardNow) 962 { 963 awardStat(GenericStats::MOARTools(), GenericStats::param_noArgs()); 964 } 965 } 966 967 } 968 969#ifdef _XBOX 970 // AWARD: Have we killed 10 creepers? 971 if ( pStats->getTotalValue( GenericStats::killsCreeper() ) >= 10 ) 972 { 973 awardStat( GenericStats::kill10Creepers(), GenericStats::param_noArgs()); 974 } 975 976 // AWARD : Have we been playing for 100 game days? 977 if ( pStats->getTotalValue( GenericStats::timePlayed() ) >= ( Level::TICKS_PER_DAY * 100 ) ) 978 { 979 awardStat( GenericStats::play100Days(), GenericStats::param_noArgs()); 980 } 981 // AWARD : Have we mined 100 blocks? 982 if ( pStats->getTotalValue( GenericStats::totalBlocksMined() ) >= 100 ) 983 { 984 awardStat( GenericStats::mine100Blocks(), GenericStats::param_noArgs()); 985 } 986#endif 987 988#ifdef _EXTENDED_ACHIEVEMENTS 989 990 // AWARD : Porkchop, cook and eat a porkchop. 991 { 992 Stat *cookPorkchop, *eatPorkchop; 993 cookPorkchop = GenericStats::itemsCrafted(Item::porkChop_cooked_Id); 994 eatPorkchop = GenericStats::itemsUsed(Item::porkChop_cooked_Id); 995 996 if ( stat == cookPorkchop || stat == eatPorkchop ) 997 { 998 int numCookPorkchop, numEatPorkchop; 999 numCookPorkchop = pStats->getTotalValue(cookPorkchop); 1000 numEatPorkchop = pStats->getTotalValue(eatPorkchop); 1001 1002 app.DebugPrintf( 1003 "[AwardStat] Check unlock 'Porkchop': " 1004 "pork_cooked=%i, pork_eaten=%i.\n", 1005 numCookPorkchop, numEatPorkchop 1006 ); 1007 1008 if ( (0 < numCookPorkchop) && (0 < numEatPorkchop) ) 1009 { 1010 awardStat( GenericStats::porkChop(), GenericStats::param_porkChop() ); 1011 } 1012 } 1013 } 1014 1015 // AWARD : Passing the Time, play for 100 minecraft days. 1016 { 1017 Stat *timePlayed = GenericStats::timePlayed(); 1018 1019 if ( stat == timePlayed ) 1020 { 1021 int iPlayedTicks, iRequiredTicks; 1022 iPlayedTicks = pStats->getTotalValue(timePlayed); 1023 iRequiredTicks = Level::TICKS_PER_DAY * 100; 1024 1025 /* app.DebugPrintf( 1026 "[AwardStat] Check unlock 'Passing the Time': " 1027 "total_ticks=%i, req=%i.\n", 1028 iPlayedTicks, iRequiredTicks 1029 ); */ 1030 1031 if (iPlayedTicks >= iRequiredTicks) 1032 { 1033 awardStat( GenericStats::passingTheTime(), GenericStats::param_passingTheTime() ); 1034 } 1035 } 1036 } 1037 1038 // AWARD : The Haggler, Acquire 30 emeralds. 1039 { 1040 Stat *emeraldMined, *emeraldBought; 1041 emeraldMined = GenericStats::blocksMined(Tile::emeraldOre_Id); 1042 emeraldBought = GenericStats::itemsBought(Item::emerald_Id); 1043 1044 if ( stat == emeraldMined || stat == emeraldBought ) 1045 { 1046 int numEmeraldMined, numEmeraldBought, totalSum; 1047 numEmeraldMined = pStats->getTotalValue(emeraldMined); 1048 numEmeraldBought = pStats->getTotalValue(emeraldBought); 1049 totalSum = numEmeraldMined + numEmeraldBought; 1050 1051 app.DebugPrintf( 1052 "[AwardStat] Check unlock 'The Haggler': " 1053 "emerald_mined=%i, emerald_bought=%i, sum=%i.\n", 1054 numEmeraldMined, numEmeraldBought, totalSum 1055 ); 1056 1057 if (totalSum >= 30) awardStat( GenericStats::theHaggler(), GenericStats::param_theHaggler() ); 1058 } 1059 } 1060 1061 // AWARD : Pot Planter, craft and place a flowerpot. 1062 { 1063 Stat *craftFlowerpot, *placeFlowerpot; 1064 craftFlowerpot = GenericStats::itemsCrafted(Item::flowerPot_Id); 1065 placeFlowerpot = GenericStats::blocksPlaced(Tile::flowerPot_Id); 1066 1067 if ( stat == craftFlowerpot || stat == placeFlowerpot ) 1068 { 1069 if ( (pStats->getTotalValue(craftFlowerpot) > 0) && (pStats->getTotalValue(placeFlowerpot) > 0) ) 1070 { 1071 awardStat( GenericStats::potPlanter(), GenericStats::param_potPlanter() ); 1072 } 1073 } 1074 } 1075 1076 // AWARD : It's a Sign, craft and place a sign. 1077 { 1078 Stat *craftSign, *placeWallsign, *placeSignpost; 1079 craftSign = GenericStats::itemsCrafted(Item::sign_Id); 1080 placeWallsign = GenericStats::blocksPlaced(Tile::wallSign_Id); 1081 placeSignpost = GenericStats::blocksPlaced(Tile::sign_Id); 1082 1083 if ( stat == craftSign || stat == placeWallsign || stat == placeSignpost ) 1084 { 1085 int numCraftedSigns, numPlacedWallSign, numPlacedSignpost; 1086 numCraftedSigns = pStats->getTotalValue(craftSign); 1087 numPlacedWallSign = pStats->getTotalValue(placeWallsign); 1088 numPlacedSignpost = pStats->getTotalValue(placeSignpost); 1089 1090 app.DebugPrintf( 1091 "[AwardStat] Check unlock 'It's a Sign': " 1092 "crafted=%i, placedWallSigns=%i, placedSignposts=%i.\n", 1093 numCraftedSigns, numPlacedWallSign, numPlacedSignpost 1094 ); 1095 1096 if ( (numCraftedSigns>0) && ((numPlacedWallSign+numPlacedSignpost)>0) ) 1097 { 1098 awardStat( GenericStats::itsASign(), GenericStats::param_itsASign()); 1099 } 1100 } 1101 } 1102 1103 // AWARD : Rainbow Collection, collect all different colours of wool. 1104 { 1105 bool justPickedupWool = false; 1106 1107 for (int i=0; i<16; i++) 1108 if ( stat == GenericStats::itemsCollected(Tile::wool_Id, i) ) 1109 justPickedupWool = true; 1110 1111 if (justPickedupWool) 1112 { 1113 unsigned int woolCount = 0; 1114 1115 for (unsigned int i = 0; i < 16; i++) 1116 { 1117 if (pStats->getTotalValue(GenericStats::itemsCollected(Tile::wool_Id, i)) > 0) 1118 woolCount++; 1119 } 1120 1121 if (woolCount >= 16) awardStat( GenericStats::rainbowCollection(), GenericStats::param_rainbowCollection() ); 1122 } 1123 } 1124 1125 // AWARD : Adventuring Time, visit at least 17 biomes 1126 { 1127 bool justEnteredBiome = false; 1128 1129 for (int i=0; i<23; i++) 1130 if ( stat == GenericStats::enteredBiome(i) ) 1131 justEnteredBiome = true; 1132 1133 if (justEnteredBiome) 1134 { 1135 unsigned int biomeCount = 0; 1136 1137 for (unsigned int i = 0; i < 23; i++) 1138 { 1139 if (pStats->getTotalValue(GenericStats::enteredBiome(i)) > 0) 1140 biomeCount++; 1141 } 1142 1143 if (biomeCount >= 17) awardStat( GenericStats::adventuringTime(), GenericStats::param_adventuringTime() ); 1144 } 1145 } 1146#endif 1147 } 1148#endif 1149} 1150 1151bool LocalPlayer::isSolidBlock(int x, int y, int z) 1152{ 1153 return level->isSolidBlockingTile(x, y, z); 1154} 1155 1156bool LocalPlayer::checkInTile(double x, double y, double z) 1157{ 1158 int xTile = Mth::floor(x); 1159 int yTile = Mth::floor(y); 1160 int zTile = Mth::floor(z); 1161 1162 double xd = x - xTile; 1163 double zd = z - zTile; 1164 1165 if (isSolidBlock(xTile, yTile, zTile) || isSolidBlock(xTile, yTile + 1, zTile)) 1166 { 1167 bool west = !isSolidBlock(xTile - 1, yTile, zTile) && !isSolidBlock(xTile - 1, yTile + 1, zTile); 1168 bool east = !isSolidBlock(xTile + 1, yTile, zTile) && !isSolidBlock(xTile + 1, yTile + 1, zTile); 1169 bool north = !isSolidBlock(xTile, yTile, zTile - 1) && !isSolidBlock(xTile, yTile + 1, zTile - 1); 1170 bool south = !isSolidBlock(xTile, yTile, zTile + 1) && !isSolidBlock(xTile, yTile + 1, zTile + 1); 1171 1172 int dir = -1; 1173 double closest = 9999; 1174 if (west && xd < closest) 1175 { 1176 closest = xd; 1177 dir = 0; 1178 } 1179 if (east && 1 - xd < closest) 1180 { 1181 closest = 1 - xd; 1182 dir = 1; 1183 } 1184 if (north && zd < closest) 1185 { 1186 closest = zd; 1187 dir = 4; 1188 } 1189 if (south && 1 - zd < closest) 1190 { 1191 closest = 1 - zd; 1192 dir = 5; 1193 } 1194 1195 float speed = 0.1f; 1196 if (dir == 0) this->xd = -speed; 1197 if (dir == 1) this->xd = +speed; 1198 if (dir == 4) this->zd = -speed; 1199 if (dir == 5) this->zd = +speed; 1200 } 1201 1202 return false; 1203 1204} 1205 1206void LocalPlayer::setSprinting(bool value) 1207{ 1208 Player::setSprinting(value); 1209 if (value == false) sprintTime = 0; 1210 else sprintTime = SPRINT_DURATION; 1211} 1212 1213void LocalPlayer::setExperienceValues(float experienceProgress, int totalExp, int experienceLevel) 1214{ 1215 this->experienceProgress = experienceProgress; 1216 this->totalExperience = totalExp; 1217 this->experienceLevel = experienceLevel; 1218} 1219 1220// 4J: removed 1221//void LocalPlayer::sendMessage(ChatMessageComponent *message) 1222//{ 1223// minecraft->gui->getChat()->addMessage(message.toString(true)); 1224//} 1225 1226Pos LocalPlayer::getCommandSenderWorldPosition() 1227{ 1228 return new Pos(floor(x + .5), floor(y + .5), floor(z + .5)); 1229} 1230 1231shared_ptr<ItemInstance> LocalPlayer::getCarriedItem() 1232{ 1233 return inventory->getSelected(); 1234} 1235 1236void LocalPlayer::playSound(int soundId, float volume, float pitch) 1237{ 1238 level->playLocalSound(x, y - heightOffset, z, soundId, volume, pitch, false); 1239} 1240 1241bool LocalPlayer::isRidingJumpable() 1242{ 1243 return riding != NULL && riding->GetType() == eTYPE_HORSE; 1244} 1245 1246float LocalPlayer::getJumpRidingScale() 1247{ 1248 return jumpRidingScale; 1249} 1250 1251void LocalPlayer::sendRidingJump() 1252{ 1253} 1254 1255bool LocalPlayer::hasPermission(EGameCommand command) 1256{ 1257 return level->getLevelData()->getAllowCommands(); 1258} 1259 1260void LocalPlayer::onCrafted(shared_ptr<ItemInstance> item) 1261{ 1262 if( minecraft->localgameModes[m_iPad] != NULL ) 1263 { 1264 TutorialMode *gameMode = (TutorialMode *)minecraft->localgameModes[m_iPad]; 1265 gameMode->getTutorial()->onCrafted(item); 1266 } 1267} 1268 1269void LocalPlayer::setAndBroadcastCustomSkin(DWORD skinId) 1270{ 1271 setCustomSkin(skinId); 1272} 1273 1274void LocalPlayer::setAndBroadcastCustomCape(DWORD capeId) 1275{ 1276 setCustomCape(capeId); 1277} 1278 1279// 4J TODO - Remove 1280#include "..\Minecraft.World\LevelChunk.h" 1281void LocalPlayer::mapPlayerChunk(const unsigned int flagTileType) 1282{ 1283 int cx = this->xChunk; 1284 int cz = this->zChunk; 1285 1286 int pZ = ((int) floor(this->z)) %16; 1287 int pX = ((int) floor(this->x)) %16; 1288 1289 cout<<"player in chunk ("<<cx<<","<<cz<<") at (" 1290 <<this->x<<","<<this->y<<","<<this->z<<")\n"; 1291 1292 for (int v = -1; v < 2; v++) 1293 for (unsigned int z = 0; z < 16; z++) 1294 { 1295 for (int u = -1; u < 2; u++) 1296 for (unsigned int x = 0; x < 16; x++) 1297 { 1298 LevelChunk *cc = level->getChunk(cx+u, cz+v); 1299 if ( x==pX && z==pZ && u==0 && v==0) 1300 cout << "O"; 1301 else for (unsigned int y = 127; y > 0; y--) 1302 { 1303 int t = cc->getTile(x,y,z); 1304 if (flagTileType != 0 && t == flagTileType) { cout << "@"; break; } 1305 else if (t != 0 && t < 10) { cout << t; break; } 1306 else if (t > 0) { cout << "#"; break; } 1307 } 1308 } 1309 cout << "\n"; 1310 } 1311 1312 cout << "\n"; 1313} 1314 1315 1316void LocalPlayer::handleMouseDown(int button, bool down) 1317{ 1318 // 4J Stu - We should not accept any input while asleep, except the above to wake up 1319 if(isSleeping() && level != NULL && level->isClientSide) 1320 { 1321 return; 1322 } 1323 if (!down) missTime = 0; 1324 if (button == 0 && missTime > 0) return; 1325 1326 if (down && minecraft->hitResult != NULL && minecraft->hitResult->type == HitResult::TILE && button == 0) 1327 { 1328 int x = minecraft->hitResult->x; 1329 int y = minecraft->hitResult->y; 1330 int z = minecraft->hitResult->z; 1331 1332 // 4J - addition to stop layer mining out of the top or bottom of the world 1333 // 4J Stu - Allow this for The End 1334 if( ( ( y == 0 ) || ( ( y == 127 ) && level->dimension->hasCeiling ) ) && level->dimension->id != 1 ) return; 1335 1336 minecraft->gameMode->continueDestroyBlock(x, y, z, minecraft->hitResult->f); 1337 1338 if(mayDestroyBlockAt(x,y,z)) 1339 { 1340 minecraft->particleEngine->crack(x, y, z, minecraft->hitResult->f); 1341 swing(); 1342 } 1343 } 1344 else 1345 { 1346 minecraft->gameMode->stopDestroyBlock(); 1347 } 1348} 1349 1350bool LocalPlayer::creativeModeHandleMouseClick(int button, bool buttonPressed) 1351{ 1352 if( buttonPressed ) 1353 { 1354 if( lastClickState == lastClick_oldRepeat ) 1355 { 1356 return false; 1357 } 1358 1359 // Are we in an auto-repeat situation? - If so only tell the game that we've clicked if we move more than a unit away from our last 1360 // click position in any axis 1361 if( lastClickState != lastClick_invalid ) 1362 { 1363 // If we're in disabled mode already (set when sprinting) then don't do anything - if we're sprinting, we don't auto-repeat at all. 1364 // With auto repeat on, we can quickly place fires causing photosensitivity issues due to rapid flashing 1365 if( lastClickState == lastClick_disabled ) return false; 1366 // If we've started sprinting, go into this mode & also don't do anything 1367 // Ignore repeate when sleeping 1368 if( isSprinting() ) 1369 { 1370 lastClickState = lastClick_disabled; 1371 return false; 1372 } 1373 1374 // Get distance from last click point in each axis 1375 float dX = (float)x - lastClickX; 1376 float dY = (float)y - lastClickY; 1377 float dZ = (float)z - lastClickZ; 1378 bool newClick = false; 1379 1380 float ddx = dX - lastClickdX; 1381 float ddy = dY - lastClickdY; 1382 float ddz = dZ - lastClickdZ; 1383 1384 if( lastClickState == lastClick_moving ) 1385 { 1386 float deltaChange = sqrtf(ddx * ddx + ddy * ddy + ddz * ddz ); 1387 if( deltaChange < 0.01f ) 1388 { 1389 lastClickState = lastClick_stopped; 1390 lastClickTolerance = 0.0f; 1391 } 1392 } 1393 else if( lastClickState == lastClick_stopped ) 1394 { 1395 float deltaChange = sqrtf(ddx * ddx + ddy * ddy + ddz * ddz ); 1396 if( deltaChange >= 0.01f ) 1397 { 1398 lastClickState = lastClick_moving; 1399 lastClickTolerance = 0.0f; 1400 } 1401 else 1402 { 1403 lastClickTolerance += 0.1f; 1404 if( lastClickTolerance > 0.7f ) 1405 { 1406 lastClickTolerance = 0.0f; 1407 lastClickState = lastClick_init; 1408 } 1409 } 1410 } 1411 1412 lastClickdX = dX; 1413 lastClickdY = dY; 1414 lastClickdZ = dZ; 1415 1416 // If we have moved more than one unit in any one axis, then register a new click 1417 // The new click position is normalised at one unit in the direction of movement, so that we don't gradually drift away if we detect the movement a fraction over 1418 // the unit distance each time 1419 1420 if( fabsf(dX) >= 1.0f ) 1421 { 1422 dX= ( dX < 0.0f ) ? ceilf(dX) : floorf(dX); 1423 newClick = true; 1424 } 1425 else if( fabsf(dY) >= 1.0f ) 1426 { 1427 dY= ( dY < 0.0f ) ? ceilf(dY) : floorf(dY); 1428 newClick = true; 1429 } 1430 else if( fabsf(dZ) >= 1.0f ) 1431 { 1432 dZ= ( dZ < 0.0f ) ? ceilf(dZ) : floorf(dZ); 1433 newClick = true; 1434 } 1435 1436 if( ( !newClick ) && ( lastClickTolerance > 0.0f ) ) 1437 { 1438 float fTarget = 1.0f - lastClickTolerance; 1439 1440 if( fabsf(dX) >= fTarget ) newClick = true; 1441 if( fabsf(dY) >= fTarget ) newClick = true; 1442 if( fabsf(dZ) >= fTarget ) newClick = true; 1443 } 1444 1445 if( newClick ) 1446 { 1447 lastClickX += dX; 1448 lastClickY += dY; 1449 lastClickZ += dZ; 1450 1451 // Get a more accurate pick from the position where the new click should ideally have come from, rather than 1452 // where we happen to be now (ie a rounded number of units from the last Click position) 1453 double oldX = x; 1454 double oldY = y; 1455 double oldZ = z; 1456 x = lastClickX; 1457 y = lastClickY; 1458 z = lastClickZ; 1459 1460 minecraft->gameRenderer->pick(1); 1461 1462 x = oldX; 1463 y = oldY; 1464 z = oldZ; 1465 1466 handleMouseClick(button); 1467 1468 if( lastClickState == lastClick_stopped ) 1469 { 1470 lastClickState = lastClick_init; 1471 lastClickTolerance = 0.0f; 1472 } 1473 else 1474 { 1475 lastClickState = lastClick_moving; 1476 lastClickTolerance = 0.0f; 1477 } 1478 } 1479 } 1480 else 1481 { 1482 // First click - just record position & handle 1483 lastClickX = (float)x; 1484 lastClickY = (float)y; 1485 lastClickZ = (float)z; 1486 // If we actually placed an item, then move into the init state as we are going to be doing the special creative mode auto repeat 1487 bool itemPlaced = handleMouseClick(button); 1488 // If we're sprinting or riding, don't auto-repeat at all. With auto repeat on, we can quickly place fires causing photosensitivity issues due to rapid flashing 1489 // Also ignore repeats when the player is sleeping 1490 if( isSprinting() || isRiding() || isSleeping() ) 1491 { 1492 lastClickState = lastClick_disabled; 1493 } 1494 else 1495 { 1496 if( itemPlaced ) 1497 { 1498 lastClickState = lastClick_init; 1499 lastClickTolerance = 0.0f; 1500 } 1501 else 1502 { 1503 // Didn't place an item - might actually be activating a switch or door or something - just do a standard auto repeat in this case 1504 lastClickState = lastClick_oldRepeat; 1505 } 1506 } 1507 return true; 1508 } 1509 } 1510 else 1511 { 1512 lastClickState = lastClick_invalid; 1513 } 1514 return false; 1515 1516} 1517 1518bool LocalPlayer::handleMouseClick(int button) 1519{ 1520 bool returnItemPlaced = false; 1521 1522 if (button == 0 && missTime > 0) return false; 1523 if (button == 0) 1524 { 1525 //app.DebugPrintf("handleMouseClick - Player %d is swinging\n",GetXboxPad()); 1526 swing(); 1527 } 1528 1529 bool mayUse = true; 1530 1531 // 4J-PB - Adding a special case in here for sleeping in a bed in a multiplayer game - we need to wake up, and we don't have the inbedchatscreen with a button 1532 1533 if(button==1 && (isSleeping() && level != NULL && level->isClientSide)) 1534 { 1535 if(lastClickState == lastClick_oldRepeat) return false; 1536 1537 1538 shared_ptr<MultiplayerLocalPlayer> mplp = dynamic_pointer_cast<MultiplayerLocalPlayer>( shared_from_this() ); 1539 1540 if(mplp && mplp->connection) mplp->StopSleeping(); 1541 1542 } 1543 // 4J Stu - We should not accept any input while asleep, except the above to wake up 1544 if(isSleeping() && level != NULL && level->isClientSide) 1545 { 1546 return false; 1547 } 1548 1549 shared_ptr<ItemInstance> oldItem = inventory->getSelected(); 1550 1551 if (minecraft->hitResult == NULL) 1552 { 1553 if (button == 0 && minecraft->localgameModes[GetXboxPad()]->hasMissTime()) missTime = 10; 1554 } 1555 else if (minecraft->hitResult->type == HitResult::ENTITY) 1556 { 1557 if (button == 0) 1558 { 1559 minecraft->gameMode->attack(minecraft->localplayers[GetXboxPad()], minecraft->hitResult->entity); 1560 } 1561 if (button == 1) 1562 { 1563 // 4J-PB - if we milk a cow here, and end up with a bucket of milk, the if (mayUse && button == 1) further down will 1564 // then empty our bucket if we're pointing at a tile 1565 // It looks like interact really should be returning a result so we can check this, but it's possibly just the 1566 // milk bucket that causes a problem 1567 1568 if(minecraft->hitResult->entity->GetType()==eTYPE_COW) 1569 { 1570 // If I have an empty bucket in my hand, it's going to be filled with milk, so turn off mayUse 1571 shared_ptr<ItemInstance> item = inventory->getSelected(); 1572 if(item && (item->id==Item::bucket_empty_Id)) 1573 { 1574 mayUse=false; 1575 } 1576 } 1577 if( minecraft->gameMode->interact(minecraft->localplayers[GetXboxPad()], minecraft->hitResult->entity) ) 1578 { 1579 mayUse = false; 1580 } 1581 } 1582 } 1583 else if (minecraft->hitResult->type == HitResult::TILE) 1584 { 1585 int x = minecraft->hitResult->x; 1586 int y = minecraft->hitResult->y; 1587 int z = minecraft->hitResult->z; 1588 int face = minecraft->hitResult->f; 1589 1590 if (button == 0) 1591 { 1592 // 4J - addition to stop layer mining out of the top or bottom of the world 1593 // 4J Stu - Allow this for The End 1594 if( !( ( y == 0 ) || ( ( y == 127 ) && level->dimension->hasCeiling ) ) || level->dimension->id == 1 ) 1595 { 1596 minecraft->gameMode->startDestroyBlock(x, y, z, minecraft->hitResult->f); 1597 } 1598 } 1599 else 1600 { 1601 shared_ptr<ItemInstance> item = oldItem; 1602 int oldCount = item != NULL ? item->count : 0; 1603 bool usedItem = false; 1604 if (minecraft->gameMode->useItemOn(minecraft->localplayers[GetXboxPad()], level, item, x, y, z, face, minecraft->hitResult->pos, false, &usedItem)) 1605 { 1606 // Presume that if we actually used the held item, then we've placed it 1607 if( usedItem ) 1608 { 1609 returnItemPlaced = true; 1610 } 1611 mayUse = false; 1612 //app.DebugPrintf("Player %d is swinging\n",GetXboxPad()); 1613 swing(); 1614 } 1615 if (item == NULL) 1616 { 1617 return false; 1618 } 1619 1620 if (item->count == 0) 1621 { 1622 inventory->items[inventory->selected] = nullptr; 1623 } 1624 else if (item->count != oldCount || minecraft->localgameModes[GetXboxPad()]->hasInfiniteItems()) 1625 { 1626 minecraft->gameRenderer->itemInHandRenderer->itemPlaced(); 1627 } 1628 } 1629 } 1630 1631 if (mayUse && button == 1) 1632 { 1633 shared_ptr<ItemInstance> item = inventory->getSelected(); 1634 if (item != NULL) 1635 { 1636 if (minecraft->gameMode->useItem(minecraft->localplayers[GetXboxPad()], level, item)) 1637 { 1638 minecraft->gameRenderer->itemInHandRenderer->itemUsed(); 1639 } 1640 } 1641 } 1642 return returnItemPlaced; 1643} 1644 1645void LocalPlayer::updateRichPresence() 1646{ 1647 if((m_iPad!=-1)/* && !ui.GetMenuDisplayed(m_iPad)*/ ) 1648 { 1649 shared_ptr<ItemInstance> selectedItem = inventory->getSelected(); 1650 if(selectedItem != NULL && selectedItem->id == Item::fishingRod_Id) 1651 { 1652 app.SetRichPresenceContext(m_iPad,CONTEXT_GAME_STATE_FISHING); 1653 } 1654 else if(selectedItem != NULL && selectedItem->id == Item::map_Id) 1655 { 1656 app.SetRichPresenceContext(m_iPad,CONTEXT_GAME_STATE_MAP); 1657 } 1658 else if ( (riding != NULL) && riding->instanceof(eTYPE_MINECART) ) 1659 { 1660 app.SetRichPresenceContext(m_iPad,CONTEXT_GAME_STATE_RIDING_MINECART); 1661 } 1662 else if ( (riding != NULL) && riding->instanceof(eTYPE_BOAT) ) 1663 { 1664 app.SetRichPresenceContext(m_iPad,CONTEXT_GAME_STATE_BOATING); 1665 } 1666 else if ( (riding != NULL) && riding->instanceof(eTYPE_PIG) ) 1667 { 1668 app.SetRichPresenceContext(m_iPad,CONTEXT_GAME_STATE_RIDING_PIG); 1669 } 1670 else if( this->dimension == -1 ) 1671 { 1672 app.SetRichPresenceContext(m_iPad,CONTEXT_GAME_STATE_NETHER); 1673 } 1674 else if( minecraft->soundEngine->GetIsPlayingStreamingCDMusic() ) 1675 { 1676 app.SetRichPresenceContext(m_iPad,CONTEXT_GAME_STATE_CD); 1677 } 1678 else 1679 { 1680 app.SetRichPresenceContext(m_iPad,CONTEXT_GAME_STATE_BLANK); 1681 } 1682 } 1683} 1684 1685// 4J Stu - Added for telemetry 1686void LocalPlayer::SetSessionTimerStart(void) 1687{ 1688 m_sessionTimeStart=app.getAppTime(); 1689 m_dimensionTimeStart=m_sessionTimeStart; 1690} 1691 1692float LocalPlayer::getSessionTimer(void) 1693{ 1694 return app.getAppTime()-m_sessionTimeStart; 1695} 1696 1697float LocalPlayer::getAndResetChangeDimensionTimer() 1698{ 1699 float appTime = app.getAppTime(); 1700 float returnVal = appTime - m_dimensionTimeStart; 1701 m_dimensionTimeStart = appTime; 1702 return returnVal; 1703} 1704 1705void LocalPlayer::handleCollectItem(shared_ptr<ItemInstance> item) 1706{ 1707 if(item != NULL) 1708 { 1709 unsigned int itemCountAnyAux = 0; 1710 unsigned int itemCountThisAux = 0; 1711 for (unsigned int k = 0; k < inventory->items.length; ++k) 1712 { 1713 if (inventory->items[k] != NULL) 1714 { 1715 // do they have the item 1716 if(inventory->items[k]->id == item->id) 1717 { 1718 unsigned int quantity = inventory->items[k]->GetCount(); 1719 1720 itemCountAnyAux += quantity; 1721 1722 if( inventory->items[k]->getAuxValue() == item->getAuxValue() ) 1723 { 1724 itemCountThisAux += quantity; 1725 } 1726 } 1727 } 1728 } 1729 TutorialMode *gameMode = (TutorialMode *)minecraft->localgameModes[m_iPad]; 1730 gameMode->getTutorial()->onTake(item, itemCountAnyAux, itemCountThisAux); 1731 } 1732 1733 if(ui.IsContainerMenuDisplayed(m_iPad)) 1734 { 1735 ui.HandleInventoryUpdated(m_iPad); 1736 } 1737} 1738 1739void LocalPlayer::SetPlayerAdditionalModelParts(vector<ModelPart *>pAdditionalModelParts) 1740{ 1741 m_pAdditionalModelParts=pAdditionalModelParts; 1742}