diff --git a/CMakeLists.txt b/CMakeLists.txt index c3ae1126..db363402 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.24) -project(MinecraftConsoles LANGUAGES C CXX ASM_MASM) +project(MinecraftConsoles LANGUAGES C CXX RC ASM_MASM) if(NOT WIN32) message(FATAL_ERROR "This CMake build currently supports Windows only.") @@ -12,11 +12,24 @@ endif() set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") +function(configure_msvc_target target) + target_compile_options(${target} PRIVATE + $<$>,$>:/W3> + $<$,$>:/W0> + $<$:/MP> + $<$:/EHsc> + $<$,$>:/GL /O2 /Oi /GT /GF> + ) +endfunction() + include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/WorldSources.cmake") include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/ClientSources.cmake") list(TRANSFORM MINECRAFT_WORLD_SOURCES PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.World/") list(TRANSFORM MINECRAFT_CLIENT_SOURCES PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/") +list(APPEND MINECRAFT_CLIENT_SOURCES + "${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Xbox/MinecraftWindows.rc" +) add_library(MinecraftWorld STATIC ${MINECRAFT_WORLD_SOURCES}) target_include_directories(MinecraftWorld PRIVATE @@ -28,11 +41,7 @@ target_compile_definitions(MinecraftWorld PRIVATE $<$>:_LARGE_WORLDS;_DEBUG_MENUS_ENABLED;_LIB;_CRT_NON_CONFORMING_SWPRINTFS;_CRT_SECURE_NO_WARNINGS;_WINDOWS64> ) if(MSVC) - target_compile_options(MinecraftWorld PRIVATE - $<$:/W3> - $<$:/MP> - $<$:/EHsc> - ) + configure_msvc_target(MinecraftWorld) endif() add_executable(MinecraftClient WIN32 ${MINECRAFT_CLIENT_SOURCES}) @@ -47,10 +56,9 @@ target_compile_definitions(MinecraftClient PRIVATE $<$>:_LARGE_WORLDS;_DEBUG_MENUS_ENABLED;_CRT_NON_CONFORMING_SWPRINTFS;_CRT_SECURE_NO_WARNINGS;_WINDOWS64> ) if(MSVC) - target_compile_options(MinecraftClient PRIVATE - $<$:/W3> - $<$:/MP> - $<$:/EHsc> + configure_msvc_target(MinecraftClient) + target_link_options(MinecraftClient PRIVATE + $<$:/LTCG /INCREMENTAL:NO> ) endif() @@ -71,12 +79,12 @@ target_link_libraries(MinecraftClient PRIVATE $<$: "${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Windows64/4JLibs/libs/4J_Input_d.lib" "${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Windows64/4JLibs/libs/4J_Storage_d.lib" - "${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Windows64/4JLibs/libs/4J_Render_PC_d.lib" + "${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Windows64/4JLibs/libs/4J_Render_d.lib" > $<$>: "${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Windows64/4JLibs/libs/4J_Input.lib" "${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Windows64/4JLibs/libs/4J_Storage.lib" - "${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Windows64/4JLibs/libs/4J_Render_PC.lib" + "${CMAKE_CURRENT_SOURCE_DIR}/Minecraft.Client/Windows64/4JLibs/libs/4J_Render.lib" > ) diff --git a/Minecraft.Client/Minecraft.Client.vcxproj b/Minecraft.Client/Minecraft.Client.vcxproj index 54915636..1eb5c506 100644 --- a/Minecraft.Client/Minecraft.Client.vcxproj +++ b/Minecraft.Client/Minecraft.Client.vcxproj @@ -45937,7 +45937,7 @@ xcopy /q /y /i /s /e $(ProjectDir)Durango\CU $(LayoutDir)Image\Loose\CUtrue true - + true true true @@ -45996,7 +45996,7 @@ xcopy /q /y /i /s /e $(ProjectDir)Durango\CU $(LayoutDir)Image\Loose\CUtrue true - + true true true @@ -48677,4 +48677,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 2be7710a..8ad7a43b 100644 --- a/Minecraft.Client/Minecraft.Client.vcxproj.filters +++ b/Minecraft.Client/Minecraft.Client.vcxproj.filters @@ -5972,10 +5972,10 @@ Durango\4JLibs\libs - + Windows64\4JLibs\libs - + Windows64\4JLibs\libs @@ -6295,4 +6295,4 @@ - \ No newline at end of file + diff --git a/Minecraft.Client/Textures.cpp b/Minecraft.Client/Textures.cpp index ab9db75d..b1f52776 100644 --- a/Minecraft.Client/Textures.cpp +++ b/Minecraft.Client/Textures.cpp @@ -424,11 +424,112 @@ 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 += _toString((int)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(0, id); + for( int i = 1; i < 4; i++ ) + { + RenderManager.TextureBind(i, -1); } } @@ -1520,3 +1621,6 @@ bool Textures::IsOriginalImage(TEXTURE_NAME texId, const wstring& name) return false; } + + + diff --git a/Minecraft.Client/Windows64/4JLibs/README.md b/Minecraft.Client/Windows64/4JLibs/README.md new file mode 100644 index 00000000..cf367f8b --- /dev/null +++ b/Minecraft.Client/Windows64/4JLibs/README.md @@ -0,0 +1,11 @@ +# Windows64 4JLibs + +This directory contains the Windows x64 `4JLibs` headers and libraries used by this project. + +Important: these files are based on the community reimplementation of `4JLibs`, not the original proprietary 4J Studios version. + +Source: + +- Community reimplementation: https://github.com/smartcmd/4JLibs + +In other words, the `inc/` and `libs/` contents here should be understood as the open community-maintained replacement that makes the Windows build possible, rather than a dump of the original upstream SDK/library package. diff --git a/Minecraft.Client/Windows64/4JLibs/inc/4J_Render.h b/Minecraft.Client/Windows64/4JLibs/inc/4J_Render.h index 737caa98..7efb48a2 100644 --- a/Minecraft.Client/Windows64/4JLibs/inc/4J_Render.h +++ b/Minecraft.Client/Windows64/4JLibs/inc/4J_Render.h @@ -145,6 +145,7 @@ public: int TextureCreate(); void TextureFree(int idx); void TextureBind(int idx); + void TextureBind(int layer, int idx); void TextureBindVertex(int idx); void TextureSetTextureLevels(int levels); int TextureGetTextureLevels(); @@ -300,3 +301,4 @@ const int GL_TRIANGLE_STRIP = C4JRender::PRIMITIVE_TYPE_TRIANGLE_STRIP; extern C4JRender RenderManager; + diff --git a/Minecraft.Client/Windows64/4JLibs/libs/4J_Input.lib b/Minecraft.Client/Windows64/4JLibs/libs/4J_Input.lib index 724a1228..7eb8adc5 100644 Binary files a/Minecraft.Client/Windows64/4JLibs/libs/4J_Input.lib and b/Minecraft.Client/Windows64/4JLibs/libs/4J_Input.lib differ diff --git a/Minecraft.Client/Windows64/4JLibs/libs/4J_Input_d.lib b/Minecraft.Client/Windows64/4JLibs/libs/4J_Input_d.lib index 84fefed3..747d00da 100644 Binary files a/Minecraft.Client/Windows64/4JLibs/libs/4J_Input_d.lib and b/Minecraft.Client/Windows64/4JLibs/libs/4J_Input_d.lib differ diff --git a/Minecraft.Client/Windows64/4JLibs/libs/4J_Input_d.lib.bak b/Minecraft.Client/Windows64/4JLibs/libs/4J_Input_d.lib.bak deleted file mode 100644 index 6b3303b4..00000000 Binary files a/Minecraft.Client/Windows64/4JLibs/libs/4J_Input_d.lib.bak and /dev/null differ diff --git a/Minecraft.Client/Windows64/4JLibs/libs/4J_Input_r.lib b/Minecraft.Client/Windows64/4JLibs/libs/4J_Input_r.lib deleted file mode 100644 index cae46c31..00000000 Binary files a/Minecraft.Client/Windows64/4JLibs/libs/4J_Input_r.lib and /dev/null differ diff --git a/Minecraft.Client/Windows64/4JLibs/libs/4J_Profile.lib b/Minecraft.Client/Windows64/4JLibs/libs/4J_Profile.lib index b3286efb..f5bcb75b 100644 Binary files a/Minecraft.Client/Windows64/4JLibs/libs/4J_Profile.lib and b/Minecraft.Client/Windows64/4JLibs/libs/4J_Profile.lib differ diff --git a/Minecraft.Client/Windows64/4JLibs/libs/4J_Profile_d.lib b/Minecraft.Client/Windows64/4JLibs/libs/4J_Profile_d.lib index 962f69e9..629f4fdf 100644 Binary files a/Minecraft.Client/Windows64/4JLibs/libs/4J_Profile_d.lib and b/Minecraft.Client/Windows64/4JLibs/libs/4J_Profile_d.lib differ diff --git a/Minecraft.Client/Windows64/4JLibs/libs/4J_Profile_r.lib b/Minecraft.Client/Windows64/4JLibs/libs/4J_Profile_r.lib deleted file mode 100644 index 4b9b716a..00000000 Binary files a/Minecraft.Client/Windows64/4JLibs/libs/4J_Profile_r.lib and /dev/null differ diff --git a/Minecraft.Client/Windows64/4JLibs/libs/4J_Render.lib b/Minecraft.Client/Windows64/4JLibs/libs/4J_Render.lib index ddfe91fe..438694fe 100644 Binary files a/Minecraft.Client/Windows64/4JLibs/libs/4J_Render.lib and b/Minecraft.Client/Windows64/4JLibs/libs/4J_Render.lib differ diff --git a/Minecraft.Client/Windows64/4JLibs/libs/4J_Render_PC.lib b/Minecraft.Client/Windows64/4JLibs/libs/4J_Render_PC.lib deleted file mode 100644 index 38c56659..00000000 Binary files a/Minecraft.Client/Windows64/4JLibs/libs/4J_Render_PC.lib and /dev/null differ diff --git a/Minecraft.Client/Windows64/4JLibs/libs/4J_Render_PC_d.lib b/Minecraft.Client/Windows64/4JLibs/libs/4J_Render_PC_d.lib deleted file mode 100644 index b311b708..00000000 Binary files a/Minecraft.Client/Windows64/4JLibs/libs/4J_Render_PC_d.lib and /dev/null differ diff --git a/Minecraft.Client/Windows64/4JLibs/libs/4J_Render_PC_d.lib.bak b/Minecraft.Client/Windows64/4JLibs/libs/4J_Render_PC_d.lib.bak deleted file mode 100644 index aa2118d3..00000000 Binary files a/Minecraft.Client/Windows64/4JLibs/libs/4J_Render_PC_d.lib.bak and /dev/null differ diff --git a/Minecraft.Client/Windows64/4JLibs/libs/4J_Render_d.lib b/Minecraft.Client/Windows64/4JLibs/libs/4J_Render_d.lib index 27a799f8..e92d2eec 100644 Binary files a/Minecraft.Client/Windows64/4JLibs/libs/4J_Render_d.lib and b/Minecraft.Client/Windows64/4JLibs/libs/4J_Render_d.lib differ diff --git a/Minecraft.Client/Windows64/4JLibs/libs/4J_Storage.lib b/Minecraft.Client/Windows64/4JLibs/libs/4J_Storage.lib index d8157a20..ab622033 100644 Binary files a/Minecraft.Client/Windows64/4JLibs/libs/4J_Storage.lib and b/Minecraft.Client/Windows64/4JLibs/libs/4J_Storage.lib differ diff --git a/Minecraft.Client/Windows64/4JLibs/libs/4J_Storage_d.lib b/Minecraft.Client/Windows64/4JLibs/libs/4J_Storage_d.lib index 013e198b..677931b6 100644 Binary files a/Minecraft.Client/Windows64/4JLibs/libs/4J_Storage_d.lib and b/Minecraft.Client/Windows64/4JLibs/libs/4J_Storage_d.lib differ diff --git a/Minecraft.Client/Windows64/4JLibs/libs/4J_Storage_d.lib.bak b/Minecraft.Client/Windows64/4JLibs/libs/4J_Storage_d.lib.bak deleted file mode 100644 index 17f457ea..00000000 Binary files a/Minecraft.Client/Windows64/4JLibs/libs/4J_Storage_d.lib.bak and /dev/null differ diff --git a/Minecraft.Client/Windows64/4JLibs/libs/4J_Storage_r.lib b/Minecraft.Client/Windows64/4JLibs/libs/4J_Storage_r.lib deleted file mode 100644 index 1d7e6b72..00000000 Binary files a/Minecraft.Client/Windows64/4JLibs/libs/4J_Storage_r.lib and /dev/null differ diff --git a/Minecraft.Client/glWrapper.cpp b/Minecraft.Client/glWrapper.cpp index 540271b9..a7bc43e6 100644 --- a/Minecraft.Client/glWrapper.cpp +++ b/Minecraft.Client/glWrapper.cpp @@ -3,6 +3,17 @@ #include "..\Minecraft.World\IntBuffer.h" #include "..\Minecraft.World\ByteBuffer.h" +static int g_activeTextureLayer = 0; + +static int getTextureLayer(int textureUnit) +{ + if (textureUnit == GL_TEXTURE1) + return 1; + if (textureUnit >= GL_TEXTURE0) + return textureUnit - GL_TEXTURE0; + return 0; +} + void glViewport(int x, int y, int w, int h) { // We don't really need anything here because minecraft doesn't current do anything other than the default viewport @@ -139,7 +150,7 @@ void Display::swapBuffers() void glBindTexture(int target,int texture) { - RenderManager.TextureBind(texture); + RenderManager.TextureBind(g_activeTextureLayer, texture); } void glTexImage2D(int target,int level,int internalformat,int width,int height,int border,int format,int type, ByteBuffer *data) @@ -190,7 +201,7 @@ void glDisable(int state) switch(state) { case GL_TEXTURE_2D: - RenderManager.TextureBind(-1); + RenderManager.TextureBind(g_activeTextureLayer, -1); break; case GL_BLEND: RenderManager.StateSetBlendEnable(false); @@ -390,4 +401,23 @@ void glTexGen(int coord, int mode, FloatBuffer *vec) void glCullFace(int dir) { RenderManager.StateSetFaceCullCW( dir == GL_BACK); -} \ No newline at end of file +} +void glClientActiveTexture(int texture) +{ + glActiveTexture(texture); +} + +void glActiveTexture(int texture) +{ + int layer = getTextureLayer(texture); + if (layer < 0) + { + layer = 0; + } + else if (layer > 3) + { + layer = 3; + } + g_activeTextureLayer = layer; +} + diff --git a/Minecraft.Client/stubs.cpp b/Minecraft.Client/stubs.cpp index 16215ba2..43eae721 100644 --- a/Minecraft.Client/stubs.cpp +++ b/Minecraft.Client/stubs.cpp @@ -122,13 +122,6 @@ void glColorMaterial(int,int) } //1.8.2 -void glClientActiveTexture(int) -{ -} - -void glActiveTexture(int) -{ -} void glFlush() { @@ -157,4 +150,4 @@ DWORD XCamSetView( ) { return 0; } XCAMDEVICESTATE XCamGetStatus() { return XCAMDEVICESTATE_DISCONNECTED; } -#endif \ No newline at end of file +#endif