From 0d4874dea5ce5cfd31a67f6b1d5e38c271a4308b Mon Sep 17 00:00:00 2001 From: Loki Date: Fri, 27 Mar 2026 00:29:08 -0500 Subject: [PATCH 1/5] Clarify Android support in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e011c1ea..303728ad 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ If you're looking for Dedicated Server software, download its [Nightly Build her - **Windows**: Supported for building and running the project - **macOS / Linux**: The Windows nightly build will run through Wine or CrossOver based on community reports, but this is unofficial and not currently tested by the maintainers when pushing updates -- **Android**: The Windows nightly build does run but has stability / frametime pacing issues frequently reported +- **Android**: VIA x86 EMULATORS (like GameNative) ONLY! The Windows nightly build does run but has stability / frametime pacing issues frequently reported - **iOS**: No current support - **All Consoles**: Console support remains in the code, but maintainers are not currently verifying console functionality / porting UI Changes to the console builds at this time. From 3c1166c45e3be1dc44f0ea83accb0408a24b2751 Mon Sep 17 00:00:00 2001 From: Sestain <35299377+sestain@users.noreply.github.com> Date: Fri, 27 Mar 2026 21:59:35 +0200 Subject: [PATCH 2/5] Added support for Big-Endian DLCs (#1291) * Added support for Big-Endian DLCs * Remove unused variable * Remove the things made for other PR --- Minecraft.Client/Common/DLC/DLCManager.cpp | 43 +++++++++++++++++----- Minecraft.Client/Common/DLC/DLCManager.h | 24 ++++++++++++ 2 files changed, 58 insertions(+), 9 deletions(-) diff --git a/Minecraft.Client/Common/DLC/DLCManager.cpp b/Minecraft.Client/Common/DLC/DLCManager.cpp index 931b0e1d..88a7756e 100644 --- a/Minecraft.Client/Common/DLC/DLCManager.cpp +++ b/Minecraft.Client/Common/DLC/DLCManager.cpp @@ -387,22 +387,34 @@ bool DLCManager::processDLCDataFile(DWORD &dwFilesProcessed, PBYTE pbData, DWORD // // unsigned long, p = number of parameters // // p * DLC_FILE_PARAM describing each parameter for this file // // ulFileSize bytes of data blob of the file added - unsigned int uiVersion=*(unsigned int *)pbData; + unsigned int uiVersion=readUInt32(pbData, false); uiCurrentByte+=sizeof(int); - if(uiVersion < CURRENT_DLC_VERSION_NUM) - { - if(pbData!=nullptr) delete [] pbData; - app.DebugPrintf("DLC version of %d is too old to be read\n", uiVersion); + bool bSwapEndian = false; + unsigned int uiVersionSwapped = SwapInt32(uiVersion); + if (uiVersion >= 0 && uiVersion <= CURRENT_DLC_VERSION_NUM) { + bSwapEndian = false; + } else if (uiVersionSwapped >= 0 && uiVersionSwapped <= CURRENT_DLC_VERSION_NUM) { + bSwapEndian = true; + } else { + if(pbData!=nullptr) delete [] pbData; + app.DebugPrintf("Unknown DLC version of %d\n", uiVersion); return false; } pack->SetDataPointer(pbData); - unsigned int uiParameterCount=*(unsigned int *)&pbData[uiCurrentByte]; + unsigned int uiParameterCount=readUInt32(&pbData[uiCurrentByte], bSwapEndian); uiCurrentByte+=sizeof(int); C4JStorage::DLC_FILE_PARAM *pParams = (C4JStorage::DLC_FILE_PARAM *)&pbData[uiCurrentByte]; //DWORD dwwchCount=0; for(unsigned int i=0;idwType = bSwapEndian ? SwapInt32(pParams->dwType) : pParams->dwType; + pParams->dwWchCount = bSwapEndian ? SwapInt32(pParams->dwWchCount) : pParams->dwWchCount; + char16_t* wchData = reinterpret_cast(pParams->wchData); + if (bSwapEndian) { + SwapUTF16Bytes(wchData, pParams->dwWchCount); + } + // Map DLC strings to application strings, then store the DLC index mapping to application index wstring parameterName(static_cast(pParams->wchData)); EDLCParameterType type = getParameterType(parameterName); @@ -414,14 +426,14 @@ bool DLCManager::processDLCDataFile(DWORD &dwFilesProcessed, PBYTE pbData, DWORD pParams = (C4JStorage::DLC_FILE_PARAM *)&pbData[uiCurrentByte]; } //ulCurrentByte+=ulParameterCount * sizeof(C4JStorage::DLC_FILE_PARAM); - - unsigned int uiFileCount=*(unsigned int *)&pbData[uiCurrentByte]; + unsigned int uiFileCount=readUInt32(&pbData[uiCurrentByte], bSwapEndian); uiCurrentByte+=sizeof(int); C4JStorage::DLC_FILE_DETAILS *pFile = (C4JStorage::DLC_FILE_DETAILS *)&pbData[uiCurrentByte]; DWORD dwTemp=uiCurrentByte; for(unsigned int i=0;idwWchCount = bSwapEndian ? SwapInt32(pFile->dwWchCount) : pFile->dwWchCount; dwTemp+=sizeof(C4JStorage::DLC_FILE_DETAILS)+pFile->dwWchCount*sizeof(WCHAR); pFile = (C4JStorage::DLC_FILE_DETAILS *)&pbData[dwTemp]; } @@ -430,6 +442,13 @@ bool DLCManager::processDLCDataFile(DWORD &dwFilesProcessed, PBYTE pbData, DWORD for(unsigned int i=0;idwType = bSwapEndian ? SwapInt32(pFile->dwType) : pFile->dwType; + pFile->uiFileSize = bSwapEndian ? SwapInt32(pFile->uiFileSize) : pFile->uiFileSize; + char16_t* wchFile = reinterpret_cast(pFile->wchFile); + if (bSwapEndian) { + SwapUTF16Bytes(wchFile, pFile->dwWchCount); + } + EDLCType type = static_cast(pFile->dwType); DLCFile *dlcFile = nullptr; @@ -445,12 +464,18 @@ bool DLCManager::processDLCDataFile(DWORD &dwFilesProcessed, PBYTE pbData, DWORD } // Params - uiParameterCount=*(unsigned int *)pbTemp; + uiParameterCount=readUInt32(pbTemp, bSwapEndian); pbTemp+=sizeof(int); pParams = (C4JStorage::DLC_FILE_PARAM *)pbTemp; for(unsigned int j=0;jdwType = bSwapEndian ? SwapInt32(pParams->dwType) : pParams->dwType; + pParams->dwWchCount = bSwapEndian ? SwapInt32(pParams->dwWchCount) : pParams->dwWchCount; + char16_t* wchData = reinterpret_cast(pParams->wchData); + if (bSwapEndian) { + SwapUTF16Bytes(wchData, pParams->dwWchCount); + } auto it = parameterMapping.find(pParams->dwType); diff --git a/Minecraft.Client/Common/DLC/DLCManager.h b/Minecraft.Client/Common/DLC/DLCManager.h index d4dd2508..7191ab0b 100644 --- a/Minecraft.Client/Common/DLC/DLCManager.h +++ b/Minecraft.Client/Common/DLC/DLCManager.h @@ -94,6 +94,30 @@ public: bool readDLCDataFile(DWORD &dwFilesProcessed, const string &path, DLCPack *pack, bool fromArchive = false); DWORD retrievePackIDFromDLCDataFile(const string &path, DLCPack *pack); + static unsigned short SwapInt16(unsigned short value) { + return (value >> 8) | (value << 8); + } + + static unsigned int SwapInt32(unsigned int value) { + return ((value & 0xFF) << 24) | + ((value & 0xFF00) << 8) | + ((value & 0xFF0000) >> 8) | + ((value & 0xFF000000) >> 24); + } + + static void SwapUTF16Bytes(char16_t* buffer, size_t count) { + for (size_t i = 0; i < count; ++i) { + char16_t& c = buffer[i]; + c = (c >> 8) | (c << 8); + } + } + + static unsigned int readUInt32(unsigned char* ptr, bool endian) { + unsigned int val = *(unsigned int*)ptr; + if (endian) val = SwapInt32(val); + return val; + } + private: bool processDLCDataFile(DWORD &dwFilesProcessed, PBYTE pbData, DWORD dwLength, DLCPack *pack); From 7447fabe0d8d97b42a6c9fb58ac121d2bb04372a Mon Sep 17 00:00:00 2001 From: Sestain <35299377+sestain@users.noreply.github.com> Date: Fri, 27 Mar 2026 22:11:27 +0200 Subject: [PATCH 3/5] Fix game crashing if DLC has XMLVERSION paramater (#1285) * Fix game crashing if DLC has XMLVERSION paramater * Better implementation of XMLVersion check * Forgot to add type name to the list * Removed extra newline --- Minecraft.Client/Common/DLC/DLCManager.cpp | 13 +++++++++++++ Minecraft.Client/Common/DLC/DLCManager.h | 3 ++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/Minecraft.Client/Common/DLC/DLCManager.cpp b/Minecraft.Client/Common/DLC/DLCManager.cpp index 88a7756e..c363becf 100644 --- a/Minecraft.Client/Common/DLC/DLCManager.cpp +++ b/Minecraft.Client/Common/DLC/DLCManager.cpp @@ -10,6 +10,7 @@ const WCHAR *DLCManager::wchTypeNamesA[]= { + L"XMLVERSION", L"DISPLAYNAME", L"THEMENAME", L"FREE", @@ -405,6 +406,7 @@ bool DLCManager::processDLCDataFile(DWORD &dwFilesProcessed, PBYTE pbData, DWORD unsigned int uiParameterCount=readUInt32(&pbData[uiCurrentByte], bSwapEndian); uiCurrentByte+=sizeof(int); C4JStorage::DLC_FILE_PARAM *pParams = (C4JStorage::DLC_FILE_PARAM *)&pbData[uiCurrentByte]; + bool bXMLVersion = false; //DWORD dwwchCount=0; for(unsigned int i=0;idwType] = type; + + if (type == e_DLCParamType_XMLVersion) + { + bXMLVersion = true; + } } uiCurrentByte+= sizeof(C4JStorage::DLC_FILE_PARAM)+(pParams->dwWchCount*sizeof(WCHAR)); pParams = (C4JStorage::DLC_FILE_PARAM *)&pbData[uiCurrentByte]; } //ulCurrentByte+=ulParameterCount * sizeof(C4JStorage::DLC_FILE_PARAM); + + if (bXMLVersion) + { + uiCurrentByte += sizeof(int); + } + unsigned int uiFileCount=readUInt32(&pbData[uiCurrentByte], bSwapEndian); uiCurrentByte+=sizeof(int); C4JStorage::DLC_FILE_DETAILS *pFile = (C4JStorage::DLC_FILE_DETAILS *)&pbData[uiCurrentByte]; diff --git a/Minecraft.Client/Common/DLC/DLCManager.h b/Minecraft.Client/Common/DLC/DLCManager.h index 7191ab0b..f114bd07 100644 --- a/Minecraft.Client/Common/DLC/DLCManager.h +++ b/Minecraft.Client/Common/DLC/DLCManager.h @@ -31,7 +31,8 @@ public: { e_DLCParamType_Invalid = -1, - e_DLCParamType_DisplayName = 0, + e_DLCParamType_XMLVersion = 0, + e_DLCParamType_DisplayName, e_DLCParamType_ThemeName, e_DLCParamType_Free, // identify free skins e_DLCParamType_Credit, // legal credits for DLC From 277d74716e9a2c937500e16273727a24f49508ee Mon Sep 17 00:00:00 2001 From: Botch Date: Sat, 28 Mar 2026 13:44:27 -0600 Subject: [PATCH 4/5] Render custom skin boxes on viewmodel (#1415) * Update PlayerRenderer.cpp * Fix fatal bug where skins with no additional boxes would crash the game --- Minecraft.Client/PlayerRenderer.cpp | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/Minecraft.Client/PlayerRenderer.cpp b/Minecraft.Client/PlayerRenderer.cpp index a9b94544..23dff77f 100644 --- a/Minecraft.Client/PlayerRenderer.cpp +++ b/Minecraft.Client/PlayerRenderer.cpp @@ -519,6 +519,29 @@ void PlayerRenderer::renderHand() { humanoidModel->arm0->render(1 / 16.0f,true); } + + + //Render custom skin boxes on viewmodel - Botch + vector* additionalModelParts = Minecraft::GetInstance()->player->GetAdditionalModelParts(); + if (!additionalModelParts) return; //If there are no custom boxes, return. This fixes bug where the game will crash if you select a skin with no additional boxes. + vector armchildren = humanoidModel->arm0->children; + std::unordered_set additionalModelPartSet(additionalModelParts->begin(), additionalModelParts->end()); + for (const auto& x : armchildren) { + if (x) { + if (additionalModelPartSet.find(x) != additionalModelPartSet.end()) { //This is to verify box is still actually on current skin - Botch + glPushMatrix(); + //We need to transform to match offset of arm - Botch + glTranslatef(-5 * 0.0625f, 2 * 0.0625f, 0); + glRotatef(0.1 * (180.0f / PI), 0, 0, 1); + x->visible = true; + x->render(1.0f / 16.0f, true); + x->visible = false; + glPopMatrix(); + } + } + } + + } void PlayerRenderer::setupPosition(shared_ptr _mob, double x, double y, double z) @@ -580,4 +603,4 @@ ResourceLocation *PlayerRenderer::getTextureLocation(shared_ptr entity) { shared_ptr player = dynamic_pointer_cast(entity); return new ResourceLocation(static_cast<_TEXTURE_NAME>(player->getTexture())); -} \ No newline at end of file +} From 38d58f2d8bb8af5516671b42940279d4e582d9c7 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Sun, 29 Mar 2026 05:35:25 +0100 Subject: [PATCH 5/5] Update actions workflows and add clang format check for PRs (#1418) * Add clang-format workflow for pull request checks * Modify push paths in nightly workflow Updated paths for push event to include all files except specified ones. * Update paths for nightly-server workflow triggers * Modify paths for pull request triggers Update pull request workflow to include specific paths. * Tidy up clang-format installation in workflow --- .github/workflows/clang-format.yml | 48 ++++++++++++++++++++++++++++ .github/workflows/nightly-server.yml | 11 ++++--- .github/workflows/nightly.yml | 11 ++++--- .github/workflows/pull-request.yml | 10 +++--- 4 files changed, 66 insertions(+), 14 deletions(-) create mode 100644 .github/workflows/clang-format.yml diff --git a/.github/workflows/clang-format.yml b/.github/workflows/clang-format.yml new file mode 100644 index 00000000..a01bada4 --- /dev/null +++ b/.github/workflows/clang-format.yml @@ -0,0 +1,48 @@ +name: Check formatting + +on: + pull_request: + paths: + - '**' + - '!.gitignore' + - '!*.md' + - '!.github/**' + - '.github/workflows/clang-format.yml' + +permissions: + contents: read + pull-requests: write + +jobs: + format-check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + with: + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 0 + + - name: Fetch base commit + run: git fetch origin ${{ github.event.pull_request.base.sha }} + + - name: Install clang-format-20 + run: | + wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | sudo tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc + sudo add-apt-repository -y "deb http://apt.llvm.org/noble/ llvm-toolchain-noble-20 main" + sudo apt-get install -y -qq clang-format-20 + + - uses: reviewdog/action-setup@v1 + + - name: Check formatting on changed lines + env: + REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + git clang-format-20 --binary clang-format-20 \ + --diff ${{ github.event.pull_request.base.sha }} -- \ + '*.c' '*.cpp' '*.cc' '*.h' '*.hpp' \ + | reviewdog \ + -name="clang-format" \ + -f=diff \ + -reporter=github-pr-check \ + -fail-level=error \ + -filter-mode=added diff --git a/.github/workflows/nightly-server.yml b/.github/workflows/nightly-server.yml index 5450de9a..0fc20eb1 100644 --- a/.github/workflows/nightly-server.yml +++ b/.github/workflows/nightly-server.yml @@ -5,11 +5,12 @@ on: push: branches: - 'main' - paths-ignore: - - '.gitignore' - - '*.md' - - '.github/**' - - '!.github/workflows/nightly-server.yml' + paths: + - '**' + - '!.gitignore' + - '!*.md' + - '!.github/**' + - '.github/workflows/nightly-server.yml' permissions: contents: write diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 789db3e8..a5b53be0 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -5,11 +5,12 @@ on: push: branches: - 'main' - paths-ignore: - - '.gitignore' - - '*.md' - - '.github/**' - - '!.github/workflows/nightly.yml' + paths: + - '**' + - '!.gitignore' + - '!*.md' + - '!.github/**' + - '.github/workflows/nightly.yml' permissions: contents: write diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index 9d57f4b4..3b5398a0 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -4,10 +4,12 @@ on: workflow_dispatch: pull_request: types: [opened, reopened, synchronize] - paths-ignore: - - '.gitignore' - - '*.md' - - '.github/*.md' + paths: + - '**' + - '!.gitignore' + - '!*.md' + - '!.github/**' + - '.github/workflows/pull-request.yml' jobs: build: