diff --git a/.clang-format b/.clang-format new file mode 100644 index 000000000..a4d4a4c2a --- /dev/null +++ b/.clang-format @@ -0,0 +1,53 @@ +--- +BasedOnStyle: Microsoft +AccessModifierOffset: -2 +BraceWrapping: + AfterCaseLabel: false + AfterClass: true + AfterControlStatement: Always + AfterEnum: true + AfterExternBlock: true + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: true + AfterStruct: true + AfterUnion: false + BeforeCatch: true + BeforeElse: true + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +ColumnLimit: 0 +IncludeBlocks: Preserve +IndentAccessModifiers: false +IndentCaseBlocks: true +IndentCaseLabels: false +IndentExportBlock: true +IndentExternBlock: AfterExternBlock +IndentGotoLabels: false +IndentPPDirectives: None +IndentWidth: 4 +InsertBraces: true +InsertNewlineAtEOF: true +NamespaceIndentation: None +PointerAlignment: Right +RemoveParentheses: Leave +RemoveSemicolon: false +SeparateDefinitionBlocks: Leave +ShortNamespaceLines: 1 +SkipMacroDefinitionBody: false +SortIncludes: CaseSensitive +SpacesInParens: Never +SpacesInParensOptions: + ExceptDoubleParentheses: false + InCStyleCasts: false + InConditionalStatements: false + InEmptyParentheses: false + Other: false +SpacesInSquareBrackets: false +Standard: Latest +TabWidth: 4 +UseTab: Never diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 9578777cb..a1c3e74aa 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,23 +1,23 @@ -# Pull Request - -## Note: IF YOUR PR CHANGES THE GAME BEHAVIOR VISIBLY, REMEMBER TO ATTACH A GAMEPLAY FOOTAGE (or at least a screenshot) OF YOU *ACTUALLY* PLAYING THE GAME WITH YOUR CHANGES. Untested PRs are *NOT* welcome. Please don't forget to describe what did you do in each commit in your PR. + ## Description -Briefly describe the changes this PR introduces. + ## Changes ### Previous Behavior -*Describe how the code behaved before this change.* + ### Root Cause -*Explain the core reason behind the erroneous/old behavior (e.g., bug, design flaw, missing edge case).* + ### New Behavior -*Describe how the code behaves after this change.* + ### Fix Implementation -*Detail exactly how the issue was resolved (specific code changes, algorithms, logic flows).* + ## Related Issues - Fixes #[issue-number] diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 0affa845e..4ef1274d2 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -8,6 +8,7 @@ on: paths-ignore: - '.gitignore' - '*.md' + - '.github/*.md' jobs: build: @@ -35,4 +36,8 @@ jobs: with: tag_name: nightly name: Nightly Release - files: LCEWindows64.zip \ No newline at end of file + body: Requires at least Windows 7 and DirectX 11 compatible GPU to run. Compiled with MSVC v14.44.35207 in Release mode with Whole Program Optimization, as well as `/O2 /Ot /Oi /Ob3 /GF /fp:precise`. + files: | + LCEWindows64.zip + ./x64/Release/Minecraft.Client.exe + ./x64/Release/Minecraft.Client.pdb diff --git a/CMakeLists.txt b/CMakeLists.txt index 825cdbab3..cceeb0569 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,6 +30,17 @@ if(MSVC) set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") endif() +function(configure_msvc_target target) + target_compile_options(${target} PRIVATE + $<$>,$>:/W3> + $<$,$>:/W0> + $<$:/MP> + $<$:/FS> + $<$:/EHsc> + $<$,$>:/GL /O2 /Oi /GT /GF> + ) +endfunction() + # minecraftworld is shared with every backend. include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/WorldSources.cmake") list(TRANSFORM MINECRAFT_WORLD_SOURCES PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.World/") @@ -47,10 +58,7 @@ target_compile_definitions(MinecraftWorld PRIVATE $<$:_CROSS64> ) if(MSVC) - target_compile_options(MinecraftWorld PRIVATE - $<$:/W3 /MP> - $<$:/EHsc> - ) + configure_msvc_target(MinecraftWorld) endif() include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/ClientSources.cmake") @@ -82,24 +90,53 @@ if(BACKEND STREQUAL "Windows64") list(TRANSFORM MINECRAFT_CLIENT_SOURCES PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/") - add_executable(MinecraftClient WIN32 ${MINECRAFT_CLIENT_SOURCES}) - target_include_directories(MinecraftClient PRIVATE - "${CMAKE_CURRENT_SOURCE_DIR}" - "${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Windows64/Iggy/include" - "${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Xbox/Sentient/Include" - "${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.World/x64headers" - ) - target_compile_definitions(MinecraftClient PRIVATE - $<$:_LARGE_WORLDS;_DEBUG_MENUS_ENABLED;_DEBUG;_CRT_NON_CONFORMING_SWPRINTFS;_CRT_SECURE_NO_WARNINGS;_WINDOWS64> - $<$>:_LARGE_WORLDS;_DEBUG_MENUS_ENABLED;_CRT_NON_CONFORMING_SWPRINTFS;_CRT_SECURE_NO_WARNINGS;_WINDOWS64> - ) - if(MSVC) - target_compile_options(MinecraftClient PRIVATE - $<$:/W /MP> - $<$:/EHsc> - ) +include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/ClientSources.cmake") + +# each backend is assumed to change these in some way. +set(BACKEND_SOURCES + "glWrapper.cpp" + "stubs.cpp" + "stdafx.cpp" + "iob_shim.asm" + "Windows64/Iggy/gdraw/gdraw_d3d11.cpp" + "Windows64/KeyboardMouseInput.cpp" + "Windows64/Leaderboards/WindowsLeaderboardManager.cpp" + "Windows64/Windows64_App.cpp" + "Windows64/Windows64_Minecraft.cpp" + "Windows64/Windows64_UIController.cpp" + "Windows64/Network/WinsockNetLayer.cpp" +) + +# remove backend specific stuff +set(CLIENT_SHARED_SOURCES ${MINECRAFT_CLIENT_SOURCES}) +list(REMOVE_ITEM CLIENT_SHARED_SOURCES ${BACKEND_SOURCES}) +list(TRANSFORM CLIENT_SHARED_SOURCES PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/") + +if(BACKEND STREQUAL "Windows64") + if(NOT WIN32) + message(FATAL_ERROR "The Windows64 backend can only be built on Windows.") endif() + list(TRANSFORM MINECRAFT_CLIENT_SOURCES PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/") + +add_executable(MinecraftClient WIN32 ${MINECRAFT_CLIENT_SOURCES}) +target_include_directories(MinecraftClient PRIVATE + "${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client" + "${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Windows64/Iggy/include" + "${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Xbox/Sentient/Include" + "${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.World/x64headers" +) +target_compile_definitions(MinecraftClient PRIVATE + $<$:_LARGE_WORLDS;_DEBUG_MENUS_ENABLED;_DEBUG;_CRT_NON_CONFORMING_SWPRINTFS;_CRT_SECURE_NO_WARNINGS;_WINDOWS64> + $<$>:_LARGE_WORLDS;_DEBUG_MENUS_ENABLED;_CRT_NON_CONFORMING_SWPRINTFS;_CRT_SECURE_NO_WARNINGS;_WINDOWS64> +) +if(MSVC) + configure_msvc_target(MinecraftClient) + target_compile_options(MinecraftClient PRIVATE + $<$:/LTCG /INCREMENTAL:NO> + ) +endif() + set_target_properties(MinecraftClient PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "$" ) diff --git a/Minecraft.Client/Chunk.cpp b/Minecraft.Client/Chunk.cpp index 98793210a..9ba2fcee7 100644 --- a/Minecraft.Client/Chunk.cpp +++ b/Minecraft.Client/Chunk.cpp @@ -52,7 +52,7 @@ Chunk::Chunk(Level *level, LevelRenderer::rteMap &globalRenderableTileEntities, : globalRenderableTileEntities( &globalRenderableTileEntities ), globalRenderableTileEntities_cs(&globalRenderableTileEntities_cs) { clipChunk->visible = false; - bb = NULL; + bb = nullptr; id = 0; this->level = level; @@ -101,15 +101,15 @@ void Chunk::setPos(int x, int y, int z) float g = 6.0f; // 4J - changed to just set the value rather than make a new one, if we've already created storage - if( bb == NULL ) + if( !bb ) { - bb = AABB::newPermanent(-g, -g, -g, XZSIZE+g, SIZE+g, XZSIZE+g); + bb = shared_ptr(AABB::newPermanent(-g, -g, -g, XZSIZE+g, SIZE+g, XZSIZE+g)); } - else - { + else + { // 4J MGH - bounds are relative to the position now, so the AABB will be setup already, either above, or from the tesselator bounds. // bb->set(-g, -g, -g, SIZE+g, SIZE+g, SIZE+g); - } + } clipChunk->aabb[0] = bb->x0 + x; clipChunk->aabb[1] = bb->y0 + y; clipChunk->aabb[2] = bb->z0 + z; @@ -154,6 +154,7 @@ void Chunk::translateToPos() Chunk::Chunk() { + bb = nullptr; } void Chunk::makeCopyForRebuild(Chunk *source) @@ -998,7 +999,7 @@ int Chunk::getList(int layer) void Chunk::cull(Culler *culler) { - clipChunk->visible = culler->isVisible(bb); + clipChunk->visible = culler->isVisible(bb.get()); } void Chunk::renderBB() @@ -1027,10 +1028,7 @@ void Chunk::clearDirty() #endif } -Chunk::~Chunk() -{ - delete bb; -} +Chunk::~Chunk() = default; bool Chunk::emptyFlagSet(int layer) { diff --git a/Minecraft.Client/Chunk.h b/Minecraft.Client/Chunk.h index af442b9bd..6bb48602c 100644 --- a/Minecraft.Client/Chunk.h +++ b/Minecraft.Client/Chunk.h @@ -46,11 +46,11 @@ public: int xRender, yRender, zRender; int xRenderOffs, yRenderOffs, zRenderOffs; - int xm, ym, zm; - AABB *bb; + int xm, ym, zm; + shared_ptr bb; ClipChunk *clipChunk; - int id; + int id; //public: // vector > renderableTileEntities; // 4J - removed diff --git a/Minecraft.Client/ClientConnection.cpp b/Minecraft.Client/ClientConnection.cpp index 981913085..bf3395be2 100644 --- a/Minecraft.Client/ClientConnection.cpp +++ b/Minecraft.Client/ClientConnection.cpp @@ -55,6 +55,12 @@ #endif #include "DLCTexturePack.h" +#ifdef _WINDOWS64 +#include "Xbox\Network\NetworkPlayerXbox.h" +#include "Common\Network\PlatformNetworkManagerStub.h" +#endif + + #ifdef _DURANGO #include "Minecraft.World/DurangoStats.h" #include "Minecraft.World/GenericStats.h" @@ -421,7 +427,6 @@ void ClientConnection::handleAddEntity(shared_ptr packet) { case AddEntityPacket::MINECART: e = Minecart::createMinecart(level, x, y, z, packet->data); - break; case AddEntityPacket::FISH_HOOK: { // 4J Stu - Brought forward from 1.4 to be able to drop XP from fishing @@ -444,7 +449,7 @@ void ClientConnection::handleAddEntity(shared_ptr packet) } } - if (owner->instanceof(eTYPE_PLAYER)) + if (owner != NULL && owner->instanceof(eTYPE_PLAYER)) { shared_ptr player = dynamic_pointer_cast(owner); shared_ptr hook = shared_ptr( new FishingHook(level, x, y, z, player) ); @@ -793,7 +798,28 @@ void ClientConnection::handleAddPlayer(shared_ptr packet) if (networkPlayer != NULL) player->m_displayName = networkPlayer->GetDisplayName(); #else // On all other platforms display name is just gamertag so don't check with the network manager - player->m_displayName = player->name; + player->m_displayName = player->getName(); +#endif + +#ifdef _WINDOWS64 + { + PlayerUID pktXuid = player->getXuid(); + const PlayerUID WIN64_XUID_BASE = (PlayerUID)0xe000d45248242f2e; + if (pktXuid >= WIN64_XUID_BASE && pktXuid < WIN64_XUID_BASE + MINECRAFT_NET_MAX_PLAYERS) + { + BYTE smallId = (BYTE)(pktXuid - WIN64_XUID_BASE); + INetworkPlayer* np = g_NetworkManager.GetPlayerBySmallId(smallId); + if (np != NULL) + { + NetworkPlayerXbox* npx = (NetworkPlayerXbox*)np; + IQNetPlayer* qp = npx->GetQNetPlayer(); + if (qp != NULL && qp->m_gamertag[0] == 0) + { + wcsncpy_s(qp->m_gamertag, 32, packet->name.c_str(), _TRUNCATE); + } + } + } + } #endif // printf("\t\t\t\t%d: Add player\n",packet->id,packet->yRot); @@ -938,6 +964,39 @@ void ClientConnection::handleMoveEntitySmall(shared_ptr p void ClientConnection::handleRemoveEntity(shared_ptr packet) { +#ifdef _WINDOWS64 + if (!g_NetworkManager.IsHost()) + { + for (int i = 0; i < packet->ids.length; i++) + { + shared_ptr entity = getEntity(packet->ids[i]); + if (entity != NULL && entity->GetType() == eTYPE_PLAYER) + { + shared_ptr player = dynamic_pointer_cast(entity); + if (player != NULL) + { + PlayerUID xuid = player->getXuid(); + INetworkPlayer* np = g_NetworkManager.GetPlayerByXuid(xuid); + if (np != NULL) + { + NetworkPlayerXbox* npx = (NetworkPlayerXbox*)np; + IQNetPlayer* qp = npx->GetQNetPlayer(); + if (qp != NULL) + { + extern CPlatformNetworkManagerStub* g_pPlatformNetworkManager; + g_pPlatformNetworkManager->NotifyPlayerLeaving(qp); + qp->m_smallId = 0; + qp->m_isRemote = false; + qp->m_isHostPlayer = false; + qp->m_gamertag[0] = 0; + qp->SetCustomDataValue(0); + } + } + } + } + } + } +#endif for (int i = 0; i < packet->ids.length; i++) { level->removeEntity(packet->ids[i]); diff --git a/Minecraft.Client/Common/App_enums.h b/Minecraft.Client/Common/App_enums.h index db7bf70b3..e8e0d147e 100644 --- a/Minecraft.Client/Common/App_enums.h +++ b/Minecraft.Client/Common/App_enums.h @@ -829,6 +829,7 @@ enum EControllerActions ACTION_MENU_OTHER_STICK_LEFT, ACTION_MENU_OTHER_STICK_RIGHT, ACTION_MENU_PAUSEMENU, + ACTION_MENU_QUICK_MOVE, #ifdef _DURANGO ACTION_MENU_GTC_PAUSE, diff --git a/Minecraft.Client/Common/Media/MediaWindows64.arc b/Minecraft.Client/Common/Media/MediaWindows64.arc index 5ea229dca..9498b91d6 100644 Binary files a/Minecraft.Client/Common/Media/MediaWindows64.arc and b/Minecraft.Client/Common/Media/MediaWindows64.arc differ diff --git a/Minecraft.Client/Common/Network/GameNetworkManager.cpp b/Minecraft.Client/Common/Network/GameNetworkManager.cpp index 41a0bbb97..94345d19a 100644 --- a/Minecraft.Client/Common/Network/GameNetworkManager.cpp +++ b/Minecraft.Client/Common/Network/GameNetworkManager.cpp @@ -1978,7 +1978,7 @@ bool CGameNetworkManager::AllowedToPlayMultiplayer(int playerIdx) return ProfileManager.AllowedToPlayMultiplayer(playerIdx); } -char *CGameNetworkManager::GetOnlineName(int playerIdx) +const char *CGameNetworkManager::GetOnlineName(int playerIdx) { return ProfileManager.GetGamertag(playerIdx); } diff --git a/Minecraft.Client/Common/Network/GameNetworkManager.h b/Minecraft.Client/Common/Network/GameNetworkManager.h index 5127e028d..4a8cdac43 100644 --- a/Minecraft.Client/Common/Network/GameNetworkManager.h +++ b/Minecraft.Client/Common/Network/GameNetworkManager.h @@ -196,7 +196,7 @@ private: int GetLockedProfile(); bool IsSignedInLive(int playerIdx); bool AllowedToPlayMultiplayer(int playerIdx); - char *GetOnlineName(int playerIdx); + const char *GetOnlineName(int playerIdx); C4JThread::Event* m_hServerStoppedEvent; C4JThread::Event* m_hServerReadyEvent; diff --git a/Minecraft.Client/Common/Network/PlatformNetworkManagerStub.cpp b/Minecraft.Client/Common/Network/PlatformNetworkManagerStub.cpp index 637e93a43..3696bf85b 100644 --- a/Minecraft.Client/Common/Network/PlatformNetworkManagerStub.cpp +++ b/Minecraft.Client/Common/Network/PlatformNetworkManagerStub.cpp @@ -362,12 +362,23 @@ void CPlatformNetworkManagerStub::HostGame(int localUsersMask, bool bOnlineGame, #ifdef _WINDOWS64 int port = WIN64_NET_DEFAULT_PORT; + const char* bindIp = NULL; + if (g_Win64DedicatedServer) + { + if (g_Win64DedicatedServerPort > 0) + port = g_Win64DedicatedServerPort; + if (g_Win64DedicatedServerBindIP[0] != 0) + bindIp = g_Win64DedicatedServerBindIP; + } if (!WinsockNetLayer::IsActive()) - WinsockNetLayer::HostGame(port); + WinsockNetLayer::HostGame(port, bindIp); - const wchar_t* hostName = IQNet::m_player[0].m_gamertag; - unsigned int settings = app.GetGameHostOption(eGameHostOption_All); - WinsockNetLayer::StartAdvertising(port, hostName, settings, 0, 0, MINECRAFT_NET_VERSION); + if (WinsockNetLayer::IsActive()) + { + const wchar_t* hostName = IQNet::m_player[0].m_gamertag; + unsigned int settings = app.GetGameHostOption(eGameHostOption_All); + WinsockNetLayer::StartAdvertising(port, hostName, settings, 0, 0, MINECRAFT_NET_VERSION); + } #endif //#endif } diff --git a/Minecraft.Client/Common/Tutorial/ChoiceTask.cpp b/Minecraft.Client/Common/Tutorial/ChoiceTask.cpp index 1dcb95f56..b91378cdf 100644 --- a/Minecraft.Client/Common/Tutorial/ChoiceTask.cpp +++ b/Minecraft.Client/Common/Tutorial/ChoiceTask.cpp @@ -63,7 +63,7 @@ bool ChoiceTask::isCompleted() #ifdef _WINDOWS64 if (!m_bConfirmMappingComplete && (InputManager.GetValue(xboxPad, m_iConfirmMapping) > 0 - || KMInput.IsKeyDown(VK_RETURN))) + || g_KBMInput.IsKeyDown(VK_RETURN))) #else if (!m_bConfirmMappingComplete && InputManager.GetValue(xboxPad, m_iConfirmMapping) > 0) @@ -75,7 +75,7 @@ bool ChoiceTask::isCompleted() #ifdef _WINDOWS64 if (!m_bCancelMappingComplete && (InputManager.GetValue(xboxPad, m_iCancelMapping) > 0 - || KMInput.IsKeyDown('B'))) + || g_KBMInput.IsKeyDown('B'))) #else if (!m_bCancelMappingComplete && InputManager.GetValue(xboxPad, m_iCancelMapping) > 0) diff --git a/Minecraft.Client/Common/Tutorial/InfoTask.cpp b/Minecraft.Client/Common/Tutorial/InfoTask.cpp index b78bfa08f..52d1c5819 100644 --- a/Minecraft.Client/Common/Tutorial/InfoTask.cpp +++ b/Minecraft.Client/Common/Tutorial/InfoTask.cpp @@ -72,7 +72,7 @@ bool InfoTask::isCompleted() if(!current) { #ifdef _WINDOWS64 - if (InputManager.GetValue(pMinecraft->player->GetXboxPad(), (*it).first) > 0 || KMInput.IsKeyDown(VK_SPACE)) + if (InputManager.GetValue(pMinecraft->player->GetXboxPad(), (*it).first) > 0 || g_KBMInput.IsKeyDown(VK_SPACE)) #else if( InputManager.GetValue(pMinecraft->player->GetXboxPad(), (*it).first) > 0) #endif diff --git a/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.cpp b/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.cpp index 4eb84da69..5fd3fc09d 100644 --- a/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.cpp +++ b/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.cpp @@ -22,6 +22,12 @@ #include #endif +#ifdef _WINDOWS64 +#include "..\..\Windows64\KeyboardMouseInput.h" + +SavedInventoryCursorPos g_savedInventoryCursorPos = { 0.0f, 0.0f, false }; +#endif + IUIScene_AbstractContainerMenu::IUIScene_AbstractContainerMenu() { m_menu = NULL; @@ -483,6 +489,34 @@ void IUIScene_AbstractContainerMenu::onMouseTick() } #endif +#ifdef _WINDOWS64 + if (!g_KBMInput.IsMouseGrabbed() && g_KBMInput.IsKBMActive()) + { + int deltaX = g_KBMInput.GetMouseDeltaX(); + int deltaY = g_KBMInput.GetMouseDeltaY(); + + extern HWND g_hWnd; + RECT rc; + GetClientRect(g_hWnd, &rc); + int winW = rc.right - rc.left; + int winH = rc.bottom - rc.top; + + if (winW > 0 && winH > 0) + { + float scaleX = (float)getMovieWidth() / (float)winW; + float scaleY = (float)getMovieHeight() / (float)winH; + + vPointerPos.x += (float)deltaX * scaleX; + vPointerPos.y += (float)deltaY * scaleY; + } + + if (deltaX != 0 || deltaY != 0) + { + bStickInput = true; + } + } +#endif + // Determine which slot the pointer is currently over. ESceneSection eSectionUnderPointer = eSectionNone; int iNewSlotX = -1; @@ -703,7 +737,11 @@ void IUIScene_AbstractContainerMenu::onMouseTick() // If there is no stick input, and we are over a slot, then snap pointer to slot centre. // 4J - TomK - only if this particular component allows so! - if(!m_bPointerDrivenByMouse && CanHaveFocus(eSectionUnderPointer)) +#ifdef _WINDOWS64 + if((g_KBMInput.IsMouseGrabbed() || !g_KBMInput.IsKBMActive()) && CanHaveFocus(eSectionUnderPointer)) +#else + if(CanHaveFocus(eSectionUnderPointer)) +#endif { vPointerPos.x = vSnapPos.x; vPointerPos.y = vSnapPos.y; @@ -1313,42 +1351,60 @@ bool IUIScene_AbstractContainerMenu::handleKeyDown(int iPad, int iAction, bool b #endif int buttonNum=0; // 0 = LeftMouse, 1 = RightMouse - BOOL quickKeyHeld=FALSE; // Represents shift key on PC - - BOOL validKeyPress = FALSE; + BOOL quickKeyHeld=false; // Represents shift key on PC + BOOL quickKeyDown = false; // Represents shift key on PC + BOOL validKeyPress = false; bool itemEditorKeyPress = false; // Ignore input from other players //if(pMinecraft->player->GetXboxPad()!=pInputData->UserIndex) return S_OK; - + switch(iAction) { #ifdef _DEBUG_MENUS_ENABLED case ACTION_MENU_OTHER_STICK_PRESS: itemEditorKeyPress = TRUE; break; -#endif +#endif case ACTION_MENU_A: #ifdef __ORBIS__ case ACTION_MENU_TOUCHPAD_PRESS: #endif - if(!bRepeat) + if (!bRepeat) { validKeyPress = TRUE; // Standard left click buttonNum = 0; - quickKeyHeld = FALSE; - - if( IsSectionSlotList( m_eCurrSection ) ) + if (g_KBMInput.IsKeyDown(VK_LSHIFT)) { - int currentIndex = getCurrentIndex( m_eCurrSection ) - getSectionStartOffset(m_eCurrSection); + { + validKeyPress = TRUE; - bool bSlotHasItem = !isSlotEmpty(m_eCurrSection, currentIndex); - if ( bSlotHasItem ) - ui.PlayUISFX(eSFX_Press); + // Shift and left click + buttonNum = 0; + quickKeyHeld = TRUE; + if (IsSectionSlotList(m_eCurrSection)) + { + int currentIndex = getCurrentIndex(m_eCurrSection) - getSectionStartOffset(m_eCurrSection); + + bool bSlotHasItem = !isSlotEmpty(m_eCurrSection, currentIndex); + if (bSlotHasItem) + ui.PlayUISFX(eSFX_Press); + } + } + } + else { + if (IsSectionSlotList(m_eCurrSection)) + { + int currentIndex = getCurrentIndex(m_eCurrSection) - getSectionStartOffset(m_eCurrSection); + + bool bSlotHasItem = !isSlotEmpty(m_eCurrSection, currentIndex); + if (bSlotHasItem) + ui.PlayUISFX(eSFX_Press); + } + // } - // } break; case ACTION_MENU_X: @@ -1370,6 +1426,7 @@ bool IUIScene_AbstractContainerMenu::handleKeyDown(int iPad, int iAction, bool b } } break; + case ACTION_MENU_Y: if(!bRepeat) { diff --git a/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.h b/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.h index fe79bf190..4877cfce8 100644 --- a/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.h +++ b/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.h @@ -1,5 +1,15 @@ #pragma once +#ifdef _WINDOWS64 +struct SavedInventoryCursorPos +{ + float x; + float y; + bool hasSavedPos; +}; +extern SavedInventoryCursorPos g_savedInventoryCursorPos; +#endif + // Uncomment to enable tap input detection to jump 1 slot. Doesn't work particularly well yet, and I feel the system does not need it. // Would probably be required if we decide to slow down the pointer movement. // 4J Stu - There was a request to be able to navigate the scenes with the dpad, so I have used much of the TAP_DETECTION @@ -265,4 +275,6 @@ protected: public: virtual int getPad() = 0; + virtual int getMovieWidth() = 0; + virtual int getMovieHeight() = 0; }; diff --git a/Minecraft.Client/Common/UI/IUIScene_CreativeMenu.cpp b/Minecraft.Client/Common/UI/IUIScene_CreativeMenu.cpp index 453d43f2a..1373c514f 100644 --- a/Minecraft.Client/Common/UI/IUIScene_CreativeMenu.cpp +++ b/Minecraft.Client/Common/UI/IUIScene_CreativeMenu.cpp @@ -223,7 +223,6 @@ void IUIScene_CreativeMenu::staticCtor() ITEM_AUX(Tile::woolCarpet_Id,13) // Green ITEM_AUX(Tile::woolCarpet_Id,12) // Brown -#if 0 ITEM_AUX(Tile::stained_glass_Id,14) // Red ITEM_AUX(Tile::stained_glass_Id,1) // Orange ITEM_AUX(Tile::stained_glass_Id,4) // Yellow @@ -257,7 +256,6 @@ void IUIScene_CreativeMenu::staticCtor() ITEM_AUX(Tile::stained_glass_pane_Id,15) // Black ITEM_AUX(Tile::stained_glass_pane_Id,13) // Green ITEM_AUX(Tile::stained_glass_pane_Id,12) // Brown -#endif #ifndef _CONTENT_PACKAGE DEF(eCreativeInventory_ArtToolsDecorations) @@ -278,40 +276,6 @@ void IUIScene_CreativeMenu::staticCtor() BuildFirework(list, FireworksItem::TYPE_CREEPER, DyePowderItem::BLUE, 1, true, false); BuildFirework(list, FireworksItem::TYPE_STAR, DyePowderItem::YELLOW, 1, false, false); BuildFirework(list, FireworksItem::TYPE_BIG, DyePowderItem::WHITE, 1, true, true); - - ITEM_AUX(Tile::stained_glass_Id,14) // Red - ITEM_AUX(Tile::stained_glass_Id,1) // Orange - ITEM_AUX(Tile::stained_glass_Id,4) // Yellow - ITEM_AUX(Tile::stained_glass_Id,5) // Lime - ITEM_AUX(Tile::stained_glass_Id,3) // Light Blue - ITEM_AUX(Tile::stained_glass_Id,9) // Cyan - ITEM_AUX(Tile::stained_glass_Id,11) // Blue - ITEM_AUX(Tile::stained_glass_Id,10) // Purple - ITEM_AUX(Tile::stained_glass_Id,2) // Magenta - ITEM_AUX(Tile::stained_glass_Id,6) // Pink - ITEM_AUX(Tile::stained_glass_Id,0) // White - ITEM_AUX(Tile::stained_glass_Id,8) // Light Gray - ITEM_AUX(Tile::stained_glass_Id,7) // Gray - ITEM_AUX(Tile::stained_glass_Id,15) // Black - ITEM_AUX(Tile::stained_glass_Id,13) // Green - ITEM_AUX(Tile::stained_glass_Id,12) // Brown - - ITEM_AUX(Tile::stained_glass_pane_Id,14) // Red - ITEM_AUX(Tile::stained_glass_pane_Id,1) // Orange - ITEM_AUX(Tile::stained_glass_pane_Id,4) // Yellow - ITEM_AUX(Tile::stained_glass_pane_Id,5) // Lime - ITEM_AUX(Tile::stained_glass_pane_Id,3) // Light Blue - ITEM_AUX(Tile::stained_glass_pane_Id,9) // Cyan - ITEM_AUX(Tile::stained_glass_pane_Id,11) // Blue - ITEM_AUX(Tile::stained_glass_pane_Id,10) // Purple - ITEM_AUX(Tile::stained_glass_pane_Id,2) // Magenta - ITEM_AUX(Tile::stained_glass_pane_Id,6) // Pink - ITEM_AUX(Tile::stained_glass_pane_Id,0) // White - ITEM_AUX(Tile::stained_glass_pane_Id,8) // Light Gray - ITEM_AUX(Tile::stained_glass_pane_Id,7) // Gray - ITEM_AUX(Tile::stained_glass_pane_Id,15) // Black - ITEM_AUX(Tile::stained_glass_pane_Id,13) // Green - ITEM_AUX(Tile::stained_glass_pane_Id,12) // Brown } #endif @@ -858,8 +822,9 @@ IUIScene_CreativeMenu::TabSpec::TabSpec(LPCWSTR icon, int descriptionId, int sta } } - m_staticPerPage = MAX_SIZE - dynamicItems; - m_pages = (int)ceil((float)m_staticItems / m_staticPerPage); + m_staticPerPage = columns; + const int totalRows = (m_staticItems + columns - 1) / columns; + m_pages = std::max(1, totalRows - 5 + 1); } IUIScene_CreativeMenu::TabSpec::~TabSpec() @@ -894,7 +859,7 @@ void IUIScene_CreativeMenu::TabSpec::populateMenu(AbstractContainerMenu *menu, i for(; currentGroup < m_staticGroupsCount; ++currentGroup) { int size = categoryGroups[m_staticGroupsA[currentGroup]].size(); - if( currentIndex + size < startIndex) + if( currentIndex + size <= startIndex) { currentIndex += size; continue; @@ -944,7 +909,7 @@ void IUIScene_CreativeMenu::TabSpec::populateMenu(AbstractContainerMenu *menu, i for(; currentGroup < m_debugGroupsCount; ++currentGroup) { int size = categoryGroups[m_debugGroupsA[currentGroup]].size(); - if( currentIndex + size < startIndex) + if( currentIndex + size <= startIndex) { currentIndex += size; continue; @@ -985,7 +950,9 @@ unsigned int IUIScene_CreativeMenu::TabSpec::getPageCount() #ifndef _CONTENT_PACKAGE if(app.DebugArtToolsOn()) { - return (int)ceil((float)(m_staticItems + m_debugItems) / m_staticPerPage); + int totalItems = m_staticItems + m_debugItems; + const int totalRows = (totalItems + columns - 1) / columns; + return std::max(1, totalRows - rows + 1); } else #endif @@ -1144,7 +1111,15 @@ void IUIScene_CreativeMenu::handleAdditionalKeyPress(int iAction) } break; case ACTION_MENU_OTHER_STICK_DOWN: - ++m_tabPage[m_curTab]; + { + int pageStep = TabSpec::rows; +#ifdef _WINDOWS64 + if (g_KBMInput.WasMouseWheelConsumed()) + { + pageStep = 1; + } +#endif + m_tabPage[m_curTab] += pageStep; if(m_tabPage[m_curTab] >= specs[m_curTab]->getPageCount()) { m_tabPage[m_curTab] = specs[m_curTab]->getPageCount() - 1; @@ -1153,9 +1128,18 @@ void IUIScene_CreativeMenu::handleAdditionalKeyPress(int iAction) { switchTab(m_curTab); } + } break; case ACTION_MENU_OTHER_STICK_UP: - --m_tabPage[m_curTab]; + { + int pageStep = TabSpec::rows; +#ifdef _WINDOWS64 + if (g_KBMInput.WasMouseWheelConsumed()) + { + pageStep = 1; + } +#endif + m_tabPage[m_curTab] -= pageStep; if(m_tabPage[m_curTab] < 0) { m_tabPage[m_curTab] = 0; @@ -1164,6 +1148,7 @@ void IUIScene_CreativeMenu::handleAdditionalKeyPress(int iAction) { switchTab(m_curTab); } + } break; } } diff --git a/Minecraft.Client/Common/UI/UIControl.cpp b/Minecraft.Client/Common/UI/UIControl.cpp index d2ccb5cec..056193bc9 100644 --- a/Minecraft.Client/Common/UI/UIControl.cpp +++ b/Minecraft.Client/Common/UI/UIControl.cpp @@ -42,7 +42,6 @@ bool UIControl::setupControl(UIScene *scene, IggyValuePath *parent, const string return res; } -#ifdef __PSVITA__ void UIControl::UpdateControl() { F64 fx, fy, fwidth, fheight; @@ -55,7 +54,6 @@ void UIControl::UpdateControl() m_width = (S32)Math::round(fwidth); m_height = (S32)Math::round(fheight); } -#endif // __PSVITA__ void UIControl::ReInit() { diff --git a/Minecraft.Client/Common/UI/UIControl.h b/Minecraft.Client/Common/UI/UIControl.h index e37f04de5..29770df28 100644 --- a/Minecraft.Client/Common/UI/UIControl.h +++ b/Minecraft.Client/Common/UI/UIControl.h @@ -61,8 +61,8 @@ public: UIControl(); virtual bool setupControl(UIScene *scene, IggyValuePath *parent, const string &controlName); -#ifdef __PSVITA__ void UpdateControl(); +#ifdef __PSVITA__ void setHidden(bool bHidden) {m_bHidden=bHidden;} bool getHidden(void) {return m_bHidden;} #endif diff --git a/Minecraft.Client/Common/UI/UIController.cpp b/Minecraft.Client/Common/UI/UIController.cpp index e0d74620d..1d438548a 100644 --- a/Minecraft.Client/Common/UI/UIController.cpp +++ b/Minecraft.Client/Common/UI/UIController.cpp @@ -2,6 +2,8 @@ #include "UIController.h" #include "UI.h" #include "UIScene.h" + +#include "UIControl_Slider.h" #include "Minecraft.World/StringHelpers.h" #include "Minecraft.Client/LocalPlayer.h" #include "Minecraft.Client/DLCTexturePack.h" @@ -11,6 +13,9 @@ #include "Minecraft.Client/EnderDragonRenderer.h" #include "Minecraft.Client/MultiPlayerLocalPlayer.h" #include "UIFontData.h" +#ifdef _WINDOWS64 +#include "..\..\Windows64\KeyboardMouseInput.h" +#endif #ifdef __PSVITA__ #include #endif @@ -41,7 +46,7 @@ #elif defined __PSVITA__ #include "PSVita\Iggy\include\iggyperfmon.h" #include "PSVita\Iggy\include\iggyperfmon_psp2.h" -#elif defined __WINDOWS64 +#elif defined _WINDOWS64 #include "Windows64\Iggy\include\iggyperfmon.h" #endif @@ -52,6 +57,21 @@ bool UIController::ms_bReloadSkinCSInitialised = false; DWORD UIController::m_dwTrialTimerLimitSecs=DYNAMIC_CONFIG_DEFAULT_TRIAL_TIME; +#ifdef _WINDOWS64 +static UIControl_Slider *FindSliderById(UIScene *pScene, int sliderId) +{ + vector *controls = pScene->GetControls(); + if (!controls) return NULL; + for (size_t i = 0; i < controls->size(); ++i) + { + UIControl *ctrl = (*controls)[i]; + if (ctrl && ctrl->getControlType() == UIControl::eSlider && ctrl->getId() == sliderId) + return (UIControl_Slider *)ctrl; + } + return NULL; +} +#endif + static void RADLINK WarningCallback(void *user_callback_data, Iggy *player, IggyResult code, const char *message) { //enum IggyResult{ IGGY_RESULT_SUCCESS = 0, IGGY_RESULT_Warning_None = 0, @@ -216,6 +236,10 @@ UIController::UIController() m_currentRenderViewport = C4JRender::VIEWPORT_TYPE_FULLSCREEN; m_bCustomRenderPosition = false; m_winUserIndex = 0; + m_mouseDraggingSliderScene = eUIScene_COUNT; + m_mouseDraggingSliderId = -1; + m_lastHoverMouseX = -1; + m_lastHoverMouseY = -1; m_accumulatedTicks = 0; m_lastUiSfx = 0; @@ -761,6 +785,168 @@ void UIController::tickInput() else #endif { +#ifdef _WINDOWS64 + if (!g_KBMInput.IsMouseGrabbed() && g_KBMInput.IsKBMActive()) + { + UIScene *pScene = NULL; + for (int grp = 0; grp < eUIGroup_COUNT && !pScene; ++grp) + { + pScene = m_groups[grp]->GetTopScene(eUILayer_Debug); + if (!pScene) pScene = m_groups[grp]->GetTopScene(eUILayer_Tooltips); + if (!pScene) pScene = m_groups[grp]->GetTopScene(eUILayer_Error); + if (!pScene) pScene = m_groups[grp]->GetTopScene(eUILayer_Alert); + if (!pScene) pScene = m_groups[grp]->GetTopScene(eUILayer_Popup); + if (!pScene) pScene = m_groups[grp]->GetTopScene(eUILayer_Fullscreen); + if (!pScene) pScene = m_groups[grp]->GetTopScene(eUILayer_Scene); + } + if (pScene && pScene->getMovie()) + { + Iggy *movie = pScene->getMovie(); + int rawMouseX = g_KBMInput.GetMouseX(); + int rawMouseY = g_KBMInput.GetMouseY(); + F32 mouseX = (F32)rawMouseX; + F32 mouseY = (F32)rawMouseY; + + extern HWND g_hWnd; + if (g_hWnd) + { + RECT rc; + GetClientRect(g_hWnd, &rc); + int winW = rc.right - rc.left; + int winH = rc.bottom - rc.top; + if (winW > 0 && winH > 0) + { + mouseX = mouseX * (m_fScreenWidth / (F32)winW); + mouseY = mouseY * (m_fScreenHeight / (F32)winH); + } + } + + // Only update hover focus when the mouse has actually moved, + // so that mouse-wheel scrolling can change list selection + // without the hover immediately snapping focus back. + bool mouseMoved = (rawMouseX != m_lastHoverMouseX || rawMouseY != m_lastHoverMouseY); + m_lastHoverMouseX = rawMouseX; + m_lastHoverMouseY = rawMouseY; + + if (mouseMoved) + { + IggyFocusHandle currentFocus = IGGY_FOCUS_NULL; + IggyFocusableObject focusables[64]; + S32 numFocusables = 0; + IggyPlayerGetFocusableObjects(movie, ¤tFocus, focusables, 64, &numFocusables); + + if (numFocusables > 0 && numFocusables <= 64) + { + IggyFocusHandle hitObject = IGGY_FOCUS_NULL; + for (S32 i = 0; i < numFocusables; ++i) + { + if (mouseX >= focusables[i].x0 && mouseX <= focusables[i].x1 && + mouseY >= focusables[i].y0 && mouseY <= focusables[i].y1) + { + hitObject = focusables[i].object; + break; + } + } + + if (hitObject != currentFocus) + { + IggyPlayerSetFocusRS(movie, hitObject, 0); + } + } + } + + // Convert mouse to scene/movie coordinates for slider hit testing + F32 sceneMouseX = mouseX; + F32 sceneMouseY = mouseY; + { + S32 displayWidth = 0, displayHeight = 0; + pScene->GetParentLayer()->getRenderDimensions(displayWidth, displayHeight); + if (displayWidth > 0 && displayHeight > 0) + { + sceneMouseX = mouseX * ((F32)pScene->getRenderWidth() / (F32)displayWidth); + sceneMouseY = mouseY * ((F32)pScene->getRenderHeight() / (F32)displayHeight); + } + } + + // Get main panel offset (controls are positioned relative to it) + S32 panelOffsetX = 0, panelOffsetY = 0; + UIControl *pMainPanel = pScene->GetMainPanel(); + if (pMainPanel) + { + pMainPanel->UpdateControl(); + panelOffsetX = pMainPanel->getXPos(); + panelOffsetY = pMainPanel->getYPos(); + } + + bool leftPressed = g_KBMInput.IsMouseButtonPressed(KeyboardMouseInput::MOUSE_LEFT); + bool leftDown = leftPressed || g_KBMInput.IsMouseButtonDown(KeyboardMouseInput::MOUSE_LEFT); + + if (m_mouseDraggingSliderScene != eUIScene_COUNT && m_mouseDraggingSliderScene != pScene->getSceneType()) + { + m_mouseDraggingSliderScene = eUIScene_COUNT; + m_mouseDraggingSliderId = -1; + } + + if (leftPressed) + { + vector *controls = pScene->GetControls(); + if (controls) + { + for (size_t i = 0; i < controls->size(); ++i) + { + UIControl *ctrl = (*controls)[i]; + if (!ctrl || ctrl->getControlType() != UIControl::eSlider || !ctrl->getVisible()) + continue; + + UIControl_Slider *pSlider = (UIControl_Slider *)ctrl; + pSlider->UpdateControl(); + S32 cx = pSlider->getXPos() + panelOffsetX; + S32 cy = pSlider->getYPos() + panelOffsetY; + S32 cw = pSlider->GetRealWidth(); + S32 ch = pSlider->getHeight(); + if (cw <= 0 || ch <= 0) + continue; + + if (sceneMouseX >= cx && sceneMouseX <= cx + cw && sceneMouseY >= cy && sceneMouseY <= cy + ch) + { + m_mouseDraggingSliderScene = pScene->getSceneType(); + m_mouseDraggingSliderId = pSlider->getId(); + break; + } + } + } + } + + if (leftDown && m_mouseDraggingSliderScene == pScene->getSceneType() && m_mouseDraggingSliderId >= 0) + { + UIControl_Slider *pSlider = FindSliderById(pScene, m_mouseDraggingSliderId); + if (pSlider && pSlider->getVisible()) + { + pSlider->UpdateControl(); + S32 sliderX = pSlider->getXPos() + panelOffsetX; + S32 sliderWidth = pSlider->GetRealWidth(); + if (sliderWidth > 0) + { + float fNewSliderPos = (sceneMouseX - (float)sliderX) / (float)sliderWidth; + if (fNewSliderPos < 0.0f) fNewSliderPos = 0.0f; + if (fNewSliderPos > 1.0f) fNewSliderPos = 1.0f; + pSlider->SetSliderTouchPos(fNewSliderPos); + } + } + else + { + m_mouseDraggingSliderScene = eUIScene_COUNT; + m_mouseDraggingSliderId = -1; + } + } + else if (!leftDown) + { + m_mouseDraggingSliderScene = eUIScene_COUNT; + m_mouseDraggingSliderId = -1; + } + } + } +#endif handleInput(); ++m_accumulatedTicks; } @@ -995,27 +1181,59 @@ void UIController::handleKeyPress(unsigned int iPad, unsigned int key) released = InputManager.ButtonReleased(iPad,key); // Toggle #ifdef _WINDOWS64 - // Keyboard menu input for player 0 if (iPad == 0) { - bool kbDown = false, kbPressed = false, kbReleased = false; - switch(key) + int vk = 0; + switch (key) { - case ACTION_MENU_UP: kbDown = KMInput.IsKeyDown(VK_UP); kbPressed = KMInput.IsKeyPressed(VK_UP); kbReleased = KMInput.IsKeyReleased(VK_UP); break; - case ACTION_MENU_DOWN: kbDown = KMInput.IsKeyDown(VK_DOWN); kbPressed = KMInput.IsKeyPressed(VK_DOWN); kbReleased = KMInput.IsKeyReleased(VK_DOWN); break; - case ACTION_MENU_LEFT: kbDown = KMInput.IsKeyDown(VK_LEFT); kbPressed = KMInput.IsKeyPressed(VK_LEFT); kbReleased = KMInput.IsKeyReleased(VK_LEFT); break; - case ACTION_MENU_RIGHT: kbDown = KMInput.IsKeyDown(VK_RIGHT); kbPressed = KMInput.IsKeyPressed(VK_RIGHT); kbReleased = KMInput.IsKeyReleased(VK_RIGHT); break; - case ACTION_MENU_OK: kbDown = KMInput.IsKeyDown(VK_RETURN); kbPressed = KMInput.IsKeyPressed(VK_RETURN); kbReleased = KMInput.IsKeyReleased(VK_RETURN); break; - case ACTION_MENU_A: kbDown = KMInput.IsKeyDown(VK_RETURN); kbPressed = KMInput.IsKeyPressed(VK_RETURN); kbReleased = KMInput.IsKeyReleased(VK_RETURN); break; - case ACTION_MENU_CANCEL: kbDown = KMInput.IsKeyDown(VK_ESCAPE); kbPressed = KMInput.IsKeyPressed(VK_ESCAPE); kbReleased = KMInput.IsKeyReleased(VK_ESCAPE); break; - case ACTION_MENU_B: kbDown = KMInput.IsKeyDown(VK_ESCAPE); kbPressed = KMInput.IsKeyPressed(VK_ESCAPE); kbReleased = KMInput.IsKeyReleased(VK_ESCAPE); break; - case ACTION_MENU_PAUSEMENU: kbDown = KMInput.IsKeyDown(VK_ESCAPE); kbPressed = KMInput.IsKeyPressed(VK_ESCAPE); kbReleased = KMInput.IsKeyReleased(VK_ESCAPE); break; - case ACTION_MENU_LEFT_SCROLL: kbDown = KMInput.IsKeyDown('Q'); kbPressed = KMInput.IsKeyPressed('Q'); kbReleased = KMInput.IsKeyReleased('Q'); break; - case ACTION_MENU_RIGHT_SCROLL: kbDown = KMInput.IsKeyDown('E'); kbPressed = KMInput.IsKeyPressed('E'); kbReleased = KMInput.IsKeyReleased('E'); break; + case ACTION_MENU_OK: case ACTION_MENU_A: vk = VK_RETURN; break; + case ACTION_MENU_CANCEL: case ACTION_MENU_B: vk = VK_ESCAPE; break; + case ACTION_MENU_UP: vk = VK_UP; break; + case ACTION_MENU_DOWN: vk = VK_DOWN; break; + case ACTION_MENU_LEFT: vk = VK_LEFT; break; + case ACTION_MENU_RIGHT: vk = VK_RIGHT; break; + case ACTION_MENU_X: vk = 'R'; break; + case ACTION_MENU_Y: vk = VK_TAB; break; + case ACTION_MENU_LEFT_SCROLL: vk = 'Q'; break; + case ACTION_MENU_RIGHT_SCROLL: vk = 'E'; break; + case ACTION_MENU_PAGEUP: vk = VK_PRIOR; break; + case ACTION_MENU_PAGEDOWN: vk = VK_NEXT; break; + } + if (vk != 0) + { + if (g_KBMInput.IsKeyPressed(vk)) { pressed = true; down = true; } + if (g_KBMInput.IsKeyReleased(vk)) { released = true; down = false; } + if (!pressed && !released && g_KBMInput.IsKeyDown(vk)) { down = true; } + } + + if ((key == ACTION_MENU_OK || key == ACTION_MENU_A) && !g_KBMInput.IsMouseGrabbed()) + { + if (m_mouseDraggingSliderId < 0) + { + if (g_KBMInput.IsMouseButtonPressed(KeyboardMouseInput::MOUSE_LEFT)) { pressed = true; down = true; } + if (g_KBMInput.IsMouseButtonReleased(KeyboardMouseInput::MOUSE_LEFT)) { released = true; down = false; } + if (!pressed && !released && g_KBMInput.IsMouseButtonDown(KeyboardMouseInput::MOUSE_LEFT)) { down = true; } + } + } + + // Scroll wheel for list scrolling — only consume the wheel value when the + // action key actually matches, so the other direction isn't lost. + if (!g_KBMInput.IsMouseGrabbed() && (key == ACTION_MENU_OTHER_STICK_UP || key == ACTION_MENU_OTHER_STICK_DOWN)) + { + int wheel = g_KBMInput.PeekMouseWheel(); + if (key == ACTION_MENU_OTHER_STICK_UP && wheel > 0) + { + g_KBMInput.ConsumeMouseWheel(); + pressed = true; + down = true; + } + else if (key == ACTION_MENU_OTHER_STICK_DOWN && wheel < 0) + { + g_KBMInput.ConsumeMouseWheel(); + pressed = true; + down = true; + } } - pressed = pressed || kbPressed; - released = released || kbReleased; - down = down || kbDown; } #endif @@ -1444,7 +1662,7 @@ GDrawTexture * RADLINK UIController::TextureSubstitutionCreateCallback ( void * // 4J Stu - All our flash controls that allow replacing textures use a special 64x64 symbol // Force this size here so that our images don't get scaled wildly - #if (defined __ORBIS__ || defined _DURANGO ) + #if (defined __ORBIS__ || defined _DURANGO || defined _WINDOWS64 ) *width = 96; *height = 96; #else @@ -3137,4 +3355,4 @@ void UIController::SendTouchInput(unsigned int iPad, unsigned int key, bool bPre } -#endif \ No newline at end of file +#endif diff --git a/Minecraft.Client/Common/UI/UIController.h b/Minecraft.Client/Common/UI/UIController.h index 49c780320..373d67b2c 100644 --- a/Minecraft.Client/Common/UI/UIController.h +++ b/Minecraft.Client/Common/UI/UIController.h @@ -158,6 +158,10 @@ private: vector m_queuedMessageBoxData; unsigned int m_winUserIndex; + EUIScene m_mouseDraggingSliderScene; + int m_mouseDraggingSliderId; + int m_lastHoverMouseX; + int m_lastHoverMouseY; //bool m_bSysUIShowing; bool m_bSystemUIShowing; C4JThread *m_reloadSkinThread; diff --git a/Minecraft.Client/Common/UI/UIGroup.h b/Minecraft.Client/Common/UI/UIGroup.h index 0ffee0ca2..28369f276 100644 --- a/Minecraft.Client/Common/UI/UIGroup.h +++ b/Minecraft.Client/Common/UI/UIGroup.h @@ -37,9 +37,7 @@ private: public: UIGroup(EUIGroup group, int iPad); -#ifdef __PSVITA__ EUIGroup GetGroup() {return m_group;} -#endif UIComponent_Tooltips *getTooltips() { return m_tooltips; } UIComponent_TutorialPopup *getTutorialPopup() { return m_tutorialPopup; } UIScene_HUD *getHUD() { return m_hud; } diff --git a/Minecraft.Client/Common/UI/UIScene.h b/Minecraft.Client/Common/UI/UIScene.h index 8c20aaae3..b4008fa01 100644 --- a/Minecraft.Client/Common/UI/UIScene.h +++ b/Minecraft.Client/Common/UI/UIScene.h @@ -107,8 +107,10 @@ public: int getRenderHeight() { return m_renderHeight; } #ifdef __PSVITA__ - UILayer *GetParentLayer() {return m_parentLayer;} EUIGroup GetParentLayerGroup() {return m_parentLayer->m_parentGroup->GetGroup();} +#endif +#if defined(__PSVITA__) || defined(_WINDOWS64) + UILayer *GetParentLayer() {return m_parentLayer;} vector *GetControls() {return &m_controls;} #endif diff --git a/Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.cpp b/Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.cpp index 365aca250..a21405286 100644 --- a/Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.cpp +++ b/Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.cpp @@ -34,12 +34,6 @@ UIScene_AbstractContainerMenu::UIScene_AbstractContainerMenu(int iPad, UILayer * ui.OverrideSFX(m_iPad,ACTION_MENU_DOWN,true); m_bIgnoreInput=false; -#ifdef _WINDOWS64 - m_bMouseDragSlider=false; - m_bHasMousePosition = false; - m_lastMouseX = 0; - m_lastMouseY = 0; -#endif } UIScene_AbstractContainerMenu::~UIScene_AbstractContainerMenu() @@ -50,6 +44,16 @@ UIScene_AbstractContainerMenu::~UIScene_AbstractContainerMenu() void UIScene_AbstractContainerMenu::handleDestroy() { app.DebugPrintf("UIScene_AbstractContainerMenu::handleDestroy\n"); + +#ifdef _WINDOWS64 + g_savedInventoryCursorPos.x = m_pointerPos.x; + g_savedInventoryCursorPos.y = m_pointerPos.y; + g_savedInventoryCursorPos.hasSavedPos = true; + + g_KBMInput.SetScreenCursorHidden(false); + g_KBMInput.SetCursorHiddenForUI(false); +#endif + Minecraft *pMinecraft = Minecraft::GetInstance(); if( pMinecraft->localgameModes[m_iPad] != NULL ) { @@ -85,6 +89,10 @@ void UIScene_AbstractContainerMenu::InitDataAssociations(int iPad, AbstractConta void UIScene_AbstractContainerMenu::PlatformInitialize(int iPad, int startIndex) { +#ifdef _WINDOWS64 + g_KBMInput.SetScreenCursorHidden(true); + g_KBMInput.SetCursorHiddenForUI(true); +#endif m_labelInventory.init( app.GetString(IDS_INVENTORY) ); @@ -169,6 +177,19 @@ void UIScene_AbstractContainerMenu::PlatformInitialize(int iPad, int startIndex) //m_pointerControl->SetPosition( &vPointerPos ); m_pointerPos = vPointerPos; +#ifdef _WINDOWS64 + if (g_savedInventoryCursorPos.hasSavedPos) + { + m_pointerPos.x = g_savedInventoryCursorPos.x; + m_pointerPos.y = g_savedInventoryCursorPos.y; + + if (m_pointerPos.x < m_fPointerMinX) m_pointerPos.x = m_fPointerMinX; + if (m_pointerPos.x > m_fPointerMaxX) m_pointerPos.x = m_fPointerMaxX; + if (m_pointerPos.y < m_fPointerMinY) m_pointerPos.y = m_fPointerMinY; + if (m_pointerPos.y > m_fPointerMaxY) m_pointerPos.y = m_fPointerMaxY; + } +#endif + IggyEvent mouseEvent; S32 width, height; m_parentLayer->getRenderDimensions(width, height); @@ -191,134 +212,15 @@ void UIScene_AbstractContainerMenu::tick() { UIScene::tick(); -#ifdef _WINDOWS64 - bool mouseActive = (m_iPad == 0 && !KMInput.IsCaptured()); - bool drivePointerFromMouse = false; - float rawMouseMovieX = 0, rawMouseMovieY = 0; - int scrollDelta = 0; - // Map Windows mouse position to the virtual pointer in movie coordinates - if (mouseActive) - { - RECT clientRect; - GetClientRect(KMInput.GetHWnd(), &clientRect); - int clientWidth = clientRect.right; - int clientHeight = clientRect.bottom; - if (clientWidth > 0 && clientHeight > 0) - { - int mouseX = KMInput.GetMouseX(); - int mouseY = KMInput.GetMouseY(); - bool mouseMoved = !m_bHasMousePosition || mouseX != m_lastMouseX || mouseY != m_lastMouseY; - - m_bHasMousePosition = true; - m_lastMouseX = mouseX; - m_lastMouseY = mouseY; - scrollDelta = KMInput.ConsumeScrollDelta(); - - // Convert mouse position to movie coordinates using the movie/client ratio - float mx = (float)mouseX * ((float)m_movieWidth / (float)clientWidth); - float my = (float)mouseY * ((float)m_movieHeight / (float)clientHeight); - - rawMouseMovieX = mx; - rawMouseMovieY = my; - - // Once the mouse has taken over the container cursor, keep following the OS cursor - // until explicit controller input takes ownership back. - drivePointerFromMouse = m_bPointerDrivenByMouse || mouseMoved || KMInput.IsMouseDown(0) || KMInput.IsMouseDown(1) || KMInput.IsMouseDown(2) || scrollDelta != 0; - if (drivePointerFromMouse) - { - m_bPointerDrivenByMouse = true; - m_eCurrTapState = eTapStateNoInput; - m_pointerPos.x = mx; - m_pointerPos.y = my; - } - } - } -#endif - onMouseTick(); -#ifdef _WINDOWS64 - // Dispatch mouse clicks AFTER onMouseTick() has updated m_eCurrSection from the new pointer position - if (mouseActive) - { - if (KMInput.ConsumeMousePress(0)) - { - if (m_eCurrSection == eSectionInventoryCreativeSlider) - { - // Scrollbar click: use raw mouse position (onMouseTick may have snapped m_pointerPos) - m_bMouseDragSlider = true; - m_pointerPos.x = rawMouseMovieX; - m_pointerPos.y = rawMouseMovieY; - handleOtherClicked(m_iPad, eSectionInventoryCreativeSlider, 0, false); - } - else - { - handleKeyDown(m_iPad, ACTION_MENU_A, false); - } - } - else if (m_bMouseDragSlider && KMInput.IsMouseDown(0)) - { - // Continue scrollbar drag: update scroll position from current mouse Y - m_pointerPos.x = rawMouseMovieX; - m_pointerPos.y = rawMouseMovieY; - handleOtherClicked(m_iPad, eSectionInventoryCreativeSlider, 0, false); - } - - if (!KMInput.IsMouseDown(0)) - m_bMouseDragSlider = false; - - if (KMInput.ConsumeMousePress(1)) - { - handleKeyDown(m_iPad, ACTION_MENU_X, false); - } - if (KMInput.ConsumeMousePress(2)) - { - handleKeyDown(m_iPad, ACTION_MENU_Y, false); - } - - // Mouse scroll wheel for page scrolling - if (scrollDelta > 0) - { - handleKeyDown(m_iPad, ACTION_MENU_OTHER_STICK_UP, false); - } - else if (scrollDelta < 0) - { - handleKeyDown(m_iPad, ACTION_MENU_OTHER_STICK_DOWN, false); - } - - // ESC to close — must be last since it may destroy this scene - if (KMInput.ConsumeKeyPress(VK_ESCAPE)) - { - handleKeyDown(m_iPad, ACTION_MENU_B, false); - return; - } - } -#endif - IggyEvent mouseEvent; S32 width, height; m_parentLayer->getRenderDimensions(width, height); -#ifdef _WINDOWS64 - S32 x, y; - if (mouseActive && m_bPointerDrivenByMouse) - { - // Send raw mouse position directly as Iggy event to avoid coordinate round-trip errors - // Scale mouse client coords to the Iggy display space (which was set to getRenderDimensions()) - RECT clientRect; - GetClientRect(KMInput.GetHWnd(), &clientRect); - x = (S32)((float)KMInput.GetMouseX() * ((float)width / (float)clientRect.right)); - y = (S32)((float)KMInput.GetMouseY() * ((float)height / (float)clientRect.bottom)); - } - else - { - x = (S32)(m_pointerPos.x * ((float)width / m_movieWidth)); - y = (S32)(m_pointerPos.y * ((float)height / m_movieHeight)); - } -#else - S32 x = m_pointerPos.x*((float)width/m_movieWidth); - S32 y = m_pointerPos.y*((float)height/m_movieHeight); -#endif + S32 x = (S32)(m_pointerPos.x * ((float)width / m_movieWidth)); + S32 y = (S32)(m_pointerPos.y * ((float)height / m_movieHeight)); + IggyMakeEventMouseMove( &mouseEvent, x, y); // 4J Stu - This seems to be broken on Durango, so do it ourself diff --git a/Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.h b/Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.h index 812c5b41c..605f5dbdf 100644 --- a/Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.h +++ b/Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.h @@ -10,12 +10,6 @@ class UIScene_AbstractContainerMenu : public UIScene, public virtual IUIScene_Ab private: ESceneSection m_focusSection; bool m_bIgnoreInput; -#ifdef _WINDOWS64 - bool m_bMouseDragSlider; - bool m_bHasMousePosition; - int m_lastMouseX; - int m_lastMouseY; -#endif protected: UIControl m_controlMainPanel; @@ -42,6 +36,8 @@ public: virtual void handleDestroy(); int getPad() { return m_iPad; } + int getMovieWidth() { return m_movieWidth; } + int getMovieHeight() { return m_movieHeight; } bool getIgnoreInput() { return m_bIgnoreInput; } void setIgnoreInput(bool bVal) { m_bIgnoreInput=bVal; } diff --git a/Minecraft.Client/Common/UI/UIScene_CreateWorldMenu.cpp b/Minecraft.Client/Common/UI/UIScene_CreateWorldMenu.cpp index dfb25b7ff..7f10af641 100644 --- a/Minecraft.Client/Common/UI/UIScene_CreateWorldMenu.cpp +++ b/Minecraft.Client/Common/UI/UIScene_CreateWorldMenu.cpp @@ -1085,6 +1085,7 @@ void UIScene_CreateWorldMenu::CreateGame(UIScene_CreateWorldMenu* pClass, DWORD __int64 seedValue = 0; NetworkGameInitData *param = new NetworkGameInitData(); + param->levelName = wWorldName; if (wSeed.length() != 0) { diff --git a/Minecraft.Client/Common/UI/UIScene_DebugOverlay.cpp b/Minecraft.Client/Common/UI/UIScene_DebugOverlay.cpp index 105c90b43..6162c47bf 100644 --- a/Minecraft.Client/Common/UI/UIScene_DebugOverlay.cpp +++ b/Minecraft.Client/Common/UI/UIScene_DebugOverlay.cpp @@ -39,17 +39,37 @@ UIScene_DebugOverlay::UIScene_DebugOverlay(int iPad, void *initData, UILayer *pa m_buttonSetNight.init(L"Set Night", eControl_SetNight); m_buttonListItems.init(eControl_Items); + + // Sort items alphabetically + std::vector> sortedItems; + for (size_t i = 0; i < Item::items.length; ++i) + { + if (Item::items[i] != NULL) + { + sortedItems.emplace_back(std::wstring(app.GetString(Item::items[i]->getDescriptionId())), i); + } + } + for (size_t i = 1; i < sortedItems.size(); ++i) + { + auto key = sortedItems[i]; + int j = i - 1; + while (j >= 0 && sortedItems[j].first > key.first) + { + sortedItems[j + 1] = sortedItems[j]; + --j; + } + sortedItems[j + 1] = key; + } + + // Populate the list in sorted order int listId = 0; - for(unsigned int i = 0; i < Item::items.length; ++i) - { - if(Item::items[i] != NULL) - { - m_itemIds.push_back(i); - m_buttonListItems.addItem(app.GetString(Item::items[i]->getDescriptionId()), listId); - ++listId; - } - } + for (const auto& entry : sortedItems) + { + m_itemIds.push_back(entry.second); + m_buttonListItems.addItem(entry.first.c_str(), listId); + ++listId; + } m_buttonListEnchantments.init(eControl_Enchantments); diff --git a/Minecraft.Client/Common/UI/UIScene_LoadMenu.cpp b/Minecraft.Client/Common/UI/UIScene_LoadMenu.cpp index fc212fa48..7c8dd8f50 100644 --- a/Minecraft.Client/Common/UI/UIScene_LoadMenu.cpp +++ b/Minecraft.Client/Common/UI/UIScene_LoadMenu.cpp @@ -238,7 +238,7 @@ UIScene_LoadMenu::UIScene_LoadMenu(int iPad, void *initData, UILayer *parentLaye #endif m_bShowTimer = true; } -#if defined(_DURANGO) +#if defined(_DURANGO) m_labelGameName.init(params->saveDetails->UTF16SaveName); #else wchar_t wSaveName[128]; @@ -246,6 +246,16 @@ UIScene_LoadMenu::UIScene_LoadMenu(int iPad, void *initData, UILayer *parentLaye mbstowcs(wSaveName, params->saveDetails->UTF8SaveName, strlen(params->saveDetails->UTF8SaveName)+1); // plus null m_labelGameName.init(wSaveName); #endif +#endif +#ifdef _WINDOWS64 + if (params->saveDetails != NULL && params->saveDetails->UTF8SaveName[0] != '\0') + { + wchar_t wSaveName[128]; + ZeroMemory(wSaveName, sizeof(wSaveName)); + mbstowcs(wSaveName, params->saveDetails->UTF8SaveName, 127); + m_levelName = wstring(wSaveName); + m_labelGameName.init(m_levelName); + } #endif } @@ -1574,6 +1584,7 @@ void UIScene_LoadMenu::StartGameFromSave(UIScene_LoadMenu* pClass, DWORD dwLocal param->saveData = NULL; param->levelGen = pClass->m_levelGen; param->texturePackId = pClass->m_MoreOptionsParams.dwTexturePack; + param->levelName = pClass->m_levelName; Minecraft *pMinecraft = Minecraft::GetInstance(); pMinecraft->skins->selectTexturePackById(pClass->m_MoreOptionsParams.dwTexturePack); diff --git a/Minecraft.Client/Common/UI/UIScene_LoadMenu.h b/Minecraft.Client/Common/UI/UIScene_LoadMenu.h index 129551519..085cb67f5 100644 --- a/Minecraft.Client/Common/UI/UIScene_LoadMenu.h +++ b/Minecraft.Client/Common/UI/UIScene_LoadMenu.h @@ -59,6 +59,7 @@ private: bool m_bIsCorrupt; bool m_bThumbnailGetFailed; __int64 m_seed; + wstring m_levelName; #ifdef __PS3__ std::vector*m_pvProductInfo; diff --git a/Minecraft.Client/Common/UI/UIScene_LoadOrJoinMenu.cpp b/Minecraft.Client/Common/UI/UIScene_LoadOrJoinMenu.cpp index 24a080931..02b485261 100644 --- a/Minecraft.Client/Common/UI/UIScene_LoadOrJoinMenu.cpp +++ b/Minecraft.Client/Common/UI/UIScene_LoadOrJoinMenu.cpp @@ -25,6 +25,98 @@ #include "message_dialog.h" #endif +#ifdef _WINDOWS64 +#include "..\..\..\Minecraft.World\NbtIo.h" +#include "..\..\..\Minecraft.World\compression.h" + +static wstring ReadLevelNameFromSaveFile(const wstring& filePath) +{ + HANDLE hFile = CreateFileW(filePath.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); + if (hFile == INVALID_HANDLE_VALUE) return L""; + + DWORD fileSize = GetFileSize(hFile, NULL); + if (fileSize < 12 || fileSize == INVALID_FILE_SIZE) { CloseHandle(hFile); return L""; } + + unsigned char *rawData = new unsigned char[fileSize]; + DWORD bytesRead = 0; + if (!ReadFile(hFile, rawData, fileSize, &bytesRead, NULL) || bytesRead != fileSize) + { + CloseHandle(hFile); + delete[] rawData; + return L""; + } + CloseHandle(hFile); + + unsigned char *saveData = NULL; + unsigned int saveSize = 0; + bool freeSaveData = false; + + if (*(unsigned int*)rawData == 0) + { + // Compressed format: bytes 0-3=0, bytes 4-7=decompressed size, bytes 8+=compressed data + unsigned int decompSize = *(unsigned int*)(rawData + 4); + if (decompSize == 0 || decompSize > 128 * 1024 * 1024) + { + delete[] rawData; + return L""; + } + saveData = new unsigned char[decompSize]; + Compression::getCompression()->Decompress(saveData, &decompSize, rawData + 8, fileSize - 8); + saveSize = decompSize; + freeSaveData = true; + } + else + { + saveData = rawData; + saveSize = fileSize; + } + + wstring result = L""; + if (saveSize >= 12) + { + unsigned int headerOffset = *(unsigned int*)saveData; + unsigned int numEntries = *(unsigned int*)(saveData + 4); + const unsigned int entrySize = sizeof(FileEntrySaveData); + + if (headerOffset < saveSize && numEntries > 0 && numEntries < 10000 && + headerOffset + numEntries * entrySize <= saveSize) + { + FileEntrySaveData *table = (FileEntrySaveData *)(saveData + headerOffset); + for (unsigned int i = 0; i < numEntries; i++) + { + if (wcscmp(table[i].filename, L"level.dat") == 0) + { + unsigned int off = table[i].startOffset; + unsigned int len = table[i].length; + if (off >= 12 && off + len <= saveSize && len > 0 && len < 4 * 1024 * 1024) + { + byteArray ba; + ba.data = (byte*)(saveData + off); + ba.length = len; + CompoundTag *root = NbtIo::decompress(ba); + if (root != NULL) + { + CompoundTag *dataTag = root->getCompound(L"Data"); + if (dataTag != NULL) + result = dataTag->getString(L"LevelName"); + delete root; + } + } + break; + } + } + } + } + + if (freeSaveData) delete[] saveData; + delete[] rawData; + // "world" is the engine default — it means no real name was ever set, so + // return empty to let the caller fall back to the save filename (timestamp). + if (result == L"world") result = L""; + return result; +} +#endif + #ifdef SONY_REMOTE_STORAGE_DOWNLOAD unsigned long UIScene_LoadOrJoinMenu::m_ulFileSize=0L; @@ -159,7 +251,7 @@ UIScene_LoadOrJoinMenu::UIScene_LoadOrJoinMenu(int iPad, void *initData, UILayer } #endif -#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) || defined(_DURANGO) +#if defined(__PS3__) || defined(__ORBIS__) || defined(__PSVITA__) || defined(_DURANGO) || defined(_WINDOWS64) // Always clear the saves when we enter this menu StorageManager.ClearSavesInfo(); #endif @@ -614,6 +706,22 @@ void UIScene_LoadOrJoinMenu::tick() m_saveDetails = new SaveListDetails[m_pSaveDetails->iSaveC]; m_iSaveDetailsCount = m_pSaveDetails->iSaveC; +#ifdef _WINDOWS64 + // Build sorted index array (newest-first by filename timestamp YYYYMMDDHHMMSS) + int *sortedIdx = new int[m_pSaveDetails->iSaveC]; + for (int si = 0; si < (int)m_pSaveDetails->iSaveC; ++si) sortedIdx[si] = si; + for (int si = 1; si < (int)m_pSaveDetails->iSaveC; ++si) + { + int key = sortedIdx[si]; + int sj = si - 1; + while (sj >= 0 && strcmp(m_pSaveDetails->SaveInfoA[sortedIdx[sj]].UTF8SaveFilename, m_pSaveDetails->SaveInfoA[key].UTF8SaveFilename) < 0) + { + sortedIdx[sj + 1] = sortedIdx[sj]; + --sj; + } + sortedIdx[sj + 1] = key; + } +#endif for(unsigned int i = 0; i < m_pSaveDetails->iSaveC; ++i) { #if defined(_XBOX_ONE) @@ -627,14 +735,40 @@ void UIScene_LoadOrJoinMenu::tick() m_saveDetails[i].saveId = i; memcpy(m_saveDetails[i].UTF16SaveName, m_pSaveDetails->SaveInfoA[i].UTF16SaveTitle, 128); memcpy(m_saveDetails[i].UTF16SaveFilename, m_pSaveDetails->SaveInfoA[i].UTF16SaveFilename, MAX_SAVEFILENAME_LENGTH); +#else +#ifdef _WINDOWS64 + { + int origIdx = sortedIdx[i]; + wchar_t wFilename[MAX_SAVEFILENAME_LENGTH]; + ZeroMemory(wFilename, sizeof(wFilename)); + mbstowcs(wFilename, m_pSaveDetails->SaveInfoA[origIdx].UTF8SaveFilename, MAX_SAVEFILENAME_LENGTH - 1); + wstring filePath = wstring(L"Windows64\\GameHDD\\") + wstring(wFilename) + wstring(L"\\saveData.ms"); + wstring levelName = ReadLevelNameFromSaveFile(filePath); + if (!levelName.empty()) + { + m_buttonListSaves.addItem(levelName, wstring(L"")); + wcstombs(m_saveDetails[i].UTF8SaveName, levelName.c_str(), 127); + m_saveDetails[i].UTF8SaveName[127] = '\0'; + } + else + { + m_buttonListSaves.addItem(m_pSaveDetails->SaveInfoA[origIdx].UTF8SaveTitle, L""); + memcpy(m_saveDetails[i].UTF8SaveName, m_pSaveDetails->SaveInfoA[origIdx].UTF8SaveTitle, 128); + } + m_saveDetails[i].saveId = origIdx; + memcpy(m_saveDetails[i].UTF8SaveFilename, m_pSaveDetails->SaveInfoA[origIdx].UTF8SaveFilename, MAX_SAVEFILENAME_LENGTH); + } #else m_buttonListSaves.addItem(m_pSaveDetails->SaveInfoA[i].UTF8SaveTitle, L""); - - m_saveDetails[i].saveId = i; memcpy(m_saveDetails[i].UTF8SaveName, m_pSaveDetails->SaveInfoA[i].UTF8SaveTitle, 128); + m_saveDetails[i].saveId = i; memcpy(m_saveDetails[i].UTF8SaveFilename, m_pSaveDetails->SaveInfoA[i].UTF8SaveFilename, MAX_SAVEFILENAME_LENGTH); +#endif #endif } +#ifdef _WINDOWS64 + delete[] sortedIdx; +#endif m_controlSavesTimer.setVisible( false ); // set focus on the first button @@ -650,7 +784,11 @@ void UIScene_LoadOrJoinMenu::tick() app.DebugPrintf("Requesting the first thumbnail\n"); // set the save to load PSAVE_DETAILS pSaveDetails=StorageManager.ReturnSavesInfo(); +#ifdef _WINDOWS64 + C4JStorage::ESaveGameState eLoadStatus=StorageManager.LoadSaveDataThumbnail(&pSaveDetails->SaveInfoA[m_saveDetails[m_iRequestingThumbnailId].saveId],&LoadSaveDataThumbnailReturned,this); +#else C4JStorage::ESaveGameState eLoadStatus=StorageManager.LoadSaveDataThumbnail(&pSaveDetails->SaveInfoA[(int)m_iRequestingThumbnailId],&LoadSaveDataThumbnailReturned,this); +#endif if(eLoadStatus!=C4JStorage::ESaveGame_GetSaveThumbnail) { @@ -713,7 +851,11 @@ void UIScene_LoadOrJoinMenu::tick() app.DebugPrintf("Requesting another thumbnail\n"); // set the save to load PSAVE_DETAILS pSaveDetails=StorageManager.ReturnSavesInfo(); +#ifdef _WINDOWS64 + C4JStorage::ESaveGameState eLoadStatus=StorageManager.LoadSaveDataThumbnail(&pSaveDetails->SaveInfoA[m_saveDetails[m_iRequestingThumbnailId].saveId],&LoadSaveDataThumbnailReturned,this); +#else C4JStorage::ESaveGameState eLoadStatus=StorageManager.LoadSaveDataThumbnail(&pSaveDetails->SaveInfoA[(int)m_iRequestingThumbnailId],&LoadSaveDataThumbnailReturned,this); +#endif if(eLoadStatus!=C4JStorage::ESaveGame_GetSaveThumbnail) { // something went wrong @@ -1175,6 +1317,14 @@ void UIScene_LoadOrJoinMenu::handleInput(int iPad, int key, bool repeat, bool pr sendInputToMovie(key, repeat, pressed, released); handled = true; break; + case ACTION_MENU_OTHER_STICK_UP: + sendInputToMovie(ACTION_MENU_UP, repeat, pressed, released); + handled = true; + break; + case ACTION_MENU_OTHER_STICK_DOWN: + sendInputToMovie(ACTION_MENU_DOWN, repeat, pressed, released); + handled = true; + break; } } @@ -1323,7 +1473,7 @@ void UIScene_LoadOrJoinMenu::handlePress(F64 controlId, F64 childId) LoadMenuInitData *params = new LoadMenuInitData(); params->iPad = m_iPad; // need to get the iIndex from the list item, since the position in the list doesn't correspond to the GetSaveGameInfo list because of sorting - params->iSaveGameInfoIndex=((int)childId)-m_iDefaultButtonsC; + params->iSaveGameInfoIndex=m_saveDetails[((int)childId)-m_iDefaultButtonsC].saveId; //params->pbSaveRenamed=&m_bSaveRenamed; params->levelGen = NULL; params->saveDetails = &m_saveDetails[ ((int)childId)-m_iDefaultButtonsC ]; diff --git a/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.cpp b/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.cpp index 1234121e9..0a76a5e5d 100644 --- a/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.cpp +++ b/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.cpp @@ -1,11 +1,41 @@ #include "stdafx.h" #include "UI.h" #include "UIScene_SettingsGraphicsMenu.h" +#include "..\..\Minecraft.h" +#include "..\..\GameRenderer.h" + +namespace +{ + const int FOV_MIN = 70; + const int FOV_MAX = 110; + const int FOV_SLIDER_MAX = 100; + + int clampFov(int value) + { + if (value < FOV_MIN) return FOV_MIN; + if (value > FOV_MAX) return FOV_MAX; + return value; + } + + int fovToSliderValue(float fov) + { + int clampedFov = clampFov((int)(fov + 0.5f)); + return ((clampedFov - FOV_MIN) * FOV_SLIDER_MAX) / (FOV_MAX - FOV_MIN); + } + + int sliderValueToFov(int sliderValue) + { + if (sliderValue < 0) sliderValue = 0; + if (sliderValue > FOV_SLIDER_MAX) sliderValue = FOV_SLIDER_MAX; + return FOV_MIN + ((sliderValue * (FOV_MAX - FOV_MIN)) / FOV_SLIDER_MAX); + } +} UIScene_SettingsGraphicsMenu::UIScene_SettingsGraphicsMenu(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) { // Setup all the Iggy references we need for this scene initialiseMovie(); + Minecraft* pMinecraft = Minecraft::GetInstance(); m_bNotInGame=(Minecraft::GetInstance()->level==NULL); @@ -18,6 +48,10 @@ UIScene_SettingsGraphicsMenu::UIScene_SettingsGraphicsMenu(int iPad, void *initD swprintf( (WCHAR *)TempString, 256, L"%ls: %d%%", app.GetString( IDS_SLIDER_GAMMA ),app.GetGameSettings(m_iPad,eGameSetting_Gamma)); m_sliderGamma.init(TempString,eControl_Gamma,0,100,app.GetGameSettings(m_iPad,eGameSetting_Gamma)); + + int initialFov = clampFov((int)(pMinecraft->gameRenderer->GetFovVal() + 0.5f)); + swprintf((WCHAR*)TempString, 256, L"FOV: %d", initialFov); + m_sliderFOV.init(TempString, eControl_FOV, 0, FOV_SLIDER_MAX, fovToSliderValue((float)initialFov)); swprintf( (WCHAR *)TempString, 256, L"%ls: %d%%", app.GetString( IDS_SLIDER_INTERFACEOPACITY ),app.GetGameSettings(m_iPad,eGameSetting_InterfaceOpacity)); m_sliderInterfaceOpacity.init(TempString,eControl_InterfaceOpacity,0,100,app.GetGameSettings(m_iPad,eGameSetting_InterfaceOpacity)); @@ -141,6 +175,19 @@ void UIScene_SettingsGraphicsMenu::handleSliderMove(F64 sliderId, F64 currentVal m_sliderGamma.setLabel(TempString); break; + + case eControl_FOV: + { + m_sliderFOV.handleSliderMove(value); + Minecraft* pMinecraft = Minecraft::GetInstance(); + int fovValue = sliderValueToFov(value); + pMinecraft->gameRenderer->SetFovVal((float)fovValue); + WCHAR TempString[256]; + swprintf((WCHAR*)TempString, 256, L"FOV: %d", fovValue); + m_sliderFOV.setLabel(TempString); + } + break; + case eControl_InterfaceOpacity: m_sliderInterfaceOpacity.handleSliderMove(value); diff --git a/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.h b/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.h index e9c4905cd..c6e1e394f 100644 --- a/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.h +++ b/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.h @@ -11,16 +11,18 @@ private: eControl_BedrockFog, eControl_CustomSkinAnim, eControl_Gamma, + eControl_FOV, eControl_InterfaceOpacity }; UIControl_CheckBox m_checkboxClouds, m_checkboxBedrockFog, m_checkboxCustomSkinAnim; // Checkboxes - UIControl_Slider m_sliderGamma, m_sliderInterfaceOpacity; // Sliders + UIControl_Slider m_sliderGamma, m_sliderFOV, m_sliderInterfaceOpacity; // Sliders UI_BEGIN_MAP_ELEMENTS_AND_NAMES(UIScene) UI_MAP_ELEMENT( m_checkboxClouds, "Clouds") UI_MAP_ELEMENT( m_checkboxBedrockFog, "BedrockFog") UI_MAP_ELEMENT( m_checkboxCustomSkinAnim, "CustomSkinAnim") UI_MAP_ELEMENT( m_sliderGamma, "Gamma") + UI_MAP_ELEMENT(m_sliderFOV, "FOV") UI_MAP_ELEMENT( m_sliderInterfaceOpacity, "InterfaceOpacity") UI_END_MAP_ELEMENTS_AND_NAMES() diff --git a/Minecraft.Client/EnderDragonRenderer.cpp b/Minecraft.Client/EnderDragonRenderer.cpp index 05c70de34..aead9d397 100644 --- a/Minecraft.Client/EnderDragonRenderer.cpp +++ b/Minecraft.Client/EnderDragonRenderer.cpp @@ -77,12 +77,7 @@ void EnderDragonRenderer::renderModel(shared_ptr _mob, float wp, f glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glColor4f(1, 0, 0, 0.5f); -#ifdef __PSVITA__ - // AP - not sure that the usecompiled flag is supposed to be false. This makes it really slow on vita. Making it true still seems to look the same model->render(mob, wp, ws, bob, headRotMinusBodyRot, headRotx, scale, true); -#else - model->render(mob, wp, ws, bob, headRotMinusBodyRot, headRotx, scale, false); -#endif glEnable(GL_TEXTURE_2D); glDisable(GL_BLEND); glDepthFunc(GL_LEQUAL); diff --git a/Minecraft.Client/Extrax64Stubs.cpp b/Minecraft.Client/Extrax64Stubs.cpp index 2f7eae6f1..13f4566d1 100644 --- a/Minecraft.Client/Extrax64Stubs.cpp +++ b/Minecraft.Client/Extrax64Stubs.cpp @@ -199,11 +199,10 @@ DWORD IQNetPlayer::GetSendQueueSize(IQNetPlayer * player, DWORD dwFlags) { retur DWORD IQNetPlayer::GetCurrentRtt() { return 0; } bool IQNetPlayer::IsHost() { return m_isHostPlayer; } bool IQNetPlayer::IsGuest() { return false; } -bool IQNetPlayer::IsLocal() { return true; } -PlayerUID IQNetPlayer::GetXuid() { return INVALID_XUID; } -extern wstring g_playerName; -LPCWSTR IQNetPlayer::GetGamertag() { return g_playerName.empty() ? L"Windows" : g_playerName.c_str(); } -int IQNetPlayer::GetSessionIndex() { return 0; } +bool IQNetPlayer::IsLocal() { return !m_isRemote; } +PlayerUID IQNetPlayer::GetXuid() { return (PlayerUID)(0xe000d45248242f2e + m_smallId); } // todo: restore to INVALID_XUID once saves support this +LPCWSTR IQNetPlayer::GetGamertag() { return m_gamertag; } +int IQNetPlayer::GetSessionIndex() { return m_smallId; } bool IQNetPlayer::IsTalking() { return false; } bool IQNetPlayer::IsMutedByLocalUser(DWORD dwUserIndex) { return false; } bool IQNetPlayer::HasVoice() { return false; } @@ -232,13 +231,17 @@ void Win64_SetupRemoteQNetPlayer(IQNetPlayer * player, BYTE smallId, bool isHost IQNet::s_playerCount = smallId + 1; } +static bool Win64_IsActivePlayer(IQNetPlayer* p, DWORD index); + HRESULT IQNet::AddLocalPlayerByUserIndex(DWORD dwUserIndex) { return S_OK; } IQNetPlayer* IQNet::GetHostPlayer() { return &m_player[0]; } IQNetPlayer* IQNet::GetLocalPlayerByUserIndex(DWORD dwUserIndex) { if (s_isHosting) { - if (dwUserIndex < MINECRAFT_NET_MAX_PLAYERS && !m_player[dwUserIndex].m_isRemote) + if (dwUserIndex < MINECRAFT_NET_MAX_PLAYERS && + !m_player[dwUserIndex].m_isRemote && + Win64_IsActivePlayer(&m_player[dwUserIndex], dwUserIndex)) return &m_player[dwUserIndex]; return NULL; } @@ -246,7 +249,7 @@ IQNetPlayer* IQNet::GetLocalPlayerByUserIndex(DWORD dwUserIndex) return NULL; for (DWORD i = 0; i < s_playerCount; i++) { - if (!m_player[i].m_isRemote) + if (!m_player[i].m_isRemote && Win64_IsActivePlayer(&m_player[i], i)) return &m_player[i]; } return NULL; @@ -299,15 +302,28 @@ QNET_STATE IQNet::GetState() { return _iQNetStubState; } bool IQNet::IsHost() { return s_isHosting; } HRESULT IQNet::JoinGameFromInviteInfo(DWORD dwUserIndex, DWORD dwUserMask, const INVITE_INFO * pInviteInfo) { return S_OK; } void IQNet::HostGame() { _iQNetStubState = QNET_STATE_SESSION_STARTING; s_isHosting = true; } -void IQNet::ClientJoinGame() { _iQNetStubState = QNET_STATE_SESSION_STARTING; s_isHosting = false; } +void IQNet::ClientJoinGame() +{ + _iQNetStubState = QNET_STATE_SESSION_STARTING; + s_isHosting = false; + + for (int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; i++) + { + m_player[i].m_smallId = (BYTE)i; + m_player[i].m_isRemote = true; + m_player[i].m_isHostPlayer = false; + m_player[i].m_gamertag[0] = 0; + m_player[i].SetCustomDataValue(0); + } +} void IQNet::EndGame() { _iQNetStubState = QNET_STATE_IDLE; s_isHosting = false; s_playerCount = 1; - for (int i = 1; i < MINECRAFT_NET_MAX_PLAYERS; i++) + for (int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; i++) { - m_player[i].m_smallId = 0; + m_player[i].m_smallId = (BYTE)i; m_player[i].m_isRemote = false; m_player[i].m_isHostPlayer = false; m_player[i].m_gamertag[0] = 0; @@ -587,7 +603,6 @@ void C_4JProfile::SetPrimaryPad(int iPad) {} #ifdef _DURANGO char fakeGamerTag[32] = "PlayerName"; void SetFakeGamertag(char* name) { strcpy_s(fakeGamerTag, name); } -char* C_4JProfile::GetGamertag(int iPad) { return fakeGamerTag; } #else char* C_4JProfile::GetGamertag(int iPad) { extern char g_Win64Username[17]; return g_Win64Username; } wstring C_4JProfile::GetDisplayName(int iPad) { extern wchar_t g_Win64UsernameW[17]; return g_Win64UsernameW; } diff --git a/Minecraft.Client/GameRenderer.cpp b/Minecraft.Client/GameRenderer.cpp index c951d92f0..e1670b2fd 100644 --- a/Minecraft.Client/GameRenderer.cpp +++ b/Minecraft.Client/GameRenderer.cpp @@ -501,23 +501,26 @@ void GameRenderer::moveCameraToPlayer(float a) else { // 4J - corrected bug where this used to just take player->xRot & yRot directly and so wasn't taking into account interpolation, allowing camera to go through walls - float playerYRot = player->yRotO + (player->yRot - player->yRotO) * a; - float playerXRot = player->xRotO + (player->xRot - player->xRotO) * a; - float yRot = playerYRot; - float xRot = playerXRot; + float yRot = player->yRotO + (player->yRot - player->yRotO) * a; + float xRot = player->xRotO + (player->xRot - player->xRotO) * a; // Thirdperson view values are now 0 for disabled, 1 for original mode, 2 for reversed. if( localplayer->ThirdPersonView() == 2 ) { - // Reverse x rotation - note that this is only used in doing collision to calculate our view + // Reverse y rotation - note that this is only used in doing collision to calculate our view // distance, the actual rotation itself is just below this else {} block - xRot += 180.0f; + yRot += 180.0f; } double xd = -Mth::sin(yRot / 180 * PI) * Mth::cos(xRot / 180 * PI) * cameraDist; double zd = Mth::cos(yRot / 180 * PI) * Mth::cos(xRot / 180 * PI) * cameraDist; double yd = -Mth::sin(xRot / 180 * PI) * cameraDist; + if (localplayer->ThirdPersonView() == 2) + { + yd = Mth::sin(xRot / 180 * PI) * cameraDist; + } + for (int i = 0; i < 8; i++) { float xo = (float)((i & 1) * 2 - 1); @@ -538,16 +541,7 @@ void GameRenderer::moveCameraToPlayer(float a) } } - if ( localplayer->ThirdPersonView() == 2) - { - glRotatef(180, 0, 1, 0); - } - - glRotatef(playerXRot - xRot, 1, 0, 0); - glRotatef(playerYRot - yRot, 0, 1, 0); glTranslatef(0, 0, (float) -cameraDist); - glRotatef(yRot - playerYRot, 0, 1, 0); - glRotatef(xRot - playerXRot, 1, 0, 0); } } else @@ -557,8 +551,21 @@ void GameRenderer::moveCameraToPlayer(float a) if (!mc->options->fixedCamera) { - glRotatef(player->xRotO + (player->xRot - player->xRotO) * a, 1, 0, 0); - glRotatef(player->yRotO + (player->yRot - player->yRotO) * a + 180, 0, 1, 0); + float pitch = player->xRotO + (player->xRot - player->xRotO) * a; + if (localplayer->ThirdPersonView() == 2) + { + pitch = -pitch; + } + + glRotatef(pitch, 1, 0, 0); + if (localplayer->ThirdPersonView() == 2) + { + glRotatef(player->yRotO + (player->yRot - player->yRotO) * a, 0, 1, 0); + } + else + { + glRotatef(player->yRotO + (player->yRot - player->yRotO) * a + 180, 0, 1, 0); + } } glTranslatef(0, heightOffset, 0); diff --git a/Minecraft.Client/Input.cpp b/Minecraft.Client/Input.cpp index b7a37d287..5adf77778 100644 --- a/Minecraft.Client/Input.cpp +++ b/Minecraft.Client/Input.cpp @@ -7,20 +7,21 @@ #include "Input.h" #include "LocalPlayer.h" #include "Options.h" +#ifdef _WINDOWS64 +#include "Windows64\KeyboardMouseInput.h" +#endif Input::Input() { xa = 0; ya = 0; - sprintForward = 0; wasJumping = false; jumping = false; sneaking = false; - usingKeyboardMovement = false; + sprinting = false; lReset = false; rReset = false; - m_gamepadSneaking = false; } void Input::tick(LocalPlayer *player) @@ -32,43 +33,43 @@ void Input::tick(LocalPlayer *player) Minecraft *pMinecraft=Minecraft::GetInstance(); int iPad=player->GetXboxPad(); + float controllerXA = 0.0f; + float controllerYA = 0.0f; + // 4J-PB minecraft movement seems to be the wrong way round, so invert x! if( pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_LEFT) || pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_RIGHT) ) - xa = -InputManager.GetJoypadStick_LX(iPad); - else - xa = 0.0f; + controllerXA = -InputManager.GetJoypadStick_LX(iPad); if( pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_FORWARD) || pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_BACKWARD) ) - ya = InputManager.GetJoypadStick_LY(iPad); - else - ya = 0.0f; - sprintForward = ya; - usingKeyboardMovement = false; + controllerYA = InputManager.GetJoypadStick_LY(iPad); + float kbXA = 0.0f; + float kbYA = 0.0f; #ifdef _WINDOWS64 - // WASD movement (combine with gamepad) - if (iPad == 0 && KMInput.IsCaptured()) + if (iPad == 0 && g_KBMInput.IsMouseGrabbed() && g_KBMInput.IsKBMActive()) { - float kbX = 0.0f, kbY = 0.0f; - if (KMInput.IsKeyDown('W')) { kbY += 1.0f; sprintForward += 1.0f; usingKeyboardMovement = true; } - if (KMInput.IsKeyDown('S')) { kbY -= 1.0f; sprintForward -= 1.0f; usingKeyboardMovement = true; } - if (KMInput.IsKeyDown('A')) { kbX += 1.0f; usingKeyboardMovement = true; } // inverted like gamepad - if (KMInput.IsKeyDown('D')) { kbX -= 1.0f; usingKeyboardMovement = true; } - // Normalize diagonal - if (kbX != 0.0f && kbY != 0.0f) { kbX *= 0.707f; kbY *= 0.707f; } - if (pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_LEFT) || pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_RIGHT)) - xa = max(min(xa + kbX, 1.0f), -1.0f); - if (pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_FORWARD) || pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_BACKWARD)) - ya = max(min(ya + kbY, 1.0f), -1.0f); + if( pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_LEFT) || pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_RIGHT) ) + kbXA = g_KBMInput.GetMoveX(); + if( pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_FORWARD) || pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_BACKWARD) ) + kbYA = g_KBMInput.GetMoveY(); } #endif - sprintForward = max(min(sprintForward, 1.0f), -1.0f); + + if (kbXA != 0.0f || kbYA != 0.0f) + { + xa = kbXA; + ya = kbYA; + } + else + { + xa = controllerXA; + ya = controllerYA; + } #ifndef _CONTENT_PACKAGE if (app.GetFreezePlayers()) { xa = ya = 0.0f; - sprintForward = 0.0f; player->abilities.flying = true; } #endif @@ -80,7 +81,6 @@ void Input::tick(LocalPlayer *player) lReset = true; } xa = ya = 0.0f; - sprintForward = 0.0f; } // 4J: In flying mode, don't actually toggle sneaking (unless we're riding in which case we need to sneak to dismount) @@ -88,15 +88,46 @@ void Input::tick(LocalPlayer *player) { if((player->ullButtonsPressed&(1LL<localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_SNEAK_TOGGLE)) { - m_gamepadSneaking=!m_gamepadSneaking; + sneaking=!sneaking; } } - sneaking = m_gamepadSneaking; #ifdef _WINDOWS64 - // Keyboard hold-to-sneak (overrides gamepad toggle) - if (iPad == 0 && KMInput.IsCaptured() && KMInput.IsKeyDown(VK_SHIFT) && !player->abilities.flying) - sneaking = true; + if (iPad == 0 && g_KBMInput.IsMouseGrabbed() && g_KBMInput.IsKBMActive()) + { + // Left Shift = sneak (hold to crouch) + if (pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_SNEAK_TOGGLE)) + { + if (!player->abilities.flying) + { + sneaking = g_KBMInput.IsKeyDown(KeyboardMouseInput::KEY_SNEAK); + } + } + + // Left Ctrl + forward = sprint (hold to sprint) + if (!player->abilities.flying) + { + bool ctrlHeld = g_KBMInput.IsKeyDown(KeyboardMouseInput::KEY_SPRINT); + bool movingForward = (kbYA > 0.0f); + + if (ctrlHeld && movingForward) + { + sprinting = true; + } + else + { + sprinting = false; + } + } + else + { + sprinting = false; + } + } + else if (iPad == 0) + { + sprinting = false; + } #endif if(sneaking) @@ -109,6 +140,7 @@ void Input::tick(LocalPlayer *player) float tx = 0.0f; float ty = 0.0f; + if( pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_LOOK_LEFT) || pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_LOOK_RIGHT) ) tx = InputManager.GetJoypadStick_RX(iPad)*(((float)app.GetGameSettings(iPad,eGameSetting_Sensitivity_InGame))/100.0f); // apply sensitivity to look if( pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_LOOK_UP) || pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_LOOK_DOWN) ) @@ -132,47 +164,52 @@ void Input::tick(LocalPlayer *player) } tx = ty = 0.0f; } - player->interpolateTurn(tx * abs(tx) * turnSpeed, ty * abs(ty) * turnSpeed); + + float turnX = tx * abs(tx) * turnSpeed; + float turnY = ty * abs(ty) * turnSpeed; #ifdef _WINDOWS64 - // Mouse look is now handled per-frame in Minecraft::applyFrameMouseLook() - // to eliminate the 20Hz tick delay. Only flush any remaining delta here - // as a safety measure. - if (iPad == 0 && KMInput.IsCaptured()) + if (iPad == 0 && g_KBMInput.IsMouseGrabbed() && g_KBMInput.IsKBMActive()) { - float rawDx, rawDy; - KMInput.ConsumeMouseDelta(rawDx, rawDy); - // Delta should normally be 0 since applyFrameMouseLook() already consumed it - if (rawDx != 0.0f || rawDy != 0.0f) + float mouseSensitivity = ((float)app.GetGameSettings(iPad,eGameSetting_Sensitivity_InGame)) / 100.0f; + float mouseLookScale = 5.0f; + float mx = g_KBMInput.GetLookX(mouseSensitivity * mouseLookScale); + float my = g_KBMInput.GetLookY(mouseSensitivity * mouseLookScale); + + if ( app.GetGameSettings(iPad,eGameSetting_ControlInvertLook) ) { - float mouseSensitivity = 0.5f; - float mdx = rawDx * mouseSensitivity; - float mdy = -rawDy * mouseSensitivity; - if (app.GetGameSettings(iPad, eGameSetting_ControlInvertLook)) - mdy = -mdy; - player->interpolateTurn(mdx, mdy); + my = -my; } + + turnX += mx; + turnY += my; } #endif + player->interpolateTurn(turnX, turnY); + //jumping = controller.isButtonPressed(0); - unsigned int jump = InputManager.GetValue(iPad, MINECRAFT_ACTION_JUMP); - if( jump > 0 && pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_JUMP) ) + bool kbJump = false; +#ifdef _WINDOWS64 + kbJump = (iPad == 0) && g_KBMInput.IsMouseGrabbed() && g_KBMInput.IsKBMActive() && g_KBMInput.IsKeyDown(KeyboardMouseInput::KEY_JUMP); +#endif + if( (jump > 0 || kbJump) && pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_JUMP) ) jumping = true; else jumping = false; -#ifdef _WINDOWS64 - // Keyboard jump (Space) - if (iPad == 0 && KMInput.IsCaptured() && KMInput.IsKeyDown(VK_SPACE) && pMinecraft->localgameModes[iPad]->isInputAllowed(MINECRAFT_ACTION_JUMP)) - jumping = true; -#endif - #ifndef _CONTENT_PACKAGE if (app.GetFreezePlayers()) jumping = false; #endif +#ifdef _WINDOWS64 + if (iPad == 0 && g_KBMInput.IsKeyPressed(VK_ESCAPE) && g_KBMInput.IsMouseGrabbed()) + { + g_KBMInput.SetMouseGrabbed(false); + } +#endif + //OutputDebugString("INPUT: End input tick\n"); } diff --git a/Minecraft.Client/Input.h b/Minecraft.Client/Input.h index d8dedd57e..c7e1eec47 100644 --- a/Minecraft.Client/Input.h +++ b/Minecraft.Client/Input.h @@ -6,20 +6,17 @@ class Input public: float xa; float ya; - float sprintForward; bool wasJumping; bool jumping; bool sneaking; - bool usingKeyboardMovement; - - Input(); // 4J - added + bool sprinting; + + Input(); virtual void tick(LocalPlayer *player); private: - bool lReset; bool rReset; - bool m_gamepadSneaking; }; diff --git a/Minecraft.Client/LevelRenderer.cpp b/Minecraft.Client/LevelRenderer.cpp index 147f00194..f83831698 100644 --- a/Minecraft.Client/LevelRenderer.cpp +++ b/Minecraft.Client/LevelRenderer.cpp @@ -1964,8 +1964,8 @@ bool LevelRenderer::updateDirtyChunks() { if( (!onlyRebuild) || globalChunkFlags[ pClipChunk->globalIdx ] & CHUNK_FLAG_COMPILED || - ( distSq < 20 * 20 ) ) // Always rebuild really near things or else building (say) at tower up into empty blocks when we are low on memory will not create render data - { + ( distSq < 96 * 96 ) ) // Always rebuild really near things or else building (say) at tower up into empty blocks when we are low on memory will not create render data + { // distSq adjusted from 20 * 20 to 96 * 96 - updated by detectiveren considered++; // Is this chunk nearer than our nearest? #ifdef _LARGE_WORLDS @@ -2557,13 +2557,19 @@ void LevelRenderer::cull(Culler *culler, float a) { unsigned char flags = pClipChunk->globalIdx == -1 ? 0 : globalChunkFlags[ pClipChunk->globalIdx ]; + // Always perform frustum cull test + bool clipres = clip(pClipChunk->aabb, fdraw); + if ( (flags & CHUNK_FLAG_COMPILED ) && ( ( flags & CHUNK_FLAG_EMPTYBOTH ) != CHUNK_FLAG_EMPTYBOTH ) ) { - bool clipres = clip(pClipChunk->aabb, fdraw); pClipChunk->visible = clipres; if( pClipChunk->visible ) vis++; total++; } + else if (clipres) + { + pClipChunk->visible = true; + } else { pClipChunk->visible = false; @@ -2572,6 +2578,7 @@ void LevelRenderer::cull(Culler *culler, float a) } } + void LevelRenderer::playStreamingMusic(const wstring& name, int x, int y, int z) { if (name != L"") diff --git a/Minecraft.Client/LevelRenderer.h b/Minecraft.Client/LevelRenderer.h index bb7d78c8a..ff3b60881 100644 --- a/Minecraft.Client/LevelRenderer.h +++ b/Minecraft.Client/LevelRenderer.h @@ -52,14 +52,16 @@ public: static const int CHUNK_SIZE = 16; #endif static const int CHUNK_Y_COUNT = Level::maxBuildHeight / CHUNK_SIZE; -#if defined _XBOX_ONE - static const int MAX_COMMANDBUFFER_ALLOCATIONS = 2047 * 1024 * 1024; // Changed to 2047. 4J had set to 512. +#if defined _WINDOWS64 + static const int MAX_COMMANDBUFFER_ALLOCATIONS = 2047 * 1024 * 1024; // Changed to 2047. 4J had set to 512. +#elif defined _XBOX_ONE + static const int MAX_COMMANDBUFFER_ALLOCATIONS = 512 * 1024 * 1024; // 4J - added #elif defined __ORBIS__ static const int MAX_COMMANDBUFFER_ALLOCATIONS = 448 * 1024 * 1024; // 4J - added - hard limit is 512 so giving a lot of headroom here for fragmentation (have seen 16MB lost to fragmentation in multiplayer crash dump before) #elif defined __PS3__ static const int MAX_COMMANDBUFFER_ALLOCATIONS = 110 * 1024 * 1024; // 4J - added #else - static const int MAX_COMMANDBUFFER_ALLOCATIONS = 55 * 1024 * 1024; // 4J - added + static const int MAX_COMMANDBUFFER_ALLOCATIONS = 55 * 1024 * 1024; // 4J - added #endif public: LevelRenderer(Minecraft *mc, Textures *textures); @@ -270,10 +272,10 @@ public: bool dirtyChunkPresent; __int64 lastDirtyChunkFound; - static const int FORCE_DIRTY_CHUNK_CHECK_PERIOD_MS = 250; + static const int FORCE_DIRTY_CHUNK_CHECK_PERIOD_MS = 125; // decreased from 250 to 125 - updated by detectiveren #ifdef _LARGE_WORLDS - static const int MAX_CONCURRENT_CHUNK_REBUILDS = 4; + static const int MAX_CONCURRENT_CHUNK_REBUILDS = 8; // increased from 4 to 8 - updated by detectiveren static const int MAX_CHUNK_REBUILD_THREADS = MAX_CONCURRENT_CHUNK_REBUILDS - 1; static Chunk permaChunk[MAX_CONCURRENT_CHUNK_REBUILDS]; static C4JThread *rebuildThreads[MAX_CHUNK_REBUILD_THREADS]; diff --git a/Minecraft.Client/LivingEntityRenderer.cpp b/Minecraft.Client/LivingEntityRenderer.cpp index 9963ca302..8d8d4667f 100644 --- a/Minecraft.Client/LivingEntityRenderer.cpp +++ b/Minecraft.Client/LivingEntityRenderer.cpp @@ -487,11 +487,11 @@ void LivingEntityRenderer::renderNameTag(shared_ptr mob, const wst Font *font = getFont(); - float size = 1.60f; - float s = 1 / 60.0f * size; + constexpr float size = 1.60f; + constexpr float s = 1 / 60.0f * size; glPushMatrix(); - glTranslatef((float) x + 0, (float) y + 2.3f, (float) z); + glTranslatef(static_cast(x) + 0, static_cast(y) + mob->bbHeight + 0.5f, static_cast(z)); glNormal3f(0, 1, 0); glRotatef(-this->entityRenderDispatcher->playerRotY, 0, 1, 0); diff --git a/Minecraft.Client/LocalPlayer.cpp b/Minecraft.Client/LocalPlayer.cpp index 83e979ccd..b62ea823b 100644 --- a/Minecraft.Client/LocalPlayer.cpp +++ b/Minecraft.Client/LocalPlayer.cpp @@ -251,13 +251,10 @@ void LocalPlayer::aiStep() if (changingDimensionDelay > 0) changingDimensionDelay--; bool wasJumping = input->jumping; float runTreshold = 0.8f; - float sprintForward = input->sprintForward; - - bool wasRunning = sprintForward >= runTreshold; + bool wasRunning = input->ya >= runTreshold; //input->tick( dynamic_pointer_cast( shared_from_this() ) ); // 4J-PB - make it a localplayer input->tick( this ); - sprintForward = input->sprintForward; if (isUsingItem() && !isRiding()) { input->xa *= 0.2f; @@ -281,25 +278,9 @@ void LocalPlayer::aiStep() // world with low food, then reload it in creative. if(abilities.mayfly || isAllowedToFly() ) enoughFoodToSprint = true; - bool forwardEnoughToTriggerSprint = sprintForward >= runTreshold; - bool forwardReturnedToDeadzone = sprintForward == 0.0f; - bool forwardEnoughToContinueSprint = sprintForward >= runTreshold; - -#ifdef _WINDOWS64 - if (GetXboxPad() == 0 && input->usingKeyboardMovement) - { - forwardEnoughToContinueSprint = sprintForward > 0.0f; - } -#endif - -#ifdef _WINDOWS64 - // Keyboard sprint: Ctrl held while moving forward - if (GetXboxPad() == 0 && input->usingKeyboardMovement && KMInput.IsKeyDown(VK_CONTROL) && sprintForward > 0.0f && - enoughFoodToSprint && !isUsingItem() && !hasEffect(MobEffect::blindness) && onGround) - { - if (!isSprinting()) setSprinting(true); - } -#endif + bool forwardEnoughToTriggerSprint = input->ya >= runTreshold; + bool forwardReturnedToDeadzone = input->ya == 0.0f; + bool forwardEnoughToContinueSprint = input->ya >= runTreshold; // 4J - altered this slightly to make sure that the joypad returns to below returnTreshold in between registering two movements up to runThreshold if (onGround && !isSprinting() && enoughFoodToSprint && !isUsingItem() && !hasEffect(MobEffect::blindness)) @@ -327,6 +308,12 @@ void LocalPlayer::aiStep() } } if (isSneaking()) sprintTriggerTime = 0; +#ifdef _WINDOWS64 + if (input->sprinting && onGround && enoughFoodToSprint && !isUsingItem() && !hasEffect(MobEffect::blindness) && !isSneaking()) + { + setSprinting(true); + } +#endif // 4J-PB - try not stopping sprint on collision //if (isSprinting() && (input->ya < runTreshold || horizontalCollision || !enoughFoodToSprint)) if (isSprinting() && (!forwardEnoughToContinueSprint || !enoughFoodToSprint || isSneaking() || isUsingItem())) diff --git a/Minecraft.Client/Minecraft.Client.vcxproj b/Minecraft.Client/Minecraft.Client.vcxproj index 99a4ea27e..d7c49acfc 100644 --- a/Minecraft.Client/Minecraft.Client.vcxproj +++ b/Minecraft.Client/Minecraft.Client.vcxproj @@ -310,6 +310,7 @@ Application MultiByte v143 + true Application @@ -774,7 +775,7 @@ - true + false $(OutDir)$(ProjectName)_D.xex $(ProjectDir)\..\Minecraft.World\x64headers;$(ProjectDir)\Xbox\Sentient\Include;$(IncludePath) @@ -1544,6 +1545,7 @@ if not exist "$(TargetDir)\savedata" mkdir "$(TargetDir)\savedata" true Default false + /FS %(AdditionalOptions) true @@ -1756,7 +1758,7 @@ xcopy /q /y /i /s /e $(ProjectDir)DurangoMedia\CU $(LayoutDir)Image\Loose\CUUse TurnOffAllWarnings ProgramDatabase - Full + MaxSpeed Sync false $(OutDir)$(ProjectName).pch @@ -1769,6 +1771,10 @@ xcopy /q /y /i /s /e $(ProjectDir)DurangoMedia\CU $(LayoutDir)Image\Loose\CUDefault false Speed + true + true + true + /FS /Ob3 %(AdditionalOptions) true @@ -1776,6 +1782,7 @@ xcopy /q /y /i /s /e $(ProjectDir)DurangoMedia\CU $(LayoutDir)Image\Loose\CUlegacy_stdio_definitions.lib;d3d11.lib;..\Minecraft.World\x64_Release\Minecraft.World.lib;XInput9_1_0.lib;Windows64\Iggy\lib\iggy_w64.lib;%(AdditionalDependencies) NotSet false + UseLinkTimeCodeGeneration Run postbuild script @@ -48671,4 +48678,4 @@ xcopy /q /y /i /s /e $(ProjectDir)Durango\CU $(LayoutDir)Image\Loose\CU - \ No newline at end of file + diff --git a/Minecraft.Client/Minecraft.Client.vcxproj.filters b/Minecraft.Client/Minecraft.Client.vcxproj.filters index 708fe0b0a..2be7710a9 100644 --- a/Minecraft.Client/Minecraft.Client.vcxproj.filters +++ b/Minecraft.Client/Minecraft.Client.vcxproj.filters @@ -1,1868 +1,6298 @@  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {e23474e2-447c-41a9-82be-e32747f5b196} + + + {d7b60dd5-624a-46b3-b81d-f5f74550f613} + + + {68105641-375c-4565-9945-7890df6d82d9} + + + {8be4617d-3699-46a4-8769-28edb23c89f0} + + + {0b94741f-653f-48c2-874f-6aa69e7e9622} + + + {20606602-63d3-460c-b33e-d3e747a3d8db} + + + {4afb96fe-3fcb-4bd1-89a1-adfea86c73fb} + + + {304b5ee1-bfdb-489f-8e24-0a4e61177ca1} + + + {225f9542-472d-45c1-9046-eb2a46ab029c} + + + {14e20ee1-fe3b-481b-acce-7a634ee9c1d6} + + + {486b537f-d140-4a23-8409-fe3bc4184009} + + + {91ef92f9-432b-4b8f-9f16-4efd211003a1} + + + {66656f96-a5da-48c6-a7f9-79ab343dbd2f} + + + {3423fd63-b0d7-4f50-b0ca-549386c6cf57} + + + {d097d6ee-2ae4-48d8-8b5a-9b48882bdb2c} + + + {1d0a6eec-14cd-4e6d-8a0a-f5f8f0ab5240} + + + {269fab49-d870-4358-baef-32ed6ac9eca7} + + + {fef42379-3d37-4ef3-aa73-b19aaa77e3cc} + + + {bce4041a-9336-45e7-bd40-ed057ed96ee8} + + + {9756cb73-3f40-4fcb-9bab-5a3ce3c4d2f6} + + + {bb820acc-a8eb-4e36-8b4e-9517263ed51b} + + + {3c3aca1d-0e3e-43f1-b4cd-f8dfce2d29e7} + + + {9f1bf1ed-5366-4a29-b3f3-296725a7b01c} + + + {3e905494-b5dc-4084-a1fe-cbd91b9af667} + + + {afb98298-0033-42ec-98a5-93f8d347ee0d} + + + {1953b4f7-41ea-430b-ad2d-e3d7c352b647} + + + {39ab4d1f-8199-4ec7-948e-3d42ad8c8573} + + + {73bbdc5b-04f3-42f8-bf3b-769335e19178} + + + {385338b7-fa77-4c46-a7f2-89c82dc6e192} + + + {0f94b57d-88f8-4a20-b4e4-d1fa95d8f439} + + + {abe2942f-f984-4930-9e2d-9c9c2b35ac74} + + + {a2be9911-8785-4f6a-932e-e03321ee466b} + + + {7cb56f76-52cf-4303-8631-e1471fdc09a0} + + + {098e2985-9c15-450f-baa2-78604e7c1f54} + + + {6c286ad1-f871-408a-be6e-db44e7edcd2c} + + + {7c254dd0-f36f-4001-83cc-1634a2c792c2} + + + {2a26afce-4160-4fb0-8d01-e394a669dae6} + + + {9229f78c-152c-47d5-858a-fd054b856a1c} + + + {81ab078c-fc67-460c-befd-616dbe4bc3bc} + + + {db324829-af2c-428d-9710-8ad20ecc3fd0} + + + {758ac0be-6bd7-42c0-9b09-fdd452c0e134} + + + {c2dcdce8-b00f-4094-b0de-dad838d49525} + + + {8fd2f4e7-b93a-4067-93b8-a7ebac6d4a9c} + + + {93a41380-e12e-4f7a-bb7b-459f7169faed} + + + {4eb1ba28-620f-4136-979c-4dc91c44b666} + + + {5ac21685-36c0-4cd1-8861-e6a0e4a37c62} + + + {1b4710ff-c513-4a11-9d34-ff36fe1b4246} + + + {f4877497-fdf4-48a8-ada4-e6042f632e7a} + + + {45f40847-5b95-4dca-82f2-7616d7a35e54} + + + {1a98ef4c-6c9d-4a22-93d7-89f0fc3320fd} + + + {3be02e3c-c628-4315-a507-a9fe7733af01} + + + {c6dffb6d-2cf6-4c3e-89a3-fb05229b98aa} + + + {7d088a48-eeda-4783-94f7-c0d09b06f347} + + + {a466219c-afde-4184-8b84-91df32e5b892} + + + {40d6ff43-3d13-42ab-99ae-ebc9d585110f} + + + {047a3693-2040-404d-a386-2e5795b231d3} + + + {2509ddc5-330c-45da-a6f9-d37b858acd34} + + + {b2935b29-33d3-4d57-a145-753a646e5de4} + + + {26661545-d0a0-438a-a775-31cec1fb7849} + + + {5f5f5678-57b0-4f7f-b7dc-1ddd01ea2774} + + + {a19d2d41-9a2f-4631-941b-c3bfa7c2fdfd} + + + {bcdb8322-b7e6-482b-a3da-eb3f84dac713} + + + {e2959475-d5c8-4874-a782-fb5266e4441c} + + + {794dfcdb-98c6-4939-b04d-86b9657d4ff6} + + + {775f3088-bc52-43a3-b9ec-7f3f58508240} + + + {ebe1835b-76a8-408d-b3ee-70ffa4db7907} + + + {45bddf1c-e6d6-4a78-9b7d-73d7511e070d} + + + {16186163-4c73-4fa8-85c7-57d2b34e3fe9} + + + {b33b6793-e585-487e-8626-0096242f8e04} + + + {1264d92e-fa06-40ef-846c-4ce2a99e8ccc} + + + {b28c2ec8-a257-41ca-aad2-cf2ced04e4fa} + + + {7369fca1-3096-4b7d-a93e-924587f23108} + + + {e0eabf73-2721-46f9-bc46-4e0292bb53d3} + + + {bf450dfd-c9e8-4120-8a4c-3860b606637e} + + + {4412cd12-307d-407c-8d4a-34df3274c892} + + + {91fbb0f7-3d94-4786-aa07-c9c57a6db9a9} + + + {afb9404f-f23d-46b1-b4d5-4b1096d5bf40} + + + {716a30f7-f9dd-43bf-9228-646dff4c58b1} + + + {3531c304-b08e-48ae-860c-773f6702ec4d} + + + {924f367a-618c-429e-9866-f60821f21d4a} + + + {e3e43b8f-e455-4222-a92e-f6567a41e326} + + + {61ac879d-17b0-402b-b29f-88c60a1161c7} + + + {4f5c7e99-5cbc-4db4-99c4-37db45537198} + + + {33341824-5702-4a56-b75c-9dac57e49349} + + + {4dbeff57-70bc-4b4c-b5d0-4c6834968d85} + + + {4be5c8d2-8944-4e8f-9d79-b1abc4b66f8f} + + + {ba24985e-3b16-45af-963e-9f2edca20b1a} + + + {77957a66-a869-4b9b-bbda-e7f43e01096f} + + + {fa09ab64-0a3f-429b-93cb-149ee490767b} + + + {dec59bc5-d9d3-4be5-b449-3df3b430eb39} + + + {0bcca89e-0d2d-407b-b1e4-878465404901} + + + {395a09e4-1ff9-458c-8fb8-a4cb28aa4881} + + + {056ec81c-c93f-4c56-9bcb-697cda24a612} + + + {d3d4cc74-edfa-4bbb-8e66-7252dbbc131b} + + + {1511a94f-13bc-49e0-bf75-7cdf98f1e77f} + + + {f0b2e12a-e042-49bc-a5fa-78d1cf79e5d3} + + + {d2020762-d261-4c89-bbb9-0c7113012882} + + + {88ebd63d-2bbc-438a-a810-9b26fcfdd908} + + + {2cf98618-28c5-46df-9ff7-3d331ee4a275} + + + {3c643f18-092d-4870-a206-8dc906748a64} + + + {11cc2598-d569-47ad-8843-7a8296878be9} + + + {33371180-d4ec-4439-8a95-059babcc1db9} + + + {c6d264ea-d4ac-4f3f-81f7-0d91fdc27713} + + + {bde45e25-7dce-4a39-a2bf-dad234708b07} + + + {9685dbaa-ed65-453c-ba57-ec01e59022ae} + + + {92ead381-f2b8-4c6d-a3ca-c6fbc7753361} + + + {2031e778-56ff-4126-b09d-4ec59453b21c} + + + {98e39923-fe62-42d5-8650-746c2d61efd2} + + + {094cddb4-1ac5-424b-80e3-e3b0e9bb3b05} + + + {914f66a5-b1a7-4615-9adc-287d28158eee} + + + {36ba326b-c3a1-473e-8cb4-054e34c276a8} + + + {f9dae5df-fabf-41f9-9b13-8d32e5b5baa5} + + + {e634a43c-ee4c-4adc-8847-c667fdc73c5f} + + + {71d6ccac-7a6e-4399-987b-06b606056f59} + + + {05765c7e-26d6-4760-b0f6-7aa9f374d163} + + + {02363026-02fd-4efc-a115-6ae3dc652546} + + + {d71c6707-d6ba-4ab5-a505-a916e007e60d} + + + {eb5eb5f3-0ea7-4658-a8fb-634eb289941d} + + + {46d5754b-1818-4685-a16d-f7415f61868c} + + + {541f67ae-2627-40af-8316-d76ee9bb6985} + + + {ccfdb851-7965-4551-88bb-4312ddbf830a} + + + {2b9abc76-798a-4aae-ba50-2dfc8f78ae81} + + + {35491a01-dd6f-4313-b857-5e3eb323b44f} + + + {bcac2142-c160-4a73-96c5-cbdf681a16f0} + + + {290b2f1c-dcd8-4ebc-9d6d-fa6de190117e} + + + {a7ec80a7-ea10-438c-a10f-7eeef759c32d} + + + {9a2c49f6-2f9d-4e9d-a4ea-a0a04ecba75f} + + + {24e96065-3dd4-4150-bde2-128d133fd2c4} + + + {10961b95-cb43-4a00-b999-04b66a1a0b43} + + + {6aaa8af3-3df6-43f4-9346-9adfe45ca3a7} + + + {aba0f713-fcfb-417e-9616-c8474225de71} + + + {94298ae6-25e0-4cc9-8c5a-efd53e156baa} + + + {6ec99327-b465-4e61-b064-023a09bdf907} + + + {2095b7df-1779-4788-b004-3479d5ab59d8} + + + {4c9eb137-a48c-44a4-be08-ef1745834ece} + + + {2bae7445-385f-4b0e-a3ec-11c1c584f930} + + + {7c655cf2-f74e-4e6a-9114-405f5bc28a56} + + + {a392080f-8e8b-42be-832a-a35869dba580} + + + {42dca5dc-e462-4537-9929-847a044eb116} + + + {0da3a534-f8c9-4d0c-a73f-dfeb402b27c1} + + + {2e1858a4-a24b-49d8-b19c-c24b45f75a4f} + + + {096eb9da-ee6c-46ba-a0f4-dd8d1748b6a1} + + + {50dc7509-93df-4e0a-8a9a-cea040e92180} + + + {67544d93-633f-46a8-9cdf-8ae646a745d1} + + + {08da2d2a-3276-4109-b190-05fbc4709398} + + + {cef89641-7631-4c30-855f-603163446077} + + + {a15076ff-0dbe-4fb5-8b58-4ceb4b189c8f} + + + {a36a05f3-bc99-4097-b7a8-f81c37eec6e3} + + + {c9fd57aa-ede6-46f3-b968-0f4a7c64f7f1} + + + {bcd2eaff-60b9-41f4-8e1a-258639b27f99} + + + {ebc154be-8d55-478b-9038-856d445aaf15} + + + {0749340b-e216-450a-a02e-001917097ba5} + + + {6b6c31a6-0b8d-4dc0-8d6e-38ab6de709ff} + + + {d7537fdd-877b-461c-9c86-3235843fcfc0} + + + {61e77fc3-d018-4e08-985c-9871eca81fe2} + + + {2c983999-feb8-40db-885b-abf061e2ab58} + + + {093a811c-5f90-4c0e-b260-4b637079730a} + + + {c2fdb165-80e4-4ce0-9bf1-12e5c58f83a5} + + + {ad68d69a-99d0-4eea-9bb4-58cb7083a7a1} + + + {a04f2d63-3e47-470f-b4ac-c1d5caf8ce56} + + + {a0aa2098-142e-4688-8d73-00ec7e5e9361} + + + {f7fc551a-1d1a-4584-af3b-2eadb712b0f7} + + + {7155e1ba-d9b6-473b-8c59-77dd883b766f} + + + {017984f1-6659-4a44-96fd-7dbb8f9b2654} + + + {5d6f34a3-c647-479d-a1a9-89a9ffca4ab9} + + + {6f049254-6585-4a90-be74-70d3878d864f} + + + {e4051e75-f566-41ce-b86a-46c838872963} + + + {18d3c9bc-132e-4770-a665-fc030eb86394} + + + {8a2156f5-3462-447b-b04d-e555a917fbf2} + + + {e0cb4d67-dd35-43ab-88cc-63173cc31125} + + + {090821e7-2a93-44de-bf5e-d5dbbcb41621} + + + {11f70fef-83b4-4fb9-85ab-51109fbb6a56} + + + {7b594635-988d-40aa-8a00-0d60b1f49a5a} + + + {e7df083d-5b13-46bc-a5b9-610c3ffb33bc} + + + {2ef42e03-cbaa-4077-a7f4-008150037f01} + + + {4d1da71a-dd84-4073-be6d-1e534eca98f3} + + + {acb27adb-45a3-45cf-85f5-3ae00cf3357d} + + + {3a9d8989-ff64-411c-84ad-b7dfb2520d5a} + + + {de5f0642-c9ab-431b-a255-a936076ffed2} + + + {76ac5981-4824-487a-992f-273bfa73fb68} + + + {b1794e73-9397-4e45-8a0d-a4f6dc72c321} + + + {ff6b8d80-d0ed-4225-b56c-1d0a19824e2f} + + + {4d0806f8-ae38-4bac-8469-0a82fc61eecd} + + + {67f51112-db23-4c8a-af1b-f748f7bbce8f} + + + {a47c9da7-bf36-42ae-aedf-c00c071c0582} + + + {017967fb-353e-448b-ae2c-639a182f3ee0} + + + {f4d6c5f9-40d6-4e52-bc03-fef06e9f0221} + + + {122ac1f3-113d-4f91-8676-bbe16e236f4f} + + + {1d28fadf-f748-4616-830b-ec2faa1b5f8e} + + + {bf865c6c-8bf4-4bd6-aaed-ff2a7c92706a} + + + {3eefa342-44e2-493a-9165-40f85bcef557} + + + {f88c0f6a-8051-41e7-9bf6-b9d3c7bb2937} + + + {a6b9803b-8dc2-4552-856e-470f78757533} + + + {21ba77e3-ca31-4dbb-b85d-48ddf892e1da} + + + {06443c48-8447-447b-895f-da725cc13c0c} + + + {ba60dadb-f607-49b7-ab07-0da3a6e06138} + + + {abc41045-2c80-41e8-a8e5-80383e3331b7} + + + {6e66e638-15af-47a6-83de-93bb0cb8ae3d} + + + {b2a3a14e-806c-4ebf-9413-0bbca21b6699} + + + {57a41953-69e1-408c-94ca-5a0fc35bee3d} + + + {afe55d4b-8cbd-4fc0-b4b5-e823d35ac9f6} + + + {ff3c3e8d-02aa-446f-912b-876aad8bb71a} + + + {5ce05bd9-a7f6-47cf-81c3-8c95d3627c5c} + + + {f90e55f2-d904-4421-8284-db37fe80c549} + + + {4c8bf8d5-d6d9-4b6b-96dd-00d64f476027} + + + {90c63e2f-0b47-4aca-a1df-26c436af7c69} + + + {ad3528e0-0c39-42d5-b756-fdf691df5f17} + + + {262a14ae-51b7-4d11-be00-2bf7840dc67d} + + + {40ad6aa5-e972-4aaf-bbb0-c783e72fb341} + + + {d705167f-d99e-49b5-a667-24c0c2fe7bcc} + + + {d52b4de1-b2d7-4c80-afb4-7c6edae1efcb} + + + {61ac299e-6446-4df9-b5cc-9b2c0890b47c} + + + {147837b5-da79-4938-abcf-f8926a72b25c} + + + {34edb787-189e-49c7-8412-f5def16b6f99} + + + {1f029554-0246-45da-8bfd-8d4bc8d4cffc} + + + {15633337-4260-4618-bffa-df945dba2b1a} + + + {81d283e0-15b7-4dcf-a85d-961169a993cd} + + + {dea799c3-4584-461c-a788-9766f61cea56} + + + {619bbb82-dfbc-499e-b078-048ad7e26222} + + + {f5065760-0ad8-4fb3-b6a9-f3ba06be0e51} + + + {360a336e-01e3-4a34-8608-efd2c7c72ef7} + + + {1d9e76bb-7f51-487f-b0b4-de3419fd1925} + + + {177ed754-f97c-4e53-9e75-1f548ae2a0b4} + + + {4b317e13-b7e6-4468-8a2e-bfbbe3bb272b} + + + {acc4e8ae-a1f1-4f2b-9bf2-e12b74fa3a1a} + + + {893769f2-22f7-4c41-ad2b-cb8668fb3b66} + + + {c1441371-f323-4549-90a0-53c6f743b4b1} + + + {b043e348-607a-4ac2-95de-f573db5dd04f} + + + {af98fe8e-ce25-437a-8ab9-efa9d8f0a5b0} + + + {9a61fbe5-f9a2-4c83-b407-5a295808664e} + + + {f55d07b2-80f2-4a01-8fb8-0b09545bf916} + + + {829b148f-b0d9-4a70-87ea-22f57281ac1f} + + + {08832b8f-5370-4c06-95ab-b5b285eb5fc5} + + + {918450ce-de83-4daf-8f25-7aaa8afcb856} + + + {5d807c82-39b9-4651-ab8a-14244deff851} + + + {9dee27ed-5aaf-4fad-b219-faebcebbe450} + + + {22d0b2d5-3279-4144-a23c-8eafb9d90e63} + + + {0061db22-43de-4b54-a161-c43958cdcd7e} + + + {889a84db-3009-4a7c-8234-4bf93d412690} + + + {e5d7fb24-25b8-413c-84ec-974bf0d4a3d1} + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + Xbox\GameConfig + + + Xbox\GameConfig + + + Xbox\res\audio + + + Xbox\res\audio + + + Xbox\res\audio + + + Xbox\4JLibs\Media + + + Xbox\res + + + Xbox\res + + + Xbox\xexxml + + + Xbox\xexxml + + + Xbox\Source Files\Sentient\Telemetry + + + Xbox\Source Files\Sentient\DynamicConf + + + + Windows64\GameConfig + + + Windows64\GameConfig + + + Durango + + + Durango + + + Durango + + + + Orbis\4JLibs\libs + + + Orbis\4JLibs\libs + + + Orbis\4JLibs\libs + + + Orbis\4JLibs\libs + + + Orbis\Miles Sound System\lib + + + PS3\Miles Sound System\lib + + + PS3\Miles Sound System\lib + + + PS3\Miles Sound System\lib + + + PS3\Miles Sound System\lib\spu + + + PS3\Miles Sound System\lib\spu + + + PS3\Miles Sound System\lib\spu + + + PS3\Miles Sound System\lib\spu + + + PS3\Miles Sound System\lib\spu + + + PS3\Miles Sound System\lib\spu + + + PS3\Miles Sound System\lib\spu + + + PS3\Miles Sound System\lib\spu + + + Windows64\Iggy\gdraw + + + Windows64\Iggy\gdraw + + + Windows64\Iggy\gdraw + + + Windows64\Iggy\gdraw + + + Durango\Iggy\gdraw + + + Durango\Iggy\gdraw + + + Durango\Iggy\gdraw + + + PS3\Iggy\gdraw + + + PS3\Iggy\gdraw + + + Windows64\Iggy\gdraw + + + Orbis\Iggy\gdraw + + + Orbis\Iggy\gdraw + + + Common\Source Files\Network + + + PSVita\GameConfig + + + PSVita\GameConfig + + + Orbis\4JLibs\libs + + + PSVita\Iggy\gdraw + + + PSVita\Iggy\gdraw + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + Header Files + + + net\minecraft\client\renderer\culling + + + net\minecraft\client\renderer\culling + + + net\minecraft\client\renderer\culling + + + net\minecraft\client\renderer\culling + + + Header Files + + + net\minecraft\client\renderer\culling + + + net\minecraft\client\renderer\culling + + + net\minecraft\client\renderer + + + net\minecraft\client\renderer + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\renderer + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\player + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\tileentity + + + net\minecraft\client\renderer\tileentity + + + net\minecraft\client\renderer\tileentity + + + net\minecraft\client\renderer\tileentity + + + net\minecraft\client\renderer + + + net\minecraft\client\skins + + + net\minecraft\client\skins + + + net\minecraft\client\skins + + + net\minecraft\client\skins + + + net\minecraft\client\renderer + + + net\minecraft\client\renderer + + + net\minecraft\client\renderer + + + net\minecraft\client\renderer + + + net\minecraft\client\renderer + + + net\minecraft\client\renderer + + + net\minecraft\client\renderer + + + net\minecraft\client\renderer + + + net\minecraft\client\renderer + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client + + + net\minecraft\client\player + + + net\minecraft\stats + + + net\minecraft\stats + + + net\minecraft\client\player + + + net\minecraft\client + + + net\minecraft\client + + + net\minecraft\client + + + net\minecraft\client + + + net\minecraft\client + + + net\minecraft\client + + + net\minecraft\client + + + net\minecraft\client\level + + + net\minecraft\client + + + net\minecraft\client\gui + + + net\minecraft\client\gui + + + net\minecraft\client + + + net\minecraft\client\gui + + + net\minecraft\client\gui + + + net\minecraft\client\gui + + + net\minecraft\client\gui\particle + + + net\minecraft\client\gui\particle + + + net\minecraft\client\gui + + + net\minecraft\client\gui + + + net\minecraft\client\gui + + + net\minecraft\client\gui + + + net\minecraft\client\gui + + + net\minecraft\client\gui + + + net\minecraft\client\gui + + + net\minecraft\client\gui + + + net\minecraft\client\gui + + + net\minecraft\client\gui + + + net\minecraft\client\gui + + + net\minecraft\client\gui + + + net\minecraft\client\gui + + + net\minecraft\client\title + + + net\minecraft\client\gui + + + net\minecraft\client\gui + + + net\minecraft\client\gui + + + net\minecraft\client\gui + + + net\minecraft\client\gui + + + net\minecraft\client\gui + + + net\minecraft\client\gui + + + net\minecraft\client\gui\inventory + + + net\minecraft\client\gui\inventory + + + net\minecraft\client\gui\inventory + + + net\minecraft\client\gui\inventory + + + net\minecraft\client\gui\inventory + + + net\minecraft\client\gui\inventory + + + net\minecraft\client\gui\inventory + + + net\minecraft\client\gui\achievement + + + net\minecraft\client\gui\achievement + + + net\minecraft\client\gui\achievement + + + Xbox\4JLibs\inc + + + Xbox\4JLibs\inc + + + Xbox\4JLibs\inc + + + Xbox\4JLibs\inc + + + Xbox\GameConfig + + + Xbox\Source Files + + + net\minecraft\server\network + + + net\minecraft\server\network + + + net\minecraft\server\level + + + net\minecraft\server\level + + + net\minecraft\server\level + + + net\minecraft\server\level + + + net\minecraft\server\level + + + net\minecraft\server\level + + + net\minecraft\server\level + + + net\minecraft\server + + + net\minecraft\server + + + net\minecraft\server + + + net\minecraft\server + + + net\minecraft\server + + + net\minecraft\server\level + + + Xbox\Source Files\XUI\Menu screens + + + Xbox\Source Files\XUI\Menu screens + + + net\minecraft\client\multiplayer + + + net\minecraft\client\multiplayer + + + net\minecraft\client\multiplayer + + + net\minecraft\client\multiplayer + + + net\minecraft\client\multiplayer + + + net\minecraft\client\multiplayer + + + net\minecraft\client\multiplayer + + + net\minecraft\client\multiplayer + + + Xbox\Source Files\XUI\Menu screens + + + Xbox\Source Files\XUI\Menu screens + + + Xbox\Source Files\XUI\Menu screens + + + Xbox\Source Files\XUI\Menu screens + + + Xbox\Source Files\XUI\Menu screens\Help & Options + + + Xbox\Source Files\XUI\Menu screens\Help & Options\Controls + + + Xbox\Source Files\XUI\Menu screens\Help & Options\Credits + + + Xbox\Source Files\XUI\Menu screens\Help & Options\How To Play + + + Xbox\Source Files\XUI\Menu screens\Help & Options\How To Play + + + Xbox\Source Files\XUI\Menu screens + + + Xbox\Source Files\XUI\Menu screens + + + Xbox\Source Files\XUI\Menu screens + + + Xbox\Source Files\XUI\Menu screens\Tutorial + + + Xbox\Source Files\XUI\Menu screens\Leaderboards + + + Xbox\Source Files\XUI\Menu screens\Pause + + + Xbox\Source Files\XUI\Menu screens + + + Xbox\Source Files\XUI\Menu screens\Debug + + + Xbox\Source Files\XUI\Menu screens\Debug + + + Xbox\Source Files\XUI\Menu screens + + + Xbox\Source Files\XUI\Menu screens + + + Xbox\Source Files\XUI\Controls + + + Xbox\Source Files\XUI\Controls + + + Xbox\Source Files\XUI\Controls + + + Xbox\Source Files\XUI\Controls + + + Xbox\Source Files\XUI\Controls + + + Xbox\Source Files\XUI\Controls + + + Xbox\Source Files\XUI\Controls + + + Xbox\Source Files\XUI\Controls + + + Xbox\Source Files\XUI\Controls + + + Xbox\Source Files\XUI\Controls + + + Xbox\Source Files\XUI\Controls + + + Xbox\Source Files\XUI\Controls + + + Xbox\Source Files\XUI\Controls + + + Xbox\Source Files\XUI\Controls + + + Xbox\Source Files\XUI\Menu screens\Social + + + Header Files + + + Header Files + + + Header Files + + + Xbox\Source Files\XUI\Menu screens + + + Xbox\Source Files\XUI\Menu screens + + + Xbox\Source Files\XUI\Menu screens + + + Xbox\XML + + + Xbox\SentientLibs\inc + + + Xbox\SentientLibs\inc + + + Xbox\SentientLibs\inc + + + Xbox\SentientLibs\inc + + + Xbox\SentientLibs\inc + + + Xbox\SentientLibs\inc + + + Xbox\SentientLibs\inc + + + Xbox\SentientLibs\inc + + + Xbox\SentientLibs\inc + + + Xbox\SentientLibs\inc + + + Xbox\SentientLibs\inc + + + Xbox\SentientLibs\inc + + + Xbox\SentientLibs\inc + + + Xbox\SentientLibs\inc + + + Xbox\SentientLibs\inc + + + Xbox\SentientLibs\inc + + + Xbox\SentientLibs\inc + + + Xbox\SentientLibs\inc + + + Xbox\SentientLibs\inc + + + Xbox\SentientLibs\inc + + + Xbox\SentientLibs\inc + + + Xbox\SentientLibs\inc + + + Xbox\SentientLibs\inc + + + Xbox\SentientLibs\inc + + + Xbox\SentientLibs\inc + + + Xbox\SentientLibs\inc + + + Xbox\SentientLibs\inc + + + Xbox\SentientLibs\inc + + + Xbox\SentientLibs\inc + + + Xbox\SentientLibs\inc + + + Xbox\Source Files\Sentient\Telemetry + + + Xbox\Source Files\Sentient\Telemetry + + + Xbox\Source Files\Sentient\Telemetry + + + Xbox\Source Files\XUI\Menu screens\Help & Options\Settings + + + Xbox\Source Files\XUI\Controls + + + Xbox\Source Files\Sentient\DynamicConf + + + Xbox\Source Files\XUI\Menu screens + + + Xbox\Source Files\XUI\Controls + + + Xbox\Source Files\Font + + + Xbox\Source Files\Font + + + Xbox\Source Files\Font + + + Xbox\Source Files\XUI\Menu screens\Debug + + + net\minecraft\server\network + + + Xbox\Source Files\XUI\Menu screens\Help & Options\Settings + + + Xbox\Source Files\XUI\Controls + + + net\minecraft\client\renderer\tileentity + + + Xbox\Source Files\Sentient + + + Xbox\Source Files\Sentient\Telemetry + + + Xbox\Source Files\XUI\Menu screens\Help & Options\Settings + + + Xbox\Source Files\XUI\Menu screens\Help & Options\Settings + + + Xbox\Source Files\XUI\Menu screens\Help & Options\Settings + + + Xbox\Source Files\XUI\Menu screens\Help & Options\Settings + + + Xbox\XML + + + net\minecraft\server\level + + + net\minecraft\server\network + + + net\minecraft\client + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\multiplayer + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client\renderer + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\tileentity + + + Xbox\Source Files\XUI\Menu screens\Debug + + + Xbox\Source Files\XUI\Menu screens\Debug + + + Xbox\Source Files\XUI\Menu screens + + + Xbox\Source Files\XUI\Menu screens + + + Xbox\Source Files\XUI\Menu screens + + + net\minecraft\client + + + Xbox\Source Files\XUI\Menu screens + + + net\minecraft\server + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\tileentity + + + net\minecraft\client\renderer\tileentity + + + net\minecraft\client\model\geom + + + net\minecraft\client\model\geom + + + net\minecraft\client\model\dragon + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client\model\geom + + + net\minecraft\client\particle + + + net\minecraft\client\model\geom + + + net\minecraft\client\model\dragon + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model\geom + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model\geom + + + Xbox\Source Files\XUI\Controls + + + Xbox\Source Files\XUI\Controls + + + Xbox\Source Files\XUI\Controls + + + Xbox\Source Files\XUI\Controls + + + Xbox\Source Files\XUI\Controls + + + Xbox\Source Files\XUI\Controls + + + Header Files + + + Xbox\Source Files\XUI\Menu screens + + + Xbox\Source Files\Social + + + Header Files + + + Windows + + + Windows + + + Durango\4JLibs\inc + + + Durango\4JLibs\inc + + + Durango\4JLibs\inc + + + Durango\4JLibs\inc + + + Common\Source Files\Trial + + + Common\Source Files\Tutorial\Constraints + + + Common\Source Files\Tutorial\Constraints + + + Common\Source Files\Tutorial\Constraints + + + Common\Source Files\Tutorial\Constraints + + + Common\Source Files\Tutorial\Constraints + + + Common\Source Files\Tutorial\Hints + + + Common\Source Files\Tutorial\Hints + + + Common\Source Files\Tutorial\Hints + + + Common\Source Files\Tutorial\Hints + + + Common\Source Files\Tutorial\Hints + + + Common\Source Files\Tutorial\Hints + + + Common\Source Files\Tutorial\Tasks + + + Common\Source Files\Tutorial\Tasks + + + Common\Source Files\Tutorial\Tasks + + + Common\Source Files\Tutorial\Tasks + + + Common\Source Files\Tutorial\Tasks + + + Common\Source Files\Tutorial\Tasks + + + Common\Source Files\Tutorial\Tasks + + + Common\Source Files\Tutorial\Tasks + + + Common\Source Files\Tutorial\Tasks + + + Common\Source Files\Tutorial\Tasks + + + Common\Source Files\Tutorial\Tasks + + + Common\Source Files\Tutorial\Tasks + + + Common\Source Files\Tutorial\Tasks + + + Common\Source Files\Tutorial\Tasks + + + Common\Source Files\Tutorial\Tasks + + + Common\Source Files\Tutorial\Tasks + + + Common\Source Files\Tutorial\Tasks + + + Common\Source Files\Tutorial\Tasks + + + Common\Source Files\GameRules\LevelGeneration\StructureActions + + + Common\Source Files\GameRules\LevelGeneration\StructureActions + + + Common\Source Files\GameRules\LevelGeneration\StructureActions + + + Common\Source Files\GameRules\LevelGeneration\StructureActions + + + Common\Source Files\GameRules\LevelGeneration + + + Common\Source Files\GameRules\LevelRules\RuleDefinitions + + + Common\Source Files\GameRules\LevelRules\RuleDefinitions + + + Common\Source Files\GameRules\LevelRules\RuleDefinitions + + + Common\Source Files\GameRules\LevelRules\RuleDefinitions + + + Common\Source Files\GameRules\LevelRules\RuleDefinitions + + + Common\Source Files\GameRules\LevelRules\RuleDefinitions + + + Common\Source Files\GameRules\LevelRules\RuleDefinitions + + + Common\Source Files\Tutorial + + + Common\Source Files\Tutorial + + + Common\Source Files\Tutorial + + + Common\Source Files\Tutorial + + + Common\Source Files\Tutorial + + + Common\Source Files\Tutorial + + + Durango\Source Files + + + Common\Source Files\Tutorial\Hints + + + Durango\Source Files\Sentient + + + Durango\Source Files\Sentient + + + Durango\Source Files\Sentient + + + Durango\Source Files\Sentient + + + Durango\Source Files\Sentient + + + Durango\XML + + + Durango\Source Files\Sentient + + + Durango\Source Files\Social + + + Durango + + + Common + + + PS3\4JLibs\inc + + + PS3\4JLibs\inc + + + PS3\4JLibs\inc + + + PS3\4JLibs\inc + + + PS3\Source Files\Social + + + PS3\Source Files\Sentient + + + PS3\Source Files\Sentient + + + PS3\Source Files\Sentient + + + PS3\Source Files\Sentient + + + PS3\Source Files\Sentient + + + PS3\Source Files\Sentient + + + PS3\Source Files + + + PS3\PS3Extras + + + PS3\PS3Extras + + + Durango + + + Common\Source Files + + + Common\Source Files + + + Common\Source Files + + + Common\Source Files\GameRules\LevelGeneration + + + Common\Source Files\GameRules\LevelGeneration + + + Common\Source Files\GameRules + + + Common\Source Files\GameRules + + + PS3 + + + Xbox\Source Files\XUI + + + Xbox\Source Files\XUI + + + Xbox\Source Files\XUI + + + Xbox\Source Files\XUI\Base Scene + + + Xbox\Source Files\XUI\Base Scene + + + Xbox\Source Files\XUI\Base Scene + + + Xbox\Source Files\XUI\Containers + + + Xbox\Source Files\XUI\Containers + + + Xbox\Source Files\XUI\Containers + + + Xbox\Source Files\XUI\Containers + + + Xbox\Source Files\XUI\Containers + + + Xbox\Source Files\XUI\Containers + + + Xbox\Source Files\XUI\Containers + + + Xbox\Source Files\XUI\Containers + + + Xbox\Source Files\XUI\Containers + + + Xbox\Source Files\XUI\Controls + + + Xbox\Source Files\XUI\Controls + + + net\minecraft\client\skins + + + net\minecraft\client\particle + + + net\minecraft\client\skins + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer + + + net\minecraft\client\renderer\texture + + + net\minecraft\client\renderer\texture + + + net\minecraft\client\renderer\texture + + + net\minecraft\client\renderer\texture + + + net\minecraft\client\renderer\texture + + + net\minecraft\client\renderer\texture + + + net\minecraft\client\renderer\texture + + + net\minecraft\client\renderer\texture\custom + + + net\minecraft\client\renderer\texture\custom + + + Xbox\Source Files\XUI\Menu screens\Help & Options\Settings + + + Xbox\Source Files\XUI + + + PS3\PS3Extras + + + PS3\PS3Extras + + + net\minecraft\client\renderer\texture + + + net\minecraft\client\renderer\texture + + + net\minecraft\client\skins + + + Common\Source Files\DLC + + + Common\Source Files\DLC + + + Common\Source Files\DLC + + + Common\Source Files\DLC + + + Common\Source Files\DLC + + + Common\Source Files\DLC + + + Header Files + + + Windows64\4JLibs\inc + + + Windows64\4JLibs\inc + + + Windows64\4JLibs\inc + + + Windows64\4JLibs\inc + + + Windows64\GameConfig + + + Windows64\XML + + + Windows64\Source Files + + + Windows64\Source Files\Social + + + Windows64\Source Files\Sentient + + + Windows64\Source Files\Sentient + + + Windows64\Source Files\Sentient + + + Windows64\Source Files\Sentient + + + Windows64\Source Files\Sentient + + + Windows64\Source Files\Sentient + + + Windows64 + + + Windows64\Source Files + + + Windows64 + + + Durango\Source Files + + + Orbis\OrbisExtras + + + Orbis\4JLibs\inc + + + Orbis\4JLibs\inc + + + Orbis\4JLibs\inc + + + Orbis\4JLibs\inc + + + Orbis\OrbisExtras + + + Orbis\OrbisExtras + + + Xbox\Source Files\XUI\Base Scene + + + Header Files + + + Common\Source Files\DLC + + + Orbis + + + Orbis\OrbisExtras + + + Orbis\Source Files\Sentient + + + Orbis\Source Files\Sentient + + + Orbis\Source Files\Sentient + + + Orbis\Source Files\Sentient + + + Orbis\Source Files\Sentient + + + Orbis\Source Files\Sentient + + + Orbis\Source Files\Social + + + Orbis\XML + + + Orbis\Source Files + + + Orbis\OrbisExtras + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + Common + + + Common + + + Common + + + Common + + + net\minecraft\client\model + + + net\minecraft\client\renderer\entity + + + Windows64\Miles Sound System\Include + + + Windows64\Miles Sound System\Include + + + Orbis\Miles Sound System\include + + + Orbis\Miles Sound System\include + + + Durango\Miles Sound System\include + + + Durango\Miles Sound System\include + + + PS3\Miles Sound System\include + + + PS3\Miles Sound System\include + + + Common\Source Files\Audio + + + Xbox\Source Files\Audio + + + Common\Source Files\Audio + + + PS3\PS3Extras + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\CompressedTile_SPU + + + Common\Source Files\Localisation + + + Common\Source Files\DLC + + + Common\Source Files\GameRules\LevelGeneration + + + Common\Source Files\GameRules\LevelGeneration + + + Common\Source Files\GameRules\LevelGeneration + + + Common\Source Files\GameRules\LevelRules\RuleDefinitions + + + Common\Source Files\GameRules\LevelRules\Rules + + + Common\Source Files\GameRules\LevelRules + + + Common\Source Files\DLC + + + PS3 + + + Common\Source Files\GameRules\LevelRules\Rules + + + Common\Source Files\GameRules + + + Common\Source Files\GameRules + + + Common\Source Files\GameRules\LevelRules\RuleDefinitions + + + Common\Source Files\GameRules\LevelRules\RuleDefinitions + + + Common\Source Files\UI + + + Windows64\Iggy\include + + + Windows64\Iggy\include + + + Windows64\Iggy\include + + + Windows64\Iggy\include + + + Windows64\Iggy\include + + + Windows64\Iggy\gdraw + + + Windows64 + + + Common\Source Files\UI + + + Common\Source Files\UI + + + Common\Source Files\UI + + + Common\Source Files\UI + + + Common\Source Files\GameRules\LevelGeneration + + + net\minecraft\client\renderer\tileentity + + + net\minecraft\client\model + + + Xbox\Source Files\XUI\Menu screens\Debug + + + Common\Source Files\DLC + + + Common\Source Files\Colours + + + Common\Source Files\DLC + + + Common\Source Files\DLC + + + Common\Source Files\DLC + + + Durango\DurangoExtras + + + Durango\Iggy\include + + + Durango\Iggy\include + + + Durango\Iggy\include + + + Durango\Iggy\include + + + Durango\Iggy\include + + + Durango\Iggy\gdraw + + + Durango + + + PS3 + + + PS3\Iggy\gdraw + + + PS3\Iggy\include + + + PS3\Iggy\include + + + PS3\Iggy\include + + + PS3\Iggy\include + + + PS3\Iggy\include + + + PS3\Iggy\include + + + Common\Source Files\zlib + + + Common\Source Files\zlib + + + Common\Source Files\zlib + + + Common\Source Files\zlib + + + Common\Source Files\zlib + + + Common\Source Files\zlib + + + Common\Source Files\zlib + + + Common\Source Files\zlib + + + Common\Source Files\zlib + + + Common\Source Files\zlib + + + Common\Source Files\zlib + + + Orbis\Iggy\gdraw + + + Orbis\Iggy\include + + + Orbis\Iggy\include + + + Orbis\Iggy\include + + + Orbis\Iggy\include + + + Orbis\Iggy\include + + + Orbis\Iggy\include + + + Common\Source Files\Network + + + Common\Source Files\UI + + + Common\Source Files\UI + + + Common\Source Files\UI\Scenes\Debug + + + Xbox\Source Files + + + Common\Source Files\Network + + + Common\Source Files\Network + + + PS3\PS3Extras + + + Common\Source Files\UI\Scenes\Frontend Menu screens + + + Common\Source Files\UI\Scenes\In-Game Menu Screens\Containers + + + Common\Source Files\UI\Scenes\In-Game Menu Screens\Containers + + + Common\Source Files\UI\Scenes\In-Game Menu Screens\Containers + + + Common\Source Files\UI\Scenes\In-Game Menu Screens\Containers + + + Common\Source Files\UI\Scenes\Frontend Menu screens + + + PS3\PS3Extras + + + Common\Source Files\UI\Scenes\Frontend Menu screens + + + Common\Source Files\UI\Scenes + + + Common\Source Files\UI\Components + + + Common\Source Files\UI\Components + + + Common\Source Files\UI\Scenes\Frontend Menu screens + + + Common\Source Files\UI\Scenes\Frontend Menu screens + + + Common\Source Files\UI\All Platforms + + + Common\Source Files\UI\All Platforms + + + Common\Source Files\UI\All Platforms + + + Common\Source Files\UI\All Platforms + + + Common\Source Files\UI\All Platforms + + + Common\Source Files\UI\All Platforms + + + Common\Source Files\UI\All Platforms + + + Common\Source Files\UI\All Platforms + + + Common\Source Files\UI\All Platforms + + + Common\Source Files\UI\All Platforms + + + Common\Source Files\UI\Scenes\In-Game Menu Screens\Containers + + + Common\Source Files\UI\Scenes\In-Game Menu Screens\Containers + + + Common\Source Files\UI\Scenes\In-Game Menu Screens\Containers + + + Common\Source Files\UI\Scenes\In-Game Menu Screens\Containers + + + Common\Source Files\UI\Scenes\Help & Options + + + Common\Source Files\UI\Scenes\Help & Options + + + Common\Source Files\UI\Scenes\Help & Options + + + Common\Source Files\UI\Controls + + + Common\Source Files\UI\Controls + + + Common\Source Files\UI\Controls + + + Common\Source Files\UI\Controls + + + Common\Source Files\UI\Controls + + + Common\Source Files\UI\Controls + + + Common\Source Files\UI\Controls + + + Common\Source Files\UI\Controls + + + Common\Source Files\UI\Controls + + + Common\Source Files\UI\Scenes\Help & Options + + + Common\Source Files\UI\Scenes\Help & Options + + + Common\Source Files\UI\Scenes\Help & Options + + + Common\Source Files\UI\Scenes\Help & Options + + + Common\Source Files\Network + + + Common\Source Files\UI\All Platforms + + + Common\Source Files\UI\Scenes\Debug + + + Common\Source Files\UI\Components + + + Xbox\Source Files\Network + + + Common\Source Files\Network + + + Xbox\Source Files\Network + + + Orbis + + + Common\Source Files\UI\Controls + + + Common\Source Files\UI\Scenes\Frontend Menu screens + + + Common\Source Files\UI\Components + + + Common\Source Files\UI\Components + + + Common\Source Files\UI\Scenes\In-Game Menu Screens + + + Common\Source Files\UI\Scenes\In-Game Menu Screens + + + Common\Source Files\UI\Scenes + + + Common\Source Files\BuildVer + + + Common\Source Files\UI\Scenes\Help & Options + + + Common\Source Files\UI\Controls + + + Common\Source Files\UI\All Platforms + + + Common\Source Files\UI\All Platforms + + + Common\Source Files\UI\Scenes\In-Game Menu Screens + + + Common\Source Files\UI\Components + + + Common\Source Files\UI\Scenes\Frontend Menu screens + + + PS3 + + + Common\Source Files\UI\Scenes\Frontend Menu screens + + + Common\Source Files\UI\Scenes\Help & Options + + + Common\Source Files\UI\Scenes\In-Game Menu Screens + + + Common\Source Files\UI\Scenes + + + Common\Source Files\UI\All Platforms + + + Common\Source Files\UI\Components + + + Common\Source Files\UI\Scenes + + + Common\Source Files\UI\Controls + + + PS3\Source Files\Network + + + PS3\Source Files\Leaderboards + + + Common\Source Files\Leaderboards + + + Xbox\Source Files\Leaderboards + + + Common\Source Files\UI\Scenes\Help & Options + + + Common\Source Files\UI\Scenes\In-Game Menu Screens + + + Common\Source Files\UI\Scenes\Frontend Menu screens + + + Common\Source Files\UI\Controls + + + Windows64\Source Files\Leaderboards + + + Orbis\Source Files\Leaderboards + + + Durango\Source Files\Leaderboards + + + Common\Source Files\UI\Scenes\Help & Options + + + Common\Source Files\UI\Scenes\Frontend Menu screens + + + Common\Source Files\UI\Scenes\Frontend Menu screens + + + Common\Source Files\UI\Controls + + + Common\Source Files\UI\Controls + + + Common\Source Files\UI\Controls + + + Common\Source Files\UI\Scenes + + + Common\Source Files\UI\Controls + + + Common\Source Files\UI\Controls + + + PS3\PS3Extras + + + Common\Source Files\UI\Scenes\In-Game Menu Screens + + + Common\Source Files\UI\Controls + + + Common\Source Files\UI\Controls + + + Common\Source Files\UI\Controls + + + Common\Source Files\UI\Scenes\In-Game Menu Screens + + + Common\Source Files\UI\Controls + + + Common\Source Files\UI\Scenes\In-Game Menu Screens + + + PS3\PS3Extras + + + Common\Source Files\UI\Scenes\Frontend Menu screens + + + Common\Source Files\UI\Scenes\Help & Options + + + Common\Source Files\UI\Scenes\Help & Options + + + Common\Source Files\UI\Components + + + PS3\4JLibs + + + Common\Source Files\UI\Components + + + Common\Source Files\UI\Scenes\Frontend Menu screens + + + PS3\Source Files + + + Common\Source Files\UI\Controls + + + Xbox\Source Files\XUI\Menu screens + + + net\minecraft\client\renderer\tileentity + + + Common\Source Files\UI\All Platforms + + + Common\Source Files\UI\Scenes\In-Game Menu Screens\Containers + + + Durango\Source Files\Achievements + + + Common\Source Files\UI\Scenes\Debug + + + Xbox\Source Files\XUI\Containers + + + Common\Source Files\UI\Scenes\In-Game Menu Screens\Containers + + + Common\Source Files\UI\All Platforms + + + Xbox\Source Files\XUI\Containers + + + net\minecraft\client\model + + + net\minecraft\client\renderer\entity + + + Orbis + + + Orbis\Source Files + + + Orbis\Network + + + net\minecraft\server\commands + + + net\minecraft\server\commands + + + Durango\Network + + + Durango\Network + + + Durango\Network + + + Common\Source Files\Network\Sony + + + Common\Source Files\Network\Sony + + + Orbis\Network + + + PS3\Source Files\Network + + + Common\Source Files\Network\Sony + + + Common\Source Files\Network\Sony + + + Orbis\Network + + + Common\Source Files\Network\Sony + + + Common\Source Files\Network\Sony + + + PS3\Source Files\Network + + + PS3\Source Files\Network + + + Orbis\Network + + + Common\Source Files\GameRules\LevelGeneration + + + Durango\Network + + + Common\Source Files\UI\Scenes\In-Game Menu Screens + + + Xbox\Source Files\XUI\Menu screens + + + Durango\Network + + + PSVita\4JLibs\inc + + + PSVita\4JLibs\inc + + + PSVita\4JLibs\inc + + + PSVita\4JLibs\inc + + + PSVita\PSVitaExtras + + + PSVita\PSVitaExtras + + + PSVita\PSVitaExtras + + + PSVita + + + PSVita\Source Files\Sentient + + + PSVita\Source Files\Sentient + + + PSVita\Source Files\Sentient + + + PSVita\Source Files\Sentient + + + PSVita\Source Files\Sentient + + + PSVita\Source Files\Sentient + + + PSVita\Source Files\Social + + + PSVita\XML + + + PSVita + + + PSVita\GameConfig + + + Orbis\Network + + + Common\Source Files\UI\Scenes\Debug + + + Durango\Source Files + + + Durango\Network + + + Durango\Source Files\Leaderboards + + + Common\Source Files\Telemetry + + + Durango\Source Files\Sentient + + + Durango\ServiceConfig + + + Common\Source Files\UI + + + Common\Source Files\Network\Sony + + + Orbis\Network + + + PS3\Source Files\Network + + + Common\Source Files\UI\Components + + + Durango\Network + + + Durango\XML + + + PSVita\Iggy\gdraw + + + PSVita\Iggy\include + + + PSVita\Iggy\include + + + PSVita\Iggy\include + + + PSVita\Iggy\include + + + PSVita\Iggy\include + + + PSVita\Iggy\include + + + PSVita\PSVitaExtras + + + PSVita\PSVitaExtras + + + PSVita\PSVitaExtras + + + PSVita\PSVitaExtras + + + PSVita\PSVitaExtras + + + PSVita\PSVitaExtras + + + PSVita\PSVitaExtras + + + Common\Source Files\UI\Controls + + + PSVita\Source Files\Network + + + PSVita\Source Files\Network + + + PSVita\Source Files\Network + + + PSVita\Source Files\Leaderboards + + + Common\Source Files\UI\Scenes\Frontend Menu screens + + + PSVita\Miles Sound System\Include + + + PSVita\Miles Sound System\Include + + + Durango\Source Files\Leaderboards + + + PSVita\Source Files\Network + + + PSVita\Source Files\Network + + + PSVita\PSVitaExtras + + + PSVita\PSVitaExtras + + + Xbox\4JLibs\inc + + + Common\Source Files\UI\Controls + + + Common\Source Files\UI\Scenes\In-Game Menu Screens + + + PSVita\Source Files\Network + + + PSVita\Source Files\Network + + + Orbis\Network + + + Xbox\Source Files\Network + + + Common\Source Files\UI\Scenes + + + Common\Source Files\Leaderboards + + + Common\Source Files\Leaderboards + + + net\minecraft\server + + + net\minecraft\server + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\particle + + + net\minecraft\client\resources + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\tileentity + + + net\minecraft\client\renderer\texture + + + net\minecraft\client\renderer + + + Common\Source Files\UI\All Platforms + + + Common\Source Files\UI\All Platforms + + + Common\Source Files\UI\All Platforms + + + Common\Source Files\UI\All Platforms + + + net\minecraft\client\model + + + Common\Source Files\UI\Scenes\In-Game Menu Screens\Containers + + + Common\Source Files\UI\Scenes\In-Game Menu Screens\Containers + + + Xbox\Source Files\XUI\Containers + + + Xbox\Source Files\XUI\Containers + + + Xbox\Source Files\XUI\Controls + + + Xbox\Source Files\XUI\Containers + + + Xbox\Source Files\XUI\Controls + + + Common\Source Files\UI\All Platforms + + + Xbox\Source Files\XUI\Containers + + + Common\Source Files\UI\Controls + + + Common\Source Files\UI\Scenes\In-Game Menu Screens\Containers + + + Common\Source Files\UI\Scenes\In-Game Menu Screens\Containers + + + Common\Source Files\UI\All Platforms + + + Common\Source Files\UI\Scenes\Help & Options + + + Common\Source Files\UI + + + Common\Source Files\UI\Controls + + + Common\Source Files\Tutorial\Tasks + + + Common\Source Files\Tutorial\Tasks + + + Common\Source Files\UI\Scenes\Frontend Menu screens + + + Common\Source Files\Leaderboards + + + Windows64\Source Files\Network + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + Source Files + + + net\minecraft\client\renderer\culling + + + net\minecraft\client\renderer\culling + + + net\minecraft\client\renderer\culling + + + net\minecraft\client\renderer\culling + + + net\minecraft\client\renderer\culling + + + Source Files + + + net\minecraft\client\renderer + + + net\minecraft\client\renderer + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\renderer + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\tileentity + + + net\minecraft\client\renderer\tileentity + + + net\minecraft\client\renderer\tileentity + + + net\minecraft\client\renderer\tileentity + + + net\minecraft\client\renderer + + + net\minecraft\client\skins + + + net\minecraft\client\skins + + + net\minecraft\client\skins + + + net\minecraft\client\renderer + + + net\minecraft\client\renderer + + + net\minecraft\client\renderer + + + net\minecraft\client\renderer + + + net\minecraft\client\renderer + + + net\minecraft\client\renderer + + + net\minecraft\client\renderer + + + net\minecraft\client\renderer + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client + + + net\minecraft\client\player + + + net\minecraft\client\player + + + net\minecraft\stats + + + net\minecraft\stats + + + net\minecraft\client\player + + + net\minecraft\client + + + net\minecraft\client + + + net\minecraft\client + + + net\minecraft\client + + + net\minecraft\client + + + net\minecraft\client + + + net\minecraft\client + + + net\minecraft\client\level + + + net\minecraft\client + + + net\minecraft\client\gui + + + net\minecraft\client + + + net\minecraft\client\gui + + + net\minecraft\client\gui + + + net\minecraft\client\gui + + + net\minecraft\client\gui + + + net\minecraft\client\gui\particle + + + net\minecraft\client\gui\particle + + + net\minecraft\client\gui + + + net\minecraft\client\gui + + + net\minecraft\client\gui + + + net\minecraft\client\gui + + + net\minecraft\client\gui + + + net\minecraft\client\gui + + + net\minecraft\client\gui + + + net\minecraft\client\gui + + + net\minecraft\client\gui + + + net\minecraft\client\gui + + + net\minecraft\client\gui + + + net\minecraft\client\gui + + + net\minecraft\client\gui + + + net\minecraft\client\title + + + net\minecraft\client\gui + + + net\minecraft\client\gui + + + net\minecraft\client\gui + + + net\minecraft\client\gui + + + net\minecraft\client\gui + + + net\minecraft\client\gui + + + net\minecraft\client\gui + + + net\minecraft\client\gui\inventory + + + net\minecraft\client\gui\inventory + + + net\minecraft\client\gui\inventory + + + net\minecraft\client\gui\inventory + + + net\minecraft\client\gui\inventory + + + net\minecraft\client\gui\inventory + + + net\minecraft\client\gui\inventory + + + net\minecraft\client\gui\achievement + + + net\minecraft\client\gui\achievement + + + net\minecraft\client\gui\achievement + + + Source Files + + + Source Files + + + Xbox\Source Files + + + Xbox\Source Files + + + net\minecraft\server\network + + + net\minecraft\server\network + + + net\minecraft\server\network + + + net\minecraft\server + + + net\minecraft\server + + + net\minecraft\server\level + + + net\minecraft\server\level + + + net\minecraft\server\level + + + net\minecraft\server\level + + + net\minecraft\server + + + net\minecraft\server\level + + + net\minecraft\server + + + net\minecraft\server\level + + + net\minecraft\server\level + + + net\minecraft\server\level + + + Xbox\Source Files\XUI\Menu screens + + + net\minecraft\client\multiplayer + + + net\minecraft\client\multiplayer + + + net\minecraft\client\multiplayer + + + net\minecraft\client\multiplayer + + + net\minecraft\client\multiplayer + + + net\minecraft\client\multiplayer + + + net\minecraft\client\multiplayer + + + net\minecraft\client\multiplayer + + + Xbox\Source Files\XUI\Menu screens + + + Xbox\Source Files\XUI\Menu screens + + + Xbox\Source Files\XUI\Menu screens + + + Xbox\Source Files\XUI\Menu screens\Help & Options + + + Xbox\Source Files\XUI\Menu screens\Help & Options\Controls + + + Xbox\Source Files\XUI\Menu screens\Help & Options\Credits + + + Xbox\Source Files\XUI\Menu screens\Help & Options\How To Play + + + Xbox\Source Files\XUI\Menu screens\Help & Options\How To Play + + + Xbox\Source Files\XUI\Menu screens + + + Xbox\Source Files\XUI\Menu screens + + + Xbox\Source Files\XUI\Menu screens + + + Xbox\Source Files\XUI\Menu screens\Tutorial + + + Xbox\Source Files\XUI\Menu screens\Leaderboards + + + Xbox\Source Files\XUI\Menu screens\Pause + + + Xbox\Source Files\XUI\Menu screens + + + Xbox\Source Files\XUI\Menu screens\Debug + + + Xbox\Source Files\XUI\Menu screens\Debug + + + Xbox\Source Files\XUI\Menu screens + + + Xbox\Source Files\XUI\Menu screens + + + Xbox\Source Files\XUI\Controls + + + Xbox\Source Files\XUI\Controls + + + Xbox\Source Files\XUI\Controls + + + Xbox\Source Files\XUI\Controls + + + Xbox\Source Files\XUI\Controls + + + Xbox\Source Files\XUI\Controls + + + Xbox\Source Files\XUI\Controls + + + Xbox\Source Files\XUI\Controls + + + Xbox\Source Files\XUI\Controls + + + Xbox\Source Files\XUI\Controls + + + Xbox\Source Files\XUI\Controls + + + Xbox\Source Files\XUI\Controls + + + Xbox\Source Files\XUI\Menu screens\Social + + + net\minecraft\client\renderer + + + net\minecraft\client\renderer + + + Xbox\Source Files\XUI\Menu screens + + + Xbox\Source Files\XUI\Menu screens + + + Xbox\Source Files\XUI\Menu screens + + + Xbox\XML + + + Xbox\Source Files\Sentient\Telemetry + + + Xbox\Source Files\XUI\Menu screens\Help & Options\Settings + + + Xbox\Source Files\XUI\Controls + + + Xbox\Source Files\Sentient\DynamicConf + + + Xbox\Source Files\XUI\Menu screens + + + Xbox\Source Files\XUI\Controls + + + Xbox\Source Files\Font + + + Xbox\Source Files\Font + + + Xbox\Source Files\Font + + + Xbox\Source Files\XUI\Menu screens\Debug + + + Xbox\Source Files\Sentient + + + Xbox\Source Files\XUI\Menu screens\Help & Options\Settings + + + Xbox\Source Files\XUI\Controls + + + net\minecraft\client\renderer\tileentity + + + Xbox\Source Files\XUI\Menu screens\Help & Options\Settings + + + Xbox\Source Files\XUI\Menu screens\Help & Options\Settings + + + Xbox\Source Files\XUI\Menu screens\Help & Options\Settings + + + Xbox\Source Files\XUI\Menu screens\Help & Options\Settings + + + net\minecraft\server\level + + + net\minecraft\client + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client\renderer + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\tileentity + + + Xbox\Source Files\XUI\Menu screens\Debug + + + Xbox\Source Files\XUI\Menu screens\Debug + + + Xbox\Source Files\XUI\Menu screens + + + Xbox\Source Files\XUI\Menu screens + + + Xbox\Source Files\XUI\Menu screens + + + net\minecraft\client + + + Xbox\Source Files\XUI\Menu screens + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\tileentity + + + net\minecraft\client\renderer\tileentity + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + net\minecraft\client\model\geom + + + net\minecraft\client\model\geom + + + net\minecraft\client\model\geom + + + net\minecraft\client\model\dragon + + + net\minecraft\client\model\geom + + + net\minecraft\client\model\dragon + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model\geom + + + Xbox\Source Files\XUI\Controls + + + Xbox\Source Files\XUI\Controls + + + Xbox\Source Files\XUI\Controls + + + Xbox\Source Files\XUI\Controls + + + Xbox\Source Files\XUI\Controls + + + Xbox\Source Files\XUI\Controls + + + Xbox\Source Files\XUI\Menu screens + + + Xbox\Source Files\Social + + + Source Files + + + Common\Source Files\Trial + + + Common\Source Files\Tutorial\Constraints + + + Common\Source Files\Tutorial\Constraints + + + Common\Source Files\Tutorial\Constraints + + + Common\Source Files\Tutorial\Hints + + + Common\Source Files\Tutorial\Hints + + + Common\Source Files\Tutorial\Hints + + + Common\Source Files\Tutorial\Hints + + + Common\Source Files\Tutorial\Hints + + + Common\Source Files\Tutorial\Tasks + + + Common\Source Files\Tutorial\Tasks + + + Common\Source Files\Tutorial\Tasks + + + Common\Source Files\Tutorial\Tasks + + + Common\Source Files\Tutorial\Tasks + + + Common\Source Files\Tutorial\Tasks + + + Common\Source Files\Tutorial\Tasks + + + Common\Source Files\Tutorial\Tasks + + + Common\Source Files\Tutorial\Tasks + + + Common\Source Files\Tutorial\Tasks + + + Common\Source Files\Tutorial\Tasks + + + Common\Source Files\Tutorial\Tasks + + + Common\Source Files\Tutorial\Tasks + + + Common\Source Files\Tutorial\Tasks + + + Common\Source Files\Tutorial\Tasks + + + Common\Source Files\Tutorial\Tasks + + + Common\Source Files\GameRules\LevelGeneration\StructureActions + + + Common\Source Files\GameRules\LevelGeneration\StructureActions + + + Common\Source Files\GameRules\LevelGeneration\StructureActions + + + Common\Source Files\GameRules\LevelGeneration\StructureActions + + + Common\Source Files\GameRules\LevelGeneration + + + Common\Source Files\GameRules\LevelRules\RuleDefinitions + + + Common\Source Files\GameRules\LevelRules\RuleDefinitions + + + Common\Source Files\GameRules\LevelRules\RuleDefinitions + + + Common\Source Files\GameRules\LevelRules\RuleDefinitions + + + Common\Source Files\GameRules\LevelRules\RuleDefinitions + + + Common\Source Files\GameRules\LevelRules\RuleDefinitions + + + Common\Source Files\GameRules\LevelRules\RuleDefinitions + + + Common\Source Files\Tutorial + + + Common\Source Files\Tutorial + + + Common\Source Files\Tutorial + + + Common\Source Files\Tutorial + + + Common\Source Files\Tutorial + + + Common\Source Files\Tutorial\Hints + + + PS3\Source Files + + + PS3\PS3Extras + + + Durango + + + Durango\Source Files + + + Common\Source Files + + + Common\Source Files + + + Common\Source Files\GameRules\LevelGeneration + + + PS3 + + + Xbox\Source Files\XUI + + + Xbox\Source Files\XUI + + + Xbox\Source Files\XUI\Base Scene + + + Xbox\Source Files\XUI\Base Scene + + + Xbox\Source Files\XUI\Base Scene + + + Xbox\Source Files\XUI\Containers + + + Xbox\Source Files\XUI\Containers + + + Xbox\Source Files\XUI\Containers + + + Xbox\Source Files\XUI\Containers + + + Xbox\Source Files\XUI\Containers + + + Xbox\Source Files\XUI\Containers + + + Xbox\Source Files\XUI\Containers + + + Xbox\Source Files\XUI\Containers + + + Xbox\Source Files\XUI\Containers + + + Xbox\Source Files\XUI\Controls + + + net\minecraft\client\skins + + + net\minecraft\client\particle + + + net\minecraft\client\skins + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer + + + net\minecraft\client\renderer\texture + + + net\minecraft\client\renderer\texture + + + net\minecraft\client\renderer\texture + + + net\minecraft\client\renderer\texture + + + net\minecraft\client\renderer\texture + + + net\minecraft\client\renderer\texture + + + net\minecraft\client\renderer\texture + + + net\minecraft\client\renderer\texture\custom + + + net\minecraft\client\renderer\texture\custom + + + Xbox\Source Files\XUI\Menu screens\Help & Options\Settings + + + PS3\PS3Extras + + + Xbox\Source Files\XUI\Menu screens + + + net\minecraft\client\skins + + + net\minecraft\client\renderer\texture + + + net\minecraft\client\renderer\texture + + + net\minecraft\client\skins + + + Common\Source Files\DLC + + + Common\Source Files\DLC + + + Common\Source Files\DLC + + + Common\Source Files\DLC + + + Common\Source Files\DLC + + + Common\Source Files\DLC + + + Windows64\Source Files + + + Windows64\Source Files + + + Windows64 + + + Durango\Source Files + + + Orbis\OrbisExtras + + + Xbox\Source Files\XUI\Base Scene + + + Common\Source Files\DLC + + + Orbis\OrbisExtras + + + Orbis + + + Orbis\Source Files + + + net\minecraft\client\particle + + + net\minecraft\client\particle + + + Common + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\model + + + Xbox\Source Files\Audio + + + Common\Source Files\Audio + + + Common\Source Files\Audio + + + PS3\PS3Extras + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\ChunkRebuild_SPU + + + PS3\CompressedTile_SPU + + + Common\Source Files\Localisation + + + Common\Source Files\DLC + + + Common\Source Files\GameRules\LevelGeneration + + + Common\Source Files\GameRules\LevelGeneration + + + Common\Source Files\GameRules\LevelGeneration + + + Common\Source Files\GameRules\LevelRules\RuleDefinitions + + + Common\Source Files\GameRules\LevelRules\Rules + + + Common\Source Files\GameRules\LevelRules + + + Common\Source Files\DLC + + + PS3 + + + Common\Source Files\GameRules + + + Common\Source Files\GameRules + + + Common\Source Files\GameRules\LevelRules\RuleDefinitions + + + Common\Source Files\GameRules\LevelRules\RuleDefinitions + + + Common\Source Files\UI + + + Windows64\Iggy\gdraw + + + Windows64 + + + Common\Source Files\UI + + + Common\Source Files\UI + + + Common\Source Files\UI + + + Common\Source Files\GameRules\LevelGeneration + + + net\minecraft\client\renderer\tileentity + + + net\minecraft\client\model + + + Xbox\Source Files\XUI\Menu screens\Debug + + + Common\Source Files\DLC + + + Common\Source Files\Colours + + + Common\Source Files\DLC + + + Common\Source Files\DLC + + + Durango\DurangoExtras + + + Durango\Iggy\gdraw + + + Durango + + + PS3 + + + PS3\Iggy\gdraw + + + Common\Source Files\zlib + + + Common\Source Files\zlib + + + Common\Source Files\zlib + + + Common\Source Files\zlib + + + Common\Source Files\zlib + + + Common\Source Files\zlib + + + Common\Source Files\zlib + + + Common\Source Files\zlib + + + Common\Source Files\zlib + + + Common\Source Files\zlib + + + Common\Source Files\zlib + + + Common\Source Files\zlib + + + Common\Source Files\zlib + + + Common\Source Files\zlib + + + Common\Source Files\zlib + + + PS3\Source Files\Audio + + + Common\Source Files\UI + + + Common\Source Files\UI + + + Orbis\Iggy\gdraw + + + Common\Source Files\UI\Scenes\Debug + + + Xbox\Source Files + + + Common\Source Files\Network + + + PS3\PS3Extras + + + Common\Source Files\UI\Scenes\Frontend Menu screens + + + Common\Source Files\UI\Scenes\In-Game Menu Screens\Containers + + + Common\Source Files\UI\Scenes\In-Game Menu Screens\Containers + + + Common\Source Files\UI\Scenes\In-Game Menu Screens\Containers + + + Common\Source Files\UI\Scenes\In-Game Menu Screens\Containers + + + Common\Source Files\UI\Scenes\Frontend Menu screens + + + Common\Source Files\UI\Scenes\Frontend Menu screens + + + Common\Source Files\UI\Scenes + + + Common\Source Files\UI\Components + + + Common\Source Files\UI\Components + + + Common\Source Files\UI\Scenes\Frontend Menu screens + + + Common\Source Files\UI\Scenes\Frontend Menu screens + + + Common\Source Files\UI\All Platforms + + + Common\Source Files\UI\All Platforms + + + Common\Source Files\UI\All Platforms + + + Common\Source Files\UI\All Platforms + + + Common\Source Files\UI\All Platforms + + + Common\Source Files\UI\All Platforms + + + Common\Source Files\UI\All Platforms + + + Common\Source Files\UI\All Platforms + + + Common\Source Files\UI\Scenes\In-Game Menu Screens\Containers + + + Common\Source Files\UI\Scenes\In-Game Menu Screens\Containers + + + Common\Source Files\UI\Scenes\In-Game Menu Screens\Containers + + + Common\Source Files\UI\Scenes\In-Game Menu Screens\Containers + + + Common\Source Files\UI\Scenes\Help & Options + + + Common\Source Files\UI\Scenes\Help & Options + + + Common\Source Files\UI\Scenes\Help & Options + + + Common\Source Files\UI\Controls + + + Common\Source Files\UI\Controls + + + Common\Source Files\UI\Controls + + + Common\Source Files\UI\Controls + + + Common\Source Files\UI\Controls + + + Common\Source Files\UI\Controls + + + Common\Source Files\UI\Controls + + + Common\Source Files\UI\Controls + + + Common\Source Files\UI\Controls + + + Common\Source Files\UI\Scenes\Help & Options + + + Common\Source Files\UI\Scenes\Help & Options + + + Common\Source Files\UI\Scenes\Help & Options + + + Common\Source Files\UI\Scenes\Help & Options + + + Common\Source Files\UI\All Platforms + + + Common\Source Files\UI\Scenes\Debug + + + Common\Source Files\UI\Components + + + Xbox\Source Files\Network + + + Common\Source Files\Network + + + Xbox\Source Files\Network + + + Orbis + + + Common\Source Files\UI\Controls + + + Common\Source Files\UI\Scenes\Frontend Menu screens + + + Common\Source Files\UI\Components + + + Common\Source Files\UI\Components + + + Common\Source Files\UI\Scenes\In-Game Menu Screens + + + Common\Source Files\UI\Scenes\In-Game Menu Screens + + + Common\Source Files\UI\Scenes + + + Common\Source Files\UI\Scenes\Help & Options + + + Common\Source Files\UI\Controls + + + Common\Source Files\UI\All Platforms + + + Common\Source Files\UI\Scenes\In-Game Menu Screens + + + Common\Source Files\UI\Components + + + Common\Source Files\UI\Scenes\Frontend Menu screens + + + Common\Source Files\UI\Scenes\Frontend Menu screens + + + Common\Source Files\UI\Scenes\Help & Options + + + Common\Source Files\UI\Scenes\In-Game Menu Screens + + + Common\Source Files\UI\Scenes + + + Common\Source Files\UI\All Platforms + + + Common\Source Files\UI\Components + + + Common\Source Files\UI\Scenes + + + Common\Source Files\UI\Controls + + + PS3\Source Files\Network + + + PS3\Source Files\Leaderboards + + + Common\Source Files\Leaderboards + + + Xbox\Source Files\Leaderboards + + + Common\Source Files\UI\Scenes\Help & Options + + + Common\Source Files\UI\Scenes\In-Game Menu Screens + + + Common\Source Files\UI\Scenes\Frontend Menu screens + + + Common\Source Files\UI\Controls + + + Windows64\Source Files\Leaderboards + + + Orbis\Source Files\Leaderboards + + + Durango\Source Files\Leaderboards + + + Common\Source Files\UI\Scenes\Help & Options + + + Common\Source Files\UI\Scenes\Frontend Menu screens + + + Common\Source Files\UI\Scenes\Frontend Menu screens + + + Common\Source Files\UI\Controls + + + Common\Source Files\UI\Controls + + + Common\Source Files\UI\Controls + + + Common\Source Files\UI\Scenes + + + Common\Source Files\UI\Controls + + + Common\Source Files\UI\Controls + + + PS3\PS3Extras + + + Common\Source Files\UI\Scenes\In-Game Menu Screens + + + Common\Source Files\UI\Controls + + + Common\Source Files\UI\Controls + + + Common\Source Files\UI\Controls + + + Common\Source Files\UI\Scenes\In-Game Menu Screens + + + Common\Source Files\UI\Controls + + + Common\Source Files\UI\Scenes\In-Game Menu Screens + + + PS3\PS3Extras + + + Common\Source Files\UI\Scenes\Frontend Menu screens + + + Common\Source Files\UI\Scenes\Help & Options + + + Common\Source Files\UI\Scenes\Help & Options + + + Common\Source Files\UI\Components + + + PS3\4JLibs + + + Common\Source Files\UI\Components + + + Common\Source Files\UI\Scenes\Frontend Menu screens + + + Common\Source Files\Audio + + + PS3\Source Files + + + Common\Source Files\UI\Controls + + + Xbox\Source Files\XUI\Menu screens + + + net\minecraft\client\renderer\tileentity + + + Common\Source Files\UI\All Platforms + + + Common\Source Files\UI\Scenes\In-Game Menu Screens\Containers + + + Durango\Source Files\Achievements + + + Common\Source Files\UI\Scenes\Debug + + + Xbox\Source Files\XUI\Containers + + + Common\Source Files\UI\All Platforms + + + Common\Source Files\UI\Scenes\In-Game Menu Screens\Containers + + + Xbox\Source Files\XUI\Containers + + + net\minecraft\client\model + + + net\minecraft\client\renderer\entity + + + Orbis + + + Orbis\Network + + + net\minecraft\server\commands + + + net\minecraft\server\commands + + + Durango\Network + + + Durango\Network + + + Durango\Network + + + Common\Source Files\Network\Sony + + + Common\Source Files\Network\Sony + + + Common\Source Files\Network\Sony + + + PS3\Source Files\Network + + + Orbis\Network + + + Orbis\Network + + + Common\Source Files\Network\Sony + + + PS3\Source Files\Network + + + PS3\Source Files\Network + + + Orbis\Network + + + Common\Source Files\GameRules\LevelGeneration + + + Durango\Network + + + Common\Source Files\UI\Scenes\In-Game Menu Screens + + + Xbox\Source Files\XUI\Menu screens + + + Durango\Network + + + PSVita + + + PSVita + + + PSVita\Source Files + + + PSVita\PSVitaExtras + + + Orbis\Network + + + Common\Source Files\Network\Sony + + + Common\Source Files\UI\Scenes\Debug + + + Durango\Network + + + Durango\Source Files\Leaderboards + + + Common\Source Files\Telemetry + + + Durango\Source Files\Sentient + + + Common\Source Files\UI + + + Orbis\Network + + + PS3\Source Files\Network + + + Common\Source Files\Network\Sony + + + Orbis + + + Orbis + + + Orbis + + + Common\Source Files\UI\Components + + + Durango\Network + + + Durango\Network + + + Durango\Network + + + Durango\Network + + + Durango\Network + + + Durango\XML + + + PSVita\Iggy\gdraw + + + PSVita\PSVitaExtras + + + PSVita\PSVitaExtras + + + PSVita\PSVitaExtras + + + PSVita\PSVitaExtras + + + PSVita\PSVitaExtras + + + PSVita\PSVitaExtras + + + Common\Source Files\UI\Controls + + + PSVita\Source Files\Network + + + PSVita\Source Files\Network + + + PSVita\Source Files\Network + + + PSVita\Source Files\Leaderboards + + + Common\Source Files\UI\Scenes\Frontend Menu screens + + + Durango\Source Files\Leaderboards + + + PSVita\Source Files\Network + + + PSVita\Source Files\Network + + + PSVita\PSVitaExtras + + + PSVita\PSVitaExtras + + + Common\Source Files\UI\Controls + + + Common\Source Files\UI\Scenes\In-Game Menu Screens + + + PSVita\Source Files\Network + + + PSVita\Source Files\Network + + + Orbis\Network + + + Common\Source Files\UI\Scenes + + + Common\Source Files\Leaderboards + + + Common\Source Files\Leaderboards + + + Common\Source Files\UI\Scenes\Help & Options + + + Common\Source Files\UI + + + net\minecraft\server + + + net\minecraft\server + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\model + + + net\minecraft\client\particle + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\entity + + + net\minecraft\client\renderer\tileentity + + + net\minecraft\client\renderer\texture + + + net\minecraft\client\renderer + + + Common\Source Files\UI\All Platforms + + + Common\Source Files\UI\All Platforms + + + Common\Source Files\UI\All Platforms + + + Common\Source Files\UI\All Platforms + + + net\minecraft\client\model + + + Common\Source Files\UI\Scenes\In-Game Menu Screens\Containers + + + Common\Source Files\UI\Scenes\In-Game Menu Screens\Containers + + + Xbox\Source Files\XUI\Containers + + + Xbox\Source Files\XUI\Containers + + + Xbox\Source Files\XUI\Controls + + + Xbox\Source Files\XUI\Containers + + + Xbox\Source Files\XUI\Controls + + + Common\Source Files\UI\All Platforms + + + Xbox\Source Files\XUI\Containers + + + Common\Source Files\UI\Controls + + + Common\Source Files\UI\Scenes\In-Game Menu Screens\Containers + + + Common\Source Files\UI\Scenes\In-Game Menu Screens\Containers + + + Common\Source Files\UI\All Platforms + + + Common\Source Files\UI\Controls + + + Common\Source Files\Tutorial\Tasks + + + Common\Source Files\Tutorial\Tasks + + + Common\Source Files\UI\Scenes\Frontend Menu screens + + + Common\Source Files\Leaderboards + + + Source Files + + + Windows64\Source Files\Network + - + + Xbox\4JLibs\libs + + + Xbox\4JLibs\libs + + + Durango\4JLibs\libs + + + Xbox\4JLibs\libs + + + Xbox\4JLibs\libs + + + Xbox\4JLibs\libs + + + Xbox\4JLibs\libs + + + Xbox\4JLibs\libs + + + Xbox\4JLibs\libs + + + Xbox\4JLibs\libs + + + Xbox\4JLibs\libs + + + Xbox\4JLibs\libs + + + Durango\4JLibs\libs + + + Durango\4JLibs\libs + + + Durango\4JLibs\libs + + + Windows64\4JLibs\libs + + + Windows64\4JLibs\libs + + + Windows64\4JLibs\libs + + + Windows64\4JLibs\libs + + + Windows64\Miles Sound System\lib + + + Windows64\Iggy\lib + + + Windows64\Iggy\lib + + + Windows64\Iggy\lib + + + Durango\Iggy\lib + + + Durango\Iggy\lib + + + Durango\Iggy\lib + + + Durango\Iggy\lib + + + PS3\Iggy\lib + + + PS3\Iggy\lib + + + PS3\Iggy\lib + + + Orbis\Iggy\lib + + + Orbis\Iggy\lib + + + PS3\4JLibs\libs + + + PS3\4JLibs\libs + + + PS3\4JLibs\libs + + + PS3\4JLibs\libs + + + PS3\4JLibs\libs + + + PS3\4JLibs\libs + + + PS3\4JLibs\libs + + + PS3\4JLibs\libs + + + Durango\Miles Sound System\lib + + + Durango\Miles Sound System\lib + + + PS3\4JLibs\libs + + + PS3\4JLibs\libs + + + PS3\4JLibs\libs + + + PS3\4JLibs\libs + + + Orbis\4JLibs\libs + + + Orbis\4JLibs\libs + + + Orbis\4JLibs\libs + + + Durango\4JLibs\libs + + + Durango\4JLibs\libs + + + Durango\4JLibs\libs + + + Windows64\4JLibs\libs + + + Windows64\4JLibs\libs + + + Durango\4JLibs\libs + + + Durango\4JLibs\libs + + + Orbis\4JLibs\libs + + + Orbis\4JLibs\libs + + + Orbis\4JLibs\libs + + + Durango\4JLibs\libs + + + Durango\4JLibs\libs + + + PSVita\4JLibs\libs + + + PSVita\4JLibs\libs + + + PSVita\4JLibs\libs + + + PSVita\4JLibs\libs + + + PSVita\4JLibs\libs + + + PSVita\4JLibs\libs + + + PSVita\4JLibs\libs + + + PSVita\4JLibs\libs + + + PSVita\4JLibs\libs + + + PSVita\4JLibs\libs + + + PSVita\4JLibs\libs + + + PSVita\4JLibs\libs + + + PSVita\Iggy\Lib + + + PSVita\Iggy\Lib + + + Xbox\4JLibs\libs + + + Xbox\4JLibs\libs + + + + + + Xbox\SentientLibs + + + + + Windows + + + Windows + + + Durango + + + + + Windows + + + + + PS3\SPUObjFiles\Release + + + PS3\SPUObjFiles\Release + + + PS3\SPUObjFiles\Release + + + PS3\SPUObjFiles\Release + + + PS3\SPUObjFiles\Release + + + PS3\SPUObjFiles\Release + + + PS3\SPUObjFiles\Release + + + PS3\SPUObjFiles\Release + + + PS3\SPUObjFiles\Release + + + PS3\SPUObjFiles\Debug + + + PS3\SPUObjFiles\Debug + + + PS3\SPUObjFiles\Debug + + + PS3\SPUObjFiles\Debug + + + PS3\SPUObjFiles\Debug + + + PS3\SPUObjFiles\Debug + + + PS3\SPUObjFiles\Debug + + + PS3\SPUObjFiles\Debug + + + PS3\SPUObjFiles\Debug + + + PS3\SPUObjFiles\ContentPackage + + + PS3\SPUObjFiles\ContentPackage + + + PS3\SPUObjFiles\ContentPackage + + + PS3\SPUObjFiles\ContentPackage + + + PS3\SPUObjFiles\ContentPackage + + + PS3\SPUObjFiles\ContentPackage + + + PS3\SPUObjFiles\ContentPackage + + + PS3\SPUObjFiles\ContentPackage + + + PS3\SPUObjFiles\ContentPackage + + + PS3\SPUObjFiles\Release + + + PS3\SPUObjFiles\Debug + + + PS3\SPUObjFiles\ContentPackage + - - - - - - + + Source Files + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Minecraft.Client/Minecraft.Client.vcxproj.user b/Minecraft.Client/Minecraft.Client.vcxproj.user index 09a7ebc4a..24ca62f80 100644 --- a/Minecraft.Client/Minecraft.Client.vcxproj.user +++ b/Minecraft.Client/Minecraft.Client.vcxproj.user @@ -19,4 +19,4 @@ $(SolutionDir)$(Platform)\$(Configuration)\ WindowsLocalDebugger - \ No newline at end of file + diff --git a/Minecraft.Client/Minecraft.cpp b/Minecraft.Client/Minecraft.cpp index 53860f131..408026eeb 100644 --- a/Minecraft.Client/Minecraft.cpp +++ b/Minecraft.Client/Minecraft.cpp @@ -502,6 +502,13 @@ void Minecraft::setScreen(Screen *screen) this->screen->removed(); } +#ifdef _WINDOWS64 + if (screen != NULL && g_KBMInput.IsMouseGrabbed()) + { + g_KBMInput.SetMouseGrabbed(false); + } +#endif + //4J Gordon: Do not force a stats save here /*if (dynamic_cast(screen)!=NULL) { @@ -1184,14 +1191,14 @@ void Minecraft::applyFrameMouseLook() int iPad = localplayers[i]->GetXboxPad(); if (iPad != 0) continue; // Mouse only applies to pad 0 - if (!KMInput.IsCaptured()) continue; + if (!g_KBMInput.IsMouseGrabbed()) continue; if (localgameModes[iPad] == NULL) continue; float rawDx, rawDy; - KMInput.ConsumeMouseDelta(rawDx, rawDy); + g_KBMInput.ConsumeMouseDelta(rawDx, rawDy); if (rawDx == 0.0f && rawDy == 0.0f) continue; - float mouseSensitivity = 0.5f; + float mouseSensitivity = ((float)app.GetGameSettings(iPad, eGameSetting_Sensitivity_InGame)) / 100.0f; float mdx = rawDx * mouseSensitivity; float mdy = -rawDy * mouseSensitivity; if (app.GetGameSettings(iPad, eGameSetting_ControlInvertLook)) @@ -1450,14 +1457,54 @@ void Minecraft::run_middle() // Keyboard/mouse button presses for player 0 if (i == 0) { - if (KMInput.ConsumeKeyPress(VK_ESCAPE)) localplayers[i]->ullButtonsPressed |= 1LL<ullButtonsPressed |= 1LL<ullButtonsPressed |= 1LL<ullButtonsPressed |= 1LL<ullButtonsPressed |= 1LL<ullButtonsPressed|=1LL<ullButtonsPressed|=1LL<ullButtonsPressed|=1LL<ullButtonsPressed|=1LL<ullButtonsPressed|=1LL<inventory) + localplayers[i]->inventory->selected = slot; + } + } + } + + // Utility keys always work regardless of KBM active state + if(g_KBMInput.IsKeyPressed(KeyboardMouseInput::KEY_PAUSE) && !ui.IsTutorialVisible(i)) + { + localplayers[i]->ullButtonsPressed|=1LL<ullButtonsPressed|=1LL<ullButtonsPressed|=1LL<abilities.flying && KMInput.IsKeyDown(VK_SHIFT)) - localplayers[i]->ullButtonsPressed |= 1LL<abilities.flying && !ui.GetMenuDisplayed(i)) + localplayers[i]->ullButtonsPressed|=1LL< 0 && gameMode->isInputAllowed(MINECRAFT_ACTION_LEFT_SCROLL)) wheel += 1; - else if (kbWheel < 0 && gameMode->isInputAllowed(MINECRAFT_ACTION_RIGHT_SCROLL)) wheel -= 1; - - // 1-9 keys for direct hotbar selection - if (gameMode->isInputAllowed(MINECRAFT_ACTION_LEFT_SCROLL)) - { - for (int k = '1'; k <= '9'; k++) - { - if (KMInput.ConsumeKeyPress(k)) - { - player->inventory->selected = k - '1'; - app.SetOpacityTimer(iPad); - break; - } - } - } + wheel = g_KBMInput.GetMouseWheel(); } #endif if (wheel != 0) @@ -3485,33 +3528,20 @@ void Minecraft::tick(bool bFirst, bool bUpdateTextures) player->handleMouseClick(0); player->lastClickTick[0] = ticks; } -#ifdef _WINDOWS64 - else if (iPad == 0 && KMInput.IsCaptured() && KMInput.ConsumeMousePress(0)) - { - player->handleMouseClick(0); - player->lastClickTick[0] = ticks; - } -#endif - if (InputManager.ButtonDown(iPad, MINECRAFT_ACTION_ACTION) && ticks - player->lastClickTick[0] >= timer->ticksPerSecond / 4) +#ifdef _WINDOWS64 + bool actionHeld = InputManager.ButtonDown(iPad, MINECRAFT_ACTION_ACTION) || (iPad == 0 && g_KBMInput.IsKBMActive() && g_KBMInput.IsMouseButtonDown(KeyboardMouseInput::MOUSE_LEFT)); +#else + bool actionHeld = InputManager.ButtonDown(iPad, MINECRAFT_ACTION_ACTION); +#endif + if (actionHeld && ticks - player->lastClickTick[0] >= timer->ticksPerSecond / 4) { //printf("MINECRAFT_ACTION_ACTION ButtonDown"); player->handleMouseClick(0); player->lastClickTick[0] = ticks; } -#ifdef _WINDOWS64 - else if (iPad == 0 && KMInput.IsCaptured() && KMInput.IsMouseDown(0) && ticks - player->lastClickTick[0] >= timer->ticksPerSecond / 4) - { - player->handleMouseClick(0); - player->lastClickTick[0] = ticks; - } -#endif - if(InputManager.ButtonDown(iPad, MINECRAFT_ACTION_ACTION) -#ifdef _WINDOWS64 - || (iPad == 0 && KMInput.IsCaptured() && KMInput.IsMouseDown(0)) -#endif - ) + if(actionHeld) { player->handleMouseDown(0, true ); } @@ -3530,25 +3560,21 @@ void Minecraft::tick(bool bFirst, bool bUpdateTextures) lastClickTick = ticks; } */ +#ifdef _WINDOWS64 + bool useHeld = InputManager.ButtonDown(iPad, MINECRAFT_ACTION_USE) || (iPad == 0 && g_KBMInput.IsKBMActive() && g_KBMInput.IsMouseButtonDown(KeyboardMouseInput::MOUSE_RIGHT)); +#else + bool useHeld = InputManager.ButtonDown(iPad, MINECRAFT_ACTION_USE); +#endif if( player->isUsingItem() ) { - if(!InputManager.ButtonDown(iPad, MINECRAFT_ACTION_USE) -#ifdef _WINDOWS64 - && !(iPad == 0 && KMInput.IsCaptured() && KMInput.IsMouseDown(1)) -#endif - ) gameMode->releaseUsingItem(player); + if(!useHeld) gameMode->releaseUsingItem(player); } else if( gameMode->isInputAllowed(MINECRAFT_ACTION_USE) ) { -#ifdef _WINDOWS64 - bool useButtonDown = InputManager.ButtonDown(iPad, MINECRAFT_ACTION_USE) || (iPad == 0 && KMInput.IsCaptured() && KMInput.IsMouseDown(1)); -#else - bool useButtonDown = InputManager.ButtonDown(iPad, MINECRAFT_ACTION_USE); -#endif if( player->abilities.instabuild ) { // 4J - attempt to handle click in special creative mode fashion if possible (used for placing blocks at regular intervals) - bool didClick = player->creativeModeHandleMouseClick(1, useButtonDown ); + bool didClick = player->creativeModeHandleMouseClick(1, useHeld ); // 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 if( player->lastClickState == LocalPlayer::lastClick_oldRepeat ) { @@ -3560,7 +3586,7 @@ void Minecraft::tick(bool bFirst, bool bUpdateTextures) else { // Otherwise just the original game code for handling autorepeat - if (useButtonDown && ticks - player->lastClickTick[1] >= timer->ticksPerSecond / 4) + if (useHeld && ticks - player->lastClickTick[1] >= timer->ticksPerSecond / 4) { player->handleMouseClick(1); player->lastClickTick[1] = ticks; @@ -3576,7 +3602,7 @@ void Minecraft::tick(bool bFirst, bool bUpdateTextures) bool firstClick = ( player->lastClickTick[1] == 0 ); bool autoRepeat = ticks - player->lastClickTick[1] >= timer->ticksPerSecond / 4; if ( player->isRiding() || player->isSprinting() || player->isSleeping() ) autoRepeat = false; - if (useButtonDown ) + if (useHeld ) { // If the player has just exited a bed, then delay the time before a repeat key is allowed without releasing if(player->isSleeping() ) player->lastClickTick[1] = ticks + (timer->ticksPerSecond * 2); @@ -3618,8 +3644,6 @@ void Minecraft::tick(bool bFirst, bool bUpdateTextures) if((player->ullButtonsPressed&(1LL<renderDebug = !options->renderDebug; #ifdef _XBOX app.EnableDebugOverlay(options->renderDebug,iPad); #else @@ -3629,13 +3653,11 @@ void Minecraft::tick(bool bFirst, bool bUpdateTextures) #endif } - if((player->ullButtonsPressed&(1LL< mob = dynamic_pointer_cast(Creeper::_class->newInstance( level )); - //shared_ptr mob = dynamic_pointer_cast(Wolf::_class->newInstance( level )); - shared_ptr mob = dynamic_pointer_cast(shared_ptr(new Spider( level ))); - mob->moveTo(player->x+1, player->y, player->z+1, level->random->nextFloat() * 360, 0); - level->addEntity(mob); + if((player->ullButtonsPressed&(1LL<renderDebug = !options->renderDebug; +#endif } } diff --git a/Minecraft.Client/MinecraftServer.cpp b/Minecraft.Client/MinecraftServer.cpp index 4412a9014..1519417d5 100644 --- a/Minecraft.Client/MinecraftServer.cpp +++ b/Minecraft.Client/MinecraftServer.cpp @@ -27,6 +27,14 @@ #include "Minecraft.World/Pos.h" #include "Minecraft.World/System.h" #include "Minecraft.World/StringHelpers.h" +#include "Minecraft.World/net.minecraft.world.entity.item.h" +#include "Minecraft.World/net.minecraft.world.item.h" +#include "Minecraft.World/net.minecraft.world.item.enchantment.h" +#include "Minecraft.World/net.minecraft.world.damagesource.h" +#ifdef _WINDOWS64 +#include "Windows64\Network\WinsockNetLayer.h" +#endif +#include #ifdef SPLIT_SAVES #include "..\Minecraft.World\ConsoleSaveFileSplit.h" #endif @@ -78,6 +86,462 @@ bool MinecraftServer::s_slowQueuePacketSent = false; unordered_map MinecraftServer::ironTimers; +static bool ShouldUseDedicatedServerProperties() +{ +#ifdef _WINDOWS64 + return g_Win64DedicatedServer; +#else + return false; +#endif +} + +static int GetDedicatedServerInt(Settings *settings, const wchar_t *key, int defaultValue) +{ + return (ShouldUseDedicatedServerProperties() && settings != NULL) ? settings->getInt(key, defaultValue) : defaultValue; +} + +static bool GetDedicatedServerBool(Settings *settings, const wchar_t *key, bool defaultValue) +{ + return (ShouldUseDedicatedServerProperties() && settings != NULL) ? settings->getBoolean(key, defaultValue) : defaultValue; +} + +static wstring GetDedicatedServerString(Settings *settings, const wchar_t *key, const wstring &defaultValue) +{ + return (ShouldUseDedicatedServerProperties() && settings != NULL) ? settings->getString(key, defaultValue) : defaultValue; +} + +static void PrintConsoleLine(const wchar_t *prefix, const wstring &message) +{ + wprintf(L"%ls%ls\n", prefix, message.c_str()); + fflush(stdout); +} + +static bool TryParseIntValue(const wstring &text, int &value) +{ + std::wistringstream stream(text); + stream >> value; + return !stream.fail() && stream.eof(); +} + +static vector SplitConsoleCommand(const wstring &command) +{ + vector tokens; + std::wistringstream stream(command); + wstring token; + while (stream >> token) + { + tokens.push_back(token); + } + return tokens; +} + +static wstring JoinConsoleCommandTokens(const vector &tokens, size_t startIndex) +{ + wstring joined; + for (size_t i = startIndex; i < tokens.size(); ++i) + { + if (!joined.empty()) joined += L" "; + joined += tokens[i]; + } + return joined; +} + +static shared_ptr FindPlayerByName(PlayerList *playerList, const wstring &name) +{ + if (playerList == NULL) return nullptr; + + for (size_t i = 0; i < playerList->players.size(); ++i) + { + shared_ptr player = playerList->players[i]; + if (player != NULL && equalsIgnoreCase(player->getName(), name)) + { + return player; + } + } + + return nullptr; +} + +static void SetAllLevelTimes(MinecraftServer *server, int value) +{ + for (unsigned int i = 0; i < server->levels.length; ++i) + { + if (server->levels[i] != NULL) + { + server->levels[i]->setDayTime(value); + } + } +} + +static bool ExecuteConsoleCommand(MinecraftServer *server, const wstring &rawCommand) +{ + if (server == NULL) + return false; + + wstring command = trimString(rawCommand); + if (command.empty()) + return true; + + if (command[0] == L'/') + { + command = trimString(command.substr(1)); + } + + vector tokens = SplitConsoleCommand(command); + if (tokens.empty()) + return true; + + const wstring action = toLower(tokens[0]); + PlayerList *playerList = server->getPlayers(); + + if (action == L"help" || action == L"?") + { + server->info(L"Commands: help, stop, list, say , save-all, time , weather [seconds], tp , give [amount] [aux], enchant [level], kill "); + return true; + } + + if (action == L"stop") + { + server->info(L"Stopping server..."); + MinecraftServer::HaltServer(); + return true; + } + + if (action == L"list") + { + wstring playerNames = (playerList != NULL) ? playerList->getPlayerNames() : L""; + if (playerNames.empty()) playerNames = L"(none)"; + server->info(L"Players (" + _toString((playerList != NULL) ? playerList->getPlayerCount() : 0) + L"): " + playerNames); + return true; + } + + if (action == L"say") + { + if (tokens.size() < 2) + { + server->warn(L"Usage: say "); + return false; + } + + wstring message = L"[Server] " + JoinConsoleCommandTokens(tokens, 1); + if (playerList != NULL) + { + playerList->broadcastAll(shared_ptr(new ChatPacket(message))); + } + server->info(message); + return true; + } + + if (action == L"save-all") + { + if (playerList != NULL) + { + playerList->saveAll(NULL, false); + } + server->info(L"World saved."); + return true; + } + + if (action == L"time") + { + if (tokens.size() < 2) + { + server->warn(L"Usage: time set | time add "); + return false; + } + + if (toLower(tokens[1]) == L"add") + { + if (tokens.size() < 3) + { + server->warn(L"Usage: time add "); + return false; + } + + int delta = 0; + if (!TryParseIntValue(tokens[2], delta)) + { + server->warn(L"Invalid tick value: " + tokens[2]); + return false; + } + + for (unsigned int i = 0; i < server->levels.length; ++i) + { + if (server->levels[i] != NULL) + { + server->levels[i]->setDayTime(server->levels[i]->getDayTime() + delta); + } + } + + server->info(L"Added " + _toString(delta) + L" ticks."); + return true; + } + + wstring timeValue = toLower(tokens[1]); + if (timeValue == L"set") + { + if (tokens.size() < 3) + { + server->warn(L"Usage: time set "); + return false; + } + timeValue = toLower(tokens[2]); + } + + int targetTime = 0; + if (timeValue == L"day") + { + targetTime = 0; + } + else if (timeValue == L"night") + { + targetTime = 12500; + } + else if (!TryParseIntValue(timeValue, targetTime)) + { + server->warn(L"Invalid time value: " + timeValue); + return false; + } + + SetAllLevelTimes(server, targetTime); + server->info(L"Time set to " + _toString(targetTime) + L"."); + return true; + } + + if (action == L"weather") + { + if (tokens.size() < 2) + { + server->warn(L"Usage: weather [seconds]"); + return false; + } + + int durationSeconds = 600; + if (tokens.size() >= 3 && !TryParseIntValue(tokens[2], durationSeconds)) + { + server->warn(L"Invalid duration: " + tokens[2]); + return false; + } + + if (server->levels[0] == NULL) + { + server->warn(L"The overworld is not loaded."); + return false; + } + + LevelData *levelData = server->levels[0]->getLevelData(); + int duration = durationSeconds * SharedConstants::TICKS_PER_SECOND; + levelData->setRainTime(duration); + levelData->setThunderTime(duration); + + wstring weather = toLower(tokens[1]); + if (weather == L"clear") + { + levelData->setRaining(false); + levelData->setThundering(false); + } + else if (weather == L"rain") + { + levelData->setRaining(true); + levelData->setThundering(false); + } + else if (weather == L"thunder") + { + levelData->setRaining(true); + levelData->setThundering(true); + } + else + { + server->warn(L"Usage: weather [seconds]"); + return false; + } + + server->info(L"Weather set to " + weather + L"."); + return true; + } + + if (action == L"tp" || action == L"teleport") + { + if (tokens.size() < 3) + { + server->warn(L"Usage: tp "); + return false; + } + + shared_ptr subject = FindPlayerByName(playerList, tokens[1]); + shared_ptr destination = FindPlayerByName(playerList, tokens[2]); + if (subject == NULL) + { + server->warn(L"Unknown player: " + tokens[1]); + return false; + } + if (destination == NULL) + { + server->warn(L"Unknown player: " + tokens[2]); + return false; + } + if (subject->level->dimension->id != destination->level->dimension->id || !subject->isAlive()) + { + server->warn(L"Teleport failed because the players are not in the same dimension or the source player is dead."); + return false; + } + + subject->ride(nullptr); + subject->connection->teleport(destination->x, destination->y, destination->z, destination->yRot, destination->xRot); + server->info(L"Teleported " + subject->getName() + L" to " + destination->getName() + L"."); + return true; + } + + if (action == L"give") + { + if (tokens.size() < 3) + { + server->warn(L"Usage: give [amount] [aux]"); + return false; + } + + shared_ptr player = FindPlayerByName(playerList, tokens[1]); + if (player == NULL) + { + server->warn(L"Unknown player: " + tokens[1]); + return false; + } + + int itemId = 0; + int amount = 1; + int aux = 0; + if (!TryParseIntValue(tokens[2], itemId)) + { + server->warn(L"Invalid item id: " + tokens[2]); + return false; + } + if (tokens.size() >= 4 && !TryParseIntValue(tokens[3], amount)) + { + server->warn(L"Invalid amount: " + tokens[3]); + return false; + } + if (tokens.size() >= 5 && !TryParseIntValue(tokens[4], aux)) + { + server->warn(L"Invalid aux value: " + tokens[4]); + return false; + } + if (itemId <= 0 || Item::items[itemId] == NULL) + { + server->warn(L"Unknown item id: " + _toString(itemId)); + return false; + } + if (amount <= 0) + { + server->warn(L"Amount must be positive."); + return false; + } + + shared_ptr itemInstance(new ItemInstance(itemId, amount, aux)); + shared_ptr drop = player->drop(itemInstance); + if (drop != NULL) + { + drop->throwTime = 0; + } + server->info(L"Gave item " + _toString(itemId) + L" x" + _toString(amount) + L" to " + player->getName() + L"."); + return true; + } + + if (action == L"enchant") + { + if (tokens.size() < 3) + { + server->warn(L"Usage: enchant [level]"); + return false; + } + + shared_ptr player = FindPlayerByName(playerList, tokens[1]); + if (player == NULL) + { + server->warn(L"Unknown player: " + tokens[1]); + return false; + } + + int enchantmentId = 0; + int enchantmentLevel = 1; + if (!TryParseIntValue(tokens[2], enchantmentId)) + { + server->warn(L"Invalid enchantment id: " + tokens[2]); + return false; + } + if (tokens.size() >= 4 && !TryParseIntValue(tokens[3], enchantmentLevel)) + { + server->warn(L"Invalid enchantment level: " + tokens[3]); + return false; + } + + shared_ptr selectedItem = player->getSelectedItem(); + if (selectedItem == NULL) + { + server->warn(L"The player is not holding an item."); + return false; + } + + Enchantment *enchantment = Enchantment::enchantments[enchantmentId]; + if (enchantment == NULL) + { + server->warn(L"Unknown enchantment id: " + _toString(enchantmentId)); + return false; + } + if (!enchantment->canEnchant(selectedItem)) + { + server->warn(L"That enchantment cannot be applied to the selected item."); + return false; + } + + if (enchantmentLevel < enchantment->getMinLevel()) enchantmentLevel = enchantment->getMinLevel(); + if (enchantmentLevel > enchantment->getMaxLevel()) enchantmentLevel = enchantment->getMaxLevel(); + + if (selectedItem->hasTag()) + { + ListTag *enchantmentTags = selectedItem->getEnchantmentTags(); + if (enchantmentTags != NULL) + { + for (int i = 0; i < enchantmentTags->size(); i++) + { + int type = enchantmentTags->get(i)->getShort((wchar_t *)ItemInstance::TAG_ENCH_ID); + if (Enchantment::enchantments[type] != NULL && !Enchantment::enchantments[type]->isCompatibleWith(enchantment)) + { + server->warn(L"That enchantment conflicts with an existing enchantment on the selected item."); + return false; + } + } + } + } + + selectedItem->enchant(enchantment, enchantmentLevel); + server->info(L"Enchanted " + player->getName() + L"'s held item with " + _toString(enchantmentId) + L" " + _toString(enchantmentLevel) + L"."); + return true; + } + + if (action == L"kill") + { + if (tokens.size() < 2) + { + server->warn(L"Usage: kill "); + return false; + } + + shared_ptr player = FindPlayerByName(playerList, tokens[1]); + if (player == NULL) + { + server->warn(L"Unknown player: " + tokens[1]); + return false; + } + + player->hurt(DamageSource::outOfWorld, 3.4e38f); + server->info(L"Killed " + player->getName() + L"."); + return true; + } + + server->warn(L"Unknown command: " + command); + return false; +} + MinecraftServer::MinecraftServer() { // 4J - added initialisers @@ -107,12 +571,14 @@ MinecraftServer::MinecraftServer() forceGameType = false; commandDispatcher = new ServerCommandDispatcher(); + InitializeCriticalSection(&m_consoleInputCS); DispenserBootstrap::bootStrap(); } MinecraftServer::~MinecraftServer() { + DeleteCriticalSection(&m_consoleInputCS); } bool MinecraftServer::initServer(__int64 seed, NetworkGameInitData *initData, DWORD initSettings, bool findSeed) @@ -150,6 +616,15 @@ bool MinecraftServer::initServer(__int64 seed, NetworkGameInitData *initData, DW #endif settings = new Settings(new File(L"server.properties")); + app.SetGameHostOption(eGameHostOption_Difficulty, GetDedicatedServerInt(settings, L"difficulty", app.GetGameHostOption(eGameHostOption_Difficulty))); + app.SetGameHostOption(eGameHostOption_GameType, GetDedicatedServerInt(settings, L"gamemode", app.GetGameHostOption(eGameHostOption_GameType))); + app.SetGameHostOption(eGameHostOption_Structures, GetDedicatedServerBool(settings, L"generate-structures", app.GetGameHostOption(eGameHostOption_Structures) > 0) ? 1 : 0); + app.SetGameHostOption(eGameHostOption_BonusChest, GetDedicatedServerBool(settings, L"bonus-chest", app.GetGameHostOption(eGameHostOption_BonusChest) > 0) ? 1 : 0); + app.SetGameHostOption(eGameHostOption_PvP, GetDedicatedServerBool(settings, L"pvp", app.GetGameHostOption(eGameHostOption_PvP) > 0) ? 1 : 0); + app.SetGameHostOption(eGameHostOption_TrustPlayers, GetDedicatedServerBool(settings, L"trust-players", app.GetGameHostOption(eGameHostOption_TrustPlayers) > 0) ? 1 : 0); + app.SetGameHostOption(eGameHostOption_FireSpreads, GetDedicatedServerBool(settings, L"fire-spreads", app.GetGameHostOption(eGameHostOption_FireSpreads) > 0) ? 1 : 0); + app.SetGameHostOption(eGameHostOption_TNT, GetDedicatedServerBool(settings, L"tnt", app.GetGameHostOption(eGameHostOption_TNT) > 0) ? 1 : 0); + app.DebugPrintf("\n*** SERVER SETTINGS ***\n"); app.DebugPrintf("ServerSettings: host-friends-only is %s\n",(app.GetGameHostOption(eGameHostOption_FriendsOfFriends)>0)?"on":"off"); app.DebugPrintf("ServerSettings: game-type is %s\n",(app.GetGameHostOption(eGameHostOption_GameType)==0)?"Survival Mode":"Creative Mode"); @@ -167,13 +642,13 @@ bool MinecraftServer::initServer(__int64 seed, NetworkGameInitData *initData, DW //motd = settings->getString(L"motd", L"A Minecraft Server"); //motd.replace('', '$'); - setAnimals(settings->getBoolean(L"spawn-animals", true)); - setNpcsEnabled(settings->getBoolean(L"spawn-npcs", true)); - setPvpAllowed(app.GetGameHostOption( eGameHostOption_PvP )>0?true:false); // settings->getBoolean(L"pvp", true); + setAnimals(GetDedicatedServerBool(settings, L"spawn-animals", true)); + setNpcsEnabled(GetDedicatedServerBool(settings, L"spawn-npcs", true)); + setPvpAllowed(app.GetGameHostOption( eGameHostOption_PvP )>0?true:false); // 4J Stu - We should never have hacked clients flying when they shouldn't be like the PC version, so enable flying always // Fix for #46612 - TU5: Code: Multiplayer: A client can be banned for flying when accidentaly being blown by dynamite - setFlightAllowed(true); //settings->getBoolean(L"allow-flight", false); + setFlightAllowed(GetDedicatedServerBool(settings, L"allow-flight", true)); // 4J Stu - Enabling flight to stop it kicking us when we use it #ifdef _DEBUG_MENUS_ENABLED @@ -219,8 +694,8 @@ bool MinecraftServer::initServer(__int64 seed, NetworkGameInitData *initData, DW __int64 levelNanoTime = System::nanoTime(); - wstring levelName = settings->getString(L"level-name", L"world"); - wstring levelTypeString; + wstring levelName = (initData && !initData->levelName.empty()) ? initData->levelName : GetDedicatedServerString(settings, L"level-name", L"world"); + wstring levelTypeString; bool gameRuleUseFlatWorld = false; if(app.getLevelGenerationOptions() != NULL) @@ -229,11 +704,11 @@ bool MinecraftServer::initServer(__int64 seed, NetworkGameInitData *initData, DW } if(gameRuleUseFlatWorld || app.GetGameHostOption(eGameHostOption_LevelType)>0) { - levelTypeString = settings->getString(L"level-type", L"flat"); + levelTypeString = GetDedicatedServerString(settings, L"level-type", L"flat"); } else { - levelTypeString = settings->getString(L"level-type",L"default"); + levelTypeString = GetDedicatedServerString(settings, L"level-type",L"default"); } LevelType *pLevelType = LevelType::getLevelType(levelTypeString); @@ -254,7 +729,7 @@ bool MinecraftServer::initServer(__int64 seed, NetworkGameInitData *initData, DW #endif } - setMaxBuildHeight(settings->getInt(L"max-build-height", Level::maxBuildHeight)); + setMaxBuildHeight(GetDedicatedServerInt(settings, L"max-build-height", Level::maxBuildHeight)); setMaxBuildHeight(((getMaxBuildHeight() + 8) / 16) * 16); setMaxBuildHeight(Mth::clamp(getMaxBuildHeight(), 64, Level::maxBuildHeight)); //settings->setProperty(L"max-build-height", maxBuildHeight); @@ -403,7 +878,7 @@ bool MinecraftServer::loadLevel(LevelStorageSource *storageSource, const wstring // 4J TODO - free levels here if there are already some? levels = ServerLevelArray(3); - int gameTypeId = settings->getInt(L"gamemode", app.GetGameHostOption(eGameHostOption_GameType));//LevelSettings::GAMETYPE_SURVIVAL); + int gameTypeId = GetDedicatedServerInt(settings, L"gamemode", app.GetGameHostOption(eGameHostOption_GameType));//LevelSettings::GAMETYPE_SURVIVAL); GameType *gameType = LevelSettings::validateGameType(gameTypeId); app.DebugPrintf("Default game type: %d\n" , gameTypeId); @@ -502,7 +977,7 @@ bool MinecraftServer::loadLevel(LevelStorageSource *storageSource, const wstring #if DEBUG_SERVER_DONT_SPAWN_MOBS levels[i]->setSpawnSettings(false, false); #else - levels[i]->setSpawnSettings(settings->getBoolean(L"spawn-monsters", true), animals); + levels[i]->setSpawnSettings(GetDedicatedServerBool(settings, L"spawn-monsters", true), animals); #endif levels[i]->getLevelData()->setGameType(gameType); @@ -590,7 +1065,7 @@ bool MinecraftServer::loadLevel(LevelStorageSource *storageSource, const wstring for (int i = 0; i < levels.length ; i++) { // logger.info("Preparing start region for level " + i); - if (i == 0 || settings->getBoolean(L"allow-nether", true)) + if (i == 0 || GetDedicatedServerBool(settings, L"allow-nether", true)) { ServerLevel *level = levels[i]; if(levelChunksNeedConverted) @@ -1332,7 +1807,7 @@ void MinecraftServer::run(__int64 seed, void *lpParameter) MinecraftServer::setTimeOfDayAtEndOfTick = false; for (unsigned int i = 0; i < levels.length; i++) { - if (i == 0 || settings->getBoolean(L"allow-nether", true)) + if (i == 0 || GetDedicatedServerBool(settings, L"allow-nether", true)) { ServerLevel *level = levels[i]; level->setDayTime( MinecraftServer::setTimeOfDay ); @@ -1707,17 +2182,23 @@ void MinecraftServer::tick() void MinecraftServer::handleConsoleInput(const wstring& msg, ConsoleInputSource *source) { + EnterCriticalSection(&m_consoleInputCS); consoleInput.push_back(new ConsoleInput(msg, source)); + LeaveCriticalSection(&m_consoleInputCS); } void MinecraftServer::handleConsoleInputs() { - while (consoleInput.size() > 0) + vector pendingInputs; + EnterCriticalSection(&m_consoleInputCS); + pendingInputs.swap(consoleInput); + LeaveCriticalSection(&m_consoleInputCS); + + for (size_t i = 0; i < pendingInputs.size(); ++i) { - AUTO_VAR(it, consoleInput.begin()); - ConsoleInput *input = *it; - consoleInput.erase(it); - // commands->handleCommand(input); // 4J - removed - TODO - do we want equivalent of console commands? + ConsoleInput *input = pendingInputs[i]; + ExecuteConsoleCommand(this, input->msg); + delete input; } } @@ -1750,10 +2231,12 @@ File *MinecraftServer::getFile(const wstring& name) void MinecraftServer::info(const wstring& string) { + PrintConsoleLine(L"[INFO] ", string); } void MinecraftServer::warn(const wstring& string) { + PrintConsoleLine(L"[WARN] ", string); } wstring MinecraftServer::getConsoleName() diff --git a/Minecraft.Client/MinecraftServer.h b/Minecraft.Client/MinecraftServer.h index 2e3cc5788..51d91c956 100644 --- a/Minecraft.Client/MinecraftServer.h +++ b/Minecraft.Client/MinecraftServer.h @@ -43,6 +43,7 @@ typedef struct _NetworkGameInitData unsigned int xzSize; unsigned char hellScale; ESavePlatform savePlatform; + wstring levelName; _NetworkGameInitData() { @@ -103,6 +104,7 @@ private: // vector tickables = new ArrayList(); // 4J - removed CommandDispatcher *commandDispatcher; vector consoleInput; // 4J - was synchronizedList - TODO - investigate + CRITICAL_SECTION m_consoleInputCS; public: bool onlineMode; bool animals; diff --git a/Minecraft.Client/MultiPlayerGameMode.cpp b/Minecraft.Client/MultiPlayerGameMode.cpp index 8467e450e..1f0055ddd 100644 --- a/Minecraft.Client/MultiPlayerGameMode.cpp +++ b/Minecraft.Client/MultiPlayerGameMode.cpp @@ -370,7 +370,9 @@ bool MultiPlayerGameMode::useItemOn(shared_ptr player, Level *level, sha // are meant to be directly caused by this. If we don't do this, then the sounds never happen as the tile's use method is only called on the // server, and that won't allow any sounds that are directly made, or broadcast back level events to us that would make the sound, since we are // the source of the event. - if( ( t > 0 ) && ( !bTestUseOnly ) && player->isAllowedToUse(Tile::tiles[t]) ) + // --------------------------------------------------------------------------------- + // Only call soundOnly version if we didn't already call the tile's use method above + if( !didSomething && ( t > 0 ) && ( !bTestUseOnly ) && player->isAllowedToUse(Tile::tiles[t]) ) { Tile::tiles[t]->use(level, x, y, z, player, face, clickX, clickY, clickZ, true); } diff --git a/Minecraft.Client/PlayerList.cpp b/Minecraft.Client/PlayerList.cpp index 71e6df142..48f0f8fb8 100644 --- a/Minecraft.Client/PlayerList.cpp +++ b/Minecraft.Client/PlayerList.cpp @@ -53,14 +53,12 @@ PlayerList::PlayerList(MinecraftServer *server) //int viewDistance = server->settings->getInt(L"view-distance", 10); - maxPlayers = server->settings->getInt(L"max-players", 20); - doWhiteList = false; - #ifdef _WINDOWS64 maxPlayers = MINECRAFT_NET_MAX_PLAYERS; #else maxPlayers = server->settings->getInt(L"max-players", 20); #endif + doWhiteList = false; InitializeCriticalSection(&m_kickPlayersCS); InitializeCriticalSection(&m_closePlayersCS); } diff --git a/Minecraft.Client/Screen.cpp b/Minecraft.Client/Screen.cpp index f8b78c1aa..dbb631146 100644 --- a/Minecraft.Client/Screen.cpp +++ b/Minecraft.Client/Screen.cpp @@ -110,13 +110,13 @@ void Screen::updateEvents() // Poll mouse button state and dispatch click/release events for (int btn = 0; btn < 3; btn++) { - if (KMInput.ConsumeMousePress(btn)) + if (g_KBMInput.IsMouseButtonPressed(btn)) { int xm = Mouse::getX() * width / minecraft->width; int ym = height - Mouse::getY() * height / minecraft->height - 1; mouseClicked(xm, ym, btn); } - if (KMInput.ConsumeMouseRelease(btn)) + if (g_KBMInput.IsMouseButtonReleased(btn)) { int xm = Mouse::getX() * width / minecraft->width; int ym = height - Mouse::getY() * height / minecraft->height - 1; @@ -127,7 +127,7 @@ void Screen::updateEvents() // Poll keyboard events for (int vk = 0; vk < 256; vk++) { - if (KMInput.ConsumeKeyPress(vk)) + if (g_KBMInput.IsKeyPressed(vk)) { // Map Windows virtual key to the Keyboard constants used by Screen::keyPressed int mappedKey = -1; @@ -144,7 +144,7 @@ void Screen::updateEvents() else if (vk >= 'A' && vk <= 'Z') { ch = (wchar_t)(vk - 'A' + L'a'); - if (KMInput.IsKeyDown(VK_SHIFT)) ch = (wchar_t)vk; + if (g_KBMInput.IsKeyDown(VK_LSHIFT) || g_KBMInput.IsKeyDown(VK_RSHIFT)) ch = (wchar_t)vk; } else if (vk >= '0' && vk <= '9') ch = (wchar_t)vk; else if (vk == VK_SPACE) ch = L' '; diff --git a/Minecraft.Client/Settings.cpp b/Minecraft.Client/Settings.cpp index a457cc910..48baddeef 100644 --- a/Minecraft.Client/Settings.cpp +++ b/Minecraft.Client/Settings.cpp @@ -1,18 +1,90 @@ #include "stdafx.h" #include "Settings.h" +#include "Minecraft.World/File.h" #include "Minecraft.World/StringHelpers.h" +#include + +static wstring ParsePropertyText(const string &text) +{ + return trimString(convStringToWstring(text)); +} + +static bool TryParseBoolean(const wstring &text, bool defaultValue) +{ + wstring lowered = toLower(trimString(text)); + if (lowered == L"true" || lowered == L"1" || lowered == L"yes" || lowered == L"on") + return true; + if (lowered == L"false" || lowered == L"0" || lowered == L"no" || lowered == L"off") + return false; + return defaultValue; +} -// 4J - TODO - serialise/deserialise from file Settings::Settings(File *file) { + if (file != NULL) + { + filePath = file->getPath(); + } + + if (filePath.empty()) + return; + + std::ifstream stream(wstringtofilename(filePath), std::ios::in | std::ios::binary); + if (!stream.is_open()) + return; + + string line; + while (std::getline(stream, line)) + { + if (!line.empty() && line[line.size() - 1] == '\r') + line.erase(line.size() - 1); + + if (line.size() >= 3 && + (unsigned char)line[0] == 0xEF && + (unsigned char)line[1] == 0xBB && + (unsigned char)line[2] == 0xBF) + { + line.erase(0, 3); + } + + size_t commentPos = line.find_first_of("#;"); + if (commentPos != string::npos && line.find_first_not_of(" \t") == commentPos) + continue; + + size_t separatorPos = line.find('='); + if (separatorPos == string::npos) + continue; + + wstring key = ParsePropertyText(line.substr(0, separatorPos)); + if (key.empty()) + continue; + + wstring value = ParsePropertyText(line.substr(separatorPos + 1)); + properties[key] = value; + } } void Settings::generateNewProperties() { + saveProperties(); } void Settings::saveProperties() { + if (filePath.empty()) + return; + + std::ofstream stream(wstringtofilename(filePath), std::ios::out | std::ios::binary | std::ios::trunc); + if (!stream.is_open()) + return; + + stream << "# MinecraftConsoles dedicated server properties\r\n"; + for (unordered_map::const_iterator it = properties.begin(); it != properties.end(); ++it) + { + string key = string(wstringtochararray(it->first)); + string value = string(wstringtochararray(it->second)); + stream << key << "=" << value << "\r\n"; + } } wstring Settings::getString(const wstring& key, const wstring& defaultValue) @@ -39,17 +111,17 @@ bool Settings::getBoolean(const wstring& key, bool defaultValue) { if(properties.find(key) == properties.end()) { - properties[key] = _toString(defaultValue); + properties[key] = defaultValue ? L"true" : L"false"; saveProperties(); } MemSect(35); - bool retval = _fromString(properties[key]); + bool retval = TryParseBoolean(properties[key], defaultValue); MemSect(0); return retval; } void Settings::setBooleanAndSave(const wstring& key, bool value) { - properties[key] = _toString(value); + properties[key] = value ? L"true" : L"false"; saveProperties(); } \ No newline at end of file diff --git a/Minecraft.Client/Settings.h b/Minecraft.Client/Settings.h index b6a2c0181..4a3c130be 100644 --- a/Minecraft.Client/Settings.h +++ b/Minecraft.Client/Settings.h @@ -7,8 +7,8 @@ class Settings // public static Logger logger = Logger.getLogger("Minecraft"); // private Properties properties = new Properties(); private: - unordered_map properties; // 4J - TODO was Properties type, will need to implement something we can serialise/deserialise too - //File *file; + unordered_map properties; + wstring filePath; public: Settings(File *file); @@ -18,4 +18,4 @@ public: int getInt(const wstring& key, int defaultValue); bool getBoolean(const wstring& key, bool defaultValue); void setBooleanAndSave(const wstring& key, bool value); -}; +}; \ No newline at end of file diff --git a/Minecraft.Client/Textures.cpp b/Minecraft.Client/Textures.cpp index aed861c26..9d2c09de6 100644 --- a/Minecraft.Client/Textures.cpp +++ b/Minecraft.Client/Textures.cpp @@ -424,12 +424,109 @@ void Textures::bindTextureLayers(ResourceLocation *resource) { assert(resource->isPreloaded()); + // Hack: 4JLibs on Windows does not currently reproduce Minecraft's layered horse texture path reliably. + // Merge the layers on the CPU and bind the cached result as a normal single texture instead. + wstring cacheKey = L"%layered%"; int layers = resource->getTextureCount(); - for( int i = 0; i < layers; i++ ) { - RenderManager.TextureBind(loadTexture(resource->getTexture(i))); + cacheKey += std::to_wstring(resource->getTexture(i)); + cacheKey += L"/"; } + + int id = -1; + bool inMap = ( idMap.find(cacheKey) != idMap.end() ); + if( inMap ) + { + id = idMap[cacheKey]; + } + else + { + // Cache by layer signature so the merge cost is only paid once per horse texture combination. + intArray mergedPixels; + int mergedWidth = 0; + int mergedHeight = 0; + bool hasMergedPixels = false; + + for( int i = 0; i < layers; i++ ) + { + TEXTURE_NAME textureName = resource->getTexture(i); + if( textureName == (_TEXTURE_NAME)-1 ) + { + continue; + } + + wstring resourceName = wstring(preLoaded[textureName]) + L".png"; + BufferedImage *image = readImage(textureName, resourceName); + if( image == NULL ) + { + continue; + } + + int width = image->getWidth(); + int height = image->getHeight(); + intArray layerPixels = loadTexturePixels(image); + delete image; + + if( !hasMergedPixels ) + { + mergedWidth = width; + mergedHeight = height; + mergedPixels = intArray(width * height); + memcpy(mergedPixels.data, layerPixels.data, width * height * sizeof(int)); + hasMergedPixels = true; + } + else if( width == mergedWidth && height == mergedHeight ) + { + for( int p = 0; p < width * height; p++ ) + { + int dst = mergedPixels[p]; + int src = layerPixels[p]; + + float srcAlpha = ((src >> 24) & 0xff) / 255.0f; + if( srcAlpha <= 0.0f ) + { + continue; + } + + float dstAlpha = ((dst >> 24) & 0xff) / 255.0f; + float outAlpha = srcAlpha + dstAlpha * (1.0f - srcAlpha); + if( outAlpha <= 0.0f ) + { + mergedPixels[p] = 0; + continue; + } + + float srcFactor = srcAlpha / outAlpha; + float dstFactor = (dstAlpha * (1.0f - srcAlpha)) / outAlpha; + + int outA = (int)(outAlpha * 255.0f + 0.5f); + int outR = (int)((((src >> 16) & 0xff) * srcFactor) + (((dst >> 16) & 0xff) * dstFactor) + 0.5f); + int outG = (int)((((src >> 8) & 0xff) * srcFactor) + (((dst >> 8) & 0xff) * dstFactor) + 0.5f); + int outB = (int)(((src & 0xff) * srcFactor) + ((dst & 0xff) * dstFactor) + 0.5f); + mergedPixels[p] = (outA << 24) | (outR << 16) | (outG << 8) | outB; + } + } + + delete[] layerPixels.data; + } + + if( hasMergedPixels ) + { + BufferedImage *mergedImage = new BufferedImage(mergedWidth, mergedHeight, BufferedImage::TYPE_INT_ARGB); + memcpy(mergedImage->getData(), mergedPixels.data, mergedWidth * mergedHeight * sizeof(int)); + delete[] mergedPixels.data; + id = getTexture(mergedImage, C4JRender::TEXTURE_FORMAT_RxGyBzAw, false); + } + else + { + id = 0; + } + + idMap[cacheKey] = id; + } + + RenderManager.TextureBind(id); } void Textures::bind(int id) diff --git a/Minecraft.Client/Windows64/KeyboardMouseInput.cpp b/Minecraft.Client/Windows64/KeyboardMouseInput.cpp index fc7633947..95c3f4fc2 100644 --- a/Minecraft.Client/Windows64/KeyboardMouseInput.cpp +++ b/Minecraft.Client/Windows64/KeyboardMouseInput.cpp @@ -3,117 +3,161 @@ #ifdef _WINDOWS64 #include "KeyboardMouseInput.h" +#include -KeyboardMouseInput KMInput; +KeyboardMouseInput g_KBMInput; -KeyboardMouseInput::KeyboardMouseInput() - : m_mouseDeltaXAccum(0.0f) - , m_mouseDeltaYAccum(0.0f) - , m_scrollDeltaAccum(0) - , m_captured(false) - , m_hWnd(NULL) - , m_initialized(false) - , m_mouseX(0) - , m_mouseY(0) +extern HWND g_hWnd; + +// Forward declaration +static void ClipCursorToWindow(HWND hWnd); + +void KeyboardMouseInput::Init() { - memset(m_keyState, 0, sizeof(m_keyState)); - memset(m_keyStatePrev, 0, sizeof(m_keyStatePrev)); - memset(m_mouseButtons, 0, sizeof(m_mouseButtons)); - memset(m_mouseButtonsPrev, 0, sizeof(m_mouseButtonsPrev)); + memset(m_keyDown, 0, sizeof(m_keyDown)); + memset(m_keyDownPrev, 0, sizeof(m_keyDownPrev)); memset(m_keyPressedAccum, 0, sizeof(m_keyPressedAccum)); - memset(m_mousePressedAccum, 0, sizeof(m_mousePressedAccum)); - memset(m_mouseReleasedAccum, 0, sizeof(m_mouseReleasedAccum)); -} + memset(m_keyReleasedAccum, 0, sizeof(m_keyReleasedAccum)); + memset(m_keyPressed, 0, sizeof(m_keyPressed)); + memset(m_keyReleased, 0, sizeof(m_keyReleased)); + memset(m_mouseButtonDown, 0, sizeof(m_mouseButtonDown)); + memset(m_mouseButtonDownPrev, 0, sizeof(m_mouseButtonDownPrev)); + memset(m_mouseBtnPressedAccum, 0, sizeof(m_mouseBtnPressedAccum)); + memset(m_mouseBtnReleasedAccum, 0, sizeof(m_mouseBtnReleasedAccum)); + memset(m_mouseBtnPressed, 0, sizeof(m_mouseBtnPressed)); + memset(m_mouseBtnReleased, 0, sizeof(m_mouseBtnReleased)); + m_mouseX = 0; + m_mouseY = 0; + m_mouseDeltaX = 0; + m_mouseDeltaY = 0; + m_mouseDeltaAccumX = 0; + m_mouseDeltaAccumY = 0; + m_mouseWheelAccum = 0; + m_mouseWheelConsumed = false; + m_mouseGrabbed = false; + m_cursorHiddenForUI = false; + m_windowFocused = true; + m_hasInput = false; + m_kbmActive = true; + m_screenWantsCursorHidden = false; -KeyboardMouseInput::~KeyboardMouseInput() -{ - if (m_captured) - { - SetCapture(false); - } -} - -void KeyboardMouseInput::Init(HWND hWnd) -{ - m_hWnd = hWnd; - m_initialized = true; - - // Register for raw mouse input RAWINPUTDEVICE rid; - rid.usUsagePage = HID_USAGE_PAGE_GENERIC; - rid.usUsage = HID_USAGE_GENERIC_MOUSE; + rid.usUsagePage = 0x01; // HID_USAGE_PAGE_GENERIC + rid.usUsage = 0x02; // HID_USAGE_GENERIC_MOUSE rid.dwFlags = 0; - rid.hwndTarget = hWnd; + rid.hwndTarget = g_hWnd; RegisterRawInputDevices(&rid, 1, sizeof(rid)); } +void KeyboardMouseInput::ClearAllState() +{ + memset(m_keyDown, 0, sizeof(m_keyDown)); + memset(m_keyDownPrev, 0, sizeof(m_keyDownPrev)); + memset(m_keyPressedAccum, 0, sizeof(m_keyPressedAccum)); + memset(m_keyReleasedAccum, 0, sizeof(m_keyReleasedAccum)); + memset(m_keyPressed, 0, sizeof(m_keyPressed)); + memset(m_keyReleased, 0, sizeof(m_keyReleased)); + memset(m_mouseButtonDown, 0, sizeof(m_mouseButtonDown)); + memset(m_mouseButtonDownPrev, 0, sizeof(m_mouseButtonDownPrev)); + memset(m_mouseBtnPressedAccum, 0, sizeof(m_mouseBtnPressedAccum)); + memset(m_mouseBtnReleasedAccum, 0, sizeof(m_mouseBtnReleasedAccum)); + memset(m_mouseBtnPressed, 0, sizeof(m_mouseBtnPressed)); + memset(m_mouseBtnReleased, 0, sizeof(m_mouseBtnReleased)); + m_mouseDeltaX = 0; + m_mouseDeltaY = 0; + m_mouseDeltaAccumX = 0; + m_mouseDeltaAccumY = 0; + m_mouseWheelAccum = 0; + m_mouseWheelConsumed = false; +} + void KeyboardMouseInput::Tick() { - // Keep cursor pinned to center while captured - if (m_captured) - CenterCursor(); -} + memcpy(m_keyDownPrev, m_keyDown, sizeof(m_keyDown)); + memcpy(m_mouseButtonDownPrev, m_mouseButtonDown, sizeof(m_mouseButtonDown)); -void KeyboardMouseInput::EndFrame() -{ - // Advance previous state for next frame's edge detection. - // Must be called AFTER all per-frame consumers have read IsKeyPressed/Released etc. - memcpy(m_keyStatePrev, m_keyState, sizeof(m_keyState)); - memcpy(m_mouseButtonsPrev, m_mouseButtons, sizeof(m_mouseButtons)); -} + memcpy(m_keyPressed, m_keyPressedAccum, sizeof(m_keyPressedAccum)); + memcpy(m_keyReleased, m_keyReleasedAccum, sizeof(m_keyReleasedAccum)); + memset(m_keyPressedAccum, 0, sizeof(m_keyPressedAccum)); + memset(m_keyReleasedAccum, 0, sizeof(m_keyReleasedAccum)); -void KeyboardMouseInput::OnKeyDown(WPARAM vk) -{ - if (vk < 256) + memcpy(m_mouseBtnPressed, m_mouseBtnPressedAccum, sizeof(m_mouseBtnPressedAccum)); + memcpy(m_mouseBtnReleased, m_mouseBtnReleasedAccum, sizeof(m_mouseBtnReleasedAccum)); + memset(m_mouseBtnPressedAccum, 0, sizeof(m_mouseBtnPressedAccum)); + memset(m_mouseBtnReleasedAccum, 0, sizeof(m_mouseBtnReleasedAccum)); + + m_mouseDeltaX = m_mouseDeltaAccumX; + m_mouseDeltaY = m_mouseDeltaAccumY; + m_mouseDeltaAccumX = 0; + m_mouseDeltaAccumY = 0; + m_mouseWheelConsumed = false; + + m_hasInput = (m_mouseDeltaX != 0 || m_mouseDeltaY != 0 || m_mouseWheelAccum != 0); + if (!m_hasInput) { - if (!m_keyState[vk]) m_keyPressedAccum[vk] = true; - m_keyState[vk] = true; - } -} - -void KeyboardMouseInput::OnKeyUp(WPARAM vk) -{ - if (vk < 256) - { - m_keyState[vk] = false; - } -} - -void KeyboardMouseInput::OnRawMouseInput(LPARAM lParam) -{ - if (!m_captured) return; - - UINT dwSize = 0; - GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER)); - - BYTE* lpb = (BYTE*)alloca(dwSize); - if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER)) != dwSize) - return; - - RAWINPUT* raw = (RAWINPUT*)lpb; - if (raw->header.dwType == RIM_TYPEMOUSE) - { - if (raw->data.mouse.usFlags == MOUSE_MOVE_RELATIVE) + for (int i = 0; i < MAX_KEYS; i++) { - m_mouseDeltaXAccum += (float)raw->data.mouse.lLastX; - m_mouseDeltaYAccum += (float)raw->data.mouse.lLastY; + if (m_keyDown[i]) { m_hasInput = true; break; } } } -} - -void KeyboardMouseInput::OnMouseButton(int button, bool down) -{ - if (button >= 0 && button < 3) + if (!m_hasInput) { - if (down && !m_mouseButtons[button]) m_mousePressedAccum[button] = true; - if (!down && m_mouseButtons[button]) m_mouseReleasedAccum[button] = true; - m_mouseButtons[button] = down; + for (int i = 0; i < MAX_MOUSE_BUTTONS; i++) + { + if (m_mouseButtonDown[i]) { m_hasInput = true; break; } + } + } + + if ((m_mouseGrabbed || m_cursorHiddenForUI) && g_hWnd) + { + RECT rc; + GetClientRect(g_hWnd, &rc); + POINT center; + center.x = (rc.right - rc.left) / 2; + center.y = (rc.bottom - rc.top) / 2; + ClientToScreen(g_hWnd, ¢er); + SetCursorPos(center.x, center.y); } } -void KeyboardMouseInput::OnMouseWheel(int delta) +void KeyboardMouseInput::OnKeyDown(int vkCode) { - m_scrollDeltaAccum += delta; + if (vkCode >= 0 && vkCode < MAX_KEYS) + { + if (!m_keyDown[vkCode]) + m_keyPressedAccum[vkCode] = true; + m_keyDown[vkCode] = true; + } +} + +void KeyboardMouseInput::OnKeyUp(int vkCode) +{ + if (vkCode >= 0 && vkCode < MAX_KEYS) + { + if (m_keyDown[vkCode]) + m_keyReleasedAccum[vkCode] = true; + m_keyDown[vkCode] = false; + } +} + +void KeyboardMouseInput::OnMouseButtonDown(int button) +{ + if (button >= 0 && button < MAX_MOUSE_BUTTONS) + { + if (!m_mouseButtonDown[button]) + m_mouseBtnPressedAccum[button] = true; + m_mouseButtonDown[button] = true; + } +} + +void KeyboardMouseInput::OnMouseButtonUp(int button) +{ + if (button >= 0 && button < MAX_MOUSE_BUTTONS) + { + if (m_mouseButtonDown[button]) + m_mouseBtnReleasedAccum[button] = true; + m_mouseButtonDown[button] = false; + } } void KeyboardMouseInput::OnMouseMove(int x, int y) @@ -122,139 +166,195 @@ void KeyboardMouseInput::OnMouseMove(int x, int y) m_mouseY = y; } -int KeyboardMouseInput::GetMouseX() const { return m_mouseX; } -int KeyboardMouseInput::GetMouseY() const { return m_mouseY; } -HWND KeyboardMouseInput::GetHWnd() const { return m_hWnd; } - -void KeyboardMouseInput::ClearAllState() +void KeyboardMouseInput::OnMouseWheel(int delta) { - memset(m_keyState, 0, sizeof(m_keyState)); - memset(m_mouseButtons, 0, sizeof(m_mouseButtons)); - memset(m_keyPressedAccum, 0, sizeof(m_keyPressedAccum)); - memset(m_mousePressedAccum, 0, sizeof(m_mousePressedAccum)); - memset(m_mouseReleasedAccum, 0, sizeof(m_mouseReleasedAccum)); - m_mouseDeltaXAccum = 0.0f; - m_mouseDeltaYAccum = 0.0f; - m_scrollDeltaAccum = 0; + // Normalize from raw Windows delta (multiples of WHEEL_DELTA=120) to discrete notch counts + m_mouseWheelAccum += delta / WHEEL_DELTA; } -// Per-frame key queries -bool KeyboardMouseInput::IsKeyDown(int vk) const +int KeyboardMouseInput::GetMouseWheel() { - if (vk < 0 || vk >= 256) return false; - return m_keyState[vk]; + int val = m_mouseWheelAccum; + if (val != 0) + m_mouseWheelConsumed = true; + m_mouseWheelAccum = 0; + return val; } -bool KeyboardMouseInput::IsKeyPressed(int vk) const +void KeyboardMouseInput::OnRawMouseDelta(int dx, int dy) { - if (vk < 0 || vk >= 256) return false; - return m_keyState[vk] && !m_keyStatePrev[vk]; + m_mouseDeltaAccumX += dx; + m_mouseDeltaAccumY += dy; } -bool KeyboardMouseInput::IsKeyReleased(int vk) const +bool KeyboardMouseInput::IsKeyDown(int vkCode) const { - if (vk < 0 || vk >= 256) return false; - return !m_keyState[vk] && m_keyStatePrev[vk]; + if (vkCode >= 0 && vkCode < MAX_KEYS) + return m_keyDown[vkCode]; + return false; } -// Per-frame mouse button queries -bool KeyboardMouseInput::IsMouseDown(int btn) const +bool KeyboardMouseInput::IsKeyPressed(int vkCode) const { - if (btn < 0 || btn >= 3) return false; - return m_mouseButtons[btn]; + if (vkCode >= 0 && vkCode < MAX_KEYS) + return m_keyPressed[vkCode]; + return false; } -bool KeyboardMouseInput::IsMousePressed(int btn) const +bool KeyboardMouseInput::IsKeyReleased(int vkCode) const { - if (btn < 0 || btn >= 3) return false; - return m_mouseButtons[btn] && !m_mouseButtonsPrev[btn]; + if (vkCode >= 0 && vkCode < MAX_KEYS) + return m_keyReleased[vkCode]; + return false; } -bool KeyboardMouseInput::IsMouseReleased(int btn) const +bool KeyboardMouseInput::IsMouseButtonDown(int button) const { - if (btn < 0 || btn >= 3) return false; - return !m_mouseButtons[btn] && m_mouseButtonsPrev[btn]; + if (button >= 0 && button < MAX_MOUSE_BUTTONS) + return m_mouseButtonDown[button]; + return false; } -// Game-tick consume methods -bool KeyboardMouseInput::ConsumeKeyPress(int vk) +bool KeyboardMouseInput::IsMouseButtonPressed(int button) const { - if (vk < 0 || vk >= 256) return false; - bool pressed = m_keyPressedAccum[vk]; - m_keyPressedAccum[vk] = false; - return pressed; + if (button >= 0 && button < MAX_MOUSE_BUTTONS) + return m_mouseBtnPressed[button]; + return false; } -bool KeyboardMouseInput::ConsumeMousePress(int btn) +bool KeyboardMouseInput::IsMouseButtonReleased(int button) const { - if (btn < 0 || btn >= 3) return false; - bool pressed = m_mousePressedAccum[btn]; - m_mousePressedAccum[btn] = false; - return pressed; -} - -bool KeyboardMouseInput::ConsumeMouseRelease(int btn) -{ - if (btn < 0 || btn >= 3) return false; - bool released = m_mouseReleasedAccum[btn]; - m_mouseReleasedAccum[btn] = false; - return released; + if (button >= 0 && button < MAX_MOUSE_BUTTONS) + return m_mouseBtnReleased[button]; + return false; } void KeyboardMouseInput::ConsumeMouseDelta(float &dx, float &dy) { - dx = m_mouseDeltaXAccum; - dy = m_mouseDeltaYAccum; - m_mouseDeltaXAccum = 0.0f; - m_mouseDeltaYAccum = 0.0f; + dx = (float)m_mouseDeltaAccumX; + dy = (float)m_mouseDeltaAccumY; + m_mouseDeltaAccumX = 0; + m_mouseDeltaAccumY = 0; } -int KeyboardMouseInput::ConsumeScrollDelta() +void KeyboardMouseInput::SetMouseGrabbed(bool grabbed) { - int delta = m_scrollDeltaAccum; - m_scrollDeltaAccum = 0; - return delta; -} + if (m_mouseGrabbed == grabbed) + return; -// Mouse capture -void KeyboardMouseInput::SetCapture(bool capture) -{ - if (capture == m_captured) return; - m_captured = capture; - - if (capture) + m_mouseGrabbed = grabbed; + if (grabbed && g_hWnd) { - ShowCursor(FALSE); - RECT rect; - GetClientRect(m_hWnd, &rect); - POINT topLeft = { rect.left, rect.top }; - POINT bottomRight = { rect.right, rect.bottom }; - ClientToScreen(m_hWnd, &topLeft); - ClientToScreen(m_hWnd, &bottomRight); - RECT screenRect = { topLeft.x, topLeft.y, bottomRight.x, bottomRight.y }; - ClipCursor(&screenRect); - CenterCursor(); + while (ShowCursor(FALSE) >= 0) {} + ClipCursorToWindow(g_hWnd); - // Flush accumulated deltas so the snap-to-center doesn't cause a jump - m_mouseDeltaXAccum = 0.0f; - m_mouseDeltaYAccum = 0.0f; + RECT rc; + GetClientRect(g_hWnd, &rc); + POINT center; + center.x = (rc.right - rc.left) / 2; + center.y = (rc.bottom - rc.top) / 2; + ClientToScreen(g_hWnd, ¢er); + SetCursorPos(center.x, center.y); + + m_mouseDeltaAccumX = 0; + m_mouseDeltaAccumY = 0; } - else + else if (!grabbed && !m_cursorHiddenForUI && g_hWnd) { - ShowCursor(TRUE); + while (ShowCursor(TRUE) < 0) {} ClipCursor(NULL); } } -bool KeyboardMouseInput::IsCaptured() const { return m_captured; } - -void KeyboardMouseInput::CenterCursor() +void KeyboardMouseInput::SetCursorHiddenForUI(bool hidden) { - RECT rect; - GetClientRect(m_hWnd, &rect); - POINT center = { (rect.left + rect.right) / 2, (rect.top + rect.bottom) / 2 }; - ClientToScreen(m_hWnd, ¢er); - SetCursorPos(center.x, center.y); + if (m_cursorHiddenForUI == hidden) + return; + + m_cursorHiddenForUI = hidden; + if (hidden && g_hWnd) + { + while (ShowCursor(FALSE) >= 0) {} + ClipCursorToWindow(g_hWnd); + + RECT rc; + GetClientRect(g_hWnd, &rc); + POINT center; + center.x = (rc.right - rc.left) / 2; + center.y = (rc.bottom - rc.top) / 2; + ClientToScreen(g_hWnd, ¢er); + SetCursorPos(center.x, center.y); + + m_mouseDeltaAccumX = 0; + m_mouseDeltaAccumY = 0; + } + else if (!hidden && !m_mouseGrabbed && g_hWnd) + { + while (ShowCursor(TRUE) < 0) {} + ClipCursor(NULL); + } +} + +static void ClipCursorToWindow(HWND hWnd) +{ + if (!hWnd) return; + RECT rc; + GetClientRect(hWnd, &rc); + POINT topLeft = { rc.left, rc.top }; + POINT bottomRight = { rc.right, rc.bottom }; + ClientToScreen(hWnd, &topLeft); + ClientToScreen(hWnd, &bottomRight); + RECT clipRect = { topLeft.x, topLeft.y, bottomRight.x, bottomRight.y }; + ClipCursor(&clipRect); +} + +void KeyboardMouseInput::SetWindowFocused(bool focused) +{ + m_windowFocused = focused; + if (focused) + { + if (m_mouseGrabbed || m_cursorHiddenForUI) + { + while (ShowCursor(FALSE) >= 0) {} + ClipCursorToWindow(g_hWnd); + } + else + { + while (ShowCursor(TRUE) < 0) {} + ClipCursor(NULL); + } + } + else + { + while (ShowCursor(TRUE) < 0) {} + ClipCursor(NULL); + } +} + +float KeyboardMouseInput::GetMoveX() const +{ + float x = 0.0f; + if (m_keyDown[KEY_LEFT]) x += 1.0f; + if (m_keyDown[KEY_RIGHT]) x -= 1.0f; + return x; +} + +float KeyboardMouseInput::GetMoveY() const +{ + float y = 0.0f; + if (m_keyDown[KEY_FORWARD]) y += 1.0f; + if (m_keyDown[KEY_BACKWARD]) y -= 1.0f; + return y; +} + +float KeyboardMouseInput::GetLookX(float sensitivity) const +{ + return (float)m_mouseDeltaX * sensitivity; +} + +float KeyboardMouseInput::GetLookY(float sensitivity) const +{ + return (float)(-m_mouseDeltaY) * sensitivity; } #endif // _WINDOWS64 diff --git a/Minecraft.Client/Windows64/KeyboardMouseInput.h b/Minecraft.Client/Windows64/KeyboardMouseInput.h index a09843f90..050670550 100644 --- a/Minecraft.Client/Windows64/KeyboardMouseInput.h +++ b/Minecraft.Client/Windows64/KeyboardMouseInput.h @@ -4,88 +4,132 @@ #include -// HID usage page and usage for raw input registration -#ifndef HID_USAGE_PAGE_GENERIC -#define HID_USAGE_PAGE_GENERIC ((USHORT)0x01) -#endif -#ifndef HID_USAGE_GENERIC_MOUSE -#define HID_USAGE_GENERIC_MOUSE ((USHORT)0x02) -#endif - class KeyboardMouseInput { public: - KeyboardMouseInput(); - ~KeyboardMouseInput(); + static const int MAX_KEYS = 256; - void Init(HWND hWnd); + static const int MOUSE_LEFT = 0; + static const int MOUSE_RIGHT = 1; + static const int MOUSE_MIDDLE = 2; + static const int MAX_MOUSE_BUTTONS = 3; + + static const int KEY_FORWARD = 'W'; + static const int KEY_BACKWARD = 'S'; + static const int KEY_LEFT = 'A'; + static const int KEY_RIGHT = 'D'; + static const int KEY_JUMP = VK_SPACE; + static const int KEY_SNEAK = VK_LSHIFT; + static const int KEY_SPRINT = VK_LCONTROL; + static const int KEY_INVENTORY = 'E'; + static const int KEY_DROP = 'Q'; + static const int KEY_CRAFTING = 'C'; + static const int KEY_CRAFTING_ALT = 'R'; + static const int KEY_CONFIRM = VK_RETURN; + static const int KEY_CANCEL = VK_ESCAPE; + static const int KEY_PAUSE = VK_ESCAPE; + static const int KEY_THIRD_PERSON = VK_F5; + static const int KEY_DEBUG_INFO = VK_F3; + + void Init(); void Tick(); - void EndFrame(); - - // Called from WndProc - void OnKeyDown(WPARAM vk); - void OnKeyUp(WPARAM vk); - void OnRawMouseInput(LPARAM lParam); - void OnMouseButton(int button, bool down); - void OnMouseWheel(int delta); void ClearAllState(); - // Per-frame edge detection (for UI / per-frame logic like Alt toggle) - bool IsKeyDown(int vk) const; - bool IsKeyPressed(int vk) const; - bool IsKeyReleased(int vk) const; - bool IsMouseDown(int btn) const; - bool IsMousePressed(int btn) const; - bool IsMouseReleased(int btn) const; - - // Game-tick consume methods: accumulate across frames, clear on read. - // Use these from code that runs at game tick rate (20Hz). - bool ConsumeKeyPress(int vk); - bool ConsumeMousePress(int btn); - bool ConsumeMouseRelease(int btn); - void ConsumeMouseDelta(float &dx, float &dy); - int ConsumeScrollDelta(); - - // Absolute cursor position (client-area coordinates, for GUI when not captured) + void OnKeyDown(int vkCode); + void OnKeyUp(int vkCode); + void OnMouseButtonDown(int button); + void OnMouseButtonUp(int button); void OnMouseMove(int x, int y); - int GetMouseX() const; - int GetMouseY() const; - HWND GetHWnd() const; + void OnMouseWheel(int delta); + void OnRawMouseDelta(int dx, int dy); - // Mouse capture for FPS look - void SetCapture(bool capture); - bool IsCaptured() const; + bool IsKeyDown(int vkCode) const; + bool IsKeyPressed(int vkCode) const; + bool IsKeyReleased(int vkCode) const; + + bool IsMouseButtonDown(int button) const; + bool IsMouseButtonPressed(int button) const; + bool IsMouseButtonReleased(int button) const; + + int GetMouseX() const { return m_mouseX; } + int GetMouseY() const { return m_mouseY; } + + int GetMouseDeltaX() const { return m_mouseDeltaX; } + int GetMouseDeltaY() const { return m_mouseDeltaY; } + + int GetMouseWheel(); + int PeekMouseWheel() const { return m_mouseWheelAccum; } + void ConsumeMouseWheel() { if (m_mouseWheelAccum != 0) m_mouseWheelConsumed = true; m_mouseWheelAccum = 0; } + bool WasMouseWheelConsumed() const { return m_mouseWheelConsumed; } + + // Per-frame delta consumption for low-latency mouse look. + // Reads and clears the raw accumulators (not the per-tick snapshot). + void ConsumeMouseDelta(float &dx, float &dy); + + void SetMouseGrabbed(bool grabbed); + bool IsMouseGrabbed() const { return m_mouseGrabbed; } + + void SetCursorHiddenForUI(bool hidden); + bool IsCursorHiddenForUI() const { return m_cursorHiddenForUI; } + + void SetWindowFocused(bool focused); + bool IsWindowFocused() const { return m_windowFocused; } + + bool HasAnyInput() const { return m_hasInput; } + + void SetKBMActive(bool active) { m_kbmActive = active; } + bool IsKBMActive() const { return m_kbmActive; } + + void SetScreenCursorHidden(bool hidden) { m_screenWantsCursorHidden = hidden; } + bool IsScreenCursorHidden() const { return m_screenWantsCursorHidden; } + + float GetMoveX() const; + float GetMoveY() const; + + float GetLookX(float sensitivity) const; + float GetLookY(float sensitivity) const; private: - void CenterCursor(); + bool m_keyDown[MAX_KEYS]; + bool m_keyDownPrev[MAX_KEYS]; - // Per-frame double-buffered state (for IsKeyPressed/Released per-frame edge detection) - bool m_keyState[256]; - bool m_keyStatePrev[256]; - bool m_mouseButtons[3]; - bool m_mouseButtonsPrev[3]; + bool m_keyPressedAccum[MAX_KEYS]; + bool m_keyReleasedAccum[MAX_KEYS]; + bool m_keyPressed[MAX_KEYS]; + bool m_keyReleased[MAX_KEYS]; - // Sticky press accumulators (persist until consumed by game tick) - bool m_keyPressedAccum[256]; - bool m_mousePressedAccum[3]; - bool m_mouseReleasedAccum[3]; + bool m_mouseButtonDown[MAX_MOUSE_BUTTONS]; + bool m_mouseButtonDownPrev[MAX_MOUSE_BUTTONS]; - // Mouse delta accumulators (persist until consumed by game tick) - float m_mouseDeltaXAccum; - float m_mouseDeltaYAccum; + bool m_mouseBtnPressedAccum[MAX_MOUSE_BUTTONS]; + bool m_mouseBtnReleasedAccum[MAX_MOUSE_BUTTONS]; + bool m_mouseBtnPressed[MAX_MOUSE_BUTTONS]; + bool m_mouseBtnReleased[MAX_MOUSE_BUTTONS]; - // Scroll accumulator (persists until consumed by game tick) - int m_scrollDeltaAccum; - - bool m_captured; - HWND m_hWnd; - bool m_initialized; - - // Absolute cursor position in client coordinates int m_mouseX; int m_mouseY; + + int m_mouseDeltaX; + int m_mouseDeltaY; + int m_mouseDeltaAccumX; + int m_mouseDeltaAccumY; + + int m_mouseWheelAccum; + bool m_mouseWheelConsumed; + + bool m_mouseGrabbed; + + bool m_cursorHiddenForUI; + + bool m_windowFocused; + + bool m_hasInput; + + bool m_kbmActive; + + bool m_screenWantsCursorHidden; }; -extern KeyboardMouseInput KMInput; +extern KeyboardMouseInput g_KBMInput; #endif // _WINDOWS64 diff --git a/Minecraft.Client/Windows64/Network/WinsockNetLayer.cpp b/Minecraft.Client/Windows64/Network/WinsockNetLayer.cpp index 9a24ca003..ab5dde532 100644 --- a/Minecraft.Client/Windows64/Network/WinsockNetLayer.cpp +++ b/Minecraft.Client/Windows64/Network/WinsockNetLayer.cpp @@ -1,3 +1,6 @@ +// Code implemented by LCEMP, credit if used on other repos +// https://github.com/LCEMP/LCEMP + #include "stdafx.h" #ifdef _WINDOWS64 @@ -48,6 +51,9 @@ bool g_Win64MultiplayerHost = false; bool g_Win64MultiplayerJoin = false; int g_Win64MultiplayerPort = WIN64_NET_DEFAULT_PORT; char g_Win64MultiplayerIP[256] = "127.0.0.1"; +bool g_Win64DedicatedServer = false; +int g_Win64DedicatedServerPort = WIN64_NET_DEFAULT_PORT; +char g_Win64DedicatedServerBindIP[256] = ""; bool WinsockNetLayer::Initialize() { @@ -136,7 +142,7 @@ void WinsockNetLayer::Shutdown() } } -bool WinsockNetLayer::HostGame(int port) +bool WinsockNetLayer::HostGame(int port, const char* bindIp) { if (!s_initialized && !Initialize()) return false; @@ -151,20 +157,24 @@ bool WinsockNetLayer::HostGame(int port) LeaveCriticalSection(&s_freeSmallIdLock); struct addrinfo hints = {}; - struct addrinfo *result = NULL; + struct addrinfo* result = NULL; hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; - hints.ai_flags = AI_PASSIVE; + hints.ai_flags = (bindIp == NULL || bindIp[0] == 0) ? AI_PASSIVE : 0; char portStr[16]; sprintf_s(portStr, "%d", port); - int iResult = getaddrinfo(NULL, portStr, &hints, &result); + const char* resolvedBindIp = (bindIp != NULL && bindIp[0] != 0) ? bindIp : NULL; + int iResult = getaddrinfo(resolvedBindIp, portStr, &hints, &result); if (iResult != 0) { - app.DebugPrintf("getaddrinfo failed: %d\n", iResult); + app.DebugPrintf("getaddrinfo failed for %s:%d - %d\n", + resolvedBindIp != NULL ? resolvedBindIp : "*", + port, + iResult); return false; } @@ -177,7 +187,7 @@ bool WinsockNetLayer::HostGame(int port) } int opt = 1; - setsockopt(s_listenSocket, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof(opt)); + setsockopt(s_listenSocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&opt, sizeof(opt)); iResult = ::bind(s_listenSocket, result->ai_addr, (int)result->ai_addrlen); freeaddrinfo(result); @@ -203,19 +213,29 @@ bool WinsockNetLayer::HostGame(int port) s_acceptThread = CreateThread(NULL, 0, AcceptThreadProc, NULL, 0, NULL); - app.DebugPrintf("Win64 LAN: Hosting on port %d\n", port); + app.DebugPrintf("Win64 LAN: Hosting on %s:%d\n", + resolvedBindIp != NULL ? resolvedBindIp : "*", + port); return true; } -bool WinsockNetLayer::JoinGame(const char *ip, int port) +bool WinsockNetLayer::JoinGame(const char* ip, int port) { if (!s_initialized && !Initialize()) return false; s_isHost = false; s_hostSmallId = 0; + s_connected = false; + s_active = false; + + if (s_hostConnectionSocket != INVALID_SOCKET) + { + closesocket(s_hostConnectionSocket); + s_hostConnectionSocket = INVALID_SOCKET; + } struct addrinfo hints = {}; - struct addrinfo *result = NULL; + struct addrinfo* result = NULL; hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; @@ -231,37 +251,55 @@ bool WinsockNetLayer::JoinGame(const char *ip, int port) return false; } - s_hostConnectionSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol); - if (s_hostConnectionSocket == INVALID_SOCKET) + bool connected = false; + BYTE assignedSmallId = 0; + const int maxAttempts = 12; + + for (int attempt = 0; attempt < maxAttempts; ++attempt) { - app.DebugPrintf("socket() failed: %d\n", WSAGetLastError()); - freeaddrinfo(result); - return false; + s_hostConnectionSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol); + if (s_hostConnectionSocket == INVALID_SOCKET) + { + app.DebugPrintf("socket() failed: %d\n", WSAGetLastError()); + break; + } + + int noDelay = 1; + setsockopt(s_hostConnectionSocket, IPPROTO_TCP, TCP_NODELAY, (const char*)&noDelay, sizeof(noDelay)); + + iResult = connect(s_hostConnectionSocket, result->ai_addr, (int)result->ai_addrlen); + if (iResult == SOCKET_ERROR) + { + int err = WSAGetLastError(); + app.DebugPrintf("connect() to %s:%d failed (attempt %d/%d): %d\n", ip, port, attempt + 1, maxAttempts, err); + closesocket(s_hostConnectionSocket); + s_hostConnectionSocket = INVALID_SOCKET; + Sleep(200); + continue; + } + + BYTE assignBuf[1]; + int bytesRecv = recv(s_hostConnectionSocket, (char*)assignBuf, 1, 0); + if (bytesRecv != 1) + { + app.DebugPrintf("Failed to receive small ID assignment from host (attempt %d/%d)\n", attempt + 1, maxAttempts); + closesocket(s_hostConnectionSocket); + s_hostConnectionSocket = INVALID_SOCKET; + Sleep(200); + continue; + } + + assignedSmallId = assignBuf[0]; + connected = true; + break; } - - int noDelay = 1; - setsockopt(s_hostConnectionSocket, IPPROTO_TCP, TCP_NODELAY, (const char *)&noDelay, sizeof(noDelay)); - - iResult = connect(s_hostConnectionSocket, result->ai_addr, (int)result->ai_addrlen); freeaddrinfo(result); - if (iResult == SOCKET_ERROR) - { - app.DebugPrintf("connect() to %s:%d failed: %d\n", ip, port, WSAGetLastError()); - closesocket(s_hostConnectionSocket); - s_hostConnectionSocket = INVALID_SOCKET; - return false; - } - BYTE assignBuf[1]; - int bytesRecv = recv(s_hostConnectionSocket, (char *)assignBuf, 1, 0); - if (bytesRecv != 1) + if (!connected) { - app.DebugPrintf("Failed to receive small ID assignment from host\n"); - closesocket(s_hostConnectionSocket); - s_hostConnectionSocket = INVALID_SOCKET; return false; } - s_localSmallId = assignBuf[0]; + s_localSmallId = assignedSmallId; app.DebugPrintf("Win64 LAN: Connected to %s:%d, assigned smallId=%d\n", ip, port, s_localSmallId); @@ -273,7 +311,7 @@ bool WinsockNetLayer::JoinGame(const char *ip, int port) return true; } -bool WinsockNetLayer::SendOnSocket(SOCKET sock, const void *data, int dataSize) +bool WinsockNetLayer::SendOnSocket(SOCKET sock, const void* data, int dataSize) { if (sock == INVALID_SOCKET || dataSize <= 0) return false; @@ -289,7 +327,7 @@ bool WinsockNetLayer::SendOnSocket(SOCKET sock, const void *data, int dataSize) int toSend = 4; while (totalSent < toSend) { - int sent = send(sock, (const char *)header + totalSent, toSend - totalSent, 0); + int sent = send(sock, (const char*)header + totalSent, toSend - totalSent, 0); if (sent == SOCKET_ERROR || sent == 0) { LeaveCriticalSection(&s_sendLock); @@ -301,7 +339,7 @@ bool WinsockNetLayer::SendOnSocket(SOCKET sock, const void *data, int dataSize) totalSent = 0; while (totalSent < dataSize) { - int sent = send(sock, (const char *)data + totalSent, dataSize - totalSent, 0); + int sent = send(sock, (const char*)data + totalSent, dataSize - totalSent, 0); if (sent == SOCKET_ERROR || sent == 0) { LeaveCriticalSection(&s_sendLock); @@ -314,7 +352,7 @@ bool WinsockNetLayer::SendOnSocket(SOCKET sock, const void *data, int dataSize) return true; } -bool WinsockNetLayer::SendToSmallId(BYTE targetSmallId, const void *data, int dataSize) +bool WinsockNetLayer::SendToSmallId(BYTE targetSmallId, const void* data, int dataSize) { if (!s_active) return false; @@ -346,34 +384,34 @@ SOCKET WinsockNetLayer::GetSocketForSmallId(BYTE smallId) return INVALID_SOCKET; } -static bool RecvExact(SOCKET sock, BYTE *buf, int len) +static bool RecvExact(SOCKET sock, BYTE* buf, int len) { int totalRecv = 0; while (totalRecv < len) { - int r = recv(sock, (char *)buf + totalRecv, len - totalRecv, 0); + int r = recv(sock, (char*)buf + totalRecv, len - totalRecv, 0); if (r <= 0) return false; totalRecv += r; } return true; } -void WinsockNetLayer::HandleDataReceived(BYTE fromSmallId, BYTE toSmallId, unsigned char *data, unsigned int dataSize) +void WinsockNetLayer::HandleDataReceived(BYTE fromSmallId, BYTE toSmallId, unsigned char* data, unsigned int dataSize) { - INetworkPlayer *pPlayerFrom = g_NetworkManager.GetPlayerBySmallId(fromSmallId); - INetworkPlayer *pPlayerTo = g_NetworkManager.GetPlayerBySmallId(toSmallId); + INetworkPlayer* pPlayerFrom = g_NetworkManager.GetPlayerBySmallId(fromSmallId); + INetworkPlayer* pPlayerTo = g_NetworkManager.GetPlayerBySmallId(toSmallId); if (pPlayerFrom == NULL || pPlayerTo == NULL) return; if (s_isHost) { - ::Socket *pSocket = pPlayerFrom->GetSocket(); + ::Socket* pSocket = pPlayerFrom->GetSocket(); if (pSocket != NULL) pSocket->pushDataToQueue(data, dataSize, false); } else { - ::Socket *pSocket = pPlayerTo->GetSocket(); + ::Socket* pSocket = pPlayerTo->GetSocket(); if (pSocket != NULL) pSocket->pushDataToQueue(data, dataSize, true); } @@ -392,7 +430,7 @@ DWORD WINAPI WinsockNetLayer::AcceptThreadProc(LPVOID param) } int noDelay = 1; - setsockopt(clientSocket, IPPROTO_TCP, TCP_NODELAY, (const char *)&noDelay, sizeof(noDelay)); + setsockopt(clientSocket, IPPROTO_TCP, TCP_NODELAY, (const char*)&noDelay, sizeof(noDelay)); extern QNET_STATE _iQNetStubState; if (_iQNetStubState != QNET_STATE_GAME_PLAY) @@ -423,7 +461,7 @@ DWORD WINAPI WinsockNetLayer::AcceptThreadProc(LPVOID param) LeaveCriticalSection(&s_freeSmallIdLock); BYTE assignBuf[1] = { assignedSmallId }; - int sent = send(clientSocket, (const char *)assignBuf, 1, 0); + int sent = send(clientSocket, (const char*)assignBuf, 1, 0); if (sent != 1) { app.DebugPrintf("Failed to send small ID to client\n"); @@ -444,15 +482,15 @@ DWORD WINAPI WinsockNetLayer::AcceptThreadProc(LPVOID param) app.DebugPrintf("Win64 LAN: Client connected, assigned smallId=%d\n", assignedSmallId); - IQNetPlayer *qnetPlayer = &IQNet::m_player[assignedSmallId]; + IQNetPlayer* qnetPlayer = &IQNet::m_player[assignedSmallId]; - extern void Win64_SetupRemoteQNetPlayer(IQNetPlayer *player, BYTE smallId, bool isHost, bool isLocal); + extern void Win64_SetupRemoteQNetPlayer(IQNetPlayer * player, BYTE smallId, bool isHost, bool isLocal); Win64_SetupRemoteQNetPlayer(qnetPlayer, assignedSmallId, false, false); - extern CPlatformNetworkManagerStub *g_pPlatformNetworkManager; + extern CPlatformNetworkManagerStub* g_pPlatformNetworkManager; g_pPlatformNetworkManager->NotifyPlayerJoined(qnetPlayer); - DWORD *threadParam = new DWORD; + DWORD* threadParam = new DWORD; *threadParam = connIdx; HANDLE hThread = CreateThread(NULL, 0, RecvThreadProc, threadParam, 0, NULL); @@ -466,8 +504,8 @@ DWORD WINAPI WinsockNetLayer::AcceptThreadProc(LPVOID param) DWORD WINAPI WinsockNetLayer::RecvThreadProc(LPVOID param) { - DWORD connIdx = *(DWORD *)param; - delete (DWORD *)param; + DWORD connIdx = *(DWORD*)param; + delete (DWORD*)param; EnterCriticalSection(&s_connectionsLock); if (connIdx >= (DWORD)s_connections.size()) @@ -479,7 +517,8 @@ DWORD WINAPI WinsockNetLayer::RecvThreadProc(LPVOID param) BYTE clientSmallId = s_connections[connIdx].smallId; LeaveCriticalSection(&s_connectionsLock); - BYTE *recvBuf = new BYTE[WIN64_NET_RECV_BUFFER_SIZE]; + std::vector recvBuf; + recvBuf.resize(WIN64_NET_RECV_BUFFER_SIZE); while (s_active) { @@ -490,33 +529,47 @@ DWORD WINAPI WinsockNetLayer::RecvThreadProc(LPVOID param) break; } - int packetSize = (header[0] << 24) | (header[1] << 16) | (header[2] << 8) | header[3]; + int packetSize = + ((uint32_t)header[0] << 24) | + ((uint32_t)header[1] << 16) | + ((uint32_t)header[2] << 8) | + ((uint32_t)header[3]); - if (packetSize <= 0 || packetSize > WIN64_NET_RECV_BUFFER_SIZE) + if (packetSize <= 0 || packetSize > WIN64_NET_MAX_PACKET_SIZE) { - app.DebugPrintf("Win64 LAN: Invalid packet size %d from client smallId=%d\n", packetSize, clientSmallId); + app.DebugPrintf("Win64 LAN: Invalid packet size %d from client smallId=%d (max=%d)\n", + packetSize, + clientSmallId, + (int)WIN64_NET_MAX_PACKET_SIZE); break; } - if (!RecvExact(sock, recvBuf, packetSize)) + if ((int)recvBuf.size() < packetSize) + { + recvBuf.resize(packetSize); + app.DebugPrintf("Win64 LAN: Resized host recv buffer to %d bytes for client smallId=%d\n", packetSize, clientSmallId); + } + + if (!RecvExact(sock, &recvBuf[0], packetSize)) { app.DebugPrintf("Win64 LAN: Client smallId=%d disconnected (body)\n", clientSmallId); break; } - HandleDataReceived(clientSmallId, s_hostSmallId, recvBuf, packetSize); + HandleDataReceived(clientSmallId, s_hostSmallId, &recvBuf[0], packetSize); } - delete[] recvBuf; - EnterCriticalSection(&s_connectionsLock); for (size_t i = 0; i < s_connections.size(); i++) { if (s_connections[i].smallId == clientSmallId) { s_connections[i].active = false; - closesocket(s_connections[i].tcpSocket); - s_connections[i].tcpSocket = INVALID_SOCKET; + if (s_connections[i].tcpSocket != INVALID_SOCKET) + { + closesocket(s_connections[i].tcpSocket); + s_connections[i].tcpSocket = INVALID_SOCKET; + } break; } } @@ -529,7 +582,7 @@ DWORD WINAPI WinsockNetLayer::RecvThreadProc(LPVOID param) return 0; } -bool WinsockNetLayer::PopDisconnectedSmallId(BYTE *outSmallId) +bool WinsockNetLayer::PopDisconnectedSmallId(BYTE* outSmallId) { bool found = false; EnterCriticalSection(&s_disconnectLock); @@ -550,9 +603,26 @@ void WinsockNetLayer::PushFreeSmallId(BYTE smallId) LeaveCriticalSection(&s_freeSmallIdLock); } +void WinsockNetLayer::CloseConnectionBySmallId(BYTE smallId) +{ + EnterCriticalSection(&s_connectionsLock); + for (size_t i = 0; i < s_connections.size(); i++) + { + if (s_connections[i].smallId == smallId && s_connections[i].active && s_connections[i].tcpSocket != INVALID_SOCKET) + { + closesocket(s_connections[i].tcpSocket); + s_connections[i].tcpSocket = INVALID_SOCKET; + app.DebugPrintf("Win64 LAN: Force-closed TCP connection for smallId=%d\n", smallId); + break; + } + } + LeaveCriticalSection(&s_connectionsLock); +} + DWORD WINAPI WinsockNetLayer::ClientRecvThreadProc(LPVOID param) { - BYTE *recvBuf = new BYTE[WIN64_NET_RECV_BUFFER_SIZE]; + std::vector recvBuf; + recvBuf.resize(WIN64_NET_RECV_BUFFER_SIZE); while (s_active && s_hostConnectionSocket != INVALID_SOCKET) { @@ -565,28 +635,34 @@ DWORD WINAPI WinsockNetLayer::ClientRecvThreadProc(LPVOID param) int packetSize = (header[0] << 24) | (header[1] << 16) | (header[2] << 8) | header[3]; - if (packetSize <= 0 || packetSize > WIN64_NET_RECV_BUFFER_SIZE) + if (packetSize <= 0 || packetSize > WIN64_NET_MAX_PACKET_SIZE) { - app.DebugPrintf("Win64 LAN: Invalid packet size %d from host\n", packetSize); + app.DebugPrintf("Win64 LAN: Invalid packet size %d from host (max=%d)\n", + packetSize, + (int)WIN64_NET_MAX_PACKET_SIZE); break; } - if (!RecvExact(s_hostConnectionSocket, recvBuf, packetSize)) + if ((int)recvBuf.size() < packetSize) + { + recvBuf.resize(packetSize); + app.DebugPrintf("Win64 LAN: Resized client recv buffer to %d bytes\n", packetSize); + } + + if (!RecvExact(s_hostConnectionSocket, &recvBuf[0], packetSize)) { app.DebugPrintf("Win64 LAN: Disconnected from host (body)\n"); break; } - HandleDataReceived(s_hostSmallId, s_localSmallId, recvBuf, packetSize); + HandleDataReceived(s_hostSmallId, s_localSmallId, &recvBuf[0], packetSize); } - delete[] recvBuf; - s_connected = false; return 0; } -bool WinsockNetLayer::StartAdvertising(int gamePort, const wchar_t *hostName, unsigned int gameSettings, unsigned int texPackId, unsigned char subTexId, unsigned short netVer) +bool WinsockNetLayer::StartAdvertising(int gamePort, const wchar_t* hostName, unsigned int gameSettings, unsigned int texPackId, unsigned char subTexId, unsigned short netVer) { if (s_advertising) return true; if (!s_initialized) return false; @@ -614,7 +690,7 @@ bool WinsockNetLayer::StartAdvertising(int gamePort, const wchar_t *hostName, un } BOOL broadcast = TRUE; - setsockopt(s_advertiseSock, SOL_SOCKET, SO_BROADCAST, (const char *)&broadcast, sizeof(broadcast)); + setsockopt(s_advertiseSock, SOL_SOCKET, SO_BROADCAST, (const char*)&broadcast, sizeof(broadcast)); s_advertising = true; s_advertiseThread = CreateThread(NULL, 0, AdvertiseThreadProc, NULL, 0, NULL); @@ -669,8 +745,8 @@ DWORD WINAPI WinsockNetLayer::AdvertiseThreadProc(LPVOID param) Win64LANBroadcast data = s_advertiseData; LeaveCriticalSection(&s_advertiseLock); - int sent = sendto(s_advertiseSock, (const char *)&data, sizeof(data), 0, - (struct sockaddr *)&broadcastAddr, sizeof(broadcastAddr)); + int sent = sendto(s_advertiseSock, (const char*)&data, sizeof(data), 0, + (struct sockaddr*)&broadcastAddr, sizeof(broadcastAddr)); if (sent == SOCKET_ERROR && s_advertising) { @@ -696,7 +772,7 @@ bool WinsockNetLayer::StartDiscovery() } BOOL reuseAddr = TRUE; - setsockopt(s_discoverySock, SOL_SOCKET, SO_REUSEADDR, (const char *)&reuseAddr, sizeof(reuseAddr)); + setsockopt(s_discoverySock, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuseAddr, sizeof(reuseAddr)); struct sockaddr_in bindAddr; memset(&bindAddr, 0, sizeof(bindAddr)); @@ -704,7 +780,7 @@ bool WinsockNetLayer::StartDiscovery() bindAddr.sin_port = htons(WIN64_LAN_DISCOVERY_PORT); bindAddr.sin_addr.s_addr = INADDR_ANY; - if (::bind(s_discoverySock, (struct sockaddr *)&bindAddr, sizeof(bindAddr)) == SOCKET_ERROR) + if (::bind(s_discoverySock, (struct sockaddr*)&bindAddr, sizeof(bindAddr)) == SOCKET_ERROR) { app.DebugPrintf("Win64 LAN: Discovery bind failed: %d\n", WSAGetLastError()); closesocket(s_discoverySock); @@ -713,7 +789,7 @@ bool WinsockNetLayer::StartDiscovery() } DWORD timeout = 500; - setsockopt(s_discoverySock, SOL_SOCKET, SO_RCVTIMEO, (const char *)&timeout, sizeof(timeout)); + setsockopt(s_discoverySock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout)); s_discovering = true; s_discoveryThread = CreateThread(NULL, 0, DiscoveryThreadProc, NULL, 0, NULL); @@ -763,7 +839,7 @@ DWORD WINAPI WinsockNetLayer::DiscoveryThreadProc(LPVOID param) int senderLen = sizeof(senderAddr); int recvLen = recvfrom(s_discoverySock, recvBuf, sizeof(recvBuf), 0, - (struct sockaddr *)&senderAddr, &senderLen); + (struct sockaddr*)&senderAddr, &senderLen); if (recvLen == SOCKET_ERROR) { @@ -773,7 +849,7 @@ DWORD WINAPI WinsockNetLayer::DiscoveryThreadProc(LPVOID param) if (recvLen < (int)sizeof(Win64LANBroadcast)) continue; - Win64LANBroadcast *broadcast = (Win64LANBroadcast *)recvBuf; + Win64LANBroadcast* broadcast = (Win64LANBroadcast*)recvBuf; if (broadcast->magic != WIN64_LAN_BROADCAST_MAGIC) continue; diff --git a/Minecraft.Client/Windows64/Network/WinsockNetLayer.h b/Minecraft.Client/Windows64/Network/WinsockNetLayer.h index e6b0ff025..bddc83cf8 100644 --- a/Minecraft.Client/Windows64/Network/WinsockNetLayer.h +++ b/Minecraft.Client/Windows64/Network/WinsockNetLayer.h @@ -1,3 +1,5 @@ +// Code implemented by LCEMP, credit if used on other repos +// https://github.com/LCEMP/LCEMP #pragma once #ifdef _WINDOWS64 @@ -12,6 +14,7 @@ #define WIN64_NET_DEFAULT_PORT 25565 #define WIN64_NET_MAX_CLIENTS 7 #define WIN64_NET_RECV_BUFFER_SIZE 65536 +#define WIN64_NET_MAX_PACKET_SIZE (4 * 1024 * 1024) #define WIN64_LAN_DISCOVERY_PORT 25566 #define WIN64_LAN_BROADCAST_MAGIC 0x4D434C4E @@ -62,11 +65,11 @@ public: static bool Initialize(); static void Shutdown(); - static bool HostGame(int port); - static bool JoinGame(const char *ip, int port); + static bool HostGame(int port, const char* bindIp = NULL); + static bool JoinGame(const char* ip, int port); - static bool SendToSmallId(BYTE targetSmallId, const void *data, int dataSize); - static bool SendOnSocket(SOCKET sock, const void *data, int dataSize); + static bool SendToSmallId(BYTE targetSmallId, const void* data, int dataSize); + static bool SendOnSocket(SOCKET sock, const void* data, int dataSize); static bool IsHosting() { return s_isHost; } static bool IsConnected() { return s_connected; } @@ -77,12 +80,13 @@ public: static SOCKET GetSocketForSmallId(BYTE smallId); - static void HandleDataReceived(BYTE fromSmallId, BYTE toSmallId, unsigned char *data, unsigned int dataSize); + static void HandleDataReceived(BYTE fromSmallId, BYTE toSmallId, unsigned char* data, unsigned int dataSize); - static bool PopDisconnectedSmallId(BYTE *outSmallId); + static bool PopDisconnectedSmallId(BYTE* outSmallId); static void PushFreeSmallId(BYTE smallId); + static void CloseConnectionBySmallId(BYTE smallId); - static bool StartAdvertising(int gamePort, const wchar_t *hostName, unsigned int gameSettings, unsigned int texPackId, unsigned char subTexId, unsigned short netVer); + static bool StartAdvertising(int gamePort, const wchar_t* hostName, unsigned int gameSettings, unsigned int texPackId, unsigned char subTexId, unsigned short netVer); static void StopAdvertising(); static void UpdateAdvertisePlayerCount(BYTE count); static void UpdateAdvertiseJoinable(bool joinable); @@ -143,5 +147,8 @@ extern bool g_Win64MultiplayerHost; extern bool g_Win64MultiplayerJoin; extern int g_Win64MultiplayerPort; extern char g_Win64MultiplayerIP[256]; +extern bool g_Win64DedicatedServer; +extern int g_Win64DedicatedServerPort; +extern char g_Win64DedicatedServerBindIP[256]; #endif diff --git a/Minecraft.Client/Windows64/Windows64_App.cpp b/Minecraft.Client/Windows64/Windows64_App.cpp index d09a1b37d..4e91075d0 100644 --- a/Minecraft.Client/Windows64/Windows64_App.cpp +++ b/Minecraft.Client/Windows64/Windows64_App.cpp @@ -10,46 +10,11 @@ #include "Minecraft.World/BiomeSource.h" #include "Minecraft.World/LevelType.h" -wstring g_playerName; - CConsoleMinecraftApp app; -static void LoadPlayerName() -{ - if (!g_playerName.empty()) return; - g_playerName = L"Windows"; - - char exePath[MAX_PATH] = {}; - GetModuleFileNameA(NULL, exePath, MAX_PATH); - char *lastSlash = strrchr(exePath, '\\'); - if (lastSlash) *(lastSlash + 1) = '\0'; - char filePath[MAX_PATH] = {}; - _snprintf_s(filePath, sizeof(filePath), _TRUNCATE, "%susername.txt", exePath); - - FILE *f = NULL; - if (fopen_s(&f, filePath, "r") == 0 && f) - { - char buf[128] = {}; - if (fgets(buf, sizeof(buf), f)) - { - int len = (int)strlen(buf); - while (len > 0 && (buf[len-1] == '\n' || buf[len-1] == '\r' || buf[len-1] == ' ')) - buf[--len] = '\0'; - if (len > 0) - { - wchar_t wbuf[128] = {}; - mbstowcs(wbuf, buf, 127); - g_playerName = wbuf; - } - } - fclose(f); - } -} - CConsoleMinecraftApp::CConsoleMinecraftApp() : CMinecraftApp() { m_bShutdown = false; - LoadPlayerName(); } void CConsoleMinecraftApp::SetRichPresenceContext(int iPad, int contextId) @@ -110,8 +75,8 @@ void CConsoleMinecraftApp::TemporaryCreateGameStart() Minecraft *pMinecraft=Minecraft::GetInstance(); app.ReleaseSaveThumbnail(); ProfileManager.SetLockedProfile(0); - LoadPlayerName(); - pMinecraft->user->name = g_playerName; + extern wchar_t g_Win64UsernameW[17]; + pMinecraft->user->name = g_Win64UsernameW; app.ApplyGameSettingsChanged(0); ////////////////////////////////////////////////////////////////////////////////////////////// From CScene_MultiGameJoinLoad::OnInit diff --git a/Minecraft.Client/Windows64/Windows64_Minecraft.cpp b/Minecraft.Client/Windows64/Windows64_Minecraft.cpp index c6c9d317d..483fe1a1f 100644 --- a/Minecraft.Client/Windows64/Windows64_Minecraft.cpp +++ b/Minecraft.Client/Windows64/Windows64_Minecraft.cpp @@ -4,7 +4,9 @@ #include "stdafx.h" #include +#include #include +#include #include "GameConfig/Minecraft.spa.h" #include "Minecraft.Client/MinecraftServer.h" #include "Minecraft.Client/LocalPlayer.h" @@ -34,6 +36,7 @@ #include "Sentient/SentientManager.h" #include "Minecraft.World/IntCache.h" #include "Minecraft.Client/Textures.h" +#include "Minecraft.Client/Settings.h" #include "Resource.h" #include "Minecraft.World/compression.h" #include "Minecraft.World/OldChunkStorage.h" @@ -85,15 +88,158 @@ BOOL g_bWidescreen = TRUE; int g_iScreenWidth = 1920; int g_iScreenHeight = 1080; -char g_Win64Username[17] = { 0 }; -wchar_t g_Win64UsernameW[17] = { 0 }; UINT g_ScreenWidth = 1920; UINT g_ScreenHeight = 1080; +char g_Win64Username[17] = { 0 }; +wchar_t g_Win64UsernameW[17] = { 0 }; + // Fullscreen toggle state static bool g_isFullscreen = false; static WINDOWPLACEMENT g_wpPrev = { sizeof(g_wpPrev) }; +struct Win64LaunchOptions +{ + int screenMode; + bool serverMode; +}; + +static void CopyWideArgToAnsi(LPCWSTR source, char* dest, size_t destSize) +{ + if (destSize == 0) + return; + + dest[0] = 0; + if (source == NULL) + return; + + WideCharToMultiByte(CP_ACP, 0, source, -1, dest, (int)destSize, NULL, NULL); + dest[destSize - 1] = 0; +} + +static void ApplyScreenMode(int screenMode) +{ + switch (screenMode) + { + case 1: + g_iScreenWidth = 1280; + g_iScreenHeight = 720; + break; + case 2: + g_iScreenWidth = 640; + g_iScreenHeight = 480; + break; + case 3: + g_iScreenWidth = 720; + g_iScreenHeight = 408; + break; + default: + break; + } +} + +static Win64LaunchOptions ParseLaunchOptions() +{ + Win64LaunchOptions options = {}; + options.screenMode = 0; + options.serverMode = false; + + g_Win64MultiplayerJoin = false; + g_Win64MultiplayerPort = WIN64_NET_DEFAULT_PORT; + g_Win64DedicatedServer = false; + g_Win64DedicatedServerPort = WIN64_NET_DEFAULT_PORT; + g_Win64DedicatedServerBindIP[0] = 0; + + int argc = 0; + LPWSTR* argv = CommandLineToArgvW(GetCommandLineW(), &argc); + if (argv == NULL) + return options; + + if (argc > 1 && lstrlenW(argv[1]) == 1) + { + if (argv[1][0] >= L'1' && argv[1][0] <= L'3') + options.screenMode = argv[1][0] - L'0'; + } + + for (int i = 1; i < argc; ++i) + { + if (_wcsicmp(argv[i], L"-server") == 0) + { + options.serverMode = true; + break; + } + } + + g_Win64DedicatedServer = options.serverMode; + + for (int i = 1; i < argc; ++i) + { + if (_wcsicmp(argv[i], L"-name") == 0 && (i + 1) < argc) + { + CopyWideArgToAnsi(argv[++i], g_Win64Username, sizeof(g_Win64Username)); + } + else if (_wcsicmp(argv[i], L"-ip") == 0 && (i + 1) < argc) + { + char ipBuf[256]; + CopyWideArgToAnsi(argv[++i], ipBuf, sizeof(ipBuf)); + if (options.serverMode) + { + strncpy_s(g_Win64DedicatedServerBindIP, sizeof(g_Win64DedicatedServerBindIP), ipBuf, _TRUNCATE); + } + else + { + strncpy_s(g_Win64MultiplayerIP, sizeof(g_Win64MultiplayerIP), ipBuf, _TRUNCATE); + g_Win64MultiplayerJoin = true; + } + } + else if (_wcsicmp(argv[i], L"-port") == 0 && (i + 1) < argc) + { + wchar_t* endPtr = NULL; + long port = wcstol(argv[++i], &endPtr, 10); + if (endPtr != argv[i] && *endPtr == 0 && port > 0 && port <= 65535) + { + if (options.serverMode) + g_Win64DedicatedServerPort = (int)port; + else + g_Win64MultiplayerPort = (int)port; + } + } + } + + LocalFree(argv); + return options; +} + +static BOOL WINAPI HeadlessServerCtrlHandler(DWORD ctrlType) +{ + switch (ctrlType) + { + case CTRL_C_EVENT: + case CTRL_BREAK_EVENT: + case CTRL_CLOSE_EVENT: + case CTRL_SHUTDOWN_EVENT: + app.m_bShutdown = true; + MinecraftServer::HaltServer(); + return TRUE; + default: + return FALSE; + } +} + +static void SetupHeadlessServerConsole() +{ + if (AllocConsole()) + { + FILE* stream = NULL; + freopen_s(&stream, "CONIN$", "r", stdin); + freopen_s(&stream, "CONOUT$", "w", stdout); + freopen_s(&stream, "CONOUT$", "w", stderr); + SetConsoleTitleA("Minecraft Server"); + } + + SetConsoleCtrlHandler(HeadlessServerCtrlHandler, TRUE); +} + void DefineActions(void) { // The app needs to define the actions required, and the possible mappings for these @@ -355,166 +501,90 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) PostQuitMessage(0); break; - // Keyboard/Mouse input handling + case WM_KILLFOCUS: + g_KBMInput.ClearAllState(); + g_KBMInput.SetWindowFocused(false); + if (g_KBMInput.IsMouseGrabbed()) + g_KBMInput.SetMouseGrabbed(false); + break; + + case WM_SETFOCUS: + g_KBMInput.SetWindowFocused(true); + break; + case WM_KEYDOWN: - if (!(lParam & 0x40000000)) // ignore auto-repeat - KMInput.OnKeyDown(wParam); - break; - case WM_KEYUP: - KMInput.OnKeyUp(wParam); - break; case WM_SYSKEYDOWN: - if (wParam == VK_MENU) // Alt key - { - if (!(lParam & 0x40000000)) - KMInput.OnKeyDown(wParam); - return 0; // prevent default Alt behavior - } - return DefWindowProc(hWnd, message, wParam, lParam); - case WM_SYSKEYUP: - if (wParam == VK_MENU) - { - KMInput.OnKeyUp(wParam); - return 0; - } - return DefWindowProc(hWnd, message, wParam, lParam); - case WM_INPUT: - KMInput.OnRawMouseInput(lParam); + { + int vk = (int)wParam; + if (lParam & 0x40000000) break; // ignore auto-repeat + if (vk == VK_SHIFT) + vk = (MapVirtualKey((lParam >> 16) & 0xFF, MAPVK_VSC_TO_VK_EX) == VK_RSHIFT) ? VK_RSHIFT : VK_LSHIFT; + else if (vk == VK_CONTROL) + vk = (lParam & (1 << 24)) ? VK_RCONTROL : VK_LCONTROL; + else if (vk == VK_MENU) + vk = (lParam & (1 << 24)) ? VK_RMENU : VK_LMENU; + g_KBMInput.OnKeyDown(vk); break; + } + case WM_KEYUP: + case WM_SYSKEYUP: + { + int vk = (int)wParam; + if (vk == VK_SHIFT) + vk = (MapVirtualKey((lParam >> 16) & 0xFF, MAPVK_VSC_TO_VK_EX) == VK_RSHIFT) ? VK_RSHIFT : VK_LSHIFT; + else if (vk == VK_CONTROL) + vk = (lParam & (1 << 24)) ? VK_RCONTROL : VK_LCONTROL; + else if (vk == VK_MENU) + vk = (lParam & (1 << 24)) ? VK_RMENU : VK_LMENU; + g_KBMInput.OnKeyUp(vk); + break; + } + case WM_LBUTTONDOWN: - KMInput.OnMouseButton(0, true); + g_KBMInput.OnMouseButtonDown(KeyboardMouseInput::MOUSE_LEFT); break; case WM_LBUTTONUP: - KMInput.OnMouseButton(0, false); + g_KBMInput.OnMouseButtonUp(KeyboardMouseInput::MOUSE_LEFT); break; case WM_RBUTTONDOWN: - KMInput.OnMouseButton(1, true); + g_KBMInput.OnMouseButtonDown(KeyboardMouseInput::MOUSE_RIGHT); break; case WM_RBUTTONUP: - KMInput.OnMouseButton(1, false); + g_KBMInput.OnMouseButtonUp(KeyboardMouseInput::MOUSE_RIGHT); break; case WM_MBUTTONDOWN: - KMInput.OnMouseButton(2, true); + g_KBMInput.OnMouseButtonDown(KeyboardMouseInput::MOUSE_MIDDLE); break; case WM_MBUTTONUP: - KMInput.OnMouseButton(2, false); - break; - case WM_MOUSEWHEEL: - KMInput.OnMouseWheel(GET_WHEEL_DELTA_WPARAM(wParam)); + g_KBMInput.OnMouseButtonUp(KeyboardMouseInput::MOUSE_MIDDLE); break; + case WM_MOUSEMOVE: - KMInput.OnMouseMove(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); + g_KBMInput.OnMouseMove(LOWORD(lParam), HIWORD(lParam)); break; - case WM_ACTIVATE: - if (LOWORD(wParam) == WA_INACTIVE) - KMInput.SetCapture(false); + + case WM_MOUSEWHEEL: + g_KBMInput.OnMouseWheel(GET_WHEEL_DELTA_WPARAM(wParam)); break; - case WM_SETFOCUS: + + case WM_INPUT: { - // Re-capture when window receives focus (e.g., after clicking on it) - Minecraft *pMinecraft = Minecraft::GetInstance(); - bool shouldCapture = pMinecraft && app.GetGameStarted() && !ui.GetMenuDisplayed(0) && pMinecraft->screen == NULL; - if (shouldCapture) - KMInput.SetCapture(true); + UINT dwSize = 0; + GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER)); + if (dwSize > 0 && dwSize <= 256) + { + BYTE rawBuffer[256]; + if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, rawBuffer, &dwSize, sizeof(RAWINPUTHEADER)) == dwSize) + { + RAWINPUT* raw = (RAWINPUT*)rawBuffer; + if (raw->header.dwType == RIM_TYPEMOUSE) + { + g_KBMInput.OnRawMouseDelta(raw->data.mouse.lLastX, raw->data.mouse.lLastY); + } + } + } } break; - case WM_KILLFOCUS: - KMInput.SetCapture(false); - KMInput.ClearAllState(); - break; - - case WM_SETCURSOR: - // Hide the OS cursor when an Iggy/Flash menu is displayed (it has its own Flash cursor) - if (LOWORD(lParam) == HTCLIENT && !KMInput.IsCaptured() && ui.GetMenuDisplayed(0)) - { - SetCursor(NULL); - return TRUE; - } - return DefWindowProc(hWnd, message, wParam, lParam); - case WM_SIZE: - { - if (wParam == SIZE_MINIMIZED) - return 0; - - UINT width = LOWORD(lParam); - UINT height = HIWORD(lParam); - - if (width == 0 || height == 0) - return 0; - - g_ScreenWidth = width; - g_ScreenHeight = height; - - if (g_pSwapChain) - { - g_pImmediateContext->OMSetRenderTargets(0, 0, 0); - g_pImmediateContext->ClearState(); - g_pImmediateContext->Flush(); - - if (g_pRenderTargetView) - { - g_pRenderTargetView->Release(); - g_pRenderTargetView = nullptr; - } - - if (g_pDepthStencilView) - { - g_pDepthStencilView->Release(); - g_pDepthStencilView = nullptr; - } - - if (g_pDepthStencilBuffer) - { - g_pDepthStencilBuffer->Release(); - g_pDepthStencilBuffer = nullptr; - } - - HRESULT hr = g_pSwapChain->ResizeBuffers( - 0, - width, - height, - DXGI_FORMAT_UNKNOWN, - 0 - ); - - if (FAILED(hr)) - { - app.DebugPrintf("ResizeBuffers Failed! HRESULT: 0x%X\n", hr); - return 0; - } - - ID3D11Texture2D* pBackBuffer = nullptr; - g_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&pBackBuffer); - - g_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, &g_pRenderTargetView); - pBackBuffer->Release(); - - D3D11_TEXTURE2D_DESC descDepth = {}; - descDepth.Width = width; - descDepth.Height = height; - descDepth.MipLevels = 1; - descDepth.ArraySize = 1; - descDepth.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; - descDepth.SampleDesc.Count = 1; - descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL; - - g_pd3dDevice->CreateTexture2D(&descDepth, NULL, &g_pDepthStencilBuffer); - g_pd3dDevice->CreateDepthStencilView(g_pDepthStencilBuffer, NULL, &g_pDepthStencilView); - - g_pImmediateContext->OMSetRenderTargets(1, &g_pRenderTargetView, g_pDepthStencilView); - - D3D11_VIEWPORT vp = {}; - vp.Width = (FLOAT)width; - vp.Height = (FLOAT)height; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - - g_pImmediateContext->RSSetViewports(1, &vp); - } - } - break; default: return DefWindowProc(hWnd, message, wParam, lParam); } @@ -790,6 +860,9 @@ void ToggleFullscreen() SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_FRAMECHANGED); } g_isFullscreen = !g_isFullscreen; + + if (g_KBMInput.IsWindowFocused()) + g_KBMInput.SetWindowFocused(true); } //-------------------------------------------------------------------------------------- @@ -805,6 +878,225 @@ void CleanupDevice() if( g_pd3dDevice ) g_pd3dDevice->Release(); } +static Minecraft* InitialiseMinecraftRuntime() +{ + app.loadMediaArchive(); + + RenderManager.Initialise(g_pd3dDevice, g_pSwapChain); + + app.loadStringTable(); + ui.init(g_pd3dDevice, g_pImmediateContext, g_pRenderTargetView, g_pDepthStencilView, g_iScreenWidth, g_iScreenHeight); + + InputManager.Initialise(1, 3, MINECRAFT_ACTION_MAX, ACTION_MAX_MENU); + g_KBMInput.Init(); + DefineActions(); + InputManager.SetJoypadMapVal(0, 0); + InputManager.SetKeyRepeatRate(0.3f, 0.2f); + + ProfileManager.Initialise(TITLEID_MINECRAFT, + app.m_dwOfferID, + PROFILE_VERSION_10, + NUM_PROFILE_VALUES, + NUM_PROFILE_SETTINGS, + dwProfileSettingsA, + app.GAME_DEFINED_PROFILE_DATA_BYTES * XUSER_MAX_COUNT, + &app.uiGameDefinedDataChangedBitmask + ); + ProfileManager.SetDefaultOptionsCallback(&CConsoleMinecraftApp::DefaultOptionsCallback, (LPVOID)&app); + + g_NetworkManager.Initialise(); + + for (int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; i++) + { + IQNet::m_player[i].m_smallId = (BYTE)i; + IQNet::m_player[i].m_isRemote = false; + IQNet::m_player[i].m_isHostPlayer = (i == 0); + swprintf_s(IQNet::m_player[i].m_gamertag, 32, L"Player%d", i); + } + wcscpy_s(IQNet::m_player[0].m_gamertag, 32, g_Win64UsernameW); + + WinsockNetLayer::Initialize(); + + ProfileManager.SetDebugFullOverride(true); + + Tesselator::CreateNewThreadStorage(1024 * 1024); + AABB::CreateNewThreadStorage(); + Vec3::CreateNewThreadStorage(); + IntCache::CreateNewThreadStorage(); + Compression::CreateNewThreadStorage(); + OldChunkStorage::CreateNewThreadStorage(); + Level::enableLightingCache(); + Tile::CreateNewThreadStorage(); + + Minecraft::main(); + Minecraft* pMinecraft = Minecraft::GetInstance(); + if (pMinecraft == NULL) + return NULL; + + app.InitGameSettings(); + app.InitialiseTips(); + + pMinecraft->options->set(Options::Option::MUSIC, 1.0f); + pMinecraft->options->set(Options::Option::SOUND, 1.0f); + + return pMinecraft; +} + +static int HeadlessServerConsoleThreadProc(void* lpParameter) +{ + UNREFERENCED_PARAMETER(lpParameter); + + std::string line; + while (!app.m_bShutdown) + { + if (!std::getline(std::cin, line)) + { + if (std::cin.eof()) + { + break; + } + + std::cin.clear(); + Sleep(50); + continue; + } + + wstring command = trimString(convStringToWstring(line)); + if (command.empty()) + continue; + + MinecraftServer* server = MinecraftServer::getInstance(); + if (server != NULL) + { + server->handleConsoleInput(command, server); + } + } + + return 0; +} + +static int RunHeadlessServer() +{ + SetupHeadlessServerConsole(); + + Settings serverSettings(new File(L"server.properties")); + wstring configuredBindIp = serverSettings.getString(L"server-ip", L""); + + const char* bindIp = "*"; + if (g_Win64DedicatedServerBindIP[0] != 0) + { + bindIp = g_Win64DedicatedServerBindIP; + } + else if (!configuredBindIp.empty()) + { + bindIp = wstringtochararray(configuredBindIp); + } + + const int port = g_Win64DedicatedServerPort > 0 ? g_Win64DedicatedServerPort : serverSettings.getInt(L"server-port", WIN64_NET_DEFAULT_PORT); + + printf("Starting headless server on %s:%d\n", bindIp, port); + fflush(stdout); + + Minecraft* pMinecraft = InitialiseMinecraftRuntime(); + if (pMinecraft == NULL) + { + fprintf(stderr, "Failed to initialise the Minecraft runtime.\n"); + return 1; + } + + app.SetGameHostOption(eGameHostOption_Difficulty, serverSettings.getInt(L"difficulty", 1)); + app.SetGameHostOption(eGameHostOption_Gamertags, 1); + app.SetGameHostOption(eGameHostOption_GameType, serverSettings.getInt(L"gamemode", 0)); + app.SetGameHostOption(eGameHostOption_LevelType, 0); + app.SetGameHostOption(eGameHostOption_Structures, serverSettings.getBoolean(L"generate-structures", true) ? 1 : 0); + app.SetGameHostOption(eGameHostOption_BonusChest, serverSettings.getBoolean(L"bonus-chest", false) ? 1 : 0); + app.SetGameHostOption(eGameHostOption_PvP, serverSettings.getBoolean(L"pvp", true) ? 1 : 0); + app.SetGameHostOption(eGameHostOption_TrustPlayers, serverSettings.getBoolean(L"trust-players", true) ? 1 : 0); + app.SetGameHostOption(eGameHostOption_FireSpreads, serverSettings.getBoolean(L"fire-spreads", true) ? 1 : 0); + app.SetGameHostOption(eGameHostOption_TNT, serverSettings.getBoolean(L"tnt", true) ? 1 : 0); + app.SetGameHostOption(eGameHostOption_HostCanFly, 1); + app.SetGameHostOption(eGameHostOption_HostCanChangeHunger, 1); + app.SetGameHostOption(eGameHostOption_HostCanBeInvisible, 1); + app.SetGameHostOption(eGameHostOption_MobGriefing, 1); + app.SetGameHostOption(eGameHostOption_KeepInventory, 0); + app.SetGameHostOption(eGameHostOption_DoMobSpawning, 1); + app.SetGameHostOption(eGameHostOption_DoMobLoot, 1); + app.SetGameHostOption(eGameHostOption_DoTileDrops, 1); + app.SetGameHostOption(eGameHostOption_NaturalRegeneration, 1); + app.SetGameHostOption(eGameHostOption_DoDaylightCycle, 1); + + MinecraftServer::resetFlags(); + g_NetworkManager.HostGame(0, false, true, MINECRAFT_NET_MAX_PLAYERS, 0); + + if (!WinsockNetLayer::IsActive()) + { + fprintf(stderr, "Failed to bind the server socket on %s:%d.\n", bindIp, port); + return 1; + } + + g_NetworkManager.FakeLocalPlayerJoined(); + + NetworkGameInitData* param = new NetworkGameInitData(); + param->seed = 0; + param->settings = app.GetGameHostOption(eGameHostOption_All); + + g_NetworkManager.ServerStoppedCreate(true); + g_NetworkManager.ServerReadyCreate(true); + + C4JThread* thread = new C4JThread(&CGameNetworkManager::ServerThreadProc, param, "Server", 256 * 1024); + thread->SetProcessor(CPU_CORE_SERVER); + thread->Run(); + + g_NetworkManager.ServerReadyWait(); + g_NetworkManager.ServerReadyDestroy(); + + if (MinecraftServer::serverHalted()) + { + fprintf(stderr, "The server halted during startup.\n"); + g_NetworkManager.LeaveGame(false); + return 1; + } + + app.SetGameStarted(true); + g_NetworkManager.DoWork(); + + printf("Server ready on %s:%d\n", bindIp, port); + printf("Type 'help' for server commands.\n"); + fflush(stdout); + + C4JThread* consoleThread = new C4JThread(&HeadlessServerConsoleThreadProc, NULL, "Server console", 128 * 1024); + consoleThread->Run(); + + MSG msg = { 0 }; + while (WM_QUIT != msg.message && !app.m_bShutdown && !MinecraftServer::serverHalted()) + { + if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + continue; + } + + app.UpdateTime(); + ProfileManager.Tick(); + StorageManager.Tick(); + RenderManager.Tick(); + ui.tick(); + g_NetworkManager.DoWork(); + app.HandleXuiActions(); + + Sleep(10); + } + + printf("Stopping server...\n"); + fflush(stdout); + + app.m_bShutdown = true; + MinecraftServer::HaltServer(); + g_NetworkManager.LeaveGame(false); + return 0; +} + int APIENTRY _tWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPTSTR lpCmdLine, @@ -826,60 +1118,47 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance, g_iScreenWidth = GetSystemMetrics(SM_CXSCREEN); g_iScreenHeight = GetSystemMetrics(SM_CYSCREEN); - if(lpCmdLine) - { - if(lpCmdLine[0] == '1') - { - g_iScreenWidth = 1280; - g_iScreenHeight = 720; - } - else if(lpCmdLine[0] == '2') - { - g_iScreenWidth = 640; - g_iScreenHeight = 480; - } - else if(lpCmdLine[0] == '3') - { - // Vita - g_iScreenWidth = 720; - g_iScreenHeight = 408; + // Load username from username.txt + char exePath[MAX_PATH] = {}; + GetModuleFileNameA(NULL, exePath, MAX_PATH); + char *lastSlash = strrchr(exePath, '\\'); + if (lastSlash) + { + *(lastSlash + 1) = '\0'; + } - // Vita native - //g_iScreenWidth = 960; - //g_iScreenHeight = 544; - } + char filePath[MAX_PATH] = {}; + _snprintf_s(filePath, sizeof(filePath), _TRUNCATE, "%susername.txt", exePath); - char cmdLineA[1024]; - strncpy_s(cmdLineA, sizeof(cmdLineA), lpCmdLine, _TRUNCATE); + FILE *f = nullptr; + if (fopen_s(&f, filePath, "r") == 0 && f) + { + char buf[128] = {}; + if (fgets(buf, sizeof(buf), f)) + { + int len = (int)strlen(buf); + while (len > 0 && (buf[len - 1] == '\n' || buf[len - 1] == '\r' || buf[len - 1] == ' ')) + { + buf[--len] = '\0'; + } - char* nameArg = strstr(cmdLineA, "-name "); - if (nameArg) - { - nameArg += 6; - while (*nameArg == ' ') nameArg++; - char nameBuf[17]; - int n = 0; - while (nameArg[n] && nameArg[n] != ' ' && n < 16) { nameBuf[n] = nameArg[n]; n++; } - nameBuf[n] = 0; - strncpy_s(g_Win64Username, 17, nameBuf, _TRUNCATE); - } - } + if (len > 0) + { + strncpy_s(g_Win64Username, sizeof(g_Win64Username), buf, _TRUNCATE); + } + } + fclose(f); + } + // Load stuff from launch options, including username + Win64LaunchOptions launchOptions = ParseLaunchOptions(); + ApplyScreenMode(launchOptions.screenMode); + + // If no username, let's fall back if (g_Win64Username[0] == 0) { - DWORD sz = 17; - static bool seeded = false; - if (!seeded) - { - seeded = true; - srand((unsigned int)time(NULL)); - } - - int r = rand() % 10000; // 0�9999 - - snprintf(g_Win64Username, 17, "Player%04d", r); - - g_Win64Username[16] = 0; + // Default username will be "Player" + strncpy_s(g_Win64Username, sizeof(g_Win64Username), "Player", _TRUNCATE); } MultiByteToWideChar(CP_ACP, 0, g_Win64Username, -1, g_Win64UsernameW, 17); @@ -888,7 +1167,7 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance, MyRegisterClass(hInstance); // Perform application initialization: - if (!InitInstance (hInstance, nCmdShow)) + if (!InitInstance (hInstance, launchOptions.serverMode ? SW_HIDE : nCmdShow)) { return FALSE; } @@ -901,6 +1180,13 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance, return 0; } + if (launchOptions.serverMode) + { + int serverResult = RunHeadlessServer(); + CleanupDevice(); + return serverResult; + } + #if 0 // Main message loop MSG msg = {0}; @@ -953,202 +1239,12 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance, } #endif - app.loadMediaArchive(); - - RenderManager.Initialise(g_pd3dDevice, g_pSwapChain); - - app.loadStringTable(); - ui.init(g_pd3dDevice,g_pImmediateContext,g_pRenderTargetView,g_pDepthStencilView,g_iScreenWidth,g_iScreenHeight); - - //////////////// - // Initialise // - //////////////// - - // Set the number of possible joypad layouts that the user can switch between, and the number of actions - InputManager.Initialise(1,3,MINECRAFT_ACTION_MAX, ACTION_MAX_MENU); - - // Initialize keyboard/mouse input - KMInput.Init(g_hWnd); - - // Set the default joypad action mappings for Minecraft - DefineActions(); - InputManager.SetJoypadMapVal(0,0); - InputManager.SetKeyRepeatRate(0.3f,0.2f); - - // Initialise the profile manager with the game Title ID, Offer ID, a profile version number, and the number of profile values and settings - ProfileManager.Initialise(TITLEID_MINECRAFT, - app.m_dwOfferID, - PROFILE_VERSION_10, - NUM_PROFILE_VALUES, - NUM_PROFILE_SETTINGS, - dwProfileSettingsA, - app.GAME_DEFINED_PROFILE_DATA_BYTES*XUSER_MAX_COUNT, - &app.uiGameDefinedDataChangedBitmask - ); -#if 0 - // register the awards - ProfileManager.RegisterAward(eAward_TakingInventory, ACHIEVEMENT_01, eAwardType_Achievement); - ProfileManager.RegisterAward(eAward_GettingWood, ACHIEVEMENT_02, eAwardType_Achievement); - ProfileManager.RegisterAward(eAward_Benchmarking, ACHIEVEMENT_03, eAwardType_Achievement); - ProfileManager.RegisterAward(eAward_TimeToMine, ACHIEVEMENT_04, eAwardType_Achievement); - ProfileManager.RegisterAward(eAward_HotTopic, ACHIEVEMENT_05, eAwardType_Achievement); - ProfileManager.RegisterAward(eAward_AquireHardware, ACHIEVEMENT_06, eAwardType_Achievement); - ProfileManager.RegisterAward(eAward_TimeToFarm, ACHIEVEMENT_07, eAwardType_Achievement); - ProfileManager.RegisterAward(eAward_BakeBread, ACHIEVEMENT_08, eAwardType_Achievement); - ProfileManager.RegisterAward(eAward_TheLie, ACHIEVEMENT_09, eAwardType_Achievement); - ProfileManager.RegisterAward(eAward_GettingAnUpgrade, ACHIEVEMENT_10, eAwardType_Achievement); - ProfileManager.RegisterAward(eAward_DeliciousFish, ACHIEVEMENT_11, eAwardType_Achievement); - ProfileManager.RegisterAward(eAward_OnARail, ACHIEVEMENT_12, eAwardType_Achievement); - ProfileManager.RegisterAward(eAward_TimeToStrike, ACHIEVEMENT_13, eAwardType_Achievement); - ProfileManager.RegisterAward(eAward_MonsterHunter, ACHIEVEMENT_14, eAwardType_Achievement); - ProfileManager.RegisterAward(eAward_CowTipper, ACHIEVEMENT_15, eAwardType_Achievement); - ProfileManager.RegisterAward(eAward_WhenPigsFly, ACHIEVEMENT_16, eAwardType_Achievement); - ProfileManager.RegisterAward(eAward_LeaderOfThePack, ACHIEVEMENT_17, eAwardType_Achievement); - ProfileManager.RegisterAward(eAward_MOARTools, ACHIEVEMENT_18, eAwardType_Achievement); - ProfileManager.RegisterAward(eAward_DispenseWithThis, ACHIEVEMENT_19, eAwardType_Achievement); - ProfileManager.RegisterAward(eAward_InToTheNether, ACHIEVEMENT_20, eAwardType_Achievement); - - ProfileManager.RegisterAward(eAward_mine100Blocks, GAMER_PICTURE_GAMERPIC1, eAwardType_GamerPic,false,app.GetStringTable(),IDS_AWARD_TITLE,IDS_AWARD_GAMERPIC1,IDS_CONFIRM_OK); - ProfileManager.RegisterAward(eAward_kill10Creepers, GAMER_PICTURE_GAMERPIC2, eAwardType_GamerPic,false,app.GetStringTable(),IDS_AWARD_TITLE,IDS_AWARD_GAMERPIC2,IDS_CONFIRM_OK); - - ProfileManager.RegisterAward(eAward_eatPorkChop, AVATARASSETAWARD_PORKCHOP_TSHIRT, eAwardType_AvatarItem,false,app.GetStringTable(),IDS_AWARD_TITLE,IDS_AWARD_AVATAR1,IDS_CONFIRM_OK); - ProfileManager.RegisterAward(eAward_play100Days, AVATARASSETAWARD_WATCH, eAwardType_AvatarItem,false,app.GetStringTable(),IDS_AWARD_TITLE,IDS_AWARD_AVATAR2,IDS_CONFIRM_OK); - ProfileManager.RegisterAward(eAward_arrowKillCreeper, AVATARASSETAWARD_CAP, eAwardType_AvatarItem,false,app.GetStringTable(),IDS_AWARD_TITLE,IDS_AWARD_AVATAR3,IDS_CONFIRM_OK); - - ProfileManager.RegisterAward(eAward_socialPost, 0, eAwardType_Theme,false,app.GetStringTable(),IDS_AWARD_TITLE,IDS_AWARD_THEME,IDS_CONFIRM_OK,THEME_NAME,THEME_FILESIZE); - - // Rich Presence init - number of presences, number of contexts - ProfileManager.RichPresenceInit(4,1); - ProfileManager.RegisterRichPresenceContext(CONTEXT_GAME_STATE); - - // initialise the storage manager with a default save display name, a Minimum save size, and a callback for displaying the saving message - StorageManager.Init(app.GetString(IDS_DEFAULT_SAVENAME),"savegame.dat",FIFTY_ONE_MB,&CConsoleMinecraftApp::DisplaySavingMessage,(LPVOID)&app); - // Set up the global title storage path - StorageManager.StoreTMSPathName(); - - // set a function to be called when there's a sign in change, so we can exit a level if the primary player signs out - ProfileManager.SetSignInChangeCallback(&CConsoleMinecraftApp::SignInChangeCallback,(LPVOID)&app); - - // set a function to be called when the ethernet is disconnected, so we can back out if required - ProfileManager.SetNotificationsCallback(&CConsoleMinecraftApp::NotificationsCallback,(LPVOID)&app); - -#endif - // Set a callback for the default player options to be set - when there is no profile data for the player - ProfileManager.SetDefaultOptionsCallback(&CConsoleMinecraftApp::DefaultOptionsCallback,(LPVOID)&app); -#if 0 - // Set a callback to deal with old profile versions needing updated to new versions - ProfileManager.SetOldProfileVersionCallback(&CConsoleMinecraftApp::OldProfileVersionCallback,(LPVOID)&app); - - // Set a callback for when there is a read error on profile data - ProfileManager.SetProfileReadErrorCallback(&CConsoleMinecraftApp::ProfileReadErrorCallback,(LPVOID)&app); - -#endif - // QNet needs to be setup after profile manager, as we do not want its Notify listener to handle - // XN_SYS_SIGNINCHANGED notifications. This does mean that we need to have a callback in the - // ProfileManager for XN_LIVE_INVITE_ACCEPTED for QNet. - g_NetworkManager.Initialise(); - - for (int i = 0; i < MINECRAFT_NET_MAX_PLAYERS; i++) + Minecraft *pMinecraft = InitialiseMinecraftRuntime(); + if (pMinecraft == NULL) { - IQNet::m_player[i].m_smallId = (BYTE)i; - IQNet::m_player[i].m_isRemote = false; - IQNet::m_player[i].m_isHostPlayer = (i == 0); - swprintf_s(IQNet::m_player[i].m_gamertag, 32, L"Player%d", i); + CleanupDevice(); + return 1; } - extern wchar_t g_Win64UsernameW[17]; - wcscpy_s(IQNet::m_player[0].m_gamertag, 32, g_Win64UsernameW); - - WinsockNetLayer::Initialize(); - - // 4J-PB moved further down - //app.InitGameSettings(); - - // debug switch to trial version - ProfileManager.SetDebugFullOverride(true); - -#if 0 - //ProfileManager.AddDLC(2); - StorageManager.SetDLCPackageRoot("DLCDrive"); - StorageManager.RegisterMarketplaceCountsCallback(&CConsoleMinecraftApp::MarketplaceCountsCallback,(LPVOID)&app); - // Kinect ! - - if(XNuiGetHardwareStatus()!=0) - { - // If the Kinect Sensor is not physically connected, this function returns 0. - NuiInitialize(NUI_INITIALIZE_FLAG_USES_HIGH_QUALITY_COLOR | NUI_INITIALIZE_FLAG_USES_DEPTH | - NUI_INITIALIZE_FLAG_EXTRAPOLATE_FLOOR_PLANE | NUI_INITIALIZE_FLAG_USES_FITNESS | NUI_INITIALIZE_FLAG_NUI_GUIDE_DISABLED | NUI_INITIALIZE_FLAG_SUPPRESS_AUTOMATIC_UI,NUI_INITIALIZE_DEFAULT_HARDWARE_THREAD ); - } - - // Sentient ! - hr = TelemetryManager->Init(); - -#endif - // Initialise TLS for tesselator, for this main thread - Tesselator::CreateNewThreadStorage(1024*1024); - // Initialise TLS for AABB and Vec3 pools, for this main thread - AABB::CreateNewThreadStorage(); - Vec3::CreateNewThreadStorage(); - IntCache::CreateNewThreadStorage(); - Compression::CreateNewThreadStorage(); - OldChunkStorage::CreateNewThreadStorage(); - Level::enableLightingCache(); - Tile::CreateNewThreadStorage(); - - Minecraft::main(); - Minecraft *pMinecraft=Minecraft::GetInstance(); - - app.InitGameSettings(); - -#if 0 - //bool bDisplayPauseMenu=false; - - // set the default gamma level - float fVal=50.0f*327.68f; - RenderManager.UpdateGamma((unsigned short)fVal); - - // load any skins - //app.AddSkinsToMemoryTextureFiles(); - - // set the achievement text for a trial achievement, now we have the string table loaded - ProfileManager.SetTrialTextStringTable(app.GetStringTable(),IDS_CONFIRM_OK, IDS_CONFIRM_CANCEL); - ProfileManager.SetTrialAwardText(eAwardType_Achievement,IDS_UNLOCK_TITLE,IDS_UNLOCK_ACHIEVEMENT_TEXT); - ProfileManager.SetTrialAwardText(eAwardType_GamerPic,IDS_UNLOCK_TITLE,IDS_UNLOCK_GAMERPIC_TEXT); - ProfileManager.SetTrialAwardText(eAwardType_AvatarItem,IDS_UNLOCK_TITLE,IDS_UNLOCK_AVATAR_TEXT); - ProfileManager.SetTrialAwardText(eAwardType_Theme,IDS_UNLOCK_TITLE,IDS_UNLOCK_THEME_TEXT); - ProfileManager.SetUpsellCallback(&app.UpsellReturnedCallback,&app); - - // Set up a debug character press sequence -#ifndef _FINAL_BUILD - app.SetDebugSequence("LRLRYYY"); -#endif - - // Initialise the social networking manager. - CSocialManager::Instance()->Initialise(); - - // Update the base scene quick selects now that the minecraft class exists - //CXuiSceneBase::UpdateScreenSettings(0); -#endif - app.InitialiseTips(); -#if 0 - - DWORD initData=0; - -#ifndef _FINAL_BUILD -#ifndef _DEBUG -#pragma message(__LOC__"Need to define the _FINAL_BUILD before submission") -#endif -#endif - - // Set the default sound levels - pMinecraft->options->set(Options::Option::MUSIC,1.0f); - pMinecraft->options->set(Options::Option::SOUND,1.0f); - - app.NavigateToScene(XUSER_INDEX_ANY,eUIScene_Intro,&initData); -#endif - - // Set the default sound levels - pMinecraft->options->set(Options::Option::MUSIC,1.0f); - pMinecraft->options->set(Options::Option::SOUND,1.0f); //app.TemporaryCreateGameStart(); @@ -1178,12 +1274,16 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance, MSG msg = {0}; while( WM_QUIT != msg.message && !app.m_bShutdown) { - if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) + g_KBMInput.Tick(); + + while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); - continue; + if (msg.message == WM_QUIT) break; } + if (msg.message == WM_QUIT) break; + RenderManager.StartFrame(); #if 0 if(pMinecraft->soundEngine->isStreamingWavebankReady() && @@ -1205,7 +1305,34 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance, app.UpdateTime(); PIXBeginNamedEvent(0,"Input manager tick"); InputManager.Tick(); - KMInput.Tick(); + + // Detect KBM vs controller input mode + if (InputManager.IsPadConnected(0)) + { + bool controllerUsed = InputManager.ButtonPressed(0) || + InputManager.GetJoypadStick_LX(0, false) != 0.0f || + InputManager.GetJoypadStick_LY(0, false) != 0.0f || + InputManager.GetJoypadStick_RX(0, false) != 0.0f || + InputManager.GetJoypadStick_RY(0, false) != 0.0f; + + if (controllerUsed) + g_KBMInput.SetKBMActive(false); + else if (g_KBMInput.HasAnyInput()) + g_KBMInput.SetKBMActive(true); + } + else + { + g_KBMInput.SetKBMActive(true); + } + + if (!g_KBMInput.IsMouseGrabbed()) + { + if (!g_KBMInput.IsKBMActive()) + g_KBMInput.SetCursorHiddenForUI(true); + else if (!g_KBMInput.IsScreenCursorHidden()) + g_KBMInput.SetCursorHiddenForUI(false); + } + PIXEndNamedEvent(); PIXBeginNamedEvent(0,"Profile manager tick"); // ProfileManager.Tick(); @@ -1335,85 +1462,88 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance, ui.CheckMenuDisplayed(); - // Update mouse capture: capture when in-game and no menu is open + // Update mouse grab: grab when in-game and no menu is open { static bool altToggleSuppressCapture = false; bool shouldCapture = app.GetGameStarted() && !ui.GetMenuDisplayed(0) && pMinecraft->screen == NULL; // Left Alt key toggles capture on/off for debugging - if (KMInput.IsKeyPressed(VK_MENU)) + if (g_KBMInput.IsKeyPressed(VK_LMENU) || g_KBMInput.IsKeyPressed(VK_RMENU)) { - if (KMInput.IsCaptured()) { KMInput.SetCapture(false); altToggleSuppressCapture = true; } - else if (shouldCapture) { KMInput.SetCapture(true); altToggleSuppressCapture = false; } + if (g_KBMInput.IsMouseGrabbed()) { g_KBMInput.SetMouseGrabbed(false); altToggleSuppressCapture = true; } + else if (shouldCapture) { g_KBMInput.SetMouseGrabbed(true); altToggleSuppressCapture = false; } } else if (!shouldCapture) { - if (KMInput.IsCaptured()) KMInput.SetCapture(false); + if (g_KBMInput.IsMouseGrabbed()) g_KBMInput.SetMouseGrabbed(false); altToggleSuppressCapture = false; } - else if (shouldCapture && !KMInput.IsCaptured() && GetFocus() == g_hWnd && !altToggleSuppressCapture) + else if (shouldCapture && !g_KBMInput.IsMouseGrabbed() && GetFocus() == g_hWnd && !altToggleSuppressCapture) { - KMInput.SetCapture(true); + g_KBMInput.SetMouseGrabbed(true); } } - // F3 toggles the debug console overlay, F11 toggles fullscreen - if (KMInput.IsKeyPressed(VK_F3)) + // F1 toggles the HUD + if (g_KBMInput.IsKeyPressed(VK_F1)) { - static bool s_debugConsole = false; - s_debugConsole = !s_debugConsole; - ui.ShowUIDebugConsole(s_debugConsole); + int primaryPad = ProfileManager.GetPrimaryPad(); + unsigned char displayHud = app.GetGameSettings(primaryPad, eGameSetting_DisplayHUD); + app.SetGameSettings(primaryPad, eGameSetting_DisplayHUD, displayHud ? 0 : 1); + app.SetGameSettings(primaryPad, eGameSetting_DisplayHand, displayHud ? 0 : 1); } -#ifdef _DEBUG_MENUS_ENABLED - if (KMInput.IsKeyPressed(VK_F4)) - { - ui.NavigateToScene(ProfileManager.GetPrimaryPad(), eUIScene_DebugOverlay, NULL, eUILayer_Debug); - } -#endif - - if (KMInput.IsKeyPressed(VK_F11)) - { - ToggleFullscreen(); - } - - // TAB opens game info menu. - Vvis :3 - Updated by detectiveren - if (KMInput.IsKeyPressed(VK_TAB) && !ui.GetMenuDisplayed(0)) - { - if (Minecraft* pMinecraft = Minecraft::GetInstance()) - { - { - ui.NavigateToScene(0, eUIScene_InGameInfoMenu); - - } - } - } - -#ifdef _DEBUG_MENUS_ENABLED // F3 toggles onscreen debug info - if (KMInput.IsKeyPressed(VK_F3)) + if (g_KBMInput.IsKeyPressed(VK_F3)) { if (Minecraft* pMinecraft = Minecraft::GetInstance()) { - if (pMinecraft->options && app.DebugSettingsOn()) + if (pMinecraft->options) { pMinecraft->options->renderDebug = !pMinecraft->options->renderDebug; } } } - // F4 opens debug overlay - if (KMInput.IsKeyPressed(VK_F4)) +#ifdef _DEBUG_MENUS_ENABLED + // F4 Open debug overlay + if (g_KBMInput.IsKeyPressed(VK_F4)) + { + if (Minecraft *pMinecraft = Minecraft::GetInstance()) + { + if (pMinecraft->options && + app.GetGameStarted() && !ui.GetMenuDisplayed(0) && pMinecraft->screen == NULL) + { + ui.NavigateToScene(0, eUIScene_DebugOverlay, NULL, eUILayer_Debug); + } + } + } + + // F6 Open debug console + if (g_KBMInput.IsKeyPressed(VK_F6)) + { + static bool s_debugConsole = false; + s_debugConsole = !s_debugConsole; + ui.ShowUIDebugConsole(s_debugConsole); + } +#endif + + // F11 Toggle fullscreen + if (g_KBMInput.IsKeyPressed(VK_F11)) + { + ToggleFullscreen(); + } + + // TAB opens game info menu. - Vvis :3 - Updated by detectiveren + if (g_KBMInput.IsKeyPressed(VK_TAB) && !ui.GetMenuDisplayed(0)) { if (Minecraft* pMinecraft = Minecraft::GetInstance()) { - if (pMinecraft->options && app.DebugSettingsOn() && - app.GetGameStarted() && !ui.GetMenuDisplayed(0) && pMinecraft->screen == NULL) { - ui.NavigateToScene(0, eUIScene_DebugOverlay, NULL, eUILayer_Debug); + ui.NavigateToScene(0, eUIScene_InGameInfoMenu); + } } } -#endif #if 0 // has the game defined profile data been changed (by a profile load) @@ -1505,8 +1635,6 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance, // Fix for #7318 - Title crashes after short soak in the leaderboards menu // A memory leak was caused because the icon renderer kept creating new Vec3's because the pool wasn't reset Vec3::resetPool(); - - KMInput.EndFrame(); } // Free resources, unregister custom classes, and exit. @@ -1701,4 +1829,4 @@ void MemPixStuff() PIXAddNamedCounter(((float)allSectsTotal)/(4096.0f),"MemSect total pages"); } -#endif \ No newline at end of file +#endif diff --git a/Minecraft.Client/Windows64Media/Media/Tutorial.pck b/Minecraft.Client/Windows64Media/Tutorial/Tutorial.pck similarity index 100% rename from Minecraft.Client/Windows64Media/Media/Tutorial.pck rename to Minecraft.Client/Windows64Media/Tutorial/Tutorial.pck diff --git a/Minecraft.Client/Xbox/Docs/Ratings_Submission_Form.doc b/Minecraft.Client/Xbox/Docs/Ratings_Submission_Form.doc index 91d965bd3..2b87aa854 100644 Binary files a/Minecraft.Client/Xbox/Docs/Ratings_Submission_Form.doc and b/Minecraft.Client/Xbox/Docs/Ratings_Submission_Form.doc differ diff --git a/Minecraft.Client/Xbox/Xbox_App.cpp b/Minecraft.Client/Xbox/Xbox_App.cpp index f604d7b06..42fe4cde9 100644 --- a/Minecraft.Client/Xbox/Xbox_App.cpp +++ b/Minecraft.Client/Xbox/Xbox_App.cpp @@ -1658,7 +1658,8 @@ HRESULT CConsoleMinecraftApp::NavigateToScene(int iPad,EUIScene eScene, void *in // If you're navigating to the multigamejoinload, and the player hasn't seen the updates message yet, display it now // display this message the first 3 times - if((eScene==eUIScene_LoadOrJoinMenu) && (bSeenUpdateTextThisSession==false) && ( app.GetGameSettings(ProfileManager.GetPrimaryPad(),eGameSetting_DisplayUpdateMessage)!=0)) + // todo: re-enable if we fix this menu, for now its just blank! + if(false && (eScene==eUIScene_LoadOrJoinMenu) && (bSeenUpdateTextThisSession==false) && ( app.GetGameSettings(ProfileManager.GetPrimaryPad(),eGameSetting_DisplayUpdateMessage)!=0)) { eScene=eUIScene_NewUpdateMessage; bSeenUpdateTextThisSession=true; diff --git a/Minecraft.Client/glWrapper.cpp b/Minecraft.Client/glWrapper.cpp index c76c0014b..163db7bc0 100644 --- a/Minecraft.Client/glWrapper.cpp +++ b/Minecraft.Client/glWrapper.cpp @@ -48,12 +48,12 @@ void glLoadIdentity() RenderManager.MatrixSetIdentity(); } -extern UINT g_ScreenWidth; -extern UINT g_ScreenHeight; +extern int g_iScreenWidth; +extern int g_iScreenHeight; void gluPerspective(float fovy, float aspect, float zNear, float zFar) { - float dynamicAspect = (float)g_ScreenWidth / (float)g_ScreenHeight; + float dynamicAspect = (float)g_iScreenWidth / (float)g_iScreenHeight; RenderManager.MatrixPerspective(fovy, dynamicAspect, zNear, zFar); } diff --git a/Minecraft.Client/stubs.cpp b/Minecraft.Client/stubs.cpp index 05f6a81e0..6caaaf2ca 100644 --- a/Minecraft.Client/stubs.cpp +++ b/Minecraft.Client/stubs.cpp @@ -3,41 +3,98 @@ #ifdef _WINDOWS64 #include "Windows64/KeyboardMouseInput.h" +static const int s_keyToVK[] = { + 'A', // KEY_A = 0 + 'B', // KEY_B = 1 + 'C', // KEY_C = 2 + 'D', // KEY_D = 3 + 'E', // KEY_E = 4 + 'F', // KEY_F = 5 + 'G', // KEY_G = 6 + 'H', // KEY_H = 7 + 'I', // KEY_I = 8 + 'J', // KEY_J = 9 + 'K', // KEY_K = 10 + 'L', // KEY_L = 11 + 'M', // KEY_M = 12 + 'N', // KEY_N = 13 + 'O', // KEY_O = 14 + 'P', // KEY_P = 15 + 'Q', // KEY_Q = 16 + 'R', // KEY_R = 17 + 'S', // KEY_S = 18 + 'T', // KEY_T = 19 + 'U', // KEY_U = 20 + 'V', // KEY_V = 21 + 'W', // KEY_W = 22 + 'X', // KEY_X = 23 + 'Y', // KEY_Y = 24 + 'Z', // KEY_Z = 25 + VK_SPACE, // KEY_SPACE = 26 + VK_LSHIFT, // KEY_LSHIFT = 27 + VK_ESCAPE, // KEY_ESCAPE = 28 + VK_BACK, // KEY_BACK = 29 + VK_RETURN, // KEY_RETURN = 30 + VK_RSHIFT, // KEY_RSHIFT = 31 + VK_UP, // KEY_UP = 32 + VK_DOWN, // KEY_DOWN = 33 + VK_TAB, // KEY_TAB = 34 + '1', // KEY_1 = 35 + '2', // KEY_2 = 36 + '3', // KEY_3 = 37 + '4', // KEY_4 = 38 + '5', // KEY_5 = 39 + '6', // KEY_6 = 40 + '7', // KEY_7 = 41 + '8', // KEY_8 = 42 + '9', // KEY_9 = 43 + VK_F1, // KEY_F1 = 44 + VK_F3, // KEY_F3 = 45 + VK_F4, // KEY_F4 = 46 + VK_F5, // KEY_F5 = 47 + VK_F6, // KEY_F6 = 48 + VK_F8, // KEY_F8 = 49 + VK_F9, // KEY_F9 = 50 + VK_F11, // KEY_F11 = 51 + VK_ADD, // KEY_ADD = 52 + VK_SUBTRACT,// KEY_SUBTRACT = 53 + VK_LEFT, // KEY_LEFT = 54 + VK_RIGHT, // KEY_RIGHT = 55 +}; +static const int s_keyToVKCount = sizeof(s_keyToVK) / sizeof(s_keyToVK[0]); + +int Keyboard::toVK(int keyConst) +{ + if (keyConst >= 0 && keyConst < s_keyToVKCount) + return s_keyToVK[keyConst]; + return 0; +} + +bool Keyboard::isKeyDown(int keyCode) +{ + int vk = toVK(keyCode); + if (vk > 0) + return g_KBMInput.IsKeyDown(vk); + return false; +} + int Mouse::getX() { - return KMInput.GetMouseX(); + return g_KBMInput.GetMouseX(); } int Mouse::getY() { // Return Y in bottom-up coordinates (OpenGL convention, matching original Java LWJGL Mouse) + extern HWND g_hWnd; RECT rect; - GetClientRect(KMInput.GetHWnd(), &rect); - return (rect.bottom - 1) - KMInput.GetMouseY(); + GetClientRect(g_hWnd, &rect); + return (rect.bottom - 1) - g_KBMInput.GetMouseY(); } bool Mouse::isButtonDown(int button) { - return KMInput.IsMouseDown(button); -} - -bool Keyboard::isKeyDown(int key) -{ - // Map Keyboard constants to Windows virtual key codes - if (key == Keyboard::KEY_LSHIFT) return KMInput.IsKeyDown(VK_LSHIFT); - if (key == Keyboard::KEY_RSHIFT) return KMInput.IsKeyDown(VK_RSHIFT); - if (key == Keyboard::KEY_ESCAPE) return KMInput.IsKeyDown(VK_ESCAPE); - if (key == Keyboard::KEY_RETURN) return KMInput.IsKeyDown(VK_RETURN); - if (key == Keyboard::KEY_BACK) return KMInput.IsKeyDown(VK_BACK); - if (key == Keyboard::KEY_SPACE) return KMInput.IsKeyDown(VK_SPACE); - if (key == Keyboard::KEY_TAB) return KMInput.IsKeyDown(VK_TAB); - if (key == Keyboard::KEY_UP) return KMInput.IsKeyDown(VK_UP); - if (key == Keyboard::KEY_DOWN) return KMInput.IsKeyDown(VK_DOWN); - if (key == Keyboard::KEY_LEFT) return KMInput.IsKeyDown(VK_LEFT); - if (key == Keyboard::KEY_RIGHT) return KMInput.IsKeyDown(VK_RIGHT); - if (key >= Keyboard::KEY_A && key <= Keyboard::KEY_Z) - return KMInput.IsKeyDown('A' + (key - Keyboard::KEY_A)); - return false; + return g_KBMInput.IsMouseButtonDown(button); } #endif diff --git a/Minecraft.Client/stubs.h b/Minecraft.Client/stubs.h index cc7888672..f4ae056f2 100644 --- a/Minecraft.Client/stubs.h +++ b/Minecraft.Client/stubs.h @@ -187,12 +187,13 @@ public: static void create() {} static void destroy() {} #ifdef _WINDOWS64 - static bool isKeyDown(int key); + static bool isKeyDown(int keyCode); #else - static bool isKeyDown(int) {return false;} + static bool isKeyDown(int) { return false; } #endif static wstring getKeyName(int) { return L"KEYNAME"; } static void enableRepeatEvents(bool) {} + static const int KEY_A = 0; static const int KEY_B = 1; static const int KEY_C = 2; @@ -228,8 +229,32 @@ public: static const int KEY_UP = 32; static const int KEY_DOWN = 33; static const int KEY_TAB = 34; - static const int KEY_LEFT = 35; - static const int KEY_RIGHT = 36; + static const int KEY_1 = 35; + static const int KEY_2 = 36; + static const int KEY_3 = 37; + static const int KEY_4 = 38; + static const int KEY_5 = 39; + static const int KEY_6 = 40; + static const int KEY_7 = 41; + static const int KEY_8 = 42; + static const int KEY_9 = 43; + static const int KEY_F1 = 44; + static const int KEY_F3 = 45; + static const int KEY_F4 = 46; + static const int KEY_F5 = 47; + static const int KEY_F6 = 48; + static const int KEY_F8 = 49; + static const int KEY_F9 = 50; + static const int KEY_F11 = 51; + static const int KEY_ADD = 52; + static const int KEY_SUBTRACT = 53; + static const int KEY_LEFT = 54; + static const int KEY_RIGHT = 55; + +#ifdef _WINDOWS64 + // Map LWJGL-style key constant to Windows VK code + static int toVK(int keyConst); +#endif }; class Mouse diff --git a/Minecraft.World/ConsoleSaveFileOriginal.cpp b/Minecraft.World/ConsoleSaveFileOriginal.cpp index 40a053edf..71841d5e4 100644 --- a/Minecraft.World/ConsoleSaveFileOriginal.cpp +++ b/Minecraft.World/ConsoleSaveFileOriginal.cpp @@ -749,7 +749,7 @@ void ConsoleSaveFileOriginal::Flush(bool autosave, bool updateThumbnail ) PBYTE pbDataSaveImage=NULL; DWORD dwDataSizeSaveImage=0; -#if ( defined _XBOX || defined _DURANGO ) +#if ( defined _XBOX || defined _DURANGO || defined _WINDOWS64 ) app.GetSaveThumbnail(&pbThumbnailData,&dwThumbnailDataSize); #elif ( defined __PS3__ || defined __ORBIS__ || defined __PSVITA__ ) app.GetSaveThumbnail(&pbThumbnailData,&dwThumbnailDataSize,&pbDataSaveImage,&dwDataSizeSaveImage); diff --git a/Minecraft.World/EntityHorse.cpp b/Minecraft.World/EntityHorse.cpp index 1239d1a5c..6d62222f1 100644 --- a/Minecraft.World/EntityHorse.cpp +++ b/Minecraft.World/EntityHorse.cpp @@ -479,7 +479,7 @@ void EntityHorse::createInventory() void EntityHorse::updateEquipment() { - if (!level->isClientSide) + if (level && !level->isClientSide) { setSaddled(inventory->getItem(INV_SLOT_SADDLE) != NULL); if (canWearArmor()) diff --git a/Minecraft.World/MapItemSavedData.cpp b/Minecraft.World/MapItemSavedData.cpp index 279619d28..71048db04 100644 --- a/Minecraft.World/MapItemSavedData.cpp +++ b/Minecraft.World/MapItemSavedData.cpp @@ -596,7 +596,14 @@ void MapItemSavedData::mergeInMapData(shared_ptr dataToAdd) void MapItemSavedData::removeItemFrameDecoration(shared_ptr item) { - AUTO_VAR(frameDecoration, nonPlayerDecorations.find( item->getFrame()->entityId ) ); + if ( !item ) + return; + + std::shared_ptr frame = item->getFrame(); + if ( !frame ) + return; + + auto frameDecoration = nonPlayerDecorations.find(frame->entityId); if ( frameDecoration != nonPlayerDecorations.end() ) { delete frameDecoration->second; diff --git a/Minecraft.World/Minecraft.World.vcxproj b/Minecraft.World/Minecraft.World.vcxproj index 30a871b57..7ab7c4ce5 100644 --- a/Minecraft.World/Minecraft.World.vcxproj +++ b/Minecraft.World/Minecraft.World.vcxproj @@ -307,6 +307,7 @@ StaticLibrary MultiByte v143 + true StaticLibrary @@ -1256,6 +1257,7 @@ false true Default + /FS %(AdditionalOptions) true @@ -1338,7 +1340,7 @@ Use TurnOffAllWarnings ProgramDatabase - Full + MaxSpeed Sync false $(OutDir)$(ProjectName).pch @@ -1351,6 +1353,10 @@ true Default Speed + true + true + true + /FS /Ob3 %(AdditionalOptions) true @@ -4952,4 +4958,4 @@ - \ No newline at end of file + diff --git a/Minecraft.World/NearestAttackableTargetGoal.cpp b/Minecraft.World/NearestAttackableTargetGoal.cpp index 1dbf587ed..7ddd88950 100644 --- a/Minecraft.World/NearestAttackableTargetGoal.cpp +++ b/Minecraft.World/NearestAttackableTargetGoal.cpp @@ -34,7 +34,7 @@ bool NearestAttackableTargetGoal::DistComp::operator() (shared_ptr e1, s double distSqr2 = source->distanceToSqr(e2); if (distSqr1 < distSqr2) return true; if (distSqr1 > distSqr2) return false; - return true; + return false; } NearestAttackableTargetGoal::NearestAttackableTargetGoal(PathfinderMob *mob, const type_info& targetType, int randomInterval, bool mustSee, bool mustReach /*= false*/, EntitySelector *entitySelector /* =NULL */) diff --git a/Minecraft.World/Player.cpp b/Minecraft.World/Player.cpp index 9c2e5a1f4..ce8ed2140 100644 --- a/Minecraft.World/Player.cpp +++ b/Minecraft.World/Player.cpp @@ -627,6 +627,7 @@ void Player::ride(shared_ptr e) return; } + this->abilities.flying = false; LivingEntity::ride(e); } diff --git a/README.md b/README.md index 84d0186d8..960deff38 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # MinecraftConsoles -[![Discord](https://img.shields.io/badge/Discord-Join%20Server-5865F2?logo=discord&logoColor=white)](https://discord.gg/5CSzhc9t) +[![Discord](https://img.shields.io/badge/Discord-Join%20Server-5865F2?logo=discord&logoColor=white)](https://discord.gg/jrum7HhegA) ![Tutorial World](.github/TutorialWorld.png) @@ -20,10 +20,11 @@ This project contains the source code of Minecraft Legacy Console Edition v1.6.0 - Fixed compilation and execution in both Debug and Release mode on Windows using Visual Studio 2022 - Added support for keyboard and mouse input - Added fullscreen mode support (toggle using F11) -- Disabled V-Sync for better performance +- (WIP) Disabled V-Sync for better performance - Added a high-resolution timer path on Windows for smoother high-FPS gameplay timing - Device's screen resolution will be used as the game resolution instead of using a fixed resolution (1920x1080) - LAN Multiplayer & Discovery +- Added persistent username system via "username.txt" ## Multiplayer @@ -33,16 +34,30 @@ Basic LAN multiplayer is available on the Windows build - Other players on the same LAN can discover the session from the in-game Join Game menu - Game connections use TCP port `25565` by default - LAN discovery uses UDP port `25566` -- You can override your in-game username at launch with `-name` - -Example: - -```powershell -Minecraft.Client.exe -name Steve -``` This feature is based on [LCEMP](https://github.com/LCEMP/LCEMP/) +### Launch Arguments + +| Argument | Description | +|--------------------|-----------------------------------------------------------------------------------------------------| +| `-name ` | Sets your in-game username | +| `-server` | Launches a headless server instead of the client | +| `-ip
` | Client mode: manually connect to an IP. Server mode: override the bind IP from `server.properties` | +| `-port ` | Client mode: override the join port. Server mode: override the listen port from `server.properties` | + +Example: +``` +Minecraft.Client.exe -name Steve -ip 192.168.0.25 -port 25565 +``` + +Headless server example: +``` +Minecraft.Client.exe -server -ip 0.0.0.0 -port 25565 +``` + +The headless server also reads and writes `server.properties` in the working directory. If `-ip` / `-port` are omitted in `-server` mode, it falls back to `server-ip` / `server-port` from that file. Dedicated-server host options such as `trust-players`, `pvp`, `fire-spreads`, `tnt`, `difficulty`, `gamemode`, `spawn-animals`, and `spawn-npcs` are persisted there as well. + ## Controls (Keyboard & Mouse) - **Movement**: `W` `A` `S` `D` @@ -51,18 +66,19 @@ This feature is based on [LCEMP](https://github.com/LCEMP/LCEMP/) - **Sprint**: `Ctrl` (Hold) or Double-tap `W` - **Inventory**: `E` - **Drop Item**: `Q` -- **Crafting**: `C` +- **Crafting**: `C` Use `Q` and `E` to move through tabs (cycles Left/Right) - **Toggle View (FPS/TPS)**: `F5` - **Fullscreen**: `F11` - **Pause Menu**: `Esc` -- **Toggle Mouse Capture**: `Left Alt` (for debugging) - **Attack / Destroy**: `Left Click` - **Use / Place**: `Right Click` - **Select Item**: `Mouse Wheel` or keys `1` to `9` - **Accept or Decline Tutorial hints**: `Enter` to accept and `B` to decline - **Game Info (Player list and Host Options)**: `TAB` +- **Toggle HUD**: `F1` - **Toggle Debug Info**: `F3` - **Open Debug Overlay**: `F4` +- **Toggle Debug Console**: `F6` ## Build & Run