13 Commits

Author SHA1 Message Date
daoge_cmd
e50603e68f fix: fix horse texture rendering 2026-03-03 22:12:59 +08:00
daoge_cmd
d2bc3342dc feat: implement multi-layer texture binding 2026-03-03 21:20:10 +08:00
daoge_cmd
5422191ed4 chore: remove duplicated /Ob3 flag from CMake Release optimization settings 2026-03-03 17:58:47 +08:00
daoge_cmd
7749d61daf chore: sync VS Release warning-disable setting into CMake
(cherry picked from commit a97ee4aab1)
2026-03-03 17:45:43 +08:00
daoge_cmd
62c2ed5cf6 chore: sync VS release optimization flags into CMake build 2026-03-03 17:40:03 +08:00
daoge_cmd
3132ad122d fix: fix executable icon when using cmake 2026-03-03 17:33:58 +08:00
daoge_cmd
f76a6a5e1c deps: update 4JLibs 2026-03-03 17:06:55 +08:00
daoge_cmd
75d4afa783 Merge branch 'main' into feat/replace-4jlibs 2026-03-03 16:41:16 +08:00
daoge_cmd
a3588c5a6d deps: update 4J_Render.lib 2026-03-03 16:37:51 +08:00
daoge_cmd
323d4ec110 Merge branch 'main' into feat/replace-4jlibs 2026-03-03 16:30:57 +08:00
daoge_cmd
64909f236e deps: update 4JLibs 2026-03-03 12:46:47 +08:00
daoge_cmd
f685015942 Merge branch 'main' into feat/replace-4jlibs 2026-03-03 12:39:22 +08:00
daoge_cmd
50d37cdd3c feat: replace the old buggy 4JLibs with the community reimpl (https://github.com/smartcmd/4JLibs) 2026-03-03 10:35:06 +08:00
24 changed files with 179 additions and 31 deletions

View File

@@ -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$<$<CONFIG:Debug>:Debug>")
function(configure_msvc_target target)
target_compile_options(${target} PRIVATE
$<$<AND:$<NOT:$<CONFIG:Release>>,$<COMPILE_LANGUAGE:C,CXX>>:/W3>
$<$<AND:$<CONFIG:Release>,$<COMPILE_LANGUAGE:C,CXX>>:/W0>
$<$<COMPILE_LANGUAGE:C,CXX>:/MP>
$<$<COMPILE_LANGUAGE:CXX>:/EHsc>
$<$<AND:$<CONFIG:Release>,$<COMPILE_LANGUAGE:C,CXX>>:/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
$<$<NOT:$<CONFIG:Debug>>:_LARGE_WORLDS;_DEBUG_MENUS_ENABLED;_LIB;_CRT_NON_CONFORMING_SWPRINTFS;_CRT_SECURE_NO_WARNINGS;_WINDOWS64>
)
if(MSVC)
target_compile_options(MinecraftWorld PRIVATE
$<$<COMPILE_LANGUAGE:C,CXX>:/W3>
$<$<COMPILE_LANGUAGE:C,CXX>:/MP>
$<$<COMPILE_LANGUAGE:CXX>:/EHsc>
)
configure_msvc_target(MinecraftWorld)
endif()
add_executable(MinecraftClient WIN32 ${MINECRAFT_CLIENT_SOURCES})
@@ -47,10 +56,9 @@ target_compile_definitions(MinecraftClient PRIVATE
$<$<NOT:$<CONFIG:Debug>>:_LARGE_WORLDS;_DEBUG_MENUS_ENABLED;_CRT_NON_CONFORMING_SWPRINTFS;_CRT_SECURE_NO_WARNINGS;_WINDOWS64>
)
if(MSVC)
target_compile_options(MinecraftClient PRIVATE
$<$<COMPILE_LANGUAGE:C,CXX>:/W3>
$<$<COMPILE_LANGUAGE:C,CXX>:/MP>
$<$<COMPILE_LANGUAGE:CXX>:/EHsc>
configure_msvc_target(MinecraftClient)
target_link_options(MinecraftClient PRIVATE
$<$<CONFIG:Release>:/LTCG /INCREMENTAL:NO>
)
endif()
@@ -71,12 +79,12 @@ target_link_libraries(MinecraftClient PRIVATE
$<$<CONFIG:Debug>:
"${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"
>
$<$<NOT:$<CONFIG:Debug>>:
"${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"
>
)

View File

@@ -45937,7 +45937,7 @@ xcopy /q /y /i /s /e $(ProjectDir)Durango\CU $(LayoutDir)Image\Loose\CU</Comman
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ORBIS'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_Vita|ORBIS'">true</ExcludedFromBuild>
</Library>
<Library Include="Windows64\4JLibs\libs\4J_Render_PC.lib">
<Library Include="Windows64\4JLibs\libs\4J_Render.lib">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage|Durango'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='CONTENTPACKAGE_SYMBOLS|Durango'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseForArt|Durango'">true</ExcludedFromBuild>
@@ -45996,7 +45996,7 @@ xcopy /q /y /i /s /e $(ProjectDir)Durango\CU $(LayoutDir)Image\Loose\CU</Comman
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ORBIS'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_Vita|ORBIS'">true</ExcludedFromBuild>
</Library>
<Library Include="Windows64\4JLibs\libs\4J_Render_PC_d.lib">
<Library Include="Windows64\4JLibs\libs\4J_Render_d.lib">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage|Durango'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='CONTENTPACKAGE_SYMBOLS|Durango'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ReleaseForArt|Durango'">true</ExcludedFromBuild>
@@ -48677,4 +48677,4 @@ xcopy /q /y /i /s /e $(ProjectDir)Durango\CU $(LayoutDir)Image\Loose\CU</Comman
<ImportGroup Label="ExtensionTargets">
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" />
</ImportGroup>
</Project>
</Project>

View File

@@ -5972,10 +5972,10 @@
<Library Include="Durango\4JLibs\libs\4J_Input_d.lib">
<Filter>Durango\4JLibs\libs</Filter>
</Library>
<Library Include="Windows64\4JLibs\libs\4J_Render_PC.lib">
<Library Include="Windows64\4JLibs\libs\4J_Render.lib">
<Filter>Windows64\4JLibs\libs</Filter>
</Library>
<Library Include="Windows64\4JLibs\libs\4J_Render_PC_d.lib">
<Library Include="Windows64\4JLibs\libs\4J_Render_d.lib">
<Filter>Windows64\4JLibs\libs</Filter>
</Library>
<Library Include="Windows64\4JLibs\libs\4J_Input.lib">
@@ -6295,4 +6295,4 @@
<ItemGroup>
<AppxManifest Include="Durango\Autogenerated.appxmanifest" />
</ItemGroup>
</Project>
</Project>

View File

@@ -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>((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;
}

View File

@@ -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.

View File

@@ -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;

View File

@@ -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);
}
}
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;
}

View File

@@ -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
#endif