the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 5137 lines 153 kB view raw
1#include "stdafx.h" 2#include "Minecraft.h" 3#include "GameMode.h" 4#include "Timer.h" 5#include "ProgressRenderer.h" 6#include "LevelRenderer.h" 7#include "ParticleEngine.h" 8#include "MultiPlayerLocalPlayer.h" 9#include "User.h" 10#include "Textures.h" 11#include "GameRenderer.h" 12#include "HumanoidModel.h" 13#include "Options.h" 14#include "TexturePackRepository.h" 15#include "StatsCounter.h" 16#include "EntityRenderDispatcher.h" 17#include "TileEntityRenderDispatcher.h" 18#include "SurvivalMode.h" 19#include "Chunk.h" 20#include "CreativeMode.h" 21#include "DemoLevel.h" 22#include "MultiPlayerLevel.h" 23#include "MultiPlayerLocalPlayer.h" 24#include "DemoUser.h" 25#include "GuiParticles.h" 26#include "Screen.h" 27#include "DeathScreen.h" 28#include "ErrorScreen.h" 29#include "TitleScreen.h" 30#include "InventoryScreen.h" 31#include "InBedChatScreen.h" 32#include "AchievementPopup.h" 33#include "Input.h" 34#include "FrustumCuller.h" 35#include "Camera.h" 36 37#include "..\Minecraft.World\MobEffect.h" 38#include "..\Minecraft.World\Difficulty.h" 39#include "..\Minecraft.World\net.minecraft.world.level.h" 40#include "..\Minecraft.World\net.minecraft.world.entity.h" 41#include "..\Minecraft.World\net.minecraft.world.entity.player.h" 42#include "..\Minecraft.World\net.minecraft.world.entity.item.h" 43#include "..\Minecraft.World\net.minecraft.world.phys.h" 44#include "..\Minecraft.World\File.h" 45#include "..\Minecraft.World\net.minecraft.world.level.storage.h" 46#include "..\Minecraft.World\net.minecraft.h" 47#include "..\Minecraft.World\net.minecraft.stats.h" 48#include "..\Minecraft.World\System.h" 49#include "..\Minecraft.World\ByteBuffer.h" 50#include "..\Minecraft.World\net.minecraft.world.level.tile.h" 51#include "..\Minecraft.World\net.minecraft.world.level.chunk.h" 52#include "..\Minecraft.World\net.minecraft.world.level.dimension.h" 53#include "..\Minecraft.World\net.minecraft.world.item.h" 54#include "..\Minecraft.World\Minecraft.World.h" 55#include "ClientConnection.h" 56#include "..\Minecraft.World\HellRandomLevelSource.h" 57#include "..\Minecraft.World\net.minecraft.world.entity.animal.h" 58#include "..\Minecraft.World\net.minecraft.world.entity.monster.h" 59#include "..\Minecraft.World\StrongholdFeature.h" 60#include "..\Minecraft.World\IntCache.h" 61#include "..\Minecraft.World\Villager.h" 62#include "..\Minecraft.World\SparseLightStorage.h" 63#include "..\Minecraft.World\SparseDataStorage.h" 64#include "..\Minecraft.World\ChestTileEntity.h" 65#include "TextureManager.h" 66#ifdef _XBOX 67#include "Xbox\Network\NetworkPlayerXbox.h" 68#endif 69#include "Common\UI\IUIScene_CreativeMenu.h" 70#include "Common\UI\UIFontData.h" 71#include "DLCTexturePack.h" 72 73#ifdef __ORBIS__ 74#include "Orbis\Network\PsPlusUpsellWrapper_Orbis.h" 75#endif 76 77// #define DISABLE_SPU_CODE 78// 4J Turning this on will change the graph at the bottom of the debug overlay to show the number of packets of each type added per fram 79//#define DEBUG_RENDER_SHOWS_PACKETS 1 80//#define SPLITSCREEN_TEST 81 82// If not disabled, this creates an event queue on a seperate thread so that the Level::tick calls can be offloaded 83// from the main thread, and have longer to run, since it's called at 20Hz instead of 60 84#define DISABLE_LEVELTICK_THREAD 85 86Minecraft *Minecraft::m_instance = NULL; 87__int64 Minecraft::frameTimes[512]; 88__int64 Minecraft::tickTimes[512]; 89int Minecraft::frameTimePos = 0; 90__int64 Minecraft::warezTime = 0; 91File Minecraft::workDir = File(L""); 92 93#ifdef __PSVITA__ 94 95TOUCHSCREENRECT QuickSelectRect[3]= 96{ 97 { 560, 890, 1360, 980 }, 98 { 450, 840, 1449, 960 }, 99 { 320, 840, 1600, 970 }, 100}; 101 102int QuickSelectBoxWidth[3]= 103{ 104 89, 105 111, 106 142 107}; 108 109// 4J - TomK ToDo: these really shouldn't be magic numbers, it should read the hud position from flash. 110int iToolTipOffset = 85; 111 112#endif 113 114ResourceLocation Minecraft::DEFAULT_FONT_LOCATION = ResourceLocation(TN_DEFAULT_FONT); 115ResourceLocation Minecraft::ALT_FONT_LOCATION = ResourceLocation(TN_ALT_FONT); 116 117 118Minecraft::Minecraft(Component *mouseComponent, Canvas *parent, MinecraftApplet *minecraftApplet, int width, int height, bool fullscreen) 119{ 120 // 4J - added this block of initialisers 121 gameMode = NULL; 122 hasCrashed = false; 123 timer = new Timer(SharedConstants::TICKS_PER_SECOND); 124 oldLevel = NULL; //4J Stu added 125 level = NULL; 126 levels = MultiPlayerLevelArray(3); // 4J Added 127 levelRenderer = NULL; 128 player = nullptr; 129 cameraTargetPlayer = nullptr; 130 particleEngine = NULL; 131 user = NULL; 132 parent = NULL; 133 pause = false; 134 textures = NULL; 135 font = NULL; 136 screen = NULL; 137 localPlayerIdx = 0; 138 rightClickDelay = 0; 139 140 // 4J Stu Added 141 InitializeCriticalSection( &ProgressRenderer::s_progress ); 142 InitializeCriticalSection(&m_setLevelCS); 143 //m_hPlayerRespawned = CreateEvent(NULL, FALSE, FALSE, NULL); 144 145 progressRenderer = NULL; 146 gameRenderer = NULL; 147 bgLoader = NULL; 148 149 ticks = 0; 150 // 4J-PB - moved into the local player 151 //missTime = 0; 152 //lastClickTick = 0; 153 //isRaining = false; 154 // 4J-PB - end 155 156 orgWidth = orgHeight = 0; 157 achievementPopup = new AchievementPopup(this); 158 gui = NULL; 159 noRender = false; 160 humanoidModel = new HumanoidModel(0); 161 hitResult = 0; 162 options = NULL; 163 soundEngine = new SoundEngine(); 164 mouseHandler = NULL; 165 skins = NULL; 166 workingDirectory = File(L""); 167 levelSource = NULL; 168 stats[0] = NULL; 169 stats[1] = NULL; 170 stats[2] = NULL; 171 stats[3] = NULL; 172 connectToPort = 0; 173 workDir = File(L""); 174 // 4J removed 175 //wasDown = false; 176 lastTimer = -1; 177 178 // 4J removed 179 //lastTickTime = System::currentTimeMillis(); 180 recheckPlayerIn = 0; 181 running = true; 182 unoccupiedQuadrant = -1; 183 184 Stats::init(); 185 186 orgHeight = height; 187 this->fullscreen = fullscreen; 188 this->minecraftApplet = NULL; 189 190 this->parent = parent; 191 // 4J - Our actual physical frame buffer is always 1280x720 ie in a 16:9 ratio. If we want to do a 4:3 mode, we are telling the original minecraft code 192 // that the width is 3/4 what it actually is, to correctly present a 4:3 image. Have added width_phys and height_phys for any code we add that requires 193 // to know the real physical dimensions of the frame buffer. 194 if( RenderManager.IsWidescreen() ) 195 { 196 this->width = width; 197 } 198 else 199 { 200 this->width = (width * 3 ) / 4; 201 } 202 this->height = height; 203 this->width_phys = width; 204 this->height_phys = height; 205 206 this->fullscreen = fullscreen; 207 208 appletMode = false; 209 210 Minecraft::m_instance = this; 211 TextureManager::createInstance(); 212 213 for(int i=0;i<XUSER_MAX_COUNT;i++) 214 { 215 m_pendingLocalConnections[i] = NULL; 216 m_connectionFailed[i] = false; 217 localgameModes[i]=NULL; 218 } 219 220 animateTickLevel = NULL; // 4J added 221 m_inFullTutorialBits = 0; // 4J Added 222 reloadTextures = false; 223 224 // initialise the audio before any textures are loaded - to avoid the problem in win64 of the Miles audio causing the codec for textures to be unloaded 225 226 // 4J-PB - Removed it from here on Orbis due to it causing a crash with the network init. 227 // We should work out why... 228#ifndef __ORBIS__ 229 this->soundEngine->init(NULL); 230#endif 231 232#ifndef DISABLE_LEVELTICK_THREAD 233 levelTickEventQueue = new C4JThread::EventQueue(levelTickUpdateFunc, levelTickThreadInitFunc, "LevelTick_EventQueuePoll"); 234 levelTickEventQueue->setProcessor(3); 235 levelTickEventQueue->setPriority(THREAD_PRIORITY_NORMAL); 236#endif // DISABLE_LEVELTICK_THREAD 237} 238 239void Minecraft::clearConnectionFailed() 240{ 241 for(int i=0;i<XUSER_MAX_COUNT;i++) 242 { 243 m_connectionFailed[i] = false; 244 m_connectionFailedReason[i] = DisconnectPacket::eDisconnect_None; 245 } 246 app.SetDisconnectReason(DisconnectPacket::eDisconnect_None); 247} 248 249void Minecraft::connectTo(const wstring& server, int port) 250{ 251 connectToIp = server; 252 connectToPort = port; 253} 254 255void Minecraft::init() 256{ 257#if 0 // 4J - removed 258 if (parent != null) 259 { 260 Graphics g = parent.getGraphics(); 261 if (g != null) { 262 g.setColor(Color.BLACK); 263 g.fillRect(0, 0, width, height); 264 g.dispose(); 265 } 266 Display.setParent(parent); 267 } else { 268 if (fullscreen) { 269 Display.setFullscreen(true); 270 width = Display.getDisplayMode().getWidth(); 271 height = Display.getDisplayMode().getHeight(); 272 if (width <= 0) width = 1; 273 if (height <= 0) height = 1; 274 } else { 275 Display.setDisplayMode(new DisplayMode(width, height)); 276 } 277 } 278 279 Display.setTitle("Minecraft " + VERSION_STRING); 280 try { 281 Display.create(); 282 /* 283 * System.out.println("LWJGL version: " + Sys.getVersion()); 284 * System.out.println("GL RENDERER: " + 285 * GL11.glGetString(GL11.GL_RENDERER)); 286 * System.out.println("GL VENDOR: " + 287 * GL11.glGetString(GL11.GL_VENDOR)); 288 * System.out.println("GL VERSION: " + 289 * GL11.glGetString(GL11.GL_VERSION)); ContextCapabilities caps = 290 * GLContext.getCapabilities(); System.out.println("OpenGL 3.0: " + 291 * caps.OpenGL30); System.out.println("OpenGL 3.1: " + 292 * caps.OpenGL31); System.out.println("OpenGL 3.2: " + 293 * caps.OpenGL32); System.out.println("ARB_compatibility: " + 294 * caps.GL_ARB_compatibility); if (caps.OpenGL32) { IntBuffer buffer 295 * = ByteBuffer.allocateDirect(16 * 296 * 4).order(ByteOrder.nativeOrder()).asIntBuffer(); 297 * GL11.glGetInteger(GL32.GL_CONTEXT_PROFILE_MASK, buffer); int 298 * profileMask = buffer.get(0); System.out.println("PROFILE MASK: " 299 * + Integer.toBinaryString(profileMask)); 300 * System.out.println("CORE PROFILE: " + ((profileMask & 301 * GL32.GL_CONTEXT_CORE_PROFILE_BIT) != 0)); 302 * System.out.println("COMPATIBILITY PROFILE: " + ((profileMask & 303 * GL32.GL_CONTEXT_COMPATIBILITY_PROFILE_BIT) != 0)); } 304 */ 305 } catch (LWJGLException e) { 306 // This COULD be because of a bug! A delay followed by a new attempt 307 // is supposed getWorkingDirectoryto fix it. 308 e.printStackTrace(); 309 try { 310 Thread.sleep(1000); 311 } catch (InterruptedException e1) { 312 } 313 Display.create(); 314 } 315 316 if (Minecraft.FLYBY_MODE) { 317 glPixelStorei(GL_PACK_ALIGNMENT, 1); 318 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 319 } 320#endif 321 322 // glClearColor(0.2f, 0.2f, 0.2f, 1); 323 324 workingDirectory = File(L"");//getWorkingDirectory(); 325 levelSource = new McRegionLevelStorageSource(File(workingDirectory, L"saves")); 326 // levelSource = new MemoryLevelStorageSource(); 327 options = new Options(this, workingDirectory); 328 skins = new TexturePackRepository(workingDirectory, this); 329 skins->addDebugPacks(); 330 textures = new Textures(skins, options); 331 //renderLoadingScreen(); 332 333 font = new Font(options, L"font/Default.png", textures, false, &DEFAULT_FONT_LOCATION, 23, 20, 8, 8, SFontData::Codepoints); 334 altFont = new Font(options, L"font/alternate.png", textures, false, &ALT_FONT_LOCATION, 16, 16, 8, 8); 335 336 //if (options.languageCode != null) { 337 // Language.getInstance().loadLanguage(options.languageCode); 338 // // font.setEnforceUnicodeSheet("true".equalsIgnoreCase(I18n.get("language.enforceUnicode"))); 339 // font.setEnforceUnicodeSheet(Language.getInstance().isSelectedLanguageIsUnicode()); 340 // font.setBidirectional(Language.isBidirectional(options.languageCode)); 341 //} 342 343 // 4J Stu - Not using these any more 344 //WaterColor::init(textures->loadTexturePixels(L"misc/watercolor.png")); 345 //GrassColor::init(textures->loadTexturePixels(L"misc/grasscolor.png")); 346 //FoliageColor::init(textures->loadTexturePixels(L"misc/foliagecolor.png")); 347 348 gameRenderer = new GameRenderer(this); 349 EntityRenderDispatcher::instance->itemInHandRenderer = new ItemInHandRenderer(this,false); 350 351 for( int i=0 ; i<4 ; ++i ) 352 stats[i] = new StatsCounter(); 353 354 /* 4J - TODO, 4J-JEV: Unnecessary. 355 Achievements::openInventory->setDescFormatter(NULL); 356 Achievements.openInventory.setDescFormatter(new DescFormatter(){ 357 public String format(String i18nValue) { 358 return String.format(i18nValue, Keyboard.getKeyName(options.keyBuild.key)); 359 } 360 }); 361 */ 362 363 // 4J-PB - We'll do this in a xui intro 364 //renderLoadingScreen(); 365 366 //Keyboard::create(); 367 Mouse::create(); 368#if 0 // 4J - removed 369 mouseHandler = new MouseHandler(parent); 370 try { 371 Controllers.create(); 372 } catch (Exception e) { 373 e.printStackTrace(); 374 } 375#endif 376 377 MemSect(31); 378 checkGlError(L"Pre startup"); 379 MemSect(0); 380 381 // width = Display.getDisplayMode().getWidth(); 382 // height = Display.getDisplayMode().getHeight(); 383 384 glEnable(GL_TEXTURE_2D); 385 glShadeModel(GL_SMOOTH); 386 glClearDepth(1.0); 387 glEnable(GL_DEPTH_TEST); 388 glDepthFunc(GL_LEQUAL); 389 glEnable(GL_ALPHA_TEST); 390 glAlphaFunc(GL_GREATER, 0.1f); 391 glCullFace(GL_BACK); 392 393 glMatrixMode(GL_PROJECTION); 394 glLoadIdentity(); 395 glMatrixMode(GL_MODELVIEW); 396 MemSect(31); 397 checkGlError(L"Startup"); 398 MemSect(0); 399 400 // openGLCapabilities = new OpenGLCapabilities(); // 4J - removed 401 402 levelRenderer = new LevelRenderer(this, textures); 403 //textures->register(&TextureAtlas::LOCATION_BLOCKS, new TextureAtlas(Icon::TYPE_TERRAIN, TN_TERRAIN)); 404 //textures->register(&TextureAtlas::LOCATION_ITEMS, new TextureAtlas(Icon::TYPE_ITEM, TN_GUI_ITEMS)); 405 textures->stitch(); 406 407 glViewport(0, 0, width, height); 408 409 particleEngine = new ParticleEngine(level, textures); 410 411 MemSect(31); 412 checkGlError(L"Post startup"); 413 MemSect(0); 414 gui = new Gui(this); 415 416 if (connectToIp != L"") // 4J - was NULL comparison 417 { 418 // setScreen(new ConnectScreen(this, connectToIp, connectToPort)); // 4J TODO - put back in 419 } 420 else 421 { 422 setScreen(new TitleScreen()); 423 } 424 progressRenderer = new ProgressRenderer(this); 425 426 RenderManager.CBuffLockStaticCreations(); 427} 428 429void Minecraft::renderLoadingScreen() 430{ 431 // 4J Unused 432 // testing stuff on vita just now 433#ifdef __PSVITA__ 434 ScreenSizeCalculator ssc(options, width, height); 435 436 // xxx 437 RenderManager.StartFrame(); 438 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 439 glMatrixMode(GL_PROJECTION); 440 glLoadIdentity(); 441 glOrtho(0, (float)ssc.rawWidth, (float)ssc.rawHeight, 0, 1000, 3000); 442 glMatrixMode(GL_MODELVIEW); 443 glLoadIdentity(); 444 glTranslatef(0, 0, -2000); 445 glViewport(0, 0, width, height); 446 glClearColor(0, 0, 0, 0); 447 448 Tesselator *t = Tesselator::getInstance(); 449 450 glDisable(GL_LIGHTING); 451 glEnable(GL_TEXTURE_2D); 452 glDisable(GL_FOG); 453 // xxx 454 glBindTexture(GL_TEXTURE_2D, textures->loadTexture(TN_MOB_PIG)); 455 t->begin(); 456 t->color(0xffffff); 457 t->vertexUV((float)(0), (float)( height), (float)( 0), (float)( 0), (float)( 0)); 458 t->vertexUV((float)(width), (float)( height), (float)( 0), (float)( 0), (float)( 0)); 459 t->vertexUV((float)(width), (float)( 0), (float)( 0), (float)( 0), (float)( 0)); 460 t->vertexUV((float)(0), (float)( 0), (float)( 0), (float)( 0), (float)( 0)); 461 t->end(); 462 463 int lw = 256; 464 int lh = 256; 465 glColor4f(1, 1, 1, 1); 466 t->color(0xffffff); 467 blit((ssc.getWidth() - lw) / 2, (ssc.getHeight() - lh) / 2, 0, 0, lw, lh); 468 glDisable(GL_LIGHTING); 469 glDisable(GL_FOG); 470 471 glEnable(GL_ALPHA_TEST); 472 glAlphaFunc(GL_GREATER, 0.1f); 473 474 Display::swapBuffers(); 475 // xxx 476 RenderManager.Present(); 477#endif 478} 479 480void Minecraft::blit(int x, int y, int sx, int sy, int w, int h) 481{ 482 float us = 1 / 256.0f; 483 float vs = 1 / 256.0f; 484 Tesselator *t = Tesselator::getInstance(); 485 t->begin(); 486 t->vertexUV((float)(x + 0), (float)( y + h), (float)( 0), (float)( (sx + 0) * us), (float)( (sy + h) * vs)); 487 t->vertexUV((float)(x + w), (float)( y + h), (float)( 0), (float)( (sx + w) * us), (float)( (sy + h) * vs)); 488 t->vertexUV((float)(x + w), (float)( y + 0), (float)( 0), (float)( (sx + w) * us), (float)( (sy + 0) * vs)); 489 t->vertexUV((float)(x + 0), (float)( y + 0), (float)( 0), (float)( (sx + 0) * us), (float)( (sy + 0) * vs)); 490 t->end(); 491} 492 493LevelStorageSource *Minecraft::getLevelSource() 494{ 495 return levelSource; 496} 497 498void Minecraft::setScreen(Screen *screen) 499{ 500 if (this->screen != NULL) 501 { 502 this->screen->removed(); 503 } 504 505 //4J Gordon: Do not force a stats save here 506 /*if (dynamic_cast<TitleScreen *>(screen)!=NULL) 507 { 508 stats->forceSend(); 509 } 510 stats->forceSave();*/ 511 512 if (screen == NULL && level == NULL) 513 { 514 screen = new TitleScreen(); 515 } 516 else if (player != NULL && !ui.GetMenuDisplayed(player->GetXboxPad()) && player->getHealth() <= 0) 517 { 518 //screen = new DeathScreen(); 519 520 // 4J Stu - If we exit from the death screen then we are saved as being dead. In the Java 521 // game when you load the game you are still dead, but this is silly so only show the dead 522 // screen if we have died during gameplay 523 if(ticks==0) 524 { 525 player->respawn(); 526 } 527 else 528 { 529 ui.NavigateToScene(player->GetXboxPad(),eUIScene_DeathMenu,NULL); 530 } 531 } 532 533 if (dynamic_cast<TitleScreen *>(screen)!=NULL) 534 { 535 options->renderDebug = false; 536 gui->clearMessages(); 537 } 538 539 this->screen = screen; 540 if (screen != NULL) 541 { 542 // releaseMouse(); // 4J - removed 543 ScreenSizeCalculator ssc(options, width, height); 544 int screenWidth = ssc.getWidth(); 545 int screenHeight = ssc.getHeight(); 546 screen->init(this, screenWidth, screenHeight); 547 noRender = false; 548 } 549 else 550 { 551 // grabMouse(); // 4J - removed 552 } 553 554 // 4J-PB - if a screen has been set, go into menu mode 555 // it's possible that player doesn't exist here yet 556 /*if(screen!=NULL) 557 { 558 if(player && player->GetXboxPad()!=-1) 559 { 560 InputManager.SetMenuDisplayed(player->GetXboxPad(),true); 561 } 562 else 563 { 564 // set all 565 //InputManager.SetMenuDisplayed(XUSER_INDEX_ANY,true); 566 } 567 } 568 else 569 { 570 if(player && player->GetXboxPad()!=-1) 571 { 572 InputManager.SetMenuDisplayed(player->GetXboxPad(),false); 573 } 574 else 575 { 576 //InputManager.SetMenuDisplayed(XUSER_INDEX_ANY,false); 577 } 578 }*/ 579} 580 581void Minecraft::checkGlError(const wstring& string) 582{ 583 // 4J - TODO 584} 585 586void Minecraft::destroy() 587{ 588 //4J Gordon: Do not force a stats save here 589 /*stats->forceSend(); 590 stats->forceSave();*/ 591 592 // try { 593 setLevel(NULL); 594 // } catch (Throwable e) { 595 // } 596 597 // try { 598 MemoryTracker::release(); 599 // } catch (Throwable e) { 600 // } 601 602 soundEngine->destroy(); 603 //} finally { 604 Display::destroy(); 605 // if (!hasCrashed) System.exit(0); //4J - removed 606 //} 607 //System.gc(); // 4J - removed 608} 609 610// 4J-PB - splitting this function into 3 parts, so we can call the middle part from our xbox game loop 611 612#if 0 613void Minecraft::run() 614{ 615 running = true; 616 // try { // 4J - removed try/catch 617 init(); 618 // } catch (Exception e) { 619 // e.printStackTrace(); 620 // crash(new CrashReport("Failed to start game", e)); 621 // return; 622 // } 623 // try { // 4J - removed try/catch 624 if (Minecraft::FLYBY_MODE) 625 { 626 generateFlyby(); 627 return; 628 } 629 630 __int64 lastTime = System::currentTimeMillis(); 631 int frames = 0; 632 633 while (running) 634 { 635 // try { // 4J - removed try/catch 636 // if (minecraftApplet != null && !minecraftApplet.isActive()) break; // 4J - removed 637 AABB::resetPool(); 638 Vec3::resetPool(); 639 640 // if (parent == NULL && Display.isCloseRequested()) { // 4J - removed 641 // stop(); 642 // } 643 644 if (pause && level != NULL) 645 { 646 float lastA = timer->a; 647 timer->advanceTime(); 648 timer->a = lastA; 649 } 650 else 651 { 652 timer->advanceTime(); 653 } 654 655 __int64 beforeTickTime = System::nanoTime(); 656 for (int i = 0; i < timer->ticks; i++) 657 { 658 ticks++; 659 // try { // 4J - try/catch removed 660 tick(); 661 // } catch (LevelConflictException e) { 662 // this.level = null; 663 // setLevel(null); 664 // setScreen(new LevelConflictScreen()); 665 // } 666 } 667 __int64 tickDuraction = System::nanoTime() - beforeTickTime; 668 checkGlError(L"Pre render"); 669 670 TileRenderer::fancy = options->fancyGraphics; 671 672 // if (pause) timer.a = 1; 673 674 soundEngine->update(player, timer->a); 675 676 glEnable(GL_TEXTURE_2D); 677 if (level != NULL) level->updateLights(); 678 679 // if (!Keyboard::isKeyDown(Keyboard.KEY_F7)) Display.update(); // 4J - removed 680 681 if (player != NULL && player->isInWall()) options->thirdPersonView = false; 682 if (!noRender) 683 { 684 if (gameMode != NULL) gameMode->render(timer->a); 685 gameRenderer->render(timer->a); 686 } 687 688 /* 4J - removed 689 if (!Display::isActive()) 690 { 691 if (fullscreen) 692 { 693 this->toggleFullScreen(); 694 } 695 Sleep(10); 696 } 697 */ 698 699 if (options->renderDebug) 700 { 701 renderFpsMeter(tickDuraction); 702 } 703 else 704 { 705 lastTimer = System::nanoTime(); 706 } 707 708 achievementPopup->render(); 709 710 Sleep(0); // 4J - was Thread.yield() 711 712 // if (Keyboard::isKeyDown(Keyboard::KEY_F7)) Display.update(); // 4J - removed condition 713 Display::update(); 714 715 // checkScreenshot(); // 4J - removed 716 717 /* 4J - removed 718 if (parent != NULL && !fullscreen) 719 { 720 if (parent.getWidth() != width || parent.getHeight() != height) 721 { 722 width = parent.getWidth(); 723 height = parent.getHeight(); 724 if (width <= 0) width = 1; 725 if (height <= 0) height = 1; 726 727 resize(width, height); 728 } 729 } 730 */ 731 checkGlError(L"Post render"); 732 frames++; 733 pause = !isClientSide() && screen != NULL && screen->isPauseScreen(); 734 735 while (System::currentTimeMillis() >= lastTime + 1000) 736 { 737 fpsString = _toString<int>(frames) + L" fps, " + _toString<int>(Chunk::updates) + L" chunk updates"; 738 Chunk::updates = 0; 739 lastTime += 1000; 740 frames = 0; 741 } 742 /* 743 } catch (LevelConflictException e) { 744 this.level = null; 745 setLevel(null); 746 setScreen(new LevelConflictScreen()); 747 } catch (OutOfMemoryError e) { 748 emergencySave(); 749 setScreen(new OutOfMemoryScreen()); 750 System.gc(); 751 } 752 */ 753 } 754 /* 755 } catch (StopGameException e) { 756 } catch (Throwable e) { 757 emergencySave(); 758 e.printStackTrace(); 759 crash(new CrashReport("Unexpected error", e)); 760 } finally { 761 destroy(); 762 } 763 */ 764 destroy(); 765} 766#endif 767 768void Minecraft::run() 769{ 770 running = true; 771 // try { // 4J - removed try/catch 772 init(); 773 // } catch (Exception e) { 774 // e.printStackTrace(); 775 // crash(new CrashReport("Failed to start game", e)); 776 // return; 777 // } 778 // try { // 4J - removed try/catch 779 } 780 781// 4J added - Selects which local player is currently active for processing by the existing minecraft code 782bool Minecraft::setLocalPlayerIdx(int idx) 783{ 784 localPlayerIdx = idx; 785 // If the player is not null, but the game mode is then this is just a temp player 786 // whose only real purpose is to hold the viewport position 787 if( localplayers[idx] == NULL || localgameModes[idx] == NULL ) return false; 788 789 gameMode = localgameModes[idx]; 790 player = localplayers[idx]; 791 cameraTargetPlayer = localplayers[idx]; 792 gameRenderer->itemInHandRenderer = localitemInHandRenderers[idx]; 793 level = getLevel( localplayers[idx]->dimension ); 794 particleEngine->setLevel( level ); 795 796 return true; 797} 798 799int Minecraft::getLocalPlayerIdx() 800{ 801 return localPlayerIdx; 802} 803 804void Minecraft::updatePlayerViewportAssignments() 805{ 806 unoccupiedQuadrant = -1; 807 // Find out how many viewports we'll be needing 808 int viewportsRequired = 0; 809 for( int i = 0; i < XUSER_MAX_COUNT; i++ ) 810 { 811 if( localplayers[i] != NULL ) viewportsRequired++; 812 } 813 if( viewportsRequired == 3 ) viewportsRequired = 4; 814 815 // Allocate away... 816 if( viewportsRequired == 1 ) 817 { 818 // Single viewport 819 for( int i = 0; i < XUSER_MAX_COUNT; i++ ) 820 { 821 if( localplayers[i] != NULL ) localplayers[i]->m_iScreenSection = C4JRender::VIEWPORT_TYPE_FULLSCREEN; 822 } 823 } 824 else if( viewportsRequired == 2 ) 825 { 826 // Split screen - TODO - option for vertical/horizontal split 827 int found = 0; 828 for( int i = 0; i < XUSER_MAX_COUNT; i++ ) 829 { 830 if( localplayers[i] != NULL ) 831 { 832 // Primary player settings decide what the mode is 833 if(app.GetGameSettings(ProfileManager.GetPrimaryPad(),eGameSetting_SplitScreenVertical)) 834 { 835 localplayers[i]->m_iScreenSection = C4JRender::VIEWPORT_TYPE_SPLIT_LEFT + found; 836 } 837 else 838 { 839 localplayers[i]->m_iScreenSection = C4JRender::VIEWPORT_TYPE_SPLIT_TOP + found; 840 } 841 found++; 842 } 843 } 844 } 845 else if( viewportsRequired >= 3 ) 846 { 847 // Quadrants - this is slightly more complicated. We don't want to move viewports around if we are going from 3 to 4, or 4 to 3 players, 848 // so persist any allocations for quadrants that already exist. 849 bool quadrantsAllocated[4] = {false,false,false,false}; 850 851 for( int i = 0; i < XUSER_MAX_COUNT; i++ ) 852 { 853 if( localplayers[i] != NULL ) 854 { 855 856 // 4J Stu - If the game hasn't started, ignore current allocations (as the players won't have seen them) 857 // This fixes an issue with the primary player being the 4th controller quadrant, but ending up in the 3rd viewport. 858 if(app.GetGameStarted()) 859 { 860 if( ( localplayers[i]->m_iScreenSection >= C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT ) && 861 ( localplayers[i]->m_iScreenSection <= C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT ) ) 862 { 863 quadrantsAllocated[localplayers[i]->m_iScreenSection - C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT] = true; 864 } 865 } 866 else 867 { 868 // Reset the viewport so that it can be assigned in the next loop 869 localplayers[i]->m_iScreenSection = C4JRender::VIEWPORT_TYPE_FULLSCREEN; 870 } 871 } 872 } 873 874 // Found which quadrants are currently in use, now allocate out any spares that are required 875 for( int i = 0; i < XUSER_MAX_COUNT; i++ ) 876 { 877 if( localplayers[i] != NULL ) 878 { 879 if( ( localplayers[i]->m_iScreenSection < C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT ) || 880 ( localplayers[i]->m_iScreenSection > C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT ) ) 881 { 882 for( int j = 0; j < 4; j++ ) 883 { 884 if( !quadrantsAllocated[j] ) 885 { 886 localplayers[i]->m_iScreenSection = C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT + j; 887 quadrantsAllocated[j] = true; 888 break; 889 } 890 } 891 } 892 } 893 } 894 // If there's an unoccupied quadrant, record which one so we can clear it to black when rendering 895 for( int i = 0; i < XUSER_MAX_COUNT; i++ ) 896 { 897 if( quadrantsAllocated[i] == false ) 898 { 899 unoccupiedQuadrant = i; 900 } 901 } 902 } 903 904 // 4J Stu - If the game is not running we do not want to do this yet, and should wait until the task 905 // that caused the app to not be running is finished 906 if(app.GetGameStarted())ui.UpdatePlayerBasePositions(); 907} 908 909// Add a temporary player so that the viewports get re-arranged, and add the player to the game session 910bool Minecraft::addLocalPlayer(int idx) 911{ 912 //int iLocalPlayerC=app.GetLocalPlayerCount(); 913 if( m_pendingLocalConnections[idx] != NULL ) 914 { 915 // 4J Stu - Should we ever be in a state where this happens? 916 assert(false); 917 m_pendingLocalConnections[idx]->close(); 918 } 919 m_connectionFailed[idx] = false; 920 m_pendingLocalConnections[idx] = NULL; 921 922 bool success=g_NetworkManager.AddLocalPlayerByUserIndex(idx); 923 924 if(success) 925 { 926 app.DebugPrintf("Adding temp local player on pad %d\n", idx); 927 localplayers[idx] = shared_ptr<MultiplayerLocalPlayer>( new MultiplayerLocalPlayer(this, level, user, NULL ) ); 928 localgameModes[idx] = NULL; 929 930 updatePlayerViewportAssignments(); 931 932#ifdef _XBOX 933 // tell the xui scenes a splitscreen player joined 934 XUIMessage xuiMsg; 935 CustomMessage_Splitscreenplayer_Struct myMsgData; 936 CustomMessage_Splitscreenplayer( &xuiMsg, &myMsgData, true); 937 938 // send the message 939 for(int i=0;i<XUSER_MAX_COUNT;i++) 940 { 941 //if((i!=idx) && (localplayers[i]!=NULL)) 942 { 943 XuiBroadcastMessage( CXuiSceneBase::GetPlayerBaseScene(i), &xuiMsg ); 944 } 945 } 946#endif 947 948 ConnectionProgressParams *param = new ConnectionProgressParams(); 949 param->iPad = idx; 950 param->stringId = IDS_PROGRESS_CONNECTING; 951 param->showTooltips = true; 952 param->setFailTimer = true; 953 param->timerTime = CONNECTING_PROGRESS_CHECK_TIME; 954 955 // Joining as second player so always the small progress 956 ui.NavigateToScene(idx, eUIScene_ConnectingProgress, param); 957 958 } 959 else 960 { 961 app.DebugPrintf("g_NetworkManager.AddLocalPlayerByUserIndex failed\n"); 962#ifdef _DURANGO 963 ProfileManager.RemoveGamepadFromGame(idx); 964#endif 965 } 966 967 return success; 968} 969 970void Minecraft::addPendingLocalConnection(int idx, ClientConnection *connection) 971{ 972 m_pendingLocalConnections[idx] = connection; 973} 974 975shared_ptr<MultiplayerLocalPlayer> Minecraft::createExtraLocalPlayer(int idx, const wstring& name, int iPad, int iDimension, ClientConnection *clientConnection /*= NULL*/,MultiPlayerLevel *levelpassedin) 976{ 977 if( clientConnection == NULL) return nullptr; 978 979 if( clientConnection == m_pendingLocalConnections[idx] ) 980 { 981 int tempScreenSection = C4JRender::VIEWPORT_TYPE_FULLSCREEN; 982 if( localplayers[idx] != NULL && localgameModes[idx] == NULL ) 983 { 984 // A temp player displaying a connecting screen 985 tempScreenSection = localplayers[idx]->m_iScreenSection; 986 } 987 wstring prevname = user->name; 988 user->name = name; 989 990 // Don't need this any more 991 m_pendingLocalConnections[idx] = NULL; 992 993 // Add the connection to the level which will now take responsibility for ticking it 994 // 4J-PB - can't use the dimension from localplayers[idx], since there may be no localplayers at this point 995 //MultiPlayerLevel *mpLevel = (MultiPlayerLevel *)getLevel( localplayers[idx]->dimension ); 996 997 MultiPlayerLevel *mpLevel; 998 999 if(levelpassedin) 1000 { 1001 level=levelpassedin; 1002 mpLevel=levelpassedin; 1003 } 1004 else 1005 { 1006 level=getLevel( iDimension ); 1007 mpLevel = getLevel( iDimension ); 1008 mpLevel->addClientConnection( clientConnection ); 1009 } 1010 1011 if( app.GetTutorialMode() ) 1012 { 1013 localgameModes[idx] = new FullTutorialMode(idx, this, clientConnection); 1014 } 1015 // check if we're in the trial version 1016 else if(ProfileManager.IsFullVersion()==false) 1017 { 1018 localgameModes[idx] = new TrialMode(idx, this, clientConnection); 1019 } 1020 else 1021 { 1022 localgameModes[idx] = new ConsoleGameMode(idx, this, clientConnection); 1023 } 1024 1025 // 4J-PB - can't do this here because they use a render context, but this is running from a thread. 1026 // Moved the creation of these into the main thread, before level launch 1027 //localitemInHandRenderers[idx] = new ItemInHandRenderer(this); 1028 localplayers[idx] = localgameModes[idx]->createPlayer(level); 1029 1030 PlayerUID playerXUIDOffline = INVALID_XUID; 1031 PlayerUID playerXUIDOnline = INVALID_XUID; 1032 ProfileManager.GetXUID(idx,&playerXUIDOffline,false); 1033 ProfileManager.GetXUID(idx,&playerXUIDOnline,true); 1034 localplayers[idx]->setXuid(playerXUIDOffline); 1035 localplayers[idx]->setOnlineXuid(playerXUIDOnline); 1036 localplayers[idx]->setIsGuest(ProfileManager.IsGuest(idx)); 1037 1038 localplayers[idx]->m_displayName = ProfileManager.GetDisplayName(idx); 1039 1040 localplayers[idx]->m_iScreenSection = tempScreenSection; 1041 1042 if( levelpassedin == NULL) level->addEntity(localplayers[idx]); // Don't add if we're passing the level in, we only do this from the client connection & we'll be handling adding it ourselves 1043 1044 localplayers[idx]->SetXboxPad(iPad); 1045 1046 if( localplayers[idx]->input != NULL ) delete localplayers[idx]->input; 1047 localplayers[idx]->input = new Input(); 1048 1049 localplayers[idx]->resetPos(); 1050 1051 levelRenderer->setLevel(idx, level); 1052 localplayers[idx]->level = level; 1053 1054 user->name = prevname; 1055 1056 updatePlayerViewportAssignments(); 1057 1058 // Fix for #105852 - TU12: Content: Gameplay: Local splitscreen Players are spawned at incorrect places after re-joining previously saved and loaded "Mass Effect World". 1059 // Move this check to ClientConnection::handleMovePlayer 1060// // 4J-PB - can't call this when this function is called from the qnet thread (GetGameStarted will be false) 1061// if(app.GetGameStarted()) 1062// { 1063// ui.CloseUIScenes(idx); 1064// } 1065 } 1066 1067 return localplayers[idx]; 1068} 1069 1070// on a respawn of the local player, just store them 1071void Minecraft::storeExtraLocalPlayer(int idx) 1072{ 1073 localplayers[idx] = player; 1074 1075 if( localplayers[idx]->input != NULL ) delete localplayers[idx]->input; 1076 localplayers[idx]->input = new Input(); 1077 1078 if(ProfileManager.IsSignedIn(idx)) 1079 { 1080 localplayers[idx]->name = convStringToWstring( ProfileManager.GetGamertag(idx) ); 1081 } 1082} 1083 1084void Minecraft::removeLocalPlayerIdx(int idx) 1085{ 1086 bool updateXui = true; 1087 if(localgameModes[idx] != NULL) 1088 { 1089 if( getLevel( localplayers[idx]->dimension )->isClientSide ) 1090 { 1091 shared_ptr<MultiplayerLocalPlayer> mplp = localplayers[idx]; 1092 ( (MultiPlayerLevel *)getLevel( localplayers[idx]->dimension ) )->removeClientConnection(mplp->connection, true); 1093 delete mplp->connection; 1094 mplp->connection = NULL; 1095 g_NetworkManager.RemoveLocalPlayerByUserIndex(idx); 1096 } 1097 getLevel( localplayers[idx]->dimension )->removeEntity(localplayers[idx]); 1098 1099#ifdef _XBOX 1100 // 4J Stu - Fix for #12368 - Crash: Game crashes when saving then exiting and selecting to save 1101 app.TutorialSceneNavigateBack(idx); 1102#endif 1103 1104 // 4J Stu - Fix for #13257 - CRASH: Gameplay: Title crashed after exiting the tutorial 1105 // It doesn't matter if they were in the tutorial already 1106 playerLeftTutorial( idx ); 1107 1108 delete localgameModes[idx]; 1109 localgameModes[idx] = NULL; 1110 } 1111 else if( m_pendingLocalConnections[idx] != NULL ) 1112 { 1113 m_pendingLocalConnections[idx]->sendAndDisconnect( shared_ptr<DisconnectPacket>( new DisconnectPacket(DisconnectPacket::eDisconnect_Quitting) ) );; 1114 delete m_pendingLocalConnections[idx]; 1115 m_pendingLocalConnections[idx] = NULL; 1116 g_NetworkManager.RemoveLocalPlayerByUserIndex(idx); 1117 } 1118 else 1119 { 1120 // Not sure how this works on qnet, but for other platforms, calling RemoveLocalPlayerByUserIndex won't do anything if there isn't a local user to remove 1121 // Now just updating the UI directly in this case 1122#ifdef _XBOX 1123 // 4J Stu - A signout early in the game creation before this player has connected to the game server 1124 updateXui = false; 1125#endif 1126 // 4J Stu - Adding this back in for exactly the reason my comment above suggests it was added in the first place 1127#if defined(_XBOX_ONE) || defined(__ORBIS__) 1128 g_NetworkManager.RemoveLocalPlayerByUserIndex(idx); 1129#endif 1130 } 1131 localplayers[idx] = nullptr; 1132 1133 if( idx == ProfileManager.GetPrimaryPad() ) 1134 { 1135 // We should never try to remove the Primary player in this way 1136 assert(false); 1137 /* 1138 // If we are removing the primary player then there can't be a valid gamemode left anymore, this 1139 // pointer will be referring to the one we've just deleted 1140 gameMode = NULL; 1141 // Remove references to player 1142 player = NULL; 1143 cameraTargetPlayer = NULL; 1144 EntityRenderDispatcher::instance->cameraEntity = NULL; 1145 TileEntityRenderDispatcher::instance->cameraEntity = NULL; 1146 */ 1147 } 1148 else if( updateXui ) 1149 { 1150 gameRenderer->DisableUpdateThread(); 1151 levelRenderer->setLevel(idx, NULL); 1152 gameRenderer->EnableUpdateThread(); 1153 ui.CloseUIScenes(idx,true); 1154 updatePlayerViewportAssignments(); 1155 } 1156 1157 // We only create these once ever so don't delete it here 1158 //delete localitemInHandRenderers[idx]; 1159} 1160 1161void Minecraft::createPrimaryLocalPlayer(int iPad) 1162{ 1163 localgameModes[iPad] = gameMode; 1164 localplayers[iPad] = player; 1165 //gameRenderer->itemInHandRenderer = localitemInHandRenderers[iPad]; 1166 // Give them the gamertag if they're signed in 1167 if(ProfileManager.IsSignedIn(ProfileManager.GetPrimaryPad())) 1168 { 1169 user->name = convStringToWstring( ProfileManager.GetGamertag(ProfileManager.GetPrimaryPad()) ); 1170 } 1171} 1172 1173#ifdef _WINDOWS64 1174void Minecraft::applyFrameMouseLook() 1175{ 1176 // Per-frame mouse look: consume mouse deltas every frame instead of waiting 1177 // for the 20Hz game tick. Apply the same delta to both xRot/yRot AND xRotO/yRotO 1178 // so the render interpolation instantly reflects the change without waiting for a tick. 1179 if (level == NULL) return; 1180 1181 for (int i = 0; i < XUSER_MAX_COUNT; i++) 1182 { 1183 if (localplayers[i] == NULL) continue; 1184 int iPad = localplayers[i]->GetXboxPad(); 1185 if (iPad != 0) continue; // Mouse only applies to pad 0 1186 1187 if (!KMInput.IsCaptured()) continue; 1188 if (localgameModes[iPad] == NULL) continue; 1189 1190 float rawDx, rawDy; 1191 KMInput.ConsumeMouseDelta(rawDx, rawDy); 1192 if (rawDx == 0.0f && rawDy == 0.0f) continue; 1193 1194 float mouseSensitivity = 0.5f; 1195 float mdx = rawDx * mouseSensitivity; 1196 float mdy = -rawDy * mouseSensitivity; 1197 if (app.GetGameSettings(iPad, eGameSetting_ControlInvertLook)) 1198 mdy = -mdy; 1199 1200 // Apply 0.15f scaling (same as Entity::interpolateTurn / Entity::turn) 1201 float dyaw = mdx * 0.15f; 1202 float dpitch = -mdy * 0.15f; 1203 1204 // Apply to both current and old rotation so render interpolation 1205 // reflects the change immediately (no 50ms tick delay) 1206 localplayers[i]->yRot += dyaw; 1207 localplayers[i]->yRotO += dyaw; 1208 localplayers[i]->xRot += dpitch; 1209 localplayers[i]->xRotO += dpitch; 1210 1211 // Clamp pitch 1212 if (localplayers[i]->xRot < -90.0f) localplayers[i]->xRot = -90.0f; 1213 if (localplayers[i]->xRot > 90.0f) localplayers[i]->xRot = 90.0f; 1214 if (localplayers[i]->xRotO < -90.0f) localplayers[i]->xRotO = -90.0f; 1215 if (localplayers[i]->xRotO > 90.0f) localplayers[i]->xRotO = 90.0f; 1216 } 1217} 1218#endif 1219 1220void Minecraft::run_middle() 1221{ 1222 static __int64 lastTime = 0; 1223 static bool bFirstTimeIntoGame = true; 1224 static bool bAutosaveTimerSet=false; 1225 static unsigned int uiAutosaveTimer=0; 1226 static int iFirstTimeCountdown=60; 1227 if( lastTime == 0 ) lastTime = System::nanoTime(); 1228 static int frames = 0; 1229 1230 EnterCriticalSection(&m_setLevelCS); 1231 1232 if(running) 1233 { 1234 if (reloadTextures) 1235 { 1236 reloadTextures = false; 1237 textures->reloadAll(); 1238 } 1239 1240 //while (running) 1241 { 1242 // try { // 4J - removed try/catch 1243 // if (minecraftApplet != null && !minecraftApplet.isActive()) break; // 4J - removed 1244 AABB::resetPool(); 1245 Vec3::resetPool(); 1246 1247 // if (parent == NULL && Display.isCloseRequested()) { // 4J - removed 1248 // stop(); 1249 // } 1250 1251 // 4J-PB - AUTOSAVE TIMER - only in the full game and if the player is the host 1252 if(level!=NULL && ProfileManager.IsFullVersion() && g_NetworkManager.IsHost()) 1253 { 1254 /*if(!bAutosaveTimerSet) 1255 { 1256 // set the timer 1257 bAutosaveTimerSet=true; 1258 1259 app.SetAutosaveTimerTime(); 1260 } 1261 else*/ 1262 { 1263 // if the pause menu is up for the primary player, don't autosave 1264 // If saving isn't disabled, and the main player has a app action running , or has any crafting or containers open, don't autosave 1265 if(!StorageManager.GetSaveDisabled() && (app.GetXuiAction(ProfileManager.GetPrimaryPad())==eAppAction_Idle) ) 1266 { 1267 if(!ui.IsPauseMenuDisplayed(ProfileManager.GetPrimaryPad()) && !ui.IsIgnoreAutosaveMenuDisplayed(ProfileManager.GetPrimaryPad())) 1268 { 1269 // check if the autotimer countdown has reached zero 1270 unsigned char ucAutosaveVal=app.GetGameSettings(ProfileManager.GetPrimaryPad(),eGameSetting_Autosave); 1271 bool bTrialTexturepack=false; 1272 if(!Minecraft::GetInstance()->skins->isUsingDefaultSkin()) 1273 { 1274 TexturePack *tPack = Minecraft::GetInstance()->skins->getSelected(); 1275 DLCTexturePack *pDLCTexPack=(DLCTexturePack *)tPack; 1276 1277 DLCPack *pDLCPack=pDLCTexPack->getDLCInfoParentPack(); 1278 1279 if( pDLCPack ) 1280 { 1281 if(!pDLCPack->hasPurchasedFile( DLCManager::e_DLCType_Texture, L"" )) 1282 { 1283 bTrialTexturepack=true; 1284 } 1285 } 1286 } 1287 1288 // If the autosave value is not zero, and the player isn't using a trial texture pack, then check whether we need to save this tick 1289 if((ucAutosaveVal!=0) && !bTrialTexturepack) 1290 { 1291 if(app.AutosaveDue()) 1292 { 1293 // disable the autosave countdown 1294 ui.ShowAutosaveCountdownTimer(false); 1295 1296 // Need to save now 1297 app.DebugPrintf("+++++++++++\n"); 1298 app.DebugPrintf("+++Autosave\n"); 1299 app.DebugPrintf("+++++++++++\n"); 1300 app.SetAction(ProfileManager.GetPrimaryPad(),eAppAction_AutosaveSaveGame); 1301 //app.SetAutosaveTimerTime(); 1302#ifndef _CONTENT_PACKAGE 1303 { 1304 // print the time 1305 SYSTEMTIME UTCSysTime; 1306 GetSystemTime( &UTCSysTime ); 1307 //char szTime[15]; 1308 1309 app.DebugPrintf("%02d:%02d:%02d\n",UTCSysTime.wHour,UTCSysTime.wMinute,UTCSysTime.wSecond); 1310 } 1311#endif 1312 } 1313 else 1314 { 1315 unsigned int uiTimeToAutosave=app.SecondsToAutosave(); 1316 1317 if(uiTimeToAutosave<6) 1318 { 1319 ui.ShowAutosaveCountdownTimer(true); 1320 ui.UpdateAutosaveCountdownTimer(uiTimeToAutosave); 1321 } 1322 } 1323 } 1324 } 1325 else 1326 { 1327 // disable the autosave countdown 1328 ui.ShowAutosaveCountdownTimer(false); 1329 } 1330 } 1331 } 1332 } 1333 1334 // 4J-PB - Once we're in the level, check if the players have the level in their banned list and ask if they want to play it 1335 for( int i = 0; i < XUSER_MAX_COUNT; i++ ) 1336 { 1337 if( localplayers[i] && (app.GetBanListCheck(i)==false) && !Minecraft::GetInstance()->isTutorial() && ProfileManager.IsSignedInLive(i) && !ProfileManager.IsGuest(i) ) 1338 { 1339 // If there is a sys ui displayed, we can't display the message box here, so ignore until we can 1340 if(!ProfileManager.IsSystemUIDisplayed()) 1341 { 1342 app.SetBanListCheck(i,true); 1343 // 4J-PB - check if the level is in the banned level list 1344 // get the unique save name and xuid from whoever is the host 1345#if defined _XBOX || defined _XBOX_ONE 1346 INetworkPlayer *pHostPlayer = g_NetworkManager.GetHostPlayer(); 1347 1348#ifdef _XBOX 1349 PlayerUID xuid=((NetworkPlayerXbox *)pHostPlayer)->GetUID(); 1350#else 1351 PlayerUID xuid=pHostPlayer->GetUID(); 1352#endif 1353 1354 if(app.IsInBannedLevelList(i,xuid,app.GetUniqueMapName())) 1355 { 1356 // put up a message box asking if the player would like to unban this level 1357 app.DebugPrintf("This level is banned\n"); 1358 // set the app action to bring up the message box to give them the option to remove from the ban list or exit the level 1359 app.SetAction(i,eAppAction_LevelInBanLevelList,(void *)TRUE); 1360 } 1361#endif 1362 } 1363 } 1364 } 1365 1366 if(!ProfileManager.IsSystemUIDisplayed() && app.DLCInstallProcessCompleted() && !app.DLCInstallPending() && app.m_dlcManager.NeedsCorruptCheck() ) 1367 { 1368 app.m_dlcManager.checkForCorruptDLCAndAlert(); 1369 } 1370 1371 // When we go into the first loaded level, check if the console has active joypads that are not in the game, and bring up the quadrant display to remind them to press start (if the session has space) 1372 if(level!=NULL && bFirstTimeIntoGame && g_NetworkManager.SessionHasSpace()) 1373 { 1374 // have a short delay before the display 1375 if(iFirstTimeCountdown==0) 1376 { 1377 bFirstTimeIntoGame=false; 1378 1379 if(app.IsLocalMultiplayerAvailable()) 1380 { 1381 for( int i = 0; i < XUSER_MAX_COUNT; i++ ) 1382 { 1383 if((localplayers[i] == NULL) && InputManager.IsPadConnected(i)) 1384 { 1385 if(!ui.PressStartPlaying(i)) 1386 { 1387 ui.ShowPressStart(i); 1388 } 1389 } 1390 } 1391 } 1392 } 1393 else iFirstTimeCountdown--; 1394 } 1395 // 4J-PB - store any button toggles for the players, since the minecraft::tick may not be called if we're running fast, and a button press and release will be missed 1396 1397 for( int i = 0; i < XUSER_MAX_COUNT; i++ ) 1398 { 1399#ifdef __ORBIS__ 1400 if ( m_pPsPlusUpsell != NULL && m_pPsPlusUpsell->hasResponse() && m_pPsPlusUpsell->m_userIndex == i ) 1401 { 1402 delete m_pPsPlusUpsell; 1403 m_pPsPlusUpsell = NULL; 1404 1405 if ( ProfileManager.HasPlayStationPlus(i) ) 1406 { 1407 app.DebugPrintf("<Minecraft.cpp> Player_%i is now authorised for PsPlus.\n", i); 1408 if (!ui.PressStartPlaying(i)) ui.ShowPressStart(i); 1409 } 1410 else 1411 { 1412 UINT uiIDA[1] = { IDS_OK }; 1413 ui.RequestErrorMessage( IDS_CANTJOIN_TITLE, IDS_NO_PLAYSTATIONPLUS, uiIDA, 1, i); 1414 } 1415 } 1416 else 1417#endif 1418 if(localplayers[i]) 1419 { 1420 // 4J-PB - add these to check for coming out of idle 1421 if(InputManager.ButtonPressed(i, MINECRAFT_ACTION_JUMP)) localplayers[i]->ullButtonsPressed|=1LL<<MINECRAFT_ACTION_JUMP; 1422 if(InputManager.ButtonPressed(i, MINECRAFT_ACTION_USE)) localplayers[i]->ullButtonsPressed|=1LL<<MINECRAFT_ACTION_USE; 1423 1424 if(InputManager.ButtonPressed(i, MINECRAFT_ACTION_INVENTORY)) localplayers[i]->ullButtonsPressed|=1LL<<MINECRAFT_ACTION_INVENTORY; 1425 if(InputManager.ButtonPressed(i, MINECRAFT_ACTION_ACTION)) localplayers[i]->ullButtonsPressed|=1LL<<MINECRAFT_ACTION_ACTION; 1426 if(InputManager.ButtonPressed(i, MINECRAFT_ACTION_CRAFTING)) localplayers[i]->ullButtonsPressed|=1LL<<MINECRAFT_ACTION_CRAFTING; 1427 if(InputManager.ButtonPressed(i, MINECRAFT_ACTION_PAUSEMENU)) 1428 { 1429 localplayers[i]->ullButtonsPressed|=1LL<<MINECRAFT_ACTION_PAUSEMENU; 1430 app.DebugPrintf("PAUSE PRESSED - ipad = %d, Storing press\n",i); 1431 } 1432#ifdef _DURANGO 1433 if(InputManager.ButtonPressed(i, ACTION_MENU_GTC_PAUSE)) localplayers[i]->ullButtonsPressed|=1LL<<ACTION_MENU_GTC_PAUSE; 1434#endif 1435 if(InputManager.ButtonPressed(i, MINECRAFT_ACTION_DROP)) localplayers[i]->ullButtonsPressed|=1LL<<MINECRAFT_ACTION_DROP; 1436 1437 // 4J-PB - If we're flying, the sneak needs to be held on to go down 1438 if(localplayers[i]->abilities.flying) 1439 { 1440 if(InputManager.ButtonDown(i, MINECRAFT_ACTION_SNEAK_TOGGLE)) localplayers[i]->ullButtonsPressed|=1LL<<MINECRAFT_ACTION_SNEAK_TOGGLE; 1441 } 1442 else 1443 { 1444 if(InputManager.ButtonPressed(i, MINECRAFT_ACTION_SNEAK_TOGGLE)) localplayers[i]->ullButtonsPressed|=1LL<<MINECRAFT_ACTION_SNEAK_TOGGLE; 1445 } 1446 if(InputManager.ButtonPressed(i, MINECRAFT_ACTION_RENDER_THIRD_PERSON)) localplayers[i]->ullButtonsPressed|=1LL<<MINECRAFT_ACTION_RENDER_THIRD_PERSON; 1447 if(InputManager.ButtonPressed(i, MINECRAFT_ACTION_GAME_INFO)) localplayers[i]->ullButtonsPressed|=1LL<<MINECRAFT_ACTION_GAME_INFO; 1448 1449#ifdef _WINDOWS64 1450 // Keyboard/mouse button presses for player 0 1451 if (i == 0) 1452 { 1453 if (KMInput.ConsumeKeyPress(VK_ESCAPE)) localplayers[i]->ullButtonsPressed |= 1LL<<MINECRAFT_ACTION_PAUSEMENU; 1454 if (KMInput.ConsumeKeyPress('E')) localplayers[i]->ullButtonsPressed |= 1LL<<MINECRAFT_ACTION_INVENTORY; 1455 if (KMInput.ConsumeKeyPress('Q')) localplayers[i]->ullButtonsPressed |= 1LL<<MINECRAFT_ACTION_DROP; 1456 if (KMInput.ConsumeKeyPress('C')) localplayers[i]->ullButtonsPressed |= 1LL<<MINECRAFT_ACTION_CRAFTING; 1457 if (KMInput.ConsumeKeyPress(VK_F5)) localplayers[i]->ullButtonsPressed |= 1LL<<MINECRAFT_ACTION_RENDER_THIRD_PERSON; 1458 // In flying mode, Shift held = sneak/descend 1459 if (localplayers[i]->abilities.flying && KMInput.IsKeyDown(VK_SHIFT)) 1460 localplayers[i]->ullButtonsPressed |= 1LL<<MINECRAFT_ACTION_SNEAK_TOGGLE; 1461 } 1462#endif 1463 1464#ifndef _FINAL_BUILD 1465 if( app.DebugSettingsOn() && app.GetUseDPadForDebug() ) 1466 { 1467 localplayers[i]->ullDpad_last = 0; 1468 localplayers[i]->ullDpad_this = 0; 1469 localplayers[i]->ullDpad_filtered = 0; 1470 if(InputManager.ButtonPressed(i, MINECRAFT_ACTION_DPAD_RIGHT)) localplayers[i]->ullButtonsPressed|=1LL<<MINECRAFT_ACTION_CHANGE_SKIN; 1471 if(InputManager.ButtonPressed(i, MINECRAFT_ACTION_DPAD_UP)) localplayers[i]->ullButtonsPressed|=1LL<<MINECRAFT_ACTION_FLY_TOGGLE; 1472 if(InputManager.ButtonPressed(i, MINECRAFT_ACTION_DPAD_DOWN)) localplayers[i]->ullButtonsPressed|=1LL<<MINECRAFT_ACTION_RENDER_DEBUG; 1473 if(InputManager.ButtonPressed(i, MINECRAFT_ACTION_DPAD_LEFT)) localplayers[i]->ullButtonsPressed|=1LL<<MINECRAFT_ACTION_SPAWN_CREEPER; 1474 } 1475 else 1476#endif 1477 { 1478 // Movement on DPAD is stored ulimately into ullDpad_filtered - this ignores any diagonals pressed, instead reporting the last single direction - otherwise 1479 // we get loads of accidental diagonal movements 1480 1481 localplayers[i]->ullDpad_this = 0; 1482 int dirCount = 0; 1483 1484#ifndef __PSVITA__ 1485 if(InputManager.ButtonDown(i, MINECRAFT_ACTION_DPAD_LEFT)) { localplayers[i]->ullDpad_this|=1LL<<MINECRAFT_ACTION_DPAD_LEFT; dirCount++; } 1486 if(InputManager.ButtonDown(i, MINECRAFT_ACTION_DPAD_RIGHT)) { localplayers[i]->ullDpad_this|=1LL<<MINECRAFT_ACTION_DPAD_RIGHT; dirCount++; } 1487 if(InputManager.ButtonDown(i, MINECRAFT_ACTION_DPAD_UP)) { localplayers[i]->ullDpad_this|=1LL<<MINECRAFT_ACTION_DPAD_UP; dirCount++; } 1488 if(InputManager.ButtonDown(i, MINECRAFT_ACTION_DPAD_DOWN)) { localplayers[i]->ullDpad_this|=1LL<<MINECRAFT_ACTION_DPAD_DOWN; dirCount++; } 1489#endif 1490 1491 if( dirCount <= 1 ) 1492 { 1493 localplayers[i]->ullDpad_last = localplayers[i]->ullDpad_this; 1494 localplayers[i]->ullDpad_filtered = localplayers[i]->ullDpad_this; 1495 } 1496 else 1497 { 1498 localplayers[i]->ullDpad_filtered = localplayers[i]->ullDpad_last; 1499 } 1500 } 1501 1502 // for the opacity timer 1503 if(InputManager.ButtonPressed(i, MINECRAFT_ACTION_LEFT_SCROLL) || InputManager.ButtonPressed(i, MINECRAFT_ACTION_RIGHT_SCROLL)) 1504 //InputManager.ButtonPressed(i, MINECRAFT_ACTION_USE) || InputManager.ButtonPressed(i, MINECRAFT_ACTION_ACTION)) 1505 { 1506 app.SetOpacityTimer(i); 1507 } 1508 } 1509 else 1510 { 1511 // 4J Stu - This doesn't make any sense with the way we handle XboxOne users 1512#ifndef _DURANGO 1513 // did we just get input from a player who doesn't exist? They'll be wanting to join the game then 1514#ifdef _WINDOWS64 1515 // The 4J toggle system is unreliable here: UIController::handleInput() calls 1516 // ButtonPressed for every ACTION_MENU_* mapped button (which covers all physical 1517 // buttons) before run_middle() runs. Bypass it with raw XInput and own edge detection. 1518 // A latch counter keeps startJustPressed active for ~120 frames after the rising edge 1519 // so the detection window is large enough to be caught reliably. 1520 static WORD s_prevXButtons[XUSER_MAX_COUNT] = {}; 1521 static int s_startPressLatch[XUSER_MAX_COUNT] = {}; 1522 XINPUT_STATE xstate_join; 1523 memset(&xstate_join, 0, sizeof(xstate_join)); 1524 WORD xCurButtons = 0; 1525 if (XInputGetState(i, &xstate_join) == ERROR_SUCCESS) 1526 { 1527 xCurButtons = xstate_join.Gamepad.wButtons; 1528 if ((xCurButtons & XINPUT_GAMEPAD_START) != 0 && (s_prevXButtons[i] & XINPUT_GAMEPAD_START) == 0) 1529 s_startPressLatch[i] = 120; // rising edge: latch for ~120 frames (~2s at 60fps) 1530 else if (s_startPressLatch[i] > 0) 1531 s_startPressLatch[i]--; 1532 s_prevXButtons[i] = xCurButtons; 1533 } 1534 bool startJustPressed = s_startPressLatch[i] > 0; 1535 bool tryJoin = !pause && !ui.IsIgnorePlayerJoinMenuDisplayed(ProfileManager.GetPrimaryPad()) && g_NetworkManager.SessionHasSpace() && xCurButtons != 0; 1536#else 1537 bool tryJoin = !pause && !ui.IsIgnorePlayerJoinMenuDisplayed(ProfileManager.GetPrimaryPad()) && g_NetworkManager.SessionHasSpace() && RenderManager.IsHiDef() && InputManager.ButtonPressed(i); 1538#endif 1539#ifdef __ORBIS__ 1540 // Check for remote play 1541 tryJoin = tryJoin && InputManager.IsLocalMultiplayerAvailable(); 1542 1543 // 4J Stu - Check that content restriction information has been received 1544 if( !g_NetworkManager.IsLocalGame() ) 1545 { 1546 tryJoin = tryJoin && ProfileManager.GetChatAndContentRestrictions(i,true,NULL,NULL,NULL); 1547 } 1548#endif 1549 if(tryJoin) 1550 { 1551 if(!ui.PressStartPlaying(i)) 1552 { 1553#ifdef __ORBIS__ 1554 // Don't let player start joining until their PS Plus check has finished 1555 if (g_NetworkManager.IsLocalGame() || !ProfileManager.RequestingPlaystationPlus(i)) 1556#endif 1557 { 1558 ui.ShowPressStart(i); 1559 } 1560 } 1561 else 1562 { 1563 // did we just get input from a player who doesn't exist? They'll be wanting to join the game then 1564#ifdef __ORBIS__ 1565 if(InputManager.ButtonPressed(i, ACTION_MENU_A)) 1566#elif defined _WINDOWS64 1567 if(startJustPressed) 1568#else 1569 if(InputManager.ButtonPressed(i, MINECRAFT_ACTION_PAUSEMENU)) 1570#endif 1571 { 1572 // Let them join 1573 1574 // are they signed in? 1575#ifdef _WINDOWS64 1576 if(ProfileManager.IsSignedIn(i) || (g_NetworkManager.IsLocalGame() && InputManager.IsPadConnected(i))) 1577#else 1578 if(ProfileManager.IsSignedIn(i)) 1579#endif 1580 { 1581 // if this is a local game, then the player just needs to be signed in 1582 if( g_NetworkManager.IsLocalGame() || (ProfileManager.IsSignedInLive(i) && ProfileManager.AllowedToPlayMultiplayer(i) ) ) 1583 { 1584#ifdef __ORBIS__ 1585 bool contentRestricted = false; 1586 ProfileManager.GetChatAndContentRestrictions(i,false,NULL,&contentRestricted,NULL); // TODO! 1587 1588 if (!g_NetworkManager.IsLocalGame() && contentRestricted) 1589 { 1590 ui.RequestContentRestrictedMessageBox(IDS_NO_MULTIPLAYER_PRIVILEGE_TITLE, IDS_CONTENT_RESTRICTION, i); 1591 } 1592 else if(!g_NetworkManager.IsLocalGame() && !ProfileManager.HasPlayStationPlus(i)) 1593 { 1594 m_pPsPlusUpsell = new PsPlusUpsellWrapper(i); 1595 m_pPsPlusUpsell->displayUpsell(); 1596 } 1597 else 1598#endif 1599 if( level->isClientSide ) 1600 { 1601 bool success=addLocalPlayer(i); 1602 1603 if(!success) 1604 { 1605 app.DebugPrintf("Bringing up the sign in ui\n"); 1606 ProfileManager.RequestSignInUI(false, g_NetworkManager.IsLocalGame(), true, false,true,&Minecraft::InGame_SignInReturned, this,i); 1607 } 1608 else 1609 { 1610#ifdef __ORBIS__ 1611 if(g_NetworkManager.IsLocalGame() == false) 1612 { 1613 bool chatRestricted = false; 1614 ProfileManager.GetChatAndContentRestrictions(i,false,&chatRestricted,NULL,NULL); 1615 if(chatRestricted) 1616 { 1617 ProfileManager.DisplaySystemMessage( SCE_MSG_DIALOG_SYSMSG_TYPE_TRC_PSN_CHAT_RESTRICTION, i ); 1618 } 1619 } 1620#endif 1621 } 1622 } 1623 else 1624 { 1625 // create the localplayer 1626 shared_ptr<Player> player = localplayers[i]; 1627 if( player == NULL) 1628 { 1629 player = createExtraLocalPlayer(i, (convStringToWstring( ProfileManager.GetGamertag(i) )).c_str(), i, level->dimension->id); 1630 } 1631 } 1632 } 1633 else 1634 { 1635 if( ProfileManager.IsSignedInLive(ProfileManager.GetPrimaryPad()) && !ProfileManager.AllowedToPlayMultiplayer(i) ) 1636 { 1637 ProfileManager.RequestConvertOfflineToGuestUI( &Minecraft::InGame_SignInReturned, this,i); 1638 // 4J Stu - Don't allow converting to guests as we don't allow any guest sign-in while in the game 1639 // Fix for #66516 - TCR #124: MPS Guest Support ; #001: BAS Game Stability: TU8: The game crashes when second Guest signs-in on console which takes part in Xbox LIVE multiplayer session. 1640 //ProfileManager.RequestConvertOfflineToGuestUI( &Minecraft::InGame_SignInReturned, this,i); 1641 1642#ifndef _XBOX 1643 ui.HidePressStart(); 1644#endif 1645 1646#ifdef __ORBIS__ 1647 int npAvailability = ProfileManager.getNPAvailability(i); 1648 1649 // Check if PSN is unavailable because of age restriction 1650 if (npAvailability == SCE_NP_ERROR_AGE_RESTRICTION) 1651 { 1652 UINT uiIDA[1]; 1653 uiIDA[0] = IDS_OK; 1654 ui.RequestErrorMessage(IDS_ONLINE_SERVICE_TITLE, IDS_CONTENT_RESTRICTION, uiIDA, 1, i); 1655 } 1656 else if (ProfileManager.IsSignedIn(i) && !ProfileManager.IsSignedInLive(i)) 1657 { 1658 // You're not signed in to PSN! 1659 UINT uiIDA[2]; 1660 uiIDA[0] = IDS_PRO_NOTONLINE_ACCEPT; 1661 uiIDA[1] = IDS_CANCEL; 1662 ui.RequestAlertMessage(IDS_PRO_NOTONLINE_TITLE, IDS_PRO_NOTONLINE_TEXT, uiIDA, 2, i,&Minecraft::MustSignInReturnedPSN, this); 1663 } 1664 else 1665#endif 1666 { 1667 UINT uiIDA[1]; 1668 uiIDA[0]=IDS_CONFIRM_OK; 1669 ui.RequestErrorMessage(IDS_NO_MULTIPLAYER_PRIVILEGE_TITLE, IDS_NO_MULTIPLAYER_PRIVILEGE_JOIN_TEXT, uiIDA, 1, i); 1670 } 1671 } 1672 //else 1673 { 1674 // player not signed in to live 1675 // bring up the sign in dialog 1676 app.DebugPrintf("Bringing up the sign in ui\n"); 1677 ProfileManager.RequestSignInUI(false, g_NetworkManager.IsLocalGame(), true, false,true,&Minecraft::InGame_SignInReturned, this,i); 1678 } 1679 } 1680 } 1681 else 1682 { 1683 // bring up the sign in dialog 1684 app.DebugPrintf("Bringing up the sign in ui\n"); 1685 ProfileManager.RequestSignInUI(false, g_NetworkManager.IsLocalGame(), true, false,true,&Minecraft::InGame_SignInReturned, this,i); 1686 } 1687 } 1688 } 1689 } 1690#endif // _DURANGO 1691 } 1692 } 1693 1694#ifdef _DURANGO 1695 // did we just get input from a player who doesn't exist? They'll be wanting to join the game then 1696 if(!pause && !ui.IsIgnorePlayerJoinMenuDisplayed(ProfileManager.GetPrimaryPad()) && g_NetworkManager.SessionHasSpace() && RenderManager.IsHiDef() ) 1697 { 1698 int firstEmptyUser = 0; 1699 for( int i = 0; i < XUSER_MAX_COUNT; i++ ) 1700 { 1701 if(localplayers[i] == NULL) 1702 { 1703 firstEmptyUser = i; 1704 break; 1705 } 1706 } 1707 1708 // For durango, check for unmapped controllers 1709 for(unsigned int iPad = XUSER_MAX_COUNT; iPad < (XUSER_MAX_COUNT + InputManager.MAX_GAMEPADS); ++iPad) 1710 { 1711 bool isPadLocked = InputManager.IsPadLocked(iPad), isPadConnected = InputManager.IsPadConnected(iPad), buttonPressed = InputManager.ButtonPressed(iPad); 1712 if (isPadLocked || !isPadConnected || !buttonPressed) continue; 1713 1714 if(!ui.PressStartPlaying(firstEmptyUser)) 1715 { 1716 ui.ShowPressStart(firstEmptyUser); 1717 } 1718 else 1719 { 1720 // did we just get input from a player who doesn't exist? They'll be wanting to join the game then 1721 if(InputManager.ButtonPressed(iPad, MINECRAFT_ACTION_PAUSEMENU)) 1722 { 1723 // bring up the sign in dialog 1724 app.DebugPrintf("Bringing up the sign in ui\n"); 1725 ProfileManager.RequestSignInUI(false, g_NetworkManager.IsLocalGame(), true, false,true,&Minecraft::InGame_SignInReturned, this,iPad); 1726 1727 // 4J Stu - If we are joining a pad here, then we don't want to try and join any others 1728 break; 1729 } 1730 } 1731 } 1732 } 1733#endif 1734 1735 if (pause && level != NULL) 1736 { 1737 float lastA = timer->a; 1738 timer->advanceTime(); 1739 timer->a = lastA; 1740 } 1741 else 1742 { 1743 timer->advanceTime(); 1744 } 1745 1746 //__int64 beforeTickTime = System::nanoTime(); 1747 for (int i = 0; i < timer->ticks; i++) 1748 { 1749 bool bLastTimerTick = ( i == ( timer->ticks - 1 ) ); 1750 // 4J-PB - the tick here can run more than once, and this is a problem for our input, which would see the a key press twice with the same time - let's tick the inputmanager again 1751 if(i!=0) 1752 { 1753 InputManager.Tick(); 1754 app.HandleButtonPresses(); 1755 } 1756 1757 ticks++; 1758 // try { // 4J - try/catch removed 1759 bool bFirst = true; 1760 for( int idx = 0; idx < XUSER_MAX_COUNT; idx++ ) 1761 { 1762 // 4J - If we are waiting for this connection to do something, then tick it here. 1763 // This replaces many of the original Java scenes which would tick the connection while showing that scene 1764 if( m_pendingLocalConnections[idx] != NULL ) 1765 { 1766 m_pendingLocalConnections[idx]->tick(); 1767 } 1768 1769 // reset the player inactive tick 1770 if(localplayers[idx]!=NULL) 1771 { 1772 // any input received? 1773 if((localplayers[idx]->ullButtonsPressed!=0) || InputManager.GetJoypadStick_LX(idx,false)!=0.0f || 1774 InputManager.GetJoypadStick_LY(idx,false)!=0.0f || InputManager.GetJoypadStick_RX(idx,false)!=0.0f || 1775 InputManager.GetJoypadStick_RY(idx,false)!=0.0f ) 1776 { 1777 localplayers[idx]->ResetInactiveTicks(); 1778 } 1779 else 1780 { 1781 localplayers[idx]->IncrementInactiveTicks(); 1782 } 1783 1784 if(localplayers[idx]->GetInactiveTicks()>200) 1785 { 1786 if(!localplayers[idx]->isIdle() && localplayers[idx]->onGround) 1787 { 1788 localplayers[idx]->setIsIdle(true); 1789 } 1790 } 1791 else 1792 { 1793 if(localplayers[idx]->isIdle()) 1794 { 1795 localplayers[idx]->setIsIdle(false); 1796 } 1797 } 1798 } 1799 1800 if( setLocalPlayerIdx(idx) ) 1801 { 1802 tick(bFirst, bLastTimerTick); 1803 bFirst = false; 1804 // clear the stored button downs since the tick for this player will now have actioned them 1805 player->ullButtonsPressed=0LL; 1806 } 1807 } 1808 1809 ui.HandleGameTick(); 1810 1811 setLocalPlayerIdx(ProfileManager.GetPrimaryPad()); 1812 1813 // 4J - added - now do the equivalent of level::animateTick, but taking into account the positions of all our players 1814 1815 for( int l = 0; l < levels.length; l++ ) 1816 { 1817 if( levels[l] ) 1818 { 1819 levels[l]->animateTickDoWork(); 1820 } 1821 } 1822 1823 // } catch (LevelConflictException e) { 1824 // this.level = null; 1825 // setLevel(null); 1826 // setScreen(new LevelConflictScreen()); 1827 // } 1828// SparseLightStorage::tick(); // 4J added 1829// CompressedTileStorage::tick(); // 4J added 1830// SparseDataStorage::tick(); // 4J added 1831 } 1832 //__int64 tickDuraction = System::nanoTime() - beforeTickTime; 1833 MemSect(31); 1834 checkGlError(L"Pre render"); 1835 MemSect(0); 1836 1837 TileRenderer::fancy = options->fancyGraphics; 1838 1839 // if (pause) timer.a = 1; 1840 1841 PIXBeginNamedEvent(0,"Sound engine update"); 1842 soundEngine->tick((shared_ptr<Mob> *)localplayers, timer->a); 1843 PIXEndNamedEvent(); 1844 1845 PIXBeginNamedEvent(0,"Light update"); 1846 1847 glEnable(GL_TEXTURE_2D); 1848 1849 PIXEndNamedEvent(); 1850 1851 // if (!Keyboard::isKeyDown(Keyboard.KEY_F7)) Display.update(); // 4J - removed 1852 1853 // 4J-PB - changing this to be per player 1854 //if (player != NULL && player->isInWall()) options->thirdPersonView = false; 1855 if (player != NULL && player->isInWall()) player->SetThirdPersonView(0); 1856 1857 if (!noRender) 1858 { 1859 bool bFirst = true; 1860 int iPrimaryPad=ProfileManager.GetPrimaryPad(); 1861 for( int i = 0; i < XUSER_MAX_COUNT; i++ ) 1862 { 1863 if( setLocalPlayerIdx(i) ) 1864 { 1865 PIXBeginNamedEvent(0,"Game render player idx %d",i); 1866 RenderManager.StateSetViewport((C4JRender::eViewportType)player->m_iScreenSection); 1867 gameRenderer->render(timer->a, bFirst); 1868 bFirst = false; 1869 PIXEndNamedEvent(); 1870 1871 if(i==iPrimaryPad) 1872 { 1873#ifdef __ORBIS__ 1874 // PS4 does much of the screen-capturing for every frame, to simplify the synchronisation when we actually want a capture. This call tells it the point in the frame to do it. 1875 RenderManager.InternalScreenCapture(); 1876#endif 1877 // check to see if we need to capture a screenshot for the save game thumbnail 1878 switch(app.GetXuiAction(i)) 1879 { 1880 case eAppAction_ExitWorldCapturedThumbnail: 1881 case eAppAction_SaveGameCapturedThumbnail: 1882 case eAppAction_AutosaveSaveGameCapturedThumbnail: 1883 // capture the save thumbnail 1884 app.CaptureSaveThumbnail(); 1885 break; 1886 } 1887 } 1888 } 1889 } 1890 // If there's an unoccupied quadrant, then clear that to black 1891 if( unoccupiedQuadrant > -1 ) 1892 { 1893 // render a logo 1894 RenderManager.StateSetViewport((C4JRender::eViewportType)(C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT + unoccupiedQuadrant)); 1895 glClearColor(0, 0, 0, 0); 1896 glClear(GL_COLOR_BUFFER_BIT); 1897 1898 ui.SetEmptyQuadrantLogo(C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_LEFT + unoccupiedQuadrant); 1899 } 1900 setLocalPlayerIdx(iPrimaryPad); 1901 RenderManager.StateSetViewport(C4JRender::VIEWPORT_TYPE_FULLSCREEN); 1902 1903#ifdef _XBOX 1904 // Do we need to capture a screenshot for a social post? 1905 for( int i = 0; i < XUSER_MAX_COUNT; i++ ) 1906 { 1907 if(app.GetXuiAction(i)==eAppAction_SocialPostScreenshot) 1908 { 1909 app.CaptureScreenshot(i); 1910 } 1911 } 1912#endif 1913 } 1914 glFlush(); 1915 1916 /* 4J - removed 1917 if (!Display::isActive()) 1918 { 1919 if (fullscreen) 1920 { 1921 this->toggleFullScreen(); 1922 } 1923 Sleep(10); 1924 } 1925 */ 1926 1927#if PACKET_ENABLE_STAT_TRACKING 1928 Packet::updatePacketStatsPIX(); 1929#endif 1930 1931 if (options->renderDebug) 1932 { 1933 //renderFpsMeter(tickDuraction); 1934 1935#if DEBUG_RENDER_SHOWS_PACKETS 1936 // To show data for only one packet type 1937 //Packet::renderPacketStats(31); 1938 1939 // To show data for all packet types selected as being renderable in the Packet:static_ctor call to Packet::map 1940 Packet::renderAllPacketStats(); 1941#else 1942 // To show the size of the QNet queue in bytes and messages 1943 g_NetworkManager.renderQueueMeter(); 1944#endif 1945 } 1946 else 1947 { 1948 lastTimer = System::nanoTime(); 1949 } 1950 1951 achievementPopup->render(); 1952 1953 PIXBeginNamedEvent(0,"Sleeping"); 1954 Sleep(0); // 4J - was Thread.yield() 1955 PIXEndNamedEvent(); 1956 1957 // if (Keyboard::isKeyDown(Keyboard::KEY_F7)) Display.update(); // 4J - removed condition 1958 PIXBeginNamedEvent(0,"Display update"); 1959 Display::update(); 1960 PIXEndNamedEvent(); 1961 1962 // checkScreenshot(); // 4J - removed 1963 1964 /* 4J - removed 1965 if (parent != NULL && !fullscreen) 1966 { 1967 if (parent.getWidth() != width || parent.getHeight() != height) 1968 { 1969 width = parent.getWidth(); 1970 height = parent.getHeight(); 1971 if (width <= 0) width = 1; 1972 if (height <= 0) height = 1; 1973 1974 resize(width, height); 1975 } 1976 } 1977 */ 1978 MemSect(31); 1979 checkGlError(L"Post render"); 1980 MemSect(0); 1981 frames++; 1982 //pause = !isClientSide() && screen != NULL && screen->isPauseScreen(); 1983 //pause = g_NetworkManager.IsLocalGame() && g_NetworkManager.GetPlayerCount() == 1 && app.IsPauseMenuDisplayed(ProfileManager.GetPrimaryPad()); 1984 pause = app.IsAppPaused(); 1985 1986#ifndef _CONTENT_PACKAGE 1987 while (System::nanoTime() >= lastTime + 1000000000) 1988 { 1989 MemSect(31); 1990 fpsString = _toString<int>(frames) + L" fps, " + _toString<int>(Chunk::updates) + L" chunk updates"; 1991 MemSect(0); 1992 Chunk::updates = 0; 1993 lastTime += 1000000000; 1994 frames = 0; 1995 } 1996#endif 1997 /* 1998 } catch (LevelConflictException e) { 1999 this.level = null; 2000 setLevel(null); 2001 setScreen(new LevelConflictScreen()); 2002 } catch (OutOfMemoryError e) { 2003 emergencySave(); 2004 setScreen(new OutOfMemoryScreen()); 2005 System.gc(); 2006 } 2007 */ 2008 } 2009 /* 2010 } catch (StopGameException e) { 2011 } catch (Throwable e) { 2012 emergencySave(); 2013 e.printStackTrace(); 2014 crash(new CrashReport("Unexpected error", e)); 2015 } finally { 2016 destroy(); 2017 } 2018 */ 2019 } 2020 LeaveCriticalSection(&m_setLevelCS); 2021} 2022 2023void Minecraft::run_end() 2024{ 2025 destroy(); 2026} 2027 2028void Minecraft::emergencySave() 2029{ 2030 // 4J - lots of try/catches removed here, and garbage collector things 2031 levelRenderer->clear(); 2032 AABB::clearPool(); 2033 Vec3::clearPool(); 2034 setLevel(NULL); 2035} 2036 2037void Minecraft::renderFpsMeter(__int64 tickTime) 2038{ 2039 int nsPer60Fps = 1000000000l / 60; 2040 if (lastTimer == -1) 2041 { 2042 lastTimer = System::nanoTime(); 2043 } 2044 __int64 now = System::nanoTime(); 2045 Minecraft::tickTimes[(Minecraft::frameTimePos) & (Minecraft::frameTimes_length - 1)] = tickTime; 2046 Minecraft::frameTimes[(Minecraft::frameTimePos++) & (Minecraft::frameTimes_length - 1)] = now - lastTimer; 2047 lastTimer = now; 2048 2049 glClear(GL_DEPTH_BUFFER_BIT); 2050 glMatrixMode(GL_PROJECTION); 2051 glEnable(GL_COLOR_MATERIAL); 2052 glLoadIdentity(); 2053 glOrtho(0, (float)width, (float)height, 0, 1000, 3000); 2054 glMatrixMode(GL_MODELVIEW); 2055 glLoadIdentity(); 2056 glTranslatef(0, 0, -2000); 2057 2058 glLineWidth(1); 2059 glDisable(GL_TEXTURE_2D); 2060 Tesselator *t = Tesselator::getInstance(); 2061 t->begin(GL_QUADS); 2062 int hh1 = (int) (nsPer60Fps / 200000); 2063 t->color(0x20000000); 2064 t->vertex((float)(0), (float)( height - hh1), (float)( 0)); 2065 t->vertex((float)(0), (float)( height), (float)( 0)); 2066 t->vertex((float)(Minecraft::frameTimes_length), (float)( height), (float)( 0)); 2067 t->vertex((float)(Minecraft::frameTimes_length), (float)( height - hh1), (float)( 0)); 2068 2069 t->color(0x20200000); 2070 t->vertex((float)(0), (float)( height - hh1 * 2), (float)( 0)); 2071 t->vertex((float)(0), (float)( height - hh1), (float)( 0)); 2072 t->vertex((float)(Minecraft::frameTimes_length), (float)( height - hh1), (float)( 0)); 2073 t->vertex((float)(Minecraft::frameTimes_length), (float)( height - hh1 * 2), (float)( 0)); 2074 2075 t->end(); 2076 __int64 totalTime = 0; 2077 for (int i = 0; i < Minecraft::frameTimes_length; i++) 2078 { 2079 totalTime += Minecraft::frameTimes[i]; 2080 } 2081 int hh = (int) (totalTime / 200000 / Minecraft::frameTimes_length); 2082 t->begin(GL_QUADS); 2083 t->color(0x20400000); 2084 t->vertex((float)(0), (float)( height - hh), (float)( 0)); 2085 t->vertex((float)(0), (float)( height), (float)( 0)); 2086 t->vertex((float)(Minecraft::frameTimes_length), (float)( height), (float)( 0)); 2087 t->vertex((float)(Minecraft::frameTimes_length), (float)( height - hh), (float)( 0)); 2088 t->end(); 2089 t->begin(GL_LINES); 2090 for (int i = 0; i < Minecraft::frameTimes_length; i++) 2091 { 2092 int col = ((i - Minecraft::frameTimePos) & (Minecraft::frameTimes_length - 1)) * 255 / Minecraft::frameTimes_length; 2093 int cc = col * col / 255; 2094 cc = cc * cc / 255; 2095 int cc2 = cc * cc / 255; 2096 cc2 = cc2 * cc2 / 255; 2097 if (Minecraft::frameTimes[i] > nsPer60Fps) 2098 { 2099 t->color(0xff000000 + cc * 65536); 2100 } 2101 else 2102 { 2103 t->color(0xff000000 + cc * 256); 2104 } 2105 2106 __int64 time = Minecraft::frameTimes[i] / 200000; 2107 __int64 time2 = Minecraft::tickTimes[i] / 200000; 2108 2109 t->vertex((float)(i + 0.5f), (float)( height - time + 0.5f), (float)( 0)); 2110 t->vertex((float)(i + 0.5f), (float)( height + 0.5f), (float)( 0)); 2111 2112 // if (Minecraft.frameTimes[i]>nsPer60Fps) { 2113 t->color(0xff000000 + cc * 65536 + cc * 256 + cc * 1); 2114 // } else { 2115 // t.color(0xff808080 + cc/2 * 256); 2116 // } 2117 t->vertex((float)(i + 0.5f), (float)( height - time + 0.5f), (float)( 0)); 2118 t->vertex((float)(i + 0.5f), (float)( height - (time - time2) + 0.5f), (float)( 0)); 2119 } 2120 t->end(); 2121 2122 glEnable(GL_TEXTURE_2D); 2123} 2124 2125void Minecraft::stop() 2126{ 2127 running = false; 2128 // keepPolling = false; 2129} 2130 2131void Minecraft::pauseGame() 2132{ 2133 if (screen != NULL) return; 2134 2135 // setScreen(new PauseScreen()); // 4J - TODO put back in 2136} 2137 2138void Minecraft::resize(int width, int height) 2139{ 2140 if (width <= 0) width = 1; 2141 if (height <= 0) height = 1; 2142 this->width = width; 2143 this->height = height; 2144 2145 if (screen != NULL) 2146 { 2147 ScreenSizeCalculator ssc(options, width, height); 2148 int screenWidth = ssc.getWidth(); 2149 int screenHeight = ssc.getHeight(); 2150 // screen->init(this, screenWidth, screenHeight); // 4J - TODO - put back in 2151 } 2152} 2153 2154void Minecraft::verify() 2155{ 2156 /* 4J - TODO 2157 new Thread() { 2158 public void run() { 2159 try { 2160 HttpURLConnection huc = (HttpURLConnection) new URL("https://login.minecraft.net/session?name=" + user.name + "&session=" + user.sessionId).openConnection(); 2161 huc.connect(); 2162 if (huc.getResponseCode() == 400) { 2163 warezTime = System.currentTimeMillis(); 2164 } 2165 huc.disconnect(); 2166 } catch (Exception e) { 2167 e.printStackTrace(); 2168 } 2169 } 2170 }.start(); 2171 */ 2172} 2173 2174 2175 2176 2177void Minecraft::levelTickUpdateFunc(void* pParam) 2178{ 2179 Level* pLevel = (Level*)pParam; 2180 pLevel->tick(); 2181} 2182 2183void Minecraft::levelTickThreadInitFunc() 2184{ 2185 AABB::CreateNewThreadStorage(); 2186 Vec3::CreateNewThreadStorage(); 2187 IntCache::CreateNewThreadStorage(); 2188 Compression::UseDefaultThreadStorage(); 2189} 2190 2191 2192// 4J - added bFirst parameter, which is true for the first active viewport in splitscreen 2193// 4J - added bUpdateTextures, which is true if the actual renderer textures are to be updated - this will be true for the last time this tick runs with bFirst true 2194void Minecraft::tick(bool bFirst, bool bUpdateTextures) 2195{ 2196 int iPad=player->GetXboxPad(); 2197 //OutputDebugString("Minecraft::tick\n"); 2198 2199 //4J-PB - only tick this player's stats 2200 stats[iPad]->tick(iPad); 2201 2202 // Tick the opacity timer (to display the interface at default opacity for a certain time if the user has been navigating it) 2203 app.TickOpacityTimer(iPad); 2204 2205 // 4J added 2206 if( bFirst ) levelRenderer->destroyedTileManager->tick(); 2207 2208 gui->tick(); 2209 gameRenderer->pick(1); 2210#if 0 2211 // 4J - removed - we don't use ChunkCache anymore 2212 if (player != NULL) 2213 { 2214 ChunkSource *cs = level->getChunkSource(); 2215 if (dynamic_cast<ChunkCache *>(cs) != NULL) 2216 { 2217 ChunkCache *spcc = (ChunkCache *)cs; 2218 2219 // 4J - there was also Mth::floors on these ints but that seems superfluous 2220 int xt = ((int) player->x) >> 4; 2221 int zt = ((int) player->z) >> 4; 2222 spcc->centerOn(xt, zt); 2223 } 2224 } 2225#endif 2226 2227 // soundEngine.playMusicTick(); 2228 2229 if (!pause && level != NULL) gameMode->tick(); 2230 MemSect(31); 2231 glBindTexture(GL_TEXTURE_2D, textures->loadTexture(TN_TERRAIN)); //L"/terrain.png")); 2232 MemSect(0); 2233 if( bFirst ) 2234 { 2235 PIXBeginNamedEvent(0,"Texture tick"); 2236 if (!pause) textures->tick(bUpdateTextures); 2237 PIXEndNamedEvent(); 2238 } 2239 2240 /* 2241 * if (serverConnection != null && !(screen instanceof ErrorScreen)) { 2242 * if (!serverConnection.isConnected()) { 2243 * progressRenderer.progressStart("Connecting.."); 2244 * progressRenderer.progressStagePercentage(0); } else { 2245 * serverConnection.tick(); serverConnection.sendPosition(player); } } 2246 */ 2247 if (screen == NULL && player != NULL ) 2248 { 2249 if (player->getHealth() <= 0 && !ui.GetMenuDisplayed(iPad) ) 2250 { 2251 setScreen(NULL); 2252 } 2253 else if (player->isSleeping() && level != NULL && level->isClientSide) 2254 { 2255 // setScreen(new InBedChatScreen()); // 4J - TODO put back in 2256 } 2257 } 2258 else if (screen != NULL && (dynamic_cast<InBedChatScreen *>(screen)!=NULL) && !player->isSleeping()) 2259 { 2260 setScreen(NULL); 2261 } 2262 2263 if (screen != NULL) 2264 { 2265 player->missTime = 10000; 2266 player->lastClickTick[0] = ticks + 10000; 2267 player->lastClickTick[1] = ticks + 10000; 2268 } 2269 2270 if (screen != NULL) 2271 { 2272 screen->updateEvents(); 2273 if (screen != NULL) 2274 { 2275 screen->particles->tick(); 2276 screen->tick(); 2277 } 2278 } 2279 2280 if (screen == NULL && !ui.GetMenuDisplayed(iPad) ) 2281 { 2282 // 4J-PB - add some tooltips if required 2283 int iA=-1, iB=-1, iX, iY=IDS_CONTROLS_INVENTORY, iLT=-1, iRT=-1, iLB=-1, iRB=-1, iLS=-1, iRS=-1; 2284 2285 if(player->abilities.instabuild) 2286 { 2287 iX=IDS_TOOLTIPS_CREATIVE; 2288 } 2289 else 2290 { 2291 iX=IDS_CONTROLS_CRAFTING; 2292 } 2293 // control scheme remapping can move the Action button, so we need to check this 2294 int *piAction; 2295 int *piJump; 2296 int *piUse; 2297 int *piAlt; 2298 2299 unsigned int uiAction = InputManager.GetGameJoypadMaps(InputManager.GetJoypadMapVal( iPad ) ,MINECRAFT_ACTION_ACTION ); 2300 unsigned int uiJump = InputManager.GetGameJoypadMaps(InputManager.GetJoypadMapVal( iPad ) ,MINECRAFT_ACTION_JUMP ); 2301 unsigned int uiUse = InputManager.GetGameJoypadMaps(InputManager.GetJoypadMapVal( iPad ) ,MINECRAFT_ACTION_USE ); 2302 unsigned int uiAlt = InputManager.GetGameJoypadMaps(InputManager.GetJoypadMapVal( iPad ) ,MINECRAFT_ACTION_SNEAK_TOGGLE ); 2303 2304 // Also need to handle PS3 having swapped triggers/bumpers 2305 switch(uiAction) 2306 { 2307 case _360_JOY_BUTTON_RT: 2308 piAction=&iRT; 2309 break; 2310 case _360_JOY_BUTTON_LT: 2311 piAction=&iLT; 2312 break; 2313 case _360_JOY_BUTTON_LB: 2314 piAction=&iLB; 2315 break; 2316 case _360_JOY_BUTTON_RB: 2317 piAction=&iRB; 2318 break; 2319 case _360_JOY_BUTTON_A: 2320 default: 2321 piAction=&iA; 2322 break; 2323 } 2324 2325 switch(uiJump) 2326 { 2327 case _360_JOY_BUTTON_LT: 2328 piJump=&iLT; 2329 break; 2330 case _360_JOY_BUTTON_RT: 2331 piJump=&iRT; 2332 break; 2333 case _360_JOY_BUTTON_LB: 2334 piJump=&iLB; 2335 break; 2336 case _360_JOY_BUTTON_RB: 2337 piJump=&iRB; 2338 break; 2339 case _360_JOY_BUTTON_A: 2340 default: 2341 piJump=&iA; 2342 break; 2343 } 2344 2345 switch(uiUse) 2346 { 2347 case _360_JOY_BUTTON_LB: 2348 piUse=&iLB; 2349 break; 2350 case _360_JOY_BUTTON_RB: 2351 piUse=&iRB; 2352 break; 2353 case _360_JOY_BUTTON_LT: 2354 piUse=&iLT; 2355 break; 2356 case _360_JOY_BUTTON_RT: 2357 default: 2358 piUse=&iRT; 2359 break; 2360 } 2361 2362 switch(uiAlt) 2363 { 2364 default: 2365 case _360_JOY_BUTTON_LSTICK_RIGHT: 2366 piAlt=&iRS; 2367 break; 2368 2369 //TODO 2370 } 2371 2372 if (player->isUnderLiquid(Material::water)) 2373 { 2374 *piJump=IDS_TOOLTIPS_SWIMUP; 2375 } 2376 else 2377 { 2378 *piJump=-1; 2379 } 2380 2381 *piUse=-1; 2382 *piAction=-1; 2383 *piAlt=-1; 2384 2385 // 4J-PB another special case for when the player is sleeping in a bed 2386 if (player->isSleeping() && (level != NULL) && level->isClientSide) 2387 { 2388 *piUse=IDS_TOOLTIPS_WAKEUP; 2389 } 2390 else 2391 { 2392 if (player->isRiding()) 2393 { 2394 shared_ptr<Entity> mount = player->riding; 2395 2396 if ( mount->instanceof(eTYPE_MINECART) || mount->instanceof(eTYPE_BOAT) ) 2397 { 2398 *piAlt = IDS_TOOLTIPS_EXIT; 2399 } 2400 else 2401 { 2402 *piAlt = IDS_TOOLTIPS_DISMOUNT; 2403 } 2404 } 2405 2406 // no hit result, but we may have something in our hand that we can do something with 2407 shared_ptr<ItemInstance> itemInstance = player->inventory->getSelected(); 2408 2409 // 4J-JEV: Moved all this here to avoid having it in 3 different places. 2410 if (itemInstance) 2411 { 2412 // 4J-PB - very special case for boat and empty bucket and glass bottle and more 2413 bool bUseItem = gameMode->useItem(player, level, itemInstance, true); 2414 2415 switch (itemInstance->getItem()->id) 2416 { 2417 // food 2418 case Item::potatoBaked_Id: 2419 case Item::potato_Id: 2420 case Item::pumpkinPie_Id: 2421 case Item::potatoPoisonous_Id: 2422 case Item::carrotGolden_Id: 2423 case Item::carrots_Id: 2424 case Item::mushroomStew_Id: 2425 case Item::apple_Id: 2426 case Item::bread_Id: 2427 case Item::porkChop_raw_Id: 2428 case Item::porkChop_cooked_Id: 2429 case Item::apple_gold_Id: 2430 case Item::fish_raw_Id: 2431 case Item::fish_cooked_Id: 2432 case Item::cookie_Id: 2433 case Item::beef_cooked_Id: 2434 case Item::beef_raw_Id: 2435 case Item::chicken_cooked_Id: 2436 case Item::chicken_raw_Id: 2437 case Item::melon_Id: 2438 case Item::rotten_flesh_Id: 2439 case Item::spiderEye_Id: 2440 // Check that we are actually hungry so will eat this item 2441 { 2442 FoodItem *food = (FoodItem *)itemInstance->getItem(); 2443 if (food != NULL && food->canEat(player)) 2444 { 2445 *piUse=IDS_TOOLTIPS_EAT; 2446 } 2447 } 2448 break; 2449 2450 case Item::bucket_milk_Id: 2451 *piUse=IDS_TOOLTIPS_DRINK; 2452 break; 2453 2454 case Item::fishingRod_Id: // use 2455 case Item::emptyMap_Id: 2456 *piUse=IDS_TOOLTIPS_USE; 2457 break; 2458 2459 case Item::egg_Id: // throw 2460 case Item::snowBall_Id: 2461 *piUse=IDS_TOOLTIPS_THROW; 2462 break; 2463 2464 case Item::bow_Id: // draw or release 2465 if ( player->abilities.instabuild || player->inventory->hasResource(Item::arrow_Id) ) 2466 { 2467 if (player->isUsingItem()) *piUse=IDS_TOOLTIPS_RELEASE_BOW; 2468 else *piUse=IDS_TOOLTIPS_DRAW_BOW; 2469 } 2470 break; 2471 2472 case Item::sword_wood_Id: 2473 case Item::sword_stone_Id: 2474 case Item::sword_iron_Id: 2475 case Item::sword_diamond_Id: 2476 case Item::sword_gold_Id: 2477 *piUse=IDS_TOOLTIPS_BLOCK; 2478 break; 2479 2480 case Item::bucket_empty_Id: 2481 case Item::glassBottle_Id: 2482 if (bUseItem) *piUse=IDS_TOOLTIPS_COLLECT; 2483 break; 2484 2485 case Item::bucket_lava_Id: 2486 case Item::bucket_water_Id: 2487 *piUse=IDS_TOOLTIPS_EMPTY; 2488 break; 2489 2490 case Item::boat_Id: 2491 case Tile::waterLily_Id: 2492 if (bUseItem) *piUse=IDS_TOOLTIPS_PLACE; 2493 break; 2494 2495 case Item::potion_Id: 2496 if (bUseItem) 2497 { 2498 if (MACRO_POTION_IS_SPLASH(itemInstance->getAuxValue())) *piUse=IDS_TOOLTIPS_THROW; 2499 else *piUse=IDS_TOOLTIPS_DRINK; 2500 } 2501 break; 2502 2503 case Item::enderPearl_Id: 2504 if (bUseItem) *piUse=IDS_TOOLTIPS_THROW; 2505 break; 2506 2507 case Item::eyeOfEnder_Id: 2508 // This will only work if there is a stronghold in this dimension 2509 if ( bUseItem && (level->dimension->id==0) && level->getLevelData()->getHasStronghold() ) 2510 { 2511 *piUse=IDS_TOOLTIPS_THROW; 2512 } 2513 break; 2514 2515 case Item::expBottle_Id: 2516 if (bUseItem) *piUse=IDS_TOOLTIPS_THROW; 2517 break; 2518 } 2519 } 2520 2521 if (hitResult!=NULL) 2522 { 2523 switch(hitResult->type) 2524 { 2525 case HitResult::TILE: 2526 { 2527 int x,y,z; 2528 x=hitResult->x; 2529 y=hitResult->y; 2530 z=hitResult->z; 2531 int face = hitResult->f; 2532 2533 int iTileID=level->getTile(x,y ,z ); 2534 int iData = level->getData(x, y, z); 2535 2536 if( gameMode != NULL && gameMode->getTutorial() != NULL ) 2537 { 2538 // 4J Stu - For the tutorial we want to be able to record what items we look at so that we can give hints 2539 gameMode->getTutorial()->onLookAt(iTileID,iData); 2540 } 2541 2542 // 4J-PB - Call the useItemOn with the TestOnly flag set 2543 bool bUseItemOn=gameMode->useItemOn(player, level, itemInstance, x, y, z, face, hitResult->pos, true); 2544 2545 /* 4J-Jev: 2546 * Moved this here so we have item tooltips to fallback on 2547 * for noteblocks, enderportals and flowerpots in case of non-standard items. 2548 * (ie. ignite behaviour) 2549 */ 2550 if (bUseItemOn && itemInstance!=NULL) 2551 { 2552 switch (itemInstance->getItem()->id) 2553 { 2554 case Tile::mushroom_brown_Id: 2555 case Tile::mushroom_red_Id: 2556 case Tile::tallgrass_Id: 2557 case Tile::cactus_Id: 2558 case Tile::sapling_Id: 2559 case Tile::reeds_Id: 2560 case Tile::flower_Id: 2561 case Tile::rose_Id: 2562 *piUse=IDS_TOOLTIPS_PLANT; 2563 break; 2564 2565 // Things to USE 2566 case Item::hoe_wood_Id: 2567 case Item::hoe_stone_Id: 2568 case Item::hoe_iron_Id: 2569 case Item::hoe_diamond_Id: 2570 case Item::hoe_gold_Id: 2571 *piUse=IDS_TOOLTIPS_TILL; 2572 break; 2573 2574 case Item::seeds_wheat_Id: 2575 case Item::netherwart_seeds_Id: 2576 *piUse=IDS_TOOLTIPS_PLANT; 2577 break; 2578 2579 case Item::dye_powder_Id: 2580 // bonemeal grows various plants 2581 if (itemInstance->getAuxValue() == DyePowderItem::WHITE) 2582 { 2583 switch(iTileID) 2584 { 2585 case Tile::sapling_Id: 2586 case Tile::wheat_Id: 2587 case Tile::grass_Id: 2588 case Tile::mushroom_brown_Id: 2589 case Tile::mushroom_red_Id: 2590 case Tile::melonStem_Id: 2591 case Tile::pumpkinStem_Id: 2592 case Tile::carrots_Id: 2593 case Tile::potatoes_Id: 2594 *piUse=IDS_TOOLTIPS_GROW; 2595 break; 2596 } 2597 } 2598 break; 2599 2600 case Item::painting_Id: 2601 *piUse=IDS_TOOLTIPS_HANG; 2602 break; 2603 2604 case Item::flintAndSteel_Id: 2605 case Item::fireball_Id: 2606 *piUse=IDS_TOOLTIPS_IGNITE; 2607 break; 2608 2609 case Item::fireworks_Id: 2610 *piUse=IDS_TOOLTIPS_FIREWORK_LAUNCH; 2611 break; 2612 2613 case Item::lead_Id: 2614 *piUse=IDS_TOOLTIPS_ATTACH; 2615 break; 2616 2617 default: 2618 *piUse=IDS_TOOLTIPS_PLACE; 2619 break; 2620 } 2621 } 2622 2623 switch(iTileID) 2624 { 2625 case Tile::anvil_Id: 2626 case Tile::enchantTable_Id: 2627 case Tile::brewingStand_Id: 2628 case Tile::workBench_Id: 2629 case Tile::furnace_Id: 2630 case Tile::furnace_lit_Id: 2631 case Tile::door_wood_Id: 2632 case Tile::dispenser_Id: 2633 case Tile::lever_Id: 2634 case Tile::button_stone_Id: 2635 case Tile::button_wood_Id: 2636 case Tile::trapdoor_Id: 2637 case Tile::fenceGate_Id: 2638 case Tile::beacon_Id: 2639 *piAction=IDS_TOOLTIPS_MINE; 2640 *piUse=IDS_TOOLTIPS_USE; 2641 break; 2642 2643 case Tile::chest_Id: 2644 *piAction = IDS_TOOLTIPS_MINE; 2645 *piUse = (Tile::chest->getContainer(level,x,y,z) != NULL) ? IDS_TOOLTIPS_OPEN : -1; 2646 break; 2647 2648 case Tile::enderChest_Id: 2649 case Tile::chest_trap_Id: 2650 case Tile::dropper_Id: 2651 case Tile::hopper_Id: 2652 *piUse=IDS_TOOLTIPS_OPEN; 2653 *piAction=IDS_TOOLTIPS_MINE; 2654 break; 2655 2656 case Tile::activatorRail_Id: 2657 case Tile::goldenRail_Id: 2658 case Tile::detectorRail_Id: 2659 case Tile::rail_Id: 2660 if (bUseItemOn) *piUse=IDS_TOOLTIPS_PLACE; 2661 *piAction=IDS_TOOLTIPS_MINE; 2662 break; 2663 2664 case Tile::bed_Id: 2665 if (bUseItemOn) *piUse=IDS_TOOLTIPS_SLEEP; 2666 *piAction=IDS_TOOLTIPS_MINE; 2667 break; 2668 2669 case Tile::noteblock_Id: 2670 // if in creative mode, we will mine 2671 if (player->abilities.instabuild) *piAction=IDS_TOOLTIPS_MINE; 2672 else *piAction=IDS_TOOLTIPS_PLAY; 2673 *piUse=IDS_TOOLTIPS_CHANGEPITCH; 2674 break; 2675 2676 case Tile::sign_Id: 2677 *piAction=IDS_TOOLTIPS_MINE; 2678 break; 2679 2680 case Tile::cauldron_Id: 2681 // special case for a cauldron of water and an empty bottle 2682 if (itemInstance) 2683 { 2684 int iID=itemInstance->getItem()->id; 2685 int currentData = level->getData(x, y, z); 2686 if ((iID==Item::glassBottle_Id) && (currentData > 0)) 2687 { 2688 *piUse=IDS_TOOLTIPS_COLLECT; 2689 } 2690 } 2691 *piAction=IDS_TOOLTIPS_MINE; 2692 break; 2693 2694 case Tile::cake_Id: 2695 if (player->abilities.instabuild) // if in creative mode, we will mine 2696 { 2697 *piAction=IDS_TOOLTIPS_MINE; 2698 } 2699 else 2700 { 2701 if (player->getFoodData()->needsFood() ) // 4J-JEV: Changed from healthto hunger. 2702 { 2703 *piAction=IDS_TOOLTIPS_EAT; 2704 *piUse=IDS_TOOLTIPS_EAT; 2705 } 2706 else 2707 { 2708 *piAction=IDS_TOOLTIPS_MINE; 2709 } 2710 } 2711 break; 2712 2713 case Tile::jukebox_Id: 2714 if (!bUseItemOn && itemInstance!=NULL) 2715 { 2716 int iID=itemInstance->getItem()->id; 2717 if ( (iID>=Item::record_01_Id) && (iID<=Item::record_12_Id) ) 2718 { 2719 *piUse=IDS_TOOLTIPS_PLAY; 2720 } 2721 *piAction=IDS_TOOLTIPS_MINE; 2722 } 2723 else 2724 { 2725 if (Tile::jukebox->TestUse(level, x, y, z, player)) // means we can eject 2726 { 2727 *piUse=IDS_TOOLTIPS_EJECT; 2728 } 2729 *piAction=IDS_TOOLTIPS_MINE; 2730 } 2731 break; 2732 2733 case Tile::flowerPot_Id: 2734 if ( !bUseItemOn && (itemInstance != NULL) && (iData == 0) ) 2735 { 2736 int iID = itemInstance->getItem()->id; 2737 if (iID<256) // is it a tile? 2738 { 2739 switch(iID) 2740 { 2741 case Tile::flower_Id: 2742 case Tile::rose_Id: 2743 case Tile::sapling_Id: 2744 case Tile::mushroom_brown_Id: 2745 case Tile::mushroom_red_Id: 2746 case Tile::cactus_Id: 2747 case Tile::deadBush_Id: 2748 *piUse=IDS_TOOLTIPS_PLANT; 2749 break; 2750 2751 case Tile::tallgrass_Id: 2752 if (itemInstance->getAuxValue() != TallGrass::TALL_GRASS) *piUse=IDS_TOOLTIPS_PLANT; 2753 break; 2754 } 2755 } 2756 } 2757 *piAction=IDS_TOOLTIPS_MINE; 2758 break; 2759 2760 case Tile::comparator_off_Id: 2761 case Tile::comparator_on_Id: 2762 *piUse=IDS_TOOLTIPS_USE; 2763 *piAction=IDS_TOOLTIPS_MINE; 2764 break; 2765 2766 case Tile::diode_off_Id: 2767 case Tile::diode_on_Id: 2768 *piUse=IDS_TOOLTIPS_USE; 2769 *piAction=IDS_TOOLTIPS_MINE; 2770 break; 2771 2772 case Tile::redStoneOre_Id: 2773 if (bUseItemOn) *piUse=IDS_TOOLTIPS_USE; 2774 *piAction=IDS_TOOLTIPS_MINE; 2775 break; 2776 2777 case Tile::door_iron_Id: 2778 if(*piUse==IDS_TOOLTIPS_PLACE) 2779 { 2780 *piUse = -1; 2781 } 2782 *piAction=IDS_TOOLTIPS_MINE; 2783 break; 2784 2785 default: 2786 *piAction=IDS_TOOLTIPS_MINE; 2787 break; 2788 } 2789 } 2790 break; 2791 2792 case HitResult::ENTITY: 2793 eINSTANCEOF entityType = hitResult->entity->GetType(); 2794 2795 if ( (gameMode != NULL) && (gameMode->getTutorial() != NULL) ) 2796 { 2797 // 4J Stu - For the tutorial we want to be able to record what items we look at so that we can give hints 2798 gameMode->getTutorial()->onLookAtEntity(hitResult->entity); 2799 } 2800 2801 shared_ptr<ItemInstance> heldItem = nullptr; 2802 if (player->inventory->IsHeldItem()) 2803 { 2804 heldItem = player->inventory->getSelected(); 2805 } 2806 int heldItemId = heldItem != NULL ? heldItem->getItem()->id : -1; 2807 2808 switch(entityType) 2809 { 2810 case eTYPE_CHICKEN: 2811 { 2812 if(player->isAllowedToAttackAnimals()) *piAction=IDS_TOOLTIPS_HIT; 2813 2814 shared_ptr<Animal> animal = dynamic_pointer_cast<Animal>(hitResult->entity); 2815 2816 if (animal->isLeashed() && animal->getLeashHolder() == player) 2817 { 2818 *piUse=IDS_TOOLTIPS_UNLEASH; 2819 break; 2820 } 2821 2822 switch(heldItemId) 2823 { 2824 case Item::nameTag_Id: 2825 *piUse=IDS_TOOLTIPS_NAME; 2826 break; 2827 2828 case Item::lead_Id: 2829 if (!animal->isLeashed()) *piUse=IDS_TOOLTIPS_LEASH; 2830 break; 2831 2832 default: 2833 { 2834 if(!animal->isBaby() && !animal->isInLove() && (animal->getAge() == 0) && animal->isFood(heldItem)) 2835 { 2836 *piUse=IDS_TOOLTIPS_LOVEMODE; 2837 } 2838 } 2839 break; 2840 2841 case -1: break; // 4J-JEV: Empty hand. 2842 } 2843 } 2844 break; 2845 2846 case eTYPE_COW: 2847 { 2848 if(player->isAllowedToAttackAnimals()) *piAction=IDS_TOOLTIPS_HIT; 2849 2850 shared_ptr<Animal> animal = dynamic_pointer_cast<Animal>(hitResult->entity); 2851 2852 if (animal->isLeashed() && animal->getLeashHolder() == player) 2853 { 2854 *piUse=IDS_TOOLTIPS_UNLEASH; 2855 break; 2856 } 2857 2858 switch (heldItemId) 2859 { 2860 // Things to USE 2861 case Item::nameTag_Id: 2862 *piUse=IDS_TOOLTIPS_NAME; 2863 break; 2864 case Item::lead_Id: 2865 if (!animal->isLeashed()) *piUse=IDS_TOOLTIPS_LEASH; 2866 break; 2867 case Item::bucket_empty_Id: 2868 *piUse=IDS_TOOLTIPS_MILK; 2869 break; 2870 default: 2871 { 2872 if(!animal->isBaby() && !animal->isInLove() && (animal->getAge() == 0) && animal->isFood(heldItem)) 2873 { 2874 *piUse=IDS_TOOLTIPS_LOVEMODE; 2875 } 2876 } 2877 break; 2878 2879 case -1: break; // 4J-JEV: Empty hand. 2880 } 2881 } 2882 break; 2883 case eTYPE_MUSHROOMCOW: 2884 { 2885 // 4J-PB - Fix for #13081 - No tooltip is displayed for hitting a cow when you have nothing in your hand 2886 if(player->isAllowedToAttackAnimals()) *piAction=IDS_TOOLTIPS_HIT; 2887 2888 shared_ptr<Animal> animal = dynamic_pointer_cast<Animal>(hitResult->entity); 2889 2890 if (animal->isLeashed() && animal->getLeashHolder() == player) 2891 { 2892 *piUse=IDS_TOOLTIPS_UNLEASH; 2893 break; 2894 } 2895 2896 // It's an item 2897 switch(heldItemId) 2898 { 2899 // Things to USE 2900 case Item::nameTag_Id: 2901 *piUse=IDS_TOOLTIPS_NAME; 2902 break; 2903 2904 case Item::lead_Id: 2905 if (!animal->isLeashed()) *piUse=IDS_TOOLTIPS_LEASH; 2906 break; 2907 2908 case Item::bowl_Id: 2909 case Item::bucket_empty_Id: // You can milk a mooshroom with either a bowl (mushroom soup) or a bucket (milk)! 2910 *piUse=IDS_TOOLTIPS_MILK; 2911 break; 2912 case Item::shears_Id: 2913 { 2914 if(player->isAllowedToAttackAnimals()) *piAction=IDS_TOOLTIPS_HIT; 2915 if(!animal->isBaby()) *piUse=IDS_TOOLTIPS_SHEAR; 2916 } 2917 break; 2918 default: 2919 { 2920 if(!animal->isBaby() && !animal->isInLove() && (animal->getAge() == 0) && animal->isFood(heldItem)) 2921 { 2922 *piUse=IDS_TOOLTIPS_LOVEMODE; 2923 } 2924 } 2925 break; 2926 2927 case -1: break; // 4J-JEV: Empty hand. 2928 } 2929 } 2930 break; 2931 2932 case eTYPE_BOAT: 2933 *piAction=IDS_TOOLTIPS_MINE; 2934 *piUse=IDS_TOOLTIPS_SAIL; 2935 break; 2936 2937 case eTYPE_MINECART_RIDEABLE: 2938 *piAction = IDS_TOOLTIPS_MINE; 2939 *piUse = IDS_TOOLTIPS_RIDE; // are we in the minecart already? - 4J-JEV: Doesn't matter anymore. 2940 break; 2941 2942 case eTYPE_MINECART_FURNACE: 2943 *piAction = IDS_TOOLTIPS_MINE; 2944 2945 // if you have coal, it'll go. Is there an object in hand? 2946 if (heldItemId == Item::coal_Id) *piUse=IDS_TOOLTIPS_USE; 2947 break; 2948 2949 case eTYPE_MINECART_CHEST: 2950 case eTYPE_MINECART_HOPPER: 2951 *piAction = IDS_TOOLTIPS_MINE; 2952 *piUse = IDS_TOOLTIPS_OPEN; 2953 break; 2954 2955 case eTYPE_MINECART_SPAWNER: 2956 case eTYPE_MINECART_TNT: 2957 *piUse = IDS_TOOLTIPS_MINE; 2958 break; 2959 2960 case eTYPE_SHEEP: 2961 { 2962 // can dye a sheep 2963 if(player->isAllowedToAttackAnimals()) *piAction=IDS_TOOLTIPS_HIT; 2964 2965 shared_ptr<Sheep> sheep = dynamic_pointer_cast<Sheep>(hitResult->entity); 2966 2967 if (sheep->isLeashed() && sheep->getLeashHolder() == player) 2968 { 2969 *piUse=IDS_TOOLTIPS_UNLEASH; 2970 break; 2971 } 2972 2973 switch(heldItemId) 2974 { 2975 case Item::nameTag_Id: 2976 *piUse=IDS_TOOLTIPS_NAME; 2977 break; 2978 2979 case Item::lead_Id: 2980 if (!sheep->isLeashed()) *piUse=IDS_TOOLTIPS_LEASH; 2981 break; 2982 2983 case Item::dye_powder_Id: 2984 { 2985 // convert to tile-based color value (0 is white instead of black) 2986 int newColor = ColoredTile::getTileDataForItemAuxValue(heldItem->getAuxValue()); 2987 2988 // can only use a dye on sheep that haven't been sheared 2989 if(!(sheep->isSheared() && sheep->getColor() != newColor)) 2990 { 2991 *piUse=IDS_TOOLTIPS_DYE; 2992 } 2993 } 2994 break; 2995 case Item::shears_Id: 2996 { 2997 // can only shear a sheep that hasn't been sheared 2998 if ( !sheep->isBaby() && !sheep->isSheared() ) 2999 { 3000 *piUse=IDS_TOOLTIPS_SHEAR; 3001 } 3002 } 3003 3004 break; 3005 default: 3006 { 3007 if(!sheep->isBaby() && !sheep->isInLove() && (sheep->getAge() == 0) && sheep->isFood(heldItem)) 3008 { 3009 *piUse=IDS_TOOLTIPS_LOVEMODE; 3010 } 3011 } 3012 break; 3013 3014 case -1: break; // 4J-JEV: Empty hand. 3015 } 3016 } 3017 break; 3018 3019 case eTYPE_PIG: 3020 { 3021 // can ride a pig 3022 if(player->isAllowedToAttackAnimals()) *piAction=IDS_TOOLTIPS_HIT; 3023 3024 shared_ptr<Pig> pig = dynamic_pointer_cast<Pig>(hitResult->entity); 3025 3026 if (pig->isLeashed() && pig->getLeashHolder() == player) 3027 { 3028 *piUse=IDS_TOOLTIPS_UNLEASH; 3029 } 3030 else if (heldItemId == Item::lead_Id) 3031 { 3032 if (!pig->isLeashed()) *piUse=IDS_TOOLTIPS_LEASH; 3033 } 3034 else if (heldItemId == Item::nameTag_Id) 3035 { 3036 *piUse = IDS_TOOLTIPS_NAME; 3037 } 3038 else if (pig->hasSaddle()) // does the pig have a saddle? 3039 { 3040 *piUse=IDS_TOOLTIPS_MOUNT; 3041 } 3042 else if (!pig->isBaby()) 3043 { 3044 if(player->inventory->IsHeldItem()) 3045 { 3046 switch(heldItemId) 3047 { 3048 case Item::saddle_Id: 3049 *piUse=IDS_TOOLTIPS_SADDLE; 3050 break; 3051 3052 default: 3053 { 3054 if (!pig->isInLove() && (pig->getAge() == 0) && pig->isFood(heldItem)) 3055 { 3056 *piUse=IDS_TOOLTIPS_LOVEMODE; 3057 } 3058 } 3059 break; 3060 } 3061 } 3062 } 3063 } 3064 break; 3065 3066 case eTYPE_WOLF: 3067 // can be tamed, fed, and made to sit/stand, or enter love mode 3068 { 3069 shared_ptr<Wolf> wolf = dynamic_pointer_cast<Wolf>(hitResult->entity); 3070 3071 if(player->isAllowedToAttackAnimals()) *piAction=IDS_TOOLTIPS_HIT; 3072 3073 if (wolf->isLeashed() && wolf->getLeashHolder() == player) 3074 { 3075 *piUse=IDS_TOOLTIPS_UNLEASH; 3076 break; 3077 } 3078 3079 switch(heldItemId) 3080 { 3081 case Item::nameTag_Id: 3082 *piUse=IDS_TOOLTIPS_NAME; 3083 break; 3084 3085 case Item::lead_Id: 3086 if (!wolf->isLeashed()) *piUse=IDS_TOOLTIPS_LEASH; 3087 break; 3088 3089 case Item::bone_Id: 3090 if (!wolf->isAngry() && !wolf->isTame()) 3091 { 3092 *piUse=IDS_TOOLTIPS_TAME; 3093 } 3094 else if (equalsIgnoreCase(player->getUUID(), wolf->getOwnerUUID())) 3095 { 3096 if(wolf->isSitting()) 3097 { 3098 *piUse=IDS_TOOLTIPS_FOLLOWME; 3099 } 3100 else 3101 { 3102 *piUse=IDS_TOOLTIPS_SIT; 3103 } 3104 } 3105 3106 break; 3107 case Item::enderPearl_Id: 3108 // Use is throw, so don't change the tips for the wolf 3109 break; 3110 case Item::dye_powder_Id: 3111 if (wolf->isTame()) 3112 { 3113 if (ColoredTile::getTileDataForItemAuxValue(heldItem->getAuxValue()) != wolf->getCollarColor()) 3114 { 3115 *piUse=IDS_TOOLTIPS_DYECOLLAR; 3116 } 3117 else if (wolf->isSitting()) 3118 { 3119 *piUse=IDS_TOOLTIPS_FOLLOWME; 3120 } 3121 else 3122 { 3123 *piUse=IDS_TOOLTIPS_SIT; 3124 } 3125 } 3126 break; 3127 default: 3128 if(wolf->isTame()) 3129 { 3130 if(wolf->isFood(heldItem)) 3131 { 3132 if(wolf->GetSynchedHealth() < wolf->getMaxHealth()) 3133 { 3134 *piUse=IDS_TOOLTIPS_HEAL; 3135 } 3136 else 3137 { 3138 if(!wolf->isBaby() && !wolf->isInLove() && (wolf->getAge() == 0)) 3139 { 3140 *piUse=IDS_TOOLTIPS_LOVEMODE; 3141 } 3142 } 3143 // break out here 3144 break; 3145 } 3146 3147 if (equalsIgnoreCase(player->getUUID(), wolf->getOwnerUUID())) 3148 { 3149 if(wolf->isSitting()) 3150 { 3151 *piUse=IDS_TOOLTIPS_FOLLOWME; 3152 } 3153 else 3154 { 3155 *piUse=IDS_TOOLTIPS_SIT; 3156 } 3157 } 3158 } 3159 break; 3160 } 3161 } 3162 break; 3163 case eTYPE_OCELOT: 3164 { 3165 shared_ptr<Ocelot> ocelot = dynamic_pointer_cast<Ocelot>(hitResult->entity); 3166 3167 if(player->isAllowedToAttackAnimals()) *piAction=IDS_TOOLTIPS_HIT; 3168 3169 if (ocelot->isLeashed() && ocelot->getLeashHolder() == player) 3170 { 3171 *piUse = IDS_TOOLTIPS_UNLEASH; 3172 } 3173 else if (heldItemId == Item::lead_Id) 3174 { 3175 if (!ocelot->isLeashed()) *piUse = IDS_TOOLTIPS_LEASH; 3176 } 3177 else if (heldItemId == Item::nameTag_Id) 3178 { 3179 *piUse = IDS_TOOLTIPS_NAME; 3180 } 3181 else if(ocelot->isTame()) 3182 { 3183 // 4J-PB - if you have a raw fish in your hand, you will feed the ocelot rather than have it sit/follow 3184 if(ocelot->isFood(heldItem)) 3185 { 3186 if(!ocelot->isBaby()) 3187 { 3188 if(!ocelot->isInLove()) 3189 { 3190 if(ocelot->getAge() == 0) 3191 { 3192 *piUse=IDS_TOOLTIPS_LOVEMODE; 3193 } 3194 } 3195 else 3196 { 3197 *piUse=IDS_TOOLTIPS_FEED; 3198 } 3199 } 3200 3201 } 3202 else if (equalsIgnoreCase(player->getUUID(), ocelot->getOwnerUUID()) && !ocelot->isSittingOnTile() ) 3203 { 3204 if(ocelot->isSitting()) 3205 { 3206 *piUse=IDS_TOOLTIPS_FOLLOWME; 3207 } 3208 else 3209 { 3210 *piUse=IDS_TOOLTIPS_SIT; 3211 } 3212 } 3213 } 3214 else if(heldItemId >= 0) 3215 { 3216 if (ocelot->isFood(heldItem)) *piUse=IDS_TOOLTIPS_TAME; 3217 } 3218 } 3219 break; 3220 3221 case eTYPE_PLAYER: 3222 { 3223 // Fix for #58576 - TU6: Content: Gameplay: Hit button prompt is available when attacking a host who has "Invisible" option turned on 3224 shared_ptr<Player> TargetPlayer = dynamic_pointer_cast<Player>(hitResult->entity); 3225 3226 if(!TargetPlayer->hasInvisiblePrivilege()) // This means they are invisible, not just that they have the privilege 3227 { 3228 if( app.GetGameHostOption(eGameHostOption_PvP) && player->isAllowedToAttackPlayers()) 3229 { 3230 *piAction=IDS_TOOLTIPS_HIT; 3231 } 3232 } 3233 } 3234 break; 3235 3236 case eTYPE_ITEM_FRAME: 3237 { 3238 shared_ptr<ItemFrame> itemFrame = dynamic_pointer_cast<ItemFrame>(hitResult->entity); 3239 3240 // is the frame occupied? 3241 if(itemFrame->getItem()!=NULL) 3242 { 3243 // rotate the item 3244 *piUse=IDS_TOOLTIPS_ROTATE; 3245 } 3246 else 3247 { 3248 // is there an object in hand? 3249 if(heldItemId >= 0) *piUse=IDS_TOOLTIPS_PLACE; 3250 } 3251 3252 *piAction=IDS_TOOLTIPS_HIT; 3253 } 3254 break; 3255 3256 case eTYPE_VILLAGER: 3257 { 3258 // 4J-JEV: Cannot leash villagers. 3259 3260 shared_ptr<Villager> villager = dynamic_pointer_cast<Villager>(hitResult->entity); 3261 if (!villager->isBaby()) 3262 { 3263 *piUse=IDS_TOOLTIPS_TRADE; 3264 } 3265 *piAction=IDS_TOOLTIPS_HIT; 3266 } 3267 break; 3268 3269 case eTYPE_ZOMBIE: 3270 { 3271 shared_ptr<Zombie> zomb = dynamic_pointer_cast<Zombie>(hitResult->entity); 3272 static GoldenAppleItem *goldapple = (GoldenAppleItem *) Item::apple_gold; 3273 3274 //zomb->hasEffect(MobEffect::weakness) - not present on client. 3275 if ( zomb->isVillager() && zomb->isWeakened() && (heldItemId == Item::apple_gold_Id) && !goldapple->isFoil(heldItem) ) 3276 { 3277 *piUse=IDS_TOOLTIPS_CURE; 3278 } 3279 *piAction=IDS_TOOLTIPS_HIT; 3280 } 3281 break; 3282 3283 case eTYPE_HORSE: 3284 { 3285 shared_ptr<EntityHorse> horse = dynamic_pointer_cast<EntityHorse>(hitResult->entity); 3286 3287 bool heldItemIsFood = false, heldItemIsLove = false, heldItemIsArmour = false; 3288 3289 switch( heldItemId ) 3290 { 3291 case Item::wheat_Id: 3292 case Item::sugar_Id: 3293 case Item::bread_Id: 3294 case Tile::hayBlock_Id: 3295 case Item::apple_Id: 3296 heldItemIsFood = true; 3297 break; 3298 case Item::carrotGolden_Id: 3299 case Item::apple_gold_Id: 3300 heldItemIsLove = true; 3301 heldItemIsFood = true; 3302 break; 3303 case Item::horseArmorDiamond_Id: 3304 case Item::horseArmorGold_Id: 3305 case Item::horseArmorMetal_Id: 3306 heldItemIsArmour = true; 3307 break; 3308 } 3309 3310 if (horse->isLeashed() && horse->getLeashHolder() == player) 3311 { 3312 *piUse=IDS_TOOLTIPS_UNLEASH; 3313 } 3314 else if ( heldItemId == Item::lead_Id) 3315 { 3316 if (!horse->isLeashed()) *piUse=IDS_TOOLTIPS_LEASH; 3317 } 3318 else if (heldItemId == Item::nameTag_Id) 3319 { 3320 *piUse = IDS_TOOLTIPS_NAME; 3321 } 3322 else if (horse->isBaby()) // 4J-JEV: Can't ride baby horses due to morals. 3323 { 3324 if (heldItemIsFood) 3325 { 3326 // 4j - Can feed foles to speed growth. 3327 *piUse = IDS_TOOLTIPS_FEED; 3328 } 3329 } 3330 else if ( !horse->isTamed() ) 3331 { 3332 if (heldItemId == -1) 3333 { 3334 // 4j - Player not holding anything, ride and attempt to break untamed horse. 3335 *piUse = IDS_TOOLTIPS_TAME; 3336 } 3337 else if (heldItemIsFood) 3338 { 3339 // 4j - Attempt to make it like you more by feeding it. 3340 *piUse = IDS_TOOLTIPS_FEED; 3341 } 3342 } 3343 else if ( player->isSneaking() 3344 || (heldItemId == Item::saddle_Id) 3345 || (horse->canWearArmor() && heldItemIsArmour) 3346 ) 3347 { 3348 // 4j - Access horses inventory 3349 if (*piUse == -1) *piUse = IDS_TOOLTIPS_OPEN; 3350 } 3351 else if ( horse->canWearBags() 3352 && !horse->isChestedHorse() 3353 && (heldItemId == Tile::chest_Id) ) 3354 { 3355 // 4j - Attach saddle-bags (chest) to donkey or mule. 3356 *piUse = IDS_TOOLTIPS_ATTACH; 3357 } 3358 else if ( horse->isReadyForParenting() 3359 && heldItemIsLove ) 3360 { 3361 // 4j - Different food to mate horses. 3362 *piUse = IDS_TOOLTIPS_LOVEMODE; 3363 } 3364 else if ( heldItemIsFood && (horse->getHealth() < horse->getMaxHealth()) ) 3365 { 3366 // 4j - Horse is damaged and can eat held item to heal 3367 *piUse = IDS_TOOLTIPS_HEAL; 3368 } 3369 else 3370 { 3371 // 4j - Ride tamed horse. 3372 *piUse = IDS_TOOLTIPS_MOUNT; 3373 } 3374 3375 if (player->isAllowedToAttackAnimals()) *piAction=IDS_TOOLTIPS_HIT; 3376 } 3377 break; 3378 3379 case eTYPE_ENDERDRAGON: 3380 // 4J-JEV: Enderdragon cannot be named. 3381 *piAction = IDS_TOOLTIPS_HIT; 3382 break; 3383 3384 case eTYPE_LEASHFENCEKNOT: 3385 *piAction = IDS_TOOLTIPS_UNLEASH; 3386 if (heldItemId == Item::lead_Id && LeashItem::bindPlayerMobsTest(player, level, player->x, player->y, player->z)) 3387 { 3388 *piUse = IDS_TOOLTIPS_ATTACH; 3389 } 3390 else 3391 { 3392 *piUse = IDS_TOOLTIPS_UNLEASH; 3393 } 3394 break; 3395 3396 default: 3397 if ( hitResult->entity->instanceof(eTYPE_MOB) ) 3398 { 3399 shared_ptr<Mob> mob = dynamic_pointer_cast<Mob>(hitResult->entity); 3400 if (mob->isLeashed() && mob->getLeashHolder() == player) 3401 { 3402 *piUse=IDS_TOOLTIPS_UNLEASH; 3403 } 3404 else if (heldItemId == Item::lead_Id) 3405 { 3406 if (!mob->isLeashed()) *piUse=IDS_TOOLTIPS_LEASH; 3407 } 3408 else if (heldItemId == Item::nameTag_Id) 3409 { 3410 *piUse=IDS_TOOLTIPS_NAME; 3411 } 3412 } 3413 *piAction=IDS_TOOLTIPS_HIT; 3414 break; 3415 } 3416 break; 3417 } 3418 } 3419 } 3420 3421 // 4J-JEV: Don't set tooltips when we're reloading the skin, it'll crash. 3422 if (!ui.IsReloadingSkin()) ui.SetTooltips( iPad, iA, iB, iX, iY, iLT, iRT, iLB, iRB, iLS, iRS); 3423 3424 int wheel = 0; 3425 if (InputManager.GetValue(iPad, MINECRAFT_ACTION_LEFT_SCROLL, true) > 0 && gameMode->isInputAllowed(MINECRAFT_ACTION_LEFT_SCROLL) ) 3426 { 3427 wheel = 1; 3428 } 3429 else if (InputManager.GetValue(iPad, MINECRAFT_ACTION_RIGHT_SCROLL,true) > 0 && gameMode->isInputAllowed(MINECRAFT_ACTION_RIGHT_SCROLL) ) 3430 { 3431 wheel = -1; 3432 } 3433 3434#ifdef _WINDOWS64 3435 // Mouse scroll wheel for hotbar 3436 if (iPad == 0) 3437 { 3438 int kbWheel = KMInput.ConsumeScrollDelta(); 3439 if (kbWheel > 0 && gameMode->isInputAllowed(MINECRAFT_ACTION_LEFT_SCROLL)) wheel += 1; 3440 else if (kbWheel < 0 && gameMode->isInputAllowed(MINECRAFT_ACTION_RIGHT_SCROLL)) wheel -= 1; 3441 3442 // 1-9 keys for direct hotbar selection 3443 if (gameMode->isInputAllowed(MINECRAFT_ACTION_LEFT_SCROLL)) 3444 { 3445 for (int k = '1'; k <= '9'; k++) 3446 { 3447 if (KMInput.ConsumeKeyPress(k)) 3448 { 3449 player->inventory->selected = k - '1'; 3450 app.SetOpacityTimer(iPad); 3451 break; 3452 } 3453 } 3454 } 3455 } 3456#endif 3457 if (wheel != 0) 3458 { 3459 player->inventory->swapPaint(wheel); 3460 3461 if( gameMode != NULL && gameMode->getTutorial() != NULL ) 3462 { 3463 // 4J Stu - For the tutorial we want to be able to record what items we are using so that we can give hints 3464 gameMode->getTutorial()->onSelectedItemChanged(player->inventory->getSelected()); 3465 } 3466 3467 // Update presence 3468 player->updateRichPresence(); 3469 3470 if (options->isFlying) 3471 { 3472 if (wheel > 0) wheel = 1; 3473 if (wheel < 0) wheel = -1; 3474 3475 options->flySpeed += wheel * .25f; 3476 } 3477 } 3478 3479 if( gameMode->isInputAllowed(MINECRAFT_ACTION_ACTION) ) 3480 { 3481 if((player->ullButtonsPressed&(1LL<<MINECRAFT_ACTION_ACTION))) 3482 //if(InputManager.ButtonPressed(iPad, MINECRAFT_ACTION_ACTION) ) 3483 { 3484 //printf("MINECRAFT_ACTION_ACTION ButtonPressed"); 3485 player->handleMouseClick(0); 3486 player->lastClickTick[0] = ticks; 3487 } 3488#ifdef _WINDOWS64 3489 else if (iPad == 0 && KMInput.IsCaptured() && KMInput.ConsumeMousePress(0)) 3490 { 3491 player->handleMouseClick(0); 3492 player->lastClickTick[0] = ticks; 3493 } 3494#endif 3495 3496 if (InputManager.ButtonDown(iPad, MINECRAFT_ACTION_ACTION) && ticks - player->lastClickTick[0] >= timer->ticksPerSecond / 4) 3497 { 3498 //printf("MINECRAFT_ACTION_ACTION ButtonDown"); 3499 player->handleMouseClick(0); 3500 player->lastClickTick[0] = ticks; 3501 } 3502#ifdef _WINDOWS64 3503 else if (iPad == 0 && KMInput.IsCaptured() && KMInput.IsMouseDown(0) && ticks - player->lastClickTick[0] >= timer->ticksPerSecond / 4) 3504 { 3505 player->handleMouseClick(0); 3506 player->lastClickTick[0] = ticks; 3507 } 3508#endif 3509 3510 if(InputManager.ButtonDown(iPad, MINECRAFT_ACTION_ACTION) 3511#ifdef _WINDOWS64 3512 || (iPad == 0 && KMInput.IsCaptured() && KMInput.IsMouseDown(0)) 3513#endif 3514 ) 3515 { 3516 player->handleMouseDown(0, true ); 3517 } 3518 else 3519 { 3520 player->handleMouseDown(0, false ); 3521 } 3522 } 3523 3524 // 4J Stu - This is how we used to handle the USE action. It has now been replaced with the block below which is more like the way the Java game does it, 3525 // however we may find that the way we had it previously is more fun to play. 3526 /* 3527 if ((InputManager.GetValue(iPad, MINECRAFT_ACTION_USE,true)>0) && gameMode->isInputAllowed(MINECRAFT_ACTION_USE) ) 3528 { 3529 handleMouseClick(1); 3530 lastClickTick = ticks; 3531 } 3532 */ 3533 if( player->isUsingItem() ) 3534 { 3535 if(!InputManager.ButtonDown(iPad, MINECRAFT_ACTION_USE) 3536#ifdef _WINDOWS64 3537 && !(iPad == 0 && KMInput.IsCaptured() && KMInput.IsMouseDown(1)) 3538#endif 3539 ) gameMode->releaseUsingItem(player); 3540 } 3541 else if( gameMode->isInputAllowed(MINECRAFT_ACTION_USE) ) 3542 { 3543#ifdef _WINDOWS64 3544 bool useButtonDown = InputManager.ButtonDown(iPad, MINECRAFT_ACTION_USE) || (iPad == 0 && KMInput.IsCaptured() && KMInput.IsMouseDown(1)); 3545#else 3546 bool useButtonDown = InputManager.ButtonDown(iPad, MINECRAFT_ACTION_USE); 3547#endif 3548 if( player->abilities.instabuild ) 3549 { 3550 // 4J - attempt to handle click in special creative mode fashion if possible (used for placing blocks at regular intervals) 3551 bool didClick = player->creativeModeHandleMouseClick(1, useButtonDown ); 3552 // If this handler has put us in lastClick_oldRepeat mode then it is because we aren't placing blocks - behave largely as the code used to 3553 if( player->lastClickState == LocalPlayer::lastClick_oldRepeat ) 3554 { 3555 // If we've already handled the click in creativeModeHandleMouseClick then just record the time of this click 3556 if( didClick ) 3557 { 3558 player->lastClickTick[1] = ticks; 3559 } 3560 else 3561 { 3562 // Otherwise just the original game code for handling autorepeat 3563 if (useButtonDown && ticks - player->lastClickTick[1] >= timer->ticksPerSecond / 4) 3564 { 3565 player->handleMouseClick(1); 3566 player->lastClickTick[1] = ticks; 3567 } 3568 } 3569 } 3570 } 3571 else 3572 { 3573 // Consider as a click if we've had a period of not pressing the button, or we've reached auto-repeat time since the last time 3574 // Auto-repeat is only considered if we aren't riding or sprinting, to avoid photo sensitivity issues when placing fire whilst doing fast things 3575 // Also disable repeat when the player is sleeping to stop the waking up right after using the bed 3576 bool firstClick = ( player->lastClickTick[1] == 0 ); 3577 bool autoRepeat = ticks - player->lastClickTick[1] >= timer->ticksPerSecond / 4; 3578 if ( player->isRiding() || player->isSprinting() || player->isSleeping() ) autoRepeat = false; 3579 if (useButtonDown ) 3580 { 3581 // If the player has just exited a bed, then delay the time before a repeat key is allowed without releasing 3582 if(player->isSleeping() ) player->lastClickTick[1] = ticks + (timer->ticksPerSecond * 2); 3583 if( firstClick || autoRepeat ) 3584 { 3585 bool wasSleeping = player->isSleeping(); 3586 3587 player->handleMouseClick(1); 3588 3589 // If the player has just exited a bed, then delay the time before a repeat key is allowed without releasing 3590 if(wasSleeping) player->lastClickTick[1] = ticks + (timer->ticksPerSecond * 2); 3591 else player->lastClickTick[1] = ticks; 3592 } 3593 } 3594 else 3595 { 3596 player->lastClickTick[1] = 0; 3597 } 3598 } 3599 } 3600 3601 if(app.DebugSettingsOn()) 3602 { 3603 if (player->ullButtonsPressed & ( 1LL << MINECRAFT_ACTION_CHANGE_SKIN) ) 3604 { 3605 player->ChangePlayerSkin(); 3606 } 3607 } 3608 3609 if (player->missTime > 0) player->missTime--; 3610 3611#ifdef _DEBUG_MENUS_ENABLED 3612 if(app.DebugSettingsOn()) 3613 { 3614#ifndef __PSVITA__ 3615 // 4J-PB - debugoverlay for primary player only 3616 if(iPad==ProfileManager.GetPrimaryPad()) 3617 { 3618 if((player->ullButtonsPressed&(1LL<<MINECRAFT_ACTION_RENDER_DEBUG)) ) 3619 { 3620#ifndef _CONTENT_PACKAGE 3621 3622 options->renderDebug = !options->renderDebug; 3623#ifdef _XBOX 3624 app.EnableDebugOverlay(options->renderDebug,iPad); 3625#else 3626 // 4J Stu - The xbox uses a completely different way of navigating to this scene 3627 ui.NavigateToScene(0, eUIScene_DebugOverlay, NULL, eUILayer_Debug); 3628#endif 3629#endif 3630 } 3631 3632 if((player->ullButtonsPressed&(1LL<<MINECRAFT_ACTION_SPAWN_CREEPER)) && app.GetMobsDontAttackEnabled()) 3633 { 3634 //shared_ptr<Mob> mob = dynamic_pointer_cast<Mob>(Creeper::_class->newInstance( level )); 3635 //shared_ptr<Mob> mob = dynamic_pointer_cast<Mob>(Wolf::_class->newInstance( level )); 3636 shared_ptr<Mob> mob = dynamic_pointer_cast<Mob>(shared_ptr<Spider>(new Spider( level ))); 3637 mob->moveTo(player->x+1, player->y, player->z+1, level->random->nextFloat() * 360, 0); 3638 level->addEntity(mob); 3639 } 3640 } 3641 3642 if( (player->ullButtonsPressed&(1LL<<MINECRAFT_ACTION_FLY_TOGGLE)) ) 3643 { 3644 player->abilities.debugflying = !player->abilities.debugflying; 3645 player->abilities.flying = !player->abilities.flying; 3646 } 3647#endif // PSVITA 3648 } 3649#endif 3650 3651 if((player->ullButtonsPressed&(1LL<<MINECRAFT_ACTION_RENDER_THIRD_PERSON)) && gameMode->isInputAllowed(MINECRAFT_ACTION_RENDER_THIRD_PERSON)) 3652 { 3653 // 4J-PB - changing this to be per player 3654 player->SetThirdPersonView((player->ThirdPersonView()+1)%3); 3655 //options->thirdPersonView = !options->thirdPersonView; 3656 } 3657 3658 if((player->ullButtonsPressed&(1LL<<MINECRAFT_ACTION_GAME_INFO)) && gameMode->isInputAllowed(MINECRAFT_ACTION_GAME_INFO)) 3659 { 3660 ui.NavigateToScene(iPad,eUIScene_InGameInfoMenu); 3661 ui.PlayUISFX(eSFX_Press); 3662 } 3663 3664 if((player->ullButtonsPressed&(1LL<<MINECRAFT_ACTION_INVENTORY)) && gameMode->isInputAllowed(MINECRAFT_ACTION_INVENTORY)) 3665 { 3666 shared_ptr<MultiplayerLocalPlayer> player = Minecraft::GetInstance()->player; 3667 ui.PlayUISFX(eSFX_Press); 3668 3669 if(gameMode->isServerControlledInventory()) 3670 { 3671 player->sendOpenInventory(); 3672 } 3673 else 3674 { 3675 app.LoadInventoryMenu(iPad,player); 3676 } 3677 } 3678 3679 if((player->ullButtonsPressed&(1LL<<MINECRAFT_ACTION_CRAFTING)) && gameMode->isInputAllowed(MINECRAFT_ACTION_CRAFTING)) 3680 { 3681 shared_ptr<MultiplayerLocalPlayer> player = Minecraft::GetInstance()->player; 3682 3683 // 4J-PB - reordered the if statement so creative mode doesn't bring up the crafting table 3684 // Fix for #39014 - TU5: Creative Mode: Pressing X to access the creative menu while looking at a crafting table causes the crafting menu to display 3685 if(gameMode->hasInfiniteItems()) 3686 { 3687 // Creative mode 3688 3689 ui.PlayUISFX(eSFX_Press); 3690 app.LoadCreativeMenu(iPad,player); 3691 } 3692 // 4J-PB - Microsoft request that we use the 3x3 crafting if someone presses X while at the workbench 3693 else if ((hitResult!=NULL) && (hitResult->type == HitResult::TILE) && (level->getTile(hitResult->x, hitResult->y, hitResult->z) == Tile::workBench_Id)) 3694 { 3695 //ui.PlayUISFX(eSFX_Press); 3696 //app.LoadXuiCrafting3x3Menu(iPad,player,hitResult->x, hitResult->y, hitResult->z); 3697 bool usedItem = false; 3698 gameMode->useItemOn(player, level, nullptr, hitResult->x, hitResult->y, hitResult->z, 0, hitResult->pos, false, &usedItem); 3699 } 3700 else 3701 { 3702 ui.PlayUISFX(eSFX_Press); 3703 app.LoadCrafting2x2Menu(iPad,player); 3704 } 3705 } 3706 3707 if ( (player->ullButtonsPressed&(1LL<<MINECRAFT_ACTION_PAUSEMENU)) 3708#ifdef _DURANGO 3709 || (player->ullButtonsPressed&(1LL<<ACTION_MENU_GTC_PAUSE)) 3710#endif 3711 ) 3712 { 3713 app.DebugPrintf("PAUSE PRESS PROCESSING - ipad = %d, NavigateToScene\n",player->GetXboxPad()); 3714 ui.PlayUISFX(eSFX_Press); 3715 ui.NavigateToScene(iPad, eUIScene_PauseMenu, NULL, eUILayer_Scene); 3716 } 3717 3718 if((player->ullButtonsPressed&(1LL<<MINECRAFT_ACTION_DROP)) && gameMode->isInputAllowed(MINECRAFT_ACTION_DROP)) 3719 { 3720 player->drop(); 3721 } 3722 3723 __uint64 ullButtonsPressed=player->ullButtonsPressed; 3724 3725 bool selected = false; 3726#ifdef __PSVITA__ 3727 // 4J-PB - use the touchscreen for quickselect 3728 SceTouchData* pTouchData = InputManager.GetTouchPadData(iPad,false); 3729 3730 if(pTouchData->reportNum==1) 3731 { 3732 int iHudSize=app.GetGameSettings(iPad,eGameSetting_UISize); 3733 int iYOffset = (app.GetGameSettings(ProfileManager.GetPrimaryPad(),eGameSetting_Tooltips) == 0) ? iToolTipOffset : 0; 3734 if((pTouchData->report[0].x>QuickSelectRect[iHudSize].left)&&(pTouchData->report[0].x<QuickSelectRect[iHudSize].right) && 3735 (pTouchData->report[0].y>QuickSelectRect[iHudSize].top+iYOffset)&&(pTouchData->report[0].y<QuickSelectRect[iHudSize].bottom+iYOffset)) 3736 { 3737 player->inventory->selected=(pTouchData->report[0].x-QuickSelectRect[iHudSize].left)/QuickSelectBoxWidth[iHudSize]; 3738 selected = true; 3739 app.DebugPrintf("Touch %d\n",player->inventory->selected); 3740 } 3741 } 3742#endif 3743 if( selected || wheel != 0 || (player->ullButtonsPressed&(1LL<<MINECRAFT_ACTION_DROP)) ) 3744 { 3745 wstring itemName = L""; 3746 shared_ptr<ItemInstance> selectedItem = player->getSelectedItem(); 3747 // Dropping items happens over network, so if we only have one then assume that we dropped it and should hide the item 3748 int iCount=0; 3749 3750 if(selectedItem != NULL) iCount=selectedItem->GetCount(); 3751 if(selectedItem != NULL && !( (player->ullButtonsPressed&(1LL<<MINECRAFT_ACTION_DROP)) && selectedItem->GetCount() == 1)) 3752 { 3753 itemName = selectedItem->getHoverName(); 3754 } 3755 if( !(player->ullButtonsPressed&(1LL<<MINECRAFT_ACTION_DROP)) || (selectedItem != NULL && selectedItem->GetCount() <= 1) ) ui.SetSelectedItem( iPad, itemName ); 3756 } 3757 } 3758 else 3759 { 3760 // 4J-PB 3761 if (InputManager.GetValue(iPad, ACTION_MENU_CANCEL) > 0 && gameMode->isInputAllowed(ACTION_MENU_CANCEL)) 3762 { 3763 setScreen(NULL); 3764 } 3765 } 3766 3767 // monitor for keyboard input 3768 // #ifndef _CONTENT_PACKAGE 3769 // if(!(ui.GetMenuDisplayed(iPad))) 3770 // { 3771 // WCHAR wchInput; 3772 // if(InputManager.InputDetected(iPad,&wchInput)) 3773 // { 3774 // printf("Input Detected!\n"); 3775 // 3776 // // see if we can react to this 3777 // if(app.GetXuiAction(iPad)==eAppAction_Idle) 3778 // { 3779 // app.SetAction(iPad,eAppAction_DebugText,(LPVOID)wchInput); 3780 // } 3781 // } 3782 // } 3783 // #endif 3784 3785#if 0 3786 // 4J - TODO - some replacement for input handling... 3787 if (screen == NULL || screen.passEvents) 3788 { 3789 while (Mouse.next()) 3790 { 3791 long passedTime = System.currentTimeMillis() - lastTickTime; 3792 if (passedTime > 200) continue; 3793 3794 int wheel = Mouse.getEventDWheel(); 3795 if (wheel != 0) { 3796 player->inventory.swapPaint(wheel); 3797 3798 if (options.isFlying) { 3799 if (wheel > 0) wheel = 1; 3800 if (wheel < 0) wheel = -1; 3801 3802 options.flySpeed += wheel * .25f; 3803 } 3804 } 3805 3806 if (screen == null) { 3807 if (!mouseGrabbed && Mouse.getEventButtonState()) { 3808 grabMouse(); 3809 } else { 3810 if (Mouse.getEventButton() == 0 && Mouse.getEventButtonState()) { 3811 handleMouseClick(0); 3812 lastClickTick = ticks; 3813 } 3814 if (Mouse.getEventButton() == 1 && Mouse.getEventButtonState()) { 3815 handleMouseClick(1); 3816 lastClickTick = ticks; 3817 } 3818 if (Mouse.getEventButton() == 2 && Mouse.getEventButtonState()) { 3819 handleGrabTexture(); 3820 } 3821 } 3822 } else if (screen != null) { 3823 screen.mouseEvent(); 3824 } 3825 } 3826 3827 if (missTime > 0) missTime--; 3828 3829 while (Keyboard.next()) { 3830 player->setKey(Keyboard.getEventKey(), Keyboard.getEventKeyState()); 3831 if (Keyboard.getEventKeyState()) { 3832 if (Keyboard.getEventKey() == Keyboard.KEY_F11) { 3833 toggleFullScreen(); 3834 continue; 3835 } 3836 /* 3837 * if (Keyboard.getEventKey() == Keyboard.KEY_F4) { new 3838 * PortalForcer().createPortal(level, player); continue; } 3839 */ 3840 3841 /* 3842 * if (Keyboard.getEventKey() == Keyboard.KEY_RETURN) { 3843 * level.pathFind(); continue; } 3844 */ 3845 3846 if (screen != null) { 3847 screen.keyboardEvent(); 3848 } else { 3849 if (Keyboard.getEventKey() == Keyboard.KEY_ESCAPE) { 3850 pauseGame(); 3851 } 3852 3853 if (Keyboard.getEventKey() == Keyboard.KEY_S && Keyboard.isKeyDown(Keyboard.KEY_F3)) { 3854 reloadSound(); 3855 } 3856 3857 // if (Keyboard.getEventKey() == Keyboard.KEY_P) { 3858 // gameMode = new DemoMode(this); 3859 // selectLevel(CreateWorldScreen.findAvailableFolderName(getLevelSource(), "Demo"), "Demo World", 0L); 3860 // setScreen(null); 3861 // 3862 // } 3863 3864 if (Keyboard.getEventKey() == Keyboard.KEY_F1) { 3865 options.hideGui = !options.hideGui; 3866 } 3867 if (Keyboard.getEventKey() == Keyboard.KEY_F3) { 3868 options.renderDebug = !options.renderDebug; 3869 } 3870 if (Keyboard.getEventKey() == Keyboard.KEY_F5) { 3871 options.thirdPersonView = !options.thirdPersonView; 3872 } 3873 if (Keyboard.getEventKey() == Keyboard.KEY_F8) { 3874 options.smoothCamera = !options.smoothCamera; 3875 } 3876 if (DEADMAU5_CAMERA_CHEATS) { 3877 if (Keyboard.getEventKey() == Keyboard.KEY_F6) { 3878 options.isFlying = !options.isFlying; 3879 } 3880 if (Keyboard.getEventKey() == Keyboard.KEY_F9) { 3881 options.fixedCamera = !options.fixedCamera; 3882 } 3883 if (Keyboard.getEventKey() == Keyboard.KEY_ADD) { 3884 options.cameraSpeed += .1f; 3885 } 3886 if (Keyboard.getEventKey() == Keyboard.KEY_SUBTRACT) { 3887 options.cameraSpeed -= .1f; 3888 if (options.cameraSpeed < 0) { 3889 options.cameraSpeed = 0; 3890 } 3891 } 3892 } 3893 3894 if (Keyboard.getEventKey() == options.keyBuild.key) { 3895 setScreen(new InventoryScreen(player)); 3896 } 3897 3898 if (Keyboard.getEventKey() == options.keyDrop.key) { 3899 player->drop(); 3900 } 3901 if (isClientSide() && Keyboard.getEventKey() == options.keyChat.key) { 3902 setScreen(new ChatScreen()); 3903 } 3904 } 3905 3906 for (int i = 0; i < 9; i++) { 3907 if (Keyboard.getEventKey() == Keyboard.KEY_1 + i) player->inventory.selected = i; 3908 } 3909 if (Keyboard.getEventKey() == options.keyFog.key) { 3910 options.toggle(Options.Option.RENDER_DISTANCE, Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT) ? -1 : 1); 3911 } 3912 } 3913 } 3914 3915 if (screen == null) { 3916 if (Mouse.isButtonDown(0) && ticks - lastClickTick >= timer.ticksPerSecond / 4 && mouseGrabbed) { 3917 handleMouseClick(0); 3918 lastClickTick = ticks; 3919 } 3920 if (Mouse.isButtonDown(1) && ticks - lastClickTick >= timer.ticksPerSecond / 4 && mouseGrabbed) { 3921 handleMouseClick(1); 3922 lastClickTick = ticks; 3923 } 3924 } 3925 3926 handleMouseDown(0, screen == null && Mouse.isButtonDown(0) && mouseGrabbed); 3927 } 3928#endif 3929 3930 if (level != NULL) 3931 { 3932 if (player != NULL) 3933 { 3934 recheckPlayerIn++; 3935 if (recheckPlayerIn == 30) 3936 { 3937 recheckPlayerIn = 0; 3938 level->ensureAdded(player); 3939 } 3940 } 3941 // 4J Changed - We are setting the difficulty the same as the server so that leaderboard updates work correctly 3942 //level->difficulty = options->difficulty; 3943 //if (level->isClientSide) level->difficulty = Difficulty::HARD; 3944 if( !level->isClientSide ) 3945 { 3946 //app.DebugPrintf("Minecraft::tick - Difficulty = %d",options->difficulty); 3947 level->difficulty = options->difficulty; 3948 } 3949 3950 PIXBeginNamedEvent(0,"Game renderer tick"); 3951 if (!pause) gameRenderer->tick( bFirst); 3952 PIXEndNamedEvent(); 3953 3954 // 4J - we want to tick each level once only per frame, and do it when a player that is actually in that level happens to be active. 3955 // This is important as things that get called in the level tick (eg the levellistener) eventually end up working out what the current 3956 // level is by determing it from the current player. Use flags here to make sure each level is only ticked the once. 3957 static unsigned int levelsTickedFlags; 3958 if( bFirst ) 3959 { 3960 levelsTickedFlags = 0; 3961 3962#ifndef DISABLE_LEVELTICK_THREAD 3963 PIXBeginNamedEvent(0,"levelTickEventQueue waitForFinish"); 3964 levelTickEventQueue->waitForFinish(); 3965 PIXEndNamedEvent(); 3966#endif // DISABLE_LEVELTICK_THREAD 3967 SparseLightStorage::tick(); // 4J added 3968 CompressedTileStorage::tick(); // 4J added 3969 SparseDataStorage::tick(); // 4J added 3970 } 3971 3972 for(unsigned int i = 0; i < levels.length; ++i) 3973 { 3974 if( player->level != levels[i] ) continue; // Don't tick if the current player isn't in this level 3975 3976 // 4J - this doesn't fully tick the animateTick here, but does register this player's position. The actual 3977 // work is now done in Level::animateTickDoWork() so we can take into account multiple players in the one level. 3978 if (!pause && levels[i] != NULL) levels[i]->animateTick(Mth::floor(player->x), Mth::floor(player->y), Mth::floor(player->z)); 3979 3980 if( levelsTickedFlags & ( 1 << i ) ) continue; // Don't tick further if we've already ticked this level this frame 3981 levelsTickedFlags |= (1 << i); 3982 3983 PIXBeginNamedEvent(0,"Level renderer tick"); 3984 if (!pause) levelRenderer->tick(); 3985 PIXEndNamedEvent(); 3986 // if (!pause && player!=null) { 3987 // if (player != null && !level.entities.contains(player)) { 3988 // level.addEntity(player); 3989 // } 3990 // } 3991 if( levels[i] != NULL ) 3992 { 3993 if (!pause) 3994 { 3995 if (levels[i]->skyFlashTime > 0) levels[i]->skyFlashTime--; 3996 PIXBeginNamedEvent(0,"Level entity tick"); 3997 levels[i]->tickEntities(); 3998 PIXEndNamedEvent(); 3999 } 4000 4001 // optimisation to set the culling off early, in parallel with other stuff 4002#if defined __PS3__ && !defined DISABLE_SPU_CODE 4003 // kick off the culling for all valid players in this level 4004 int currPlayerIdx = getLocalPlayerIdx(); 4005 for( int idx = 0; idx < XUSER_MAX_COUNT; idx++ ) 4006 { 4007 if(localplayers[idx]!=NULL) 4008 { 4009 if( localplayers[idx]->level == levels[i] ) 4010 { 4011 setLocalPlayerIdx(idx); 4012 gameRenderer->setupCamera(timer->a, i); 4013 Camera::prepare(localplayers[idx], localplayers[idx]->ThirdPersonView() == 2); 4014 shared_ptr<LivingEntity> cameraEntity = cameraTargetPlayer; 4015 double xOff = cameraEntity->xOld + (cameraEntity->x - cameraEntity->xOld) * timer->a; 4016 double yOff = cameraEntity->yOld + (cameraEntity->y - cameraEntity->yOld) * timer->a; 4017 double zOff = cameraEntity->zOld + (cameraEntity->z - cameraEntity->zOld) * timer->a; 4018 FrustumCuller frustObj; 4019 Culler *frustum = &frustObj; 4020 MemSect(0); 4021 frustum->prepare(xOff, yOff, zOff); 4022 levelRenderer->cull_SPU(idx, frustum, 0); 4023 } 4024 } 4025 } 4026 setLocalPlayerIdx(currPlayerIdx); 4027#endif // __PS3__ 4028 4029 // 4J Stu - We are always online, but still could be paused 4030 if (!pause) // || isClientSide()) 4031 { 4032 //app.DebugPrintf("Minecraft::tick spawn settings - Difficulty = %d",options->difficulty); 4033 levels[i]->setSpawnSettings(level->difficulty > 0, true); 4034 PIXBeginNamedEvent(0,"Level tick"); 4035#ifdef DISABLE_LEVELTICK_THREAD 4036 levels[i]->tick(); 4037#else 4038 levelTickEventQueue->sendEvent(levels[i]); 4039#endif // DISABLE_LEVELTICK_THREAD 4040 PIXEndNamedEvent(); 4041 } 4042 } 4043 } 4044 4045 if( bFirst ) 4046 { 4047 PIXBeginNamedEvent(0,"Particle tick"); 4048 if (!pause) particleEngine->tick(); 4049 PIXEndNamedEvent(); 4050 } 4051 4052 // 4J Stu - Keep ticking the connections if paused so that they don't time out 4053 if( pause ) tickAllConnections(); 4054 // player->tick(); 4055 } 4056#ifdef __PS3__ 4057 4058// while(!g_tickLevelQueue.empty()) 4059// { 4060// Level* pLevel = g_tickLevelQueue.front(); 4061// g_tickLevelQueue.pop(); 4062// pLevel->tick(); 4063// }; 4064 4065#endif 4066 4067 // if (Keyboard.isKeyDown(Keyboard.KEY_NUMPAD7) || 4068 // Keyboard.isKeyDown(Keyboard.KEY_Q)) rota++; 4069 // if (Keyboard.isKeyDown(Keyboard.KEY_NUMPAD9) || 4070 // Keyboard.isKeyDown(Keyboard.KEY_E)) rota--; 4071 // 4J removed 4072 //lastTickTime = System::currentTimeMillis(); 4073} 4074 4075void Minecraft::reloadSound() 4076{ 4077 // System.out.println("FORCING RELOAD!"); // 4J - removed 4078 soundEngine = new SoundEngine(); 4079 soundEngine->init(options); 4080 bgLoader->forceReload(); 4081} 4082 4083bool Minecraft::isClientSide() 4084{ 4085 return level != NULL && level->isClientSide; 4086} 4087 4088void Minecraft::selectLevel(ConsoleSaveFile *saveFile, const wstring& levelId, const wstring& levelName, LevelSettings *levelSettings) 4089{ 4090 } 4091 4092bool Minecraft::saveSlot(int slot, const wstring& name) 4093{ 4094 return false; 4095} 4096 4097bool Minecraft::loadSlot(const wstring& userName, int slot) 4098{ 4099 return false; 4100} 4101 4102void Minecraft::releaseLevel(int message) 4103{ 4104 //this->level = NULL; 4105 setLevel(NULL, message); 4106} 4107 4108// 4J Stu - This code was within setLevel, but I moved it out so that I can call it at a better 4109// time when exiting from an online game 4110void Minecraft::forceStatsSave(int idx) 4111{ 4112 //4J Gordon: Force a stats save 4113 stats[idx]->save(idx, true); 4114 4115 //4J Gordon: If the player is signed in, save the leaderboards 4116 if( ProfileManager.IsSignedInLive(idx) ) 4117 { 4118 int tempLockedProfile = ProfileManager.GetLockedProfile(); 4119 ProfileManager.SetLockedProfile(idx); 4120 stats[idx]->saveLeaderboards(); 4121 ProfileManager.SetLockedProfile(tempLockedProfile); 4122 } 4123} 4124 4125// 4J Added 4126MultiPlayerLevel *Minecraft::getLevel(int dimension) 4127{ 4128 if (dimension == -1) return levels[1]; 4129 else if(dimension == 1) return levels[2]; 4130 else return levels[0]; 4131} 4132 4133// 4J Stu - Removed as redundant with default values in params. 4134//void Minecraft::setLevel(Level *level, bool doForceStatsSave /*= true*/) 4135//{ 4136// setLevel(level, -1, NULL, doForceStatsSave); 4137//} 4138 4139// Also causing ambiguous call for some reason 4140// as it is matching shared_ptr<Player> from the func below with bool from this one 4141//void Minecraft::setLevel(Level *level, const wstring& message, bool doForceStatsSave /*= true*/) 4142//{ 4143// setLevel(level, message, NULL, doForceStatsSave); 4144//} 4145 4146void Minecraft::forceaddLevel(MultiPlayerLevel *level) 4147{ 4148 int dimId = level->dimension->id; 4149 if (dimId == -1) levels[1] = level; 4150 else if(dimId == 1) levels[2] = level; 4151 else levels[0] = level; 4152} 4153 4154void Minecraft::setLevel(MultiPlayerLevel *level, int message /*=-1*/, shared_ptr<Player> forceInsertPlayer /*=NULL*/, bool doForceStatsSave /*=true*/, bool bPrimaryPlayerSignedOut /*=false*/) 4155{ 4156 EnterCriticalSection(&m_setLevelCS); 4157 bool playerAdded = false; 4158 this->cameraTargetPlayer = nullptr; 4159 4160 if(progressRenderer != NULL) 4161 { 4162 this->progressRenderer->progressStart(message); 4163 this->progressRenderer->progressStage(-1); 4164 } 4165 4166 // 4J-PB - since we now play music in the menu, just let it keep playing 4167 //soundEngine->playStreaming(L"", 0, 0, 0, 0, 0); 4168 4169 // 4J - stop update thread from processing this level, which blocks until it is safe to move on - will be re-enabled if we set the level to be non-NULL 4170 gameRenderer->DisableUpdateThread(); 4171 4172 for(unsigned int i = 0; i < levels.length; ++i) 4173 { 4174 // 4J We only need to save out in multiplayer is we are setting the level to NULL 4175 // If we ever go back to making single player only then this will not work properly! 4176 if (levels[i] != NULL && level == NULL) 4177 { 4178 // 4J Stu - This is really only relevant for single player (ie not what we do at the moment) 4179 if((doForceStatsSave==true) && player!=NULL) 4180 forceStatsSave(player->GetXboxPad() ); 4181 4182 // 4J Stu - Added these for the case when we exit a level so we are setting the level to NULL 4183 // The level renderer needs to have it's stored level set to NULL so that it doesn't break next time we set one 4184 if (levelRenderer != NULL) 4185 { 4186 for(DWORD p = 0; p < XUSER_MAX_COUNT; ++p) 4187 { 4188 levelRenderer->setLevel(p, NULL); 4189 } 4190 } 4191 if (particleEngine != NULL) particleEngine->setLevel(NULL); 4192 } 4193 } 4194 // 4J If we are setting the level to NULL then we are exiting, so delete the levels 4195 if( level == NULL ) 4196 { 4197 if(levels[0]!=NULL) 4198 { 4199 delete levels[0]; 4200 levels[0] = NULL; 4201 4202 // Both level share the same savedDataStorage 4203 if(levels[1]!=NULL) levels[1]->savedDataStorage = NULL; 4204 } 4205 if(levels[1]!=NULL) 4206 { 4207 delete levels[1]; 4208 levels[1] = NULL; 4209 } 4210 if(levels[2]!=NULL) 4211 { 4212 delete levels[2]; 4213 levels[2] = NULL; 4214 } 4215 4216 // Delete all the player objects 4217 for(unsigned int idx = 0; idx < XUSER_MAX_COUNT; ++idx) 4218 { 4219 shared_ptr<MultiplayerLocalPlayer> mplp = localplayers[idx]; 4220 if(mplp != NULL && mplp->connection != NULL ) 4221 { 4222 delete mplp->connection; 4223 mplp->connection = NULL; 4224 } 4225 4226 if( localgameModes[idx] != NULL ) 4227 { 4228 delete localgameModes[idx]; 4229 localgameModes[idx] = NULL; 4230 } 4231 4232 if( m_pendingLocalConnections[idx] != NULL ) 4233 { 4234 delete m_pendingLocalConnections[idx]; 4235 m_pendingLocalConnections[idx] = NULL; 4236 } 4237 4238 localplayers[idx] = nullptr; 4239 } 4240 // If we are removing the primary player then there can't be a valid gamemode left anymore, this 4241 // pointer will be referring to the one we've just deleted 4242 gameMode = NULL; 4243 // Remove references to player 4244 player = nullptr; 4245 cameraTargetPlayer = nullptr; 4246 EntityRenderDispatcher::instance->cameraEntity = nullptr; 4247 TileEntityRenderDispatcher::instance->cameraEntity = nullptr; 4248 } 4249 this->level = level; 4250 4251 if (level != NULL) 4252 { 4253 int dimId = level->dimension->id; 4254 if (dimId == -1) levels[1] = level; 4255 else if(dimId == 1) levels[2] = level; 4256 else levels[0] = level; 4257 4258 // If no player has been set, then this is the first level to be set this game, so set up 4259 // a primary player & initialise some other things 4260 if (player == NULL) 4261 { 4262 int iPrimaryPlayer = ProfileManager.GetPrimaryPad(); 4263 4264 player = gameMode->createPlayer(level); 4265 4266 PlayerUID playerXUIDOffline = INVALID_XUID; 4267 PlayerUID playerXUIDOnline = INVALID_XUID; 4268 ProfileManager.GetXUID(iPrimaryPlayer,&playerXUIDOffline,false); 4269 ProfileManager.GetXUID(iPrimaryPlayer,&playerXUIDOnline,true); 4270#ifdef __PSVITA__ 4271 if(CGameNetworkManager::usingAdhocMode() && playerXUIDOnline.getOnlineID()[0] == 0) 4272 { 4273 // player doesn't have an online UID, set it from the player name 4274 playerXUIDOnline.setForAdhoc(); 4275 } 4276#endif 4277 player->setXuid(playerXUIDOffline); 4278 player->setOnlineXuid(playerXUIDOnline); 4279 4280 player->m_displayName = ProfileManager.GetDisplayName(iPrimaryPlayer); 4281 4282 4283 4284 player->resetPos(); 4285 gameMode->initPlayer(player); 4286 4287 player->SetXboxPad(iPrimaryPlayer); 4288 4289 for(int i=0;i<XUSER_MAX_COUNT;i++) 4290 { 4291 m_pendingLocalConnections[i] = NULL; 4292 if( i != iPrimaryPlayer ) localgameModes[i] = NULL; 4293 } 4294 } 4295 4296 if (player != NULL) 4297 { 4298 player->resetPos(); 4299 // gameMode.initPlayer(player); 4300 if (level != NULL) 4301 { 4302 level->addEntity(player); 4303 playerAdded = true; 4304 } 4305 } 4306 4307 if(player->input != NULL) delete player->input; 4308 player->input = new Input(); 4309 4310 if (levelRenderer != NULL) levelRenderer->setLevel(player->GetXboxPad(), level); 4311 if (particleEngine != NULL) particleEngine->setLevel(level); 4312 4313#if 0 4314 // 4J - removed - we don't use ChunkCache anymore 4315 ChunkSource *cs = level->getChunkSource(); 4316 if (dynamic_cast<ChunkCache *>(cs) != NULL) 4317 { 4318 ChunkCache *spcc = (ChunkCache *)cs; 4319 4320 // 4J - these had a Mth::floor which seems unrequired 4321 int xt = ((int) player->x) >> 4; 4322 int zt = ((int) player->z) >> 4; 4323 4324 spcc->centerOn(xt, zt); 4325 } 4326#endif 4327 gameMode->adjustPlayer(player); 4328 4329 for(int i=0;i<XUSER_MAX_COUNT;i++) 4330 { 4331 m_pendingLocalConnections[i] = NULL; 4332 } 4333 updatePlayerViewportAssignments(); 4334 4335 this->cameraTargetPlayer = player; 4336 4337 // 4J - allow update thread to start processing the level now both it & the player should be ok 4338 gameRenderer->EnableUpdateThread(); 4339 } 4340 else 4341 { 4342 levelSource->clearAll(); 4343 player = nullptr; 4344 4345 // Clear all players if the new level is NULL 4346 for(int i=0;i<XUSER_MAX_COUNT;i++) 4347 { 4348 if( m_pendingLocalConnections[i] != NULL ) m_pendingLocalConnections[i]->close(); 4349 m_pendingLocalConnections[i] = NULL; 4350 localplayers[i] = nullptr; 4351 localgameModes[i] = NULL; 4352 } 4353 } 4354 4355 // System.gc(); // 4J - removed 4356 // 4J removed 4357 //this->lastTickTime = 0; 4358 LeaveCriticalSection(&m_setLevelCS); 4359} 4360 4361void Minecraft::prepareLevel(int title) 4362{ 4363 if(progressRenderer != NULL) 4364 { 4365 this->progressRenderer->progressStart(title); 4366 this->progressRenderer->progressStage(IDS_PROGRESS_BUILDING_TERRAIN); 4367 } 4368 int r = 128; 4369 if (gameMode->isCutScene()) r = 64; 4370 int pp = 0; 4371 int max = r * 2 / 16 + 1; 4372 max = max * max; 4373 ChunkSource *cs = level->getChunkSource(); 4374 4375 Pos *spawnPos = level->getSharedSpawnPos(); 4376 if (player != NULL) 4377 { 4378 spawnPos->x = (int) player->x; 4379 spawnPos->z = (int) player->z; 4380 } 4381 4382#if 0 4383 // 4J - removed - we don't use ChunkCache anymore 4384 if (dynamic_cast<ChunkCache *>(cs)!=NULL) 4385 { 4386 ChunkCache *spcc = (ChunkCache *) cs; 4387 4388 spcc->centerOn(spawnPos->x >> 4, spawnPos->z >> 4); 4389 } 4390#endif 4391 4392 for (int x = -r; x <= r; x += 16) 4393 { 4394 for (int z = -r; z <= r; z += 16) 4395 { 4396 if(progressRenderer != NULL) this->progressRenderer->progressStagePercentage((pp++) * 100 / max); 4397 level->getTile(spawnPos->x + x, 64, spawnPos->z + z); 4398 if (!gameMode->isCutScene()) { 4399 } 4400 } 4401 } 4402 delete spawnPos; 4403 if (!gameMode->isCutScene()) 4404 { 4405 if(progressRenderer != NULL) this->progressRenderer->progressStage(IDS_PROGRESS_SIMULATING_WORLD); 4406 max = 2000; 4407} 4408} 4409 4410wstring Minecraft::gatherStats1() 4411{ 4412 //return levelRenderer->gatherStats1(); 4413 return L"Time to autosave: " + _toString<unsigned int>( app.SecondsToAutosave() ) + L"s"; 4414} 4415 4416wstring Minecraft::gatherStats2() 4417{ 4418 return g_NetworkManager.GatherStats(); 4419 //return levelRenderer->gatherStats2(); 4420} 4421 4422wstring Minecraft::gatherStats3() 4423{ 4424 return g_NetworkManager.GatherRTTStats(); 4425 //return L"P: " + particleEngine->countParticles() + L". T: " + level->gatherStats(); 4426} 4427 4428wstring Minecraft::gatherStats4() 4429{ 4430 return level->gatherChunkSourceStats(); 4431} 4432 4433void Minecraft::respawnPlayer(int iPad, int dimension, int newEntityId) 4434{ 4435 gameRenderer->DisableUpdateThread(); // 4J - don't do updating whilst we are adjusting the player & localplayer array 4436 shared_ptr<MultiplayerLocalPlayer> localPlayer = localplayers[iPad]; 4437 4438 level->validateSpawn(); 4439 level->removeAllPendingEntityRemovals(); 4440 4441 if (localPlayer != NULL) 4442 { 4443 level->removeEntity(localPlayer); 4444 } 4445 4446 shared_ptr<Player> oldPlayer = localPlayer; 4447 cameraTargetPlayer = nullptr; 4448 4449 // 4J-PB - copy and set the players xbox pad 4450 int iTempPad=localPlayer->GetXboxPad(); 4451 int iTempScreenSection = localPlayer->m_iScreenSection; 4452 EDefaultSkins skin = localPlayer->getPlayerDefaultSkin(); 4453 player = localgameModes[iPad]->createPlayer(level); 4454 4455 PlayerUID playerXUIDOffline = INVALID_XUID; 4456 PlayerUID playerXUIDOnline = INVALID_XUID; 4457 ProfileManager.GetXUID(iTempPad,&playerXUIDOffline,false); 4458 ProfileManager.GetXUID(iTempPad,&playerXUIDOnline,true); 4459 player->setXuid(playerXUIDOffline); 4460 player->setOnlineXuid(playerXUIDOnline); 4461 player->setIsGuest( ProfileManager.IsGuest(iTempPad) ); 4462 4463 player->m_displayName = ProfileManager.GetDisplayName(iPad); 4464 4465 player->SetXboxPad(iTempPad); 4466 4467 player->m_iScreenSection = iTempScreenSection; 4468 player->setPlayerIndex( localPlayer->getPlayerIndex() ); 4469 player->setCustomSkin(localPlayer->getCustomSkin()); 4470 player->setPlayerDefaultSkin( skin ); 4471 player->setCustomCape(localPlayer->getCustomCape()); 4472 player->m_sessionTimeStart = localPlayer->m_sessionTimeStart; 4473 player->m_dimensionTimeStart = localPlayer->m_dimensionTimeStart; 4474 player->setPlayerGamePrivilege(Player::ePlayerGamePrivilege_All, localPlayer->getAllPlayerGamePrivileges()); 4475 4476 player->SetThirdPersonView(oldPlayer->ThirdPersonView()); 4477 4478 // Fix for #63021 - TU7: Content: UI: Travelling from/to the Nether results in switching currently held item to another. 4479 // Fix for #81759 - TU9: Content: Gameplay: Entering The End Exit Portal replaces the Player's currently held item with the first one from the Quickbar 4480 if( localPlayer->getHealth() > 0 && localPlayer->y > -64) 4481 { 4482 player->inventory->selected = localPlayer->inventory->selected; 4483 } 4484 4485 // Set the animation override if the skin has one 4486 DWORD dwSkinID=app.getSkinIdFromPath(player->customTextureUrl); 4487 if(GET_IS_DLC_SKIN_FROM_BITMASK(dwSkinID)) 4488 { 4489 player->setAnimOverrideBitmask(player->getSkinAnimOverrideBitmask(dwSkinID)); 4490 } 4491 4492 player->dimension = dimension; 4493 cameraTargetPlayer = player; 4494 4495 // 4J-PB - are we the primary player or a local player? 4496 if(iPad==ProfileManager.GetPrimaryPad()) 4497 { 4498 createPrimaryLocalPlayer(iPad); 4499 4500 // update the debugoptions 4501 app.SetGameSettingsDebugMask(ProfileManager.GetPrimaryPad(),app.GetGameSettingsDebugMask(-1,true)); 4502 } 4503 else 4504 { 4505 storeExtraLocalPlayer(iPad); 4506 } 4507 4508 player->setShowOnMaps(app.GetGameHostOption(eGameHostOption_Gamertags)!=0?true:false); 4509 4510 player->resetPos(); 4511 level->addEntity(player); 4512 gameMode->initPlayer(player); 4513 4514 if(player->input != NULL) delete player->input; 4515 player->input = new Input(); 4516 player->entityId = newEntityId; 4517 player->animateRespawn(); 4518 gameMode->adjustPlayer(player); 4519 4520 // 4J - added isClientSide check here 4521 if (!level->isClientSide) 4522 { 4523 prepareLevel(IDS_PROGRESS_RESPAWNING); 4524 } 4525 4526 // 4J Added for multiplayer. At this point we know everything is ready to run again 4527 //SetEvent(m_hPlayerRespawned); 4528 player->SetPlayerRespawned(true); 4529 4530 if (dynamic_cast<DeathScreen *>(screen) != NULL) setScreen(NULL); 4531 4532 gameRenderer->EnableUpdateThread(); 4533} 4534 4535void Minecraft::start(const wstring& name, const wstring& sid) 4536{ 4537 startAndConnectTo(name, sid, L""); 4538} 4539 4540void Minecraft::startAndConnectTo(const wstring& name, const wstring& sid, const wstring& url) 4541{ 4542 bool fullScreen = false; 4543 wstring userName = name; 4544 4545 /* 4J - removed window handling things here 4546 final Frame frame = new Frame("Minecraft"); 4547 Canvas canvas = new Canvas(); 4548 frame.setLayout(new BorderLayout()); 4549 4550 frame.add(canvas, BorderLayout.CENTER); 4551 4552 // OverlayLayout oll = new OverlayLayout(frame); 4553 // oll.addLayoutComponent(canvas, BorderLayout.CENTER); 4554 // oll.addLayoutComponent(new JLabel("TEST"), BorderLayout.EAST); 4555 4556 canvas.setPreferredSize(new Dimension(854, 480)); 4557 frame.pack(); 4558 frame.setLocationRelativeTo(null); 4559 */ 4560 4561 Minecraft *minecraft; 4562 // 4J - was new Minecraft(frame, canvas, NULL, 854, 480, fullScreen); 4563 4564 minecraft = new Minecraft(NULL, NULL, NULL, 1280, 720, fullScreen); 4565 4566 /* - 4J - removed 4567 { 4568 @Override 4569 public void onCrash(CrashReport crashReport) { 4570 frame.removeAll(); 4571 frame.add(new CrashInfoPanel(crashReport), BorderLayout.CENTER); 4572 frame.validate(); 4573 } 4574 }; */ 4575 4576 /* 4J - removed 4577 final Thread thread = new Thread(minecraft, "Minecraft main thread"); 4578 thread.setPriority(Thread.MAX_PRIORITY); 4579 */ 4580 minecraft->serverDomain = L"www.minecraft.net"; 4581 4582 // 4J Stu - We never want the player to be DemoUser, we always want them to have their gamertag displayed 4583 //if (ProfileManager.IsFullVersion()) 4584 { 4585 if (userName != L"" && sid != L"") // 4J - username & side were compared with NULL rather than empty strings 4586 { 4587 minecraft->user = new User(userName, sid); 4588 } 4589 else 4590 { 4591 minecraft->user = new User(L"Player" + _toString<int>(System::currentTimeMillis() % 1000), L""); 4592 } 4593 } 4594 //else 4595 //{ 4596 // minecraft->user = new DemoUser(); 4597 //} 4598 4599 /* 4J - TODO 4600 if (url != NULL) 4601 { 4602 String[] tokens = url.split(":"); 4603 minecraft.connectTo(tokens[0], Integer.parseInt(tokens[1])); 4604 } 4605 */ 4606 4607 /* 4J - removed 4608 frame.setVisible(true); 4609 frame.addWindowListener(new WindowAdapter() { 4610 public void windowClosing(WindowEvent arg0) { 4611 minecraft.stop(); 4612 try { 4613 thread.join(); 4614 } catch (InterruptedException e) { 4615 e.printStackTrace(); 4616 } 4617 System.exit(0); 4618 } 4619 }); 4620 */ 4621 // 4J - TODO - consider whether we need to actually create a thread here 4622 minecraft->run(); 4623} 4624 4625ClientConnection *Minecraft::getConnection(int iPad) 4626{ 4627 return localplayers[iPad]->connection; 4628} 4629 4630// 4J-PB - so we can access this from within our xbox game loop 4631Minecraft *Minecraft::GetInstance() 4632{ 4633 return m_instance; 4634} 4635 4636bool useLomp = false; 4637 4638int g_iMainThreadId; 4639 4640void Minecraft::main() 4641{ 4642 wstring name; 4643 wstring sessionId; 4644 4645 //g_iMainThreadId = GetCurrentThreadId(); 4646 4647 useLomp = true; 4648 4649 MinecraftWorld_RunStaticCtors(); 4650 EntityRenderDispatcher::staticCtor(); 4651 TileEntityRenderDispatcher::staticCtor(); 4652 User::staticCtor(); 4653 Tutorial::staticCtor(); 4654 ColourTable::staticCtor(); 4655 app.loadDefaultGameRules(); 4656 4657#ifdef _LARGE_WORLDS 4658 LevelRenderer::staticCtor(); 4659#endif 4660 4661 // 4J Stu - This block generates XML for the game rules schema 4662#if 0 4663 for(unsigned int i = 0; i < Item::items.length; ++i) 4664 { 4665 if(Item::items[i] != NULL) 4666 { 4667 app.DebugPrintf("<xs:enumeration value=\"%d\"><xs:annotation><xs:documentation>%ls</xs:documentation></xs:annotation></xs:enumeration>\n", i, app.GetString( Item::items[i]->getDescriptionId() )); 4668 } 4669 } 4670 4671 app.DebugPrintf("\n\n\n\n\n"); 4672 4673 for(unsigned int i = 0; i < 256; ++i) 4674 { 4675 if(Tile::tiles[i] != NULL) 4676 { 4677 app.DebugPrintf("<xs:enumeration value=\"%d\"><xs:annotation><xs:documentation>%ls</xs:documentation></xs:annotation></xs:enumeration>\n", i, app.GetString( Tile::tiles[i]->getDescriptionId() )); 4678 } 4679 } 4680 __debugbreak(); 4681#endif 4682 4683 // 4J-PB - Can't call this for the first 5 seconds of a game - MS rule 4684 //if (ProfileManager.IsFullVersion()) 4685 { 4686 name = L"Player" + _toString<__int64>(System::currentTimeMillis() % 1000); 4687 sessionId = L"-"; 4688 /* 4J - TODO - get a session ID from somewhere? 4689 if (args.length > 0) name = args[0]; 4690 sessionId = "-"; 4691 if (args.length > 1) sessionId = args[1]; 4692 */ 4693 } 4694 4695 // Common for all platforms 4696 IUIScene_CreativeMenu::staticCtor(); 4697 4698 // On PS4, we call Minecraft::Start from another thread, as this has been timed taking ~2.5 seconds and we need to do some basic 4699 // rendering stuff so that we don't break the TRCs on SubmitDone calls 4700#ifndef __ORBIS__ 4701 Minecraft::start(name, sessionId); 4702#endif 4703} 4704 4705bool Minecraft::renderNames() 4706{ 4707 if (m_instance == NULL || !m_instance->options->hideGui) 4708 { 4709 return true; 4710 } 4711 return false; 4712} 4713 4714bool Minecraft::useFancyGraphics() 4715{ 4716 return (m_instance != NULL && m_instance->options->fancyGraphics); 4717} 4718 4719bool Minecraft::useAmbientOcclusion() 4720{ 4721 return (m_instance != NULL && m_instance->options->ambientOcclusion != Options::AO_OFF); 4722} 4723 4724bool Minecraft::renderDebug() 4725{ 4726 return (m_instance != NULL && m_instance->options->renderDebug); 4727} 4728 4729bool Minecraft::handleClientSideCommand(const wstring& chatMessage) 4730{ 4731 return false; 4732} 4733 4734int Minecraft::maxSupportedTextureSize() 4735{ 4736 // 4J Force value 4737 return 1024; 4738 4739 //for (int texSize = 16384; texSize > 0; texSize >>= 1) { 4740 // GL11.glTexImage2D(GL11.GL_PROXY_TEXTURE_2D, 0, GL11.GL_RGBA, texSize, texSize, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, (ByteBuffer) null); 4741 // final int width = GL11.glGetTexLevelParameteri(GL11.GL_PROXY_TEXTURE_2D, 0, GL11.GL_TEXTURE_WIDTH); 4742 // if (width != 0) { 4743 // return texSize; 4744 // } 4745 //} 4746 //return -1; 4747} 4748 4749void Minecraft::delayTextureReload() 4750{ 4751 reloadTextures = true; 4752} 4753 4754__int64 Minecraft::currentTimeMillis() 4755{ 4756 return System::currentTimeMillis();//(Sys.getTime() * 1000) / Sys.getTimerResolution(); 4757} 4758 4759/*void Minecraft::handleMouseDown(int button, bool down) 4760{ 4761if (gameMode->instaBuild) return; 4762if (!down) missTime = 0; 4763if (button == 0 && missTime > 0) return; 4764 4765if (down && hitResult != NULL && hitResult->type == HitResult::TILE && button == 0) 4766{ 4767int x = hitResult->x; 4768int y = hitResult->y; 4769int z = hitResult->z; 4770gameMode->continueDestroyBlock(x, y, z, hitResult->f); 4771particleEngine->crack(x, y, z, hitResult->f); 4772} 4773else 4774{ 4775gameMode->stopDestroyBlock(); 4776} 4777} 4778 4779void Minecraft::handleMouseClick(int button) 4780{ 4781if (button == 0 && missTime > 0) return; 4782if (button == 0) 4783{ 4784app.DebugPrintf("handleMouseClick - Player %d is swinging\n",player->GetXboxPad()); 4785player->swing(); 4786} 4787 4788bool mayUse = true; 4789 4790// * if (button == 1) { ItemInstance item = 4791// * player.inventory.getSelected(); if (item != null) { if 4792// * (gameMode.useItem(player, item)) { 4793// * gameRenderer.itemInHandRenderer.itemUsed(); return; } } } 4794 4795// 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 4796 4797if(button==1 && (player->isSleeping() && level != NULL && level->isClientSide)) 4798{ 4799shared_ptr<MultiplayerLocalPlayer> mplp = dynamic_pointer_cast<MultiplayerLocalPlayer>( player ); 4800 4801if(mplp) mplp->StopSleeping(); 4802 4803// 4J - TODO 4804//if (minecraft.player instanceof MultiplayerLocalPlayer) 4805//{ 4806// ClientConnection connection = ((MultiplayerLocalPlayer) minecraft.player).connection; 4807// connection.send(new PlayerCommandPacket(minecraft.player, PlayerCommandPacket.STOP_SLEEPING)); 4808//} 4809} 4810 4811if (hitResult == NULL) 4812{ 4813if (button == 0 && !(dynamic_cast<CreativeMode *>(gameMode) != NULL)) missTime = 10; 4814} 4815else if (hitResult->type == HitResult::ENTITY) 4816{ 4817if (button == 0) 4818{ 4819gameMode->attack(player, hitResult->entity); 4820} 4821if (button == 1) 4822{ 4823gameMode->interact(player, hitResult->entity); 4824} 4825} 4826else if (hitResult->type == HitResult::TILE) 4827{ 4828int x = hitResult->x; 4829int y = hitResult->y; 4830int z = hitResult->z; 4831int face = hitResult->f; 4832 4833// * if (button != 0) { if (hitResult.f == 0) y--; if (hitResult.f == 4834// * 1) y++; if (hitResult.f == 2) z--; if (hitResult.f == 3) z++; if 4835// * (hitResult.f == 4) x--; if (hitResult.f == 5) x++; } 4836 4837// if (isClientSide()) 4838// { 4839// return; 4840// } 4841 4842if (button == 0) 4843{ 4844gameMode->startDestroyBlock(x, y, z, hitResult->f); 4845} 4846else 4847{ 4848shared_ptr<ItemInstance> item = player->inventory->getSelected(); 4849int oldCount = item != NULL ? item->count : 0; 4850if (gameMode->useItemOn(player, level, item, x, y, z, face)) 4851{ 4852mayUse = false; 4853app.DebugPrintf("Player %d is swinging\n",player->GetXboxPad()); 4854player->swing(); 4855} 4856if (item == NULL) 4857{ 4858return; 4859} 4860 4861if (item->count == 0) 4862{ 4863player->inventory->items[player->inventory->selected] = NULL; 4864} 4865else if (item->count != oldCount) 4866{ 4867gameRenderer->itemInHandRenderer->itemPlaced(); 4868} 4869} 4870} 4871 4872if (mayUse && button == 1) 4873{ 4874shared_ptr<ItemInstance> item = player->inventory->getSelected(); 4875if (item != NULL) 4876{ 4877if (gameMode->useItem(player, level, item)) 4878{ 4879gameRenderer->itemInHandRenderer->itemUsed(); 4880} 4881} 4882} 4883} 4884*/ 4885 4886// 4J-PB 4887Screen * Minecraft::getScreen() 4888{ 4889 return screen; 4890} 4891 4892bool Minecraft::isTutorial() 4893{ 4894 return m_inFullTutorialBits > 0; 4895 4896 /*if( gameMode != NULL && gameMode->isTutorial() ) 4897 { 4898 return true; 4899 } 4900 else 4901 { 4902 return false; 4903 }*/ 4904} 4905 4906void Minecraft::playerStartedTutorial(int iPad) 4907{ 4908 // If the app doesn't think we are in a tutorial mode then just ignore this add 4909 if( app.GetTutorialMode() ) m_inFullTutorialBits = m_inFullTutorialBits | ( 1 << iPad ); 4910} 4911 4912void Minecraft::playerLeftTutorial(int iPad) 4913{ 4914 // 4J Stu - Fix for bug that was flooding Sentient with LevelStart events 4915 // If the tutorial bits are already 0 then don't need to update anything 4916 if(m_inFullTutorialBits == 0) 4917 { 4918 app.SetTutorialMode( false ); 4919 return; 4920 } 4921 4922 m_inFullTutorialBits = m_inFullTutorialBits & ~( 1 << iPad ); 4923 if(m_inFullTutorialBits == 0) 4924 { 4925 app.SetTutorialMode( false ); 4926 4927 // 4J Stu -This telemetry event means something different on XboxOne, so we don't call it for simple state changes like this 4928#ifndef _XBOX_ONE 4929 for(DWORD idx = 0; idx < XUSER_MAX_COUNT; ++idx) 4930 { 4931 if(localplayers[idx] != NULL) 4932 { 4933 TelemetryManager->RecordLevelStart(idx, eSen_FriendOrMatch_Playing_With_Invited_Friends, eSen_CompeteOrCoop_Coop_and_Competitive, level->difficulty, app.GetLocalPlayerCount(), g_NetworkManager.GetOnlinePlayerCount()); 4934 } 4935 } 4936#endif 4937 } 4938} 4939 4940#ifdef _DURANGO 4941void Minecraft::inGameSignInCheckAllPrivilegesCallback(LPVOID lpParam, bool hasPrivileges, int iPad) 4942{ 4943 Minecraft* pClass = (Minecraft*)lpParam; 4944 4945 if(!hasPrivileges) 4946 { 4947 ProfileManager.RemoveGamepadFromGame(iPad); 4948 } 4949 else 4950 { 4951 if( !g_NetworkManager.SessionHasSpace() ) 4952 { 4953 UINT uiIDA[1]; 4954 uiIDA[0]=IDS_OK; 4955 ui.RequestErrorMessage(IDS_MULTIPLAYER_FULL_TITLE, IDS_MULTIPLAYER_FULL_TEXT, uiIDA, 1); 4956 ProfileManager.RemoveGamepadFromGame(iPad); 4957 } 4958 else if( ProfileManager.IsSignedInLive(iPad) && ProfileManager.AllowedToPlayMultiplayer(iPad) ) 4959 { 4960 // create the local player for the iPad 4961 shared_ptr<Player> player = pClass->localplayers[iPad]; 4962 if( player == NULL) 4963 { 4964 if( pClass->level->isClientSide ) 4965 { 4966 pClass->addLocalPlayer(iPad); 4967 } 4968 else 4969 { 4970 // create the local player for the iPad 4971 shared_ptr<Player> player = pClass->localplayers[iPad]; 4972 if( player == NULL) 4973 { 4974 player = pClass->createExtraLocalPlayer(iPad, (convStringToWstring( ProfileManager.GetGamertag(iPad) )).c_str(), iPad, pClass->level->dimension->id); 4975 } 4976 } 4977 } 4978 } 4979 } 4980} 4981#endif 4982 4983#ifdef _XBOX_ONE 4984int Minecraft::InGame_SignInReturned(void *pParam,bool bContinue, int iPad, int iController) 4985#else 4986int Minecraft::InGame_SignInReturned(void *pParam,bool bContinue, int iPad) 4987#endif 4988{ 4989 Minecraft* pMinecraftClass = (Minecraft*)pParam; 4990 4991 if(g_NetworkManager.IsInSession()) 4992 { 4993 // 4J Stu - There seems to be a bug in the signin ui call that enables guest sign in. We never allow this within game, so make sure that it's disabled 4994 // Fix for #66516 - TCR #124: MPS Guest Support ; #001: BAS Game Stability: TU8: The game crashes when second Guest signs-in on console which takes part in Xbox LIVE multiplayer session. 4995 app.DebugPrintf("Disabling Guest Signin\n"); 4996 XEnableGuestSignin(FALSE); 4997 } 4998 4999 // If sign in succeded, we're in game and this player isn't already playing, continue 5000 if(bContinue==true && g_NetworkManager.IsInSession() && pMinecraftClass->localplayers[iPad] == NULL) 5001 { 5002 // It's possible that the player has not signed in - they can back out or choose no for the converttoguest 5003 if(ProfileManager.IsSignedIn(iPad)) 5004 { 5005#ifdef _DURANGO 5006 if(!g_NetworkManager.IsLocalGame() && ProfileManager.IsSignedInLive(iPad) && ProfileManager.AllowedToPlayMultiplayer(iPad)) 5007 { 5008 ProfileManager.CheckMultiplayerPrivileges(iPad, true, &inGameSignInCheckAllPrivilegesCallback, pMinecraftClass); 5009 } 5010 else 5011#endif 5012 if( !g_NetworkManager.SessionHasSpace() ) 5013 { 5014 UINT uiIDA[1]; 5015 uiIDA[0]=IDS_OK; 5016 ui.RequestErrorMessage(IDS_MULTIPLAYER_FULL_TITLE, IDS_MULTIPLAYER_FULL_TEXT, uiIDA, 1); 5017#ifdef _DURANGO 5018 ProfileManager.RemoveGamepadFromGame(iPad); 5019#endif 5020 } 5021 // if this is a local game then profiles just need to be signed in 5022 else if( g_NetworkManager.IsLocalGame() || (ProfileManager.IsSignedInLive(iPad) && ProfileManager.AllowedToPlayMultiplayer(iPad)) ) 5023 { 5024#ifdef __ORBIS__ 5025 bool contentRestricted = false; 5026 ProfileManager.GetChatAndContentRestrictions(iPad,false,NULL,&contentRestricted,NULL); // TODO! 5027 5028 if (!g_NetworkManager.IsLocalGame() && contentRestricted) 5029 { 5030 ui.RequestContentRestrictedMessageBox(IDS_NO_MULTIPLAYER_PRIVILEGE_TITLE, IDS_CONTENT_RESTRICTION, iPad); 5031 } 5032 else if(!g_NetworkManager.IsLocalGame() && !ProfileManager.HasPlayStationPlus(iPad)) 5033 { 5034 pMinecraftClass->m_pPsPlusUpsell = new PsPlusUpsellWrapper(iPad); 5035 pMinecraftClass->m_pPsPlusUpsell->displayUpsell(); 5036 } 5037 else 5038#endif 5039 if( pMinecraftClass->level->isClientSide ) 5040 { 5041 pMinecraftClass->addLocalPlayer(iPad); 5042 } 5043 else 5044 { 5045 // create the local player for the iPad 5046 shared_ptr<Player> player = pMinecraftClass->localplayers[iPad]; 5047 if( player == NULL) 5048 { 5049 player = pMinecraftClass->createExtraLocalPlayer(iPad, (convStringToWstring( ProfileManager.GetGamertag(iPad) )).c_str(), iPad, pMinecraftClass->level->dimension->id); 5050 } 5051 } 5052 } 5053 else if( ProfileManager.IsSignedInLive(ProfileManager.GetPrimaryPad()) && !ProfileManager.AllowedToPlayMultiplayer(iPad) ) 5054 { 5055 // 4J Stu - Don't allow converting to guests as we don't allow any guest sign-in while in the game 5056 // Fix for #66516 - TCR #124: MPS Guest Support ; #001: BAS Game Stability: TU8: The game crashes when second Guest signs-in on console which takes part in Xbox LIVE multiplayer session. 5057 //ProfileManager.RequestConvertOfflineToGuestUI( &Minecraft::InGame_SignInReturned, pMinecraftClass,iPad); 5058 UINT uiIDA[1]; 5059 uiIDA[0]=IDS_CONFIRM_OK; 5060 ui.RequestErrorMessage( IDS_NO_MULTIPLAYER_PRIVILEGE_TITLE, IDS_NO_MULTIPLAYER_PRIVILEGE_JOIN_TEXT, uiIDA,1,iPad); 5061#ifdef _DURANGO 5062 ProfileManager.RemoveGamepadFromGame(iPad); 5063#endif 5064 } 5065 } 5066 } 5067 return 0; 5068} 5069 5070void Minecraft::tickAllConnections() 5071{ 5072 int oldIdx = getLocalPlayerIdx(); 5073 for(unsigned int i = 0; i < XUSER_MAX_COUNT; i++ ) 5074 { 5075 shared_ptr<MultiplayerLocalPlayer> mplp = localplayers[i]; 5076 if( mplp && mplp->connection) 5077 { 5078 setLocalPlayerIdx(i); 5079 mplp->connection->tick(); 5080 } 5081 } 5082 setLocalPlayerIdx(oldIdx); 5083} 5084 5085bool Minecraft::addPendingClientTextureRequest(const wstring &textureName) 5086{ 5087 AUTO_VAR(it, find( m_pendingTextureRequests.begin(), m_pendingTextureRequests.end(), textureName)); 5088 if( it == m_pendingTextureRequests.end() ) 5089 { 5090 m_pendingTextureRequests.push_back(textureName); 5091 return true; 5092 } 5093 return false; 5094} 5095 5096void Minecraft::handleClientTextureReceived(const wstring &textureName) 5097{ 5098 AUTO_VAR(it, find( m_pendingTextureRequests.begin(), m_pendingTextureRequests.end(), textureName)); 5099 if( it != m_pendingTextureRequests.end() ) 5100 { 5101 m_pendingTextureRequests.erase(it); 5102 } 5103} 5104 5105unsigned int Minecraft::getCurrentTexturePackId() 5106{ 5107 return skins->getSelected()->getId(); 5108} 5109 5110ColourTable *Minecraft::getColourTable() 5111{ 5112 TexturePack *selected = skins->getSelected(); 5113 5114 ColourTable *colours = selected->getColourTable(); 5115 5116 if(colours == NULL) 5117 { 5118 colours = skins->getDefault()->getColourTable(); 5119 } 5120 5121 return colours; 5122} 5123 5124#if defined __ORBIS__ 5125int Minecraft::MustSignInReturnedPSN(void *pParam, int iPad, C4JStorage::EMessageResult result) 5126{ 5127 Minecraft* pMinecraft = (Minecraft *)pParam; 5128 5129 if(result == C4JStorage::EMessage_ResultAccept) 5130 { 5131 SQRNetworkManager_Orbis::AttemptPSNSignIn(&Minecraft::InGame_SignInReturned, pMinecraft, false, iPad); 5132 } 5133 5134 return 0; 5135} 5136#endif 5137