From 44b4ba84c2fa2df77e5b34a5c7920b8223af42c3 Mon Sep 17 00:00:00 2001 From: JuiceyDev Date: Thu, 5 Mar 2026 19:06:07 +0100 Subject: [PATCH] Horrible code alert --- .../Build/Common/Consoles_App.cpp | 2 +- .../Common/Network/GameNetworkManager.cpp | 10 ++++ .../Common/UI/UIScene_FullscreenProgress.cpp | 4 ++ .../Build/Common/UI/UIScene_Intro.cpp | 1 - .../Build/Common/UI/UIScene_MainMenu.cpp | 1 + Minecraft.Client/MinecraftServer.cpp | 17 +++++- .../Platform/Linux/Linux_Minecraft.cpp | 33 +++++++++++ .../Platform/Linux/Stubs/winapi_stubs.h | 59 ++++++++++++++++++- Minecraft.World/Build/stlHaEcC | 1 + Minecraft.World/Network/Connection.cpp | 4 -- 10 files changed, 121 insertions(+), 11 deletions(-) create mode 100644 Minecraft.World/Build/stlHaEcC diff --git a/Minecraft.Client/Build/Common/Consoles_App.cpp b/Minecraft.Client/Build/Common/Consoles_App.cpp index a79ab5e61..aeb8b66a4 100644 --- a/Minecraft.Client/Build/Common/Consoles_App.cpp +++ b/Minecraft.Client/Build/Common/Consoles_App.cpp @@ -7729,7 +7729,7 @@ unsigned int CMinecraftApp::CreateImageTextData(PBYTE bTextMetadata, __int64 see if(hasSeed) { strcpy((char *)bTextMetadata,"4J_SEED"); - snprintf((char *)&bTextMetadata[8], 42, NULL, seed); + snprintf((char *)&bTextMetadata[8], 42, "%lld", (long long)seed); // get the length iTextMetadataBytes+=8; diff --git a/Minecraft.Client/Build/Common/Network/GameNetworkManager.cpp b/Minecraft.Client/Build/Common/Network/GameNetworkManager.cpp index ce7d42325..810366d39 100644 --- a/Minecraft.Client/Build/Common/Network/GameNetworkManager.cpp +++ b/Minecraft.Client/Build/Common/Network/GameNetworkManager.cpp @@ -226,8 +226,10 @@ bool CGameNetworkManager::StartNetworkGame(Minecraft *minecraft, LPVOID lpParame thread->SetProcessor(CPU_CORE_SERVER); thread->Run(); + app.DebugPrintf("[NET] Waiting for server ready...\n"); ServerReadyWait(); ServerReadyDestroy(); + app.DebugPrintf("[NET] Server ready! serverHalted=%d\n", MinecraftServer::serverHalted()); if( MinecraftServer::serverHalted() ) return false; @@ -241,6 +243,7 @@ bool CGameNetworkManager::StartNetworkGame(Minecraft *minecraft, LPVOID lpParame #ifndef _XBOX Minecraft *pMinecraft = Minecraft::GetInstance(); + app.DebugPrintf("[NET] IsReadyToPlayOrIdle=%d IsInSession=%d\n", IsReadyToPlayOrIdle(), IsInSession()); // Make sure that we have transitioned through any joining/creating stages and are actually playing the game, so that we know the players should be valid bool changedMessage = false; while(!IsReadyToPlayOrIdle()) @@ -257,12 +260,15 @@ bool CGameNetworkManager::StartNetworkGame(Minecraft *minecraft, LPVOID lpParame #endif // If we aren't in session, then something bad must have happened - we aren't joining, creating or ready play + app.DebugPrintf("[NET] Checking IsInSession...=%d\n", IsInSession()); if(!IsInSession() ) { + app.DebugPrintf("[NET] NOT in session! Halting server.\n"); MinecraftServer::HaltServer(); return false; } + app.DebugPrintf("[NET] DLC check: completed=%d pending=%d\n", app.DLCInstallProcessCompleted(), app.DLCInstallPending()); // 4J Stu - Wait a while to make sure that DLC is loaded. This is the last point before the network communication starts // so the latest we can check this while( !app.DLCInstallProcessCompleted() && app.DLCInstallPending() && !g_NetworkManager.IsLeavingGame() ) @@ -277,12 +283,14 @@ bool CGameNetworkManager::StartNetworkGame(Minecraft *minecraft, LPVOID lpParame // PRIMARY PLAYER + app.DebugPrintf("[NET] Creating ClientConnection (IsHost=%d)...\n", g_NetworkManager.IsHost()); vector createdConnections; ClientConnection *connection; if( g_NetworkManager.IsHost() ) { connection = new ClientConnection(minecraft, NULL); + app.DebugPrintf("[NET] ClientConnection created, createdOk=%d\n", connection->createdOk); } else { @@ -318,7 +326,9 @@ bool CGameNetworkManager::StartNetworkGame(Minecraft *minecraft, LPVOID lpParame return false; } + app.DebugPrintf("[NET] Sending PreLoginPacket...\n"); connection->send( shared_ptr( new PreLoginPacket(minecraft->user->name) ) ); + app.DebugPrintf("[NET] PreLoginPacket sent. Entering connection tick loop...\n"); // Tick connection until we're ready to go. The stages involved in this are: // (1) Creating the ClientConnection sends a prelogin packet to the server diff --git a/Minecraft.Client/Build/Common/UI/UIScene_FullscreenProgress.cpp b/Minecraft.Client/Build/Common/UI/UIScene_FullscreenProgress.cpp index 7875af1c1..07e728355 100644 --- a/Minecraft.Client/Build/Common/UI/UIScene_FullscreenProgress.cpp +++ b/Minecraft.Client/Build/Common/UI/UIScene_FullscreenProgress.cpp @@ -154,6 +154,10 @@ void UIScene_FullscreenProgress::tick() int code = thread->GetExitCode(); DWORD exitcode = *((DWORD *)&code); + static int s_FPTickCount = 0; + if(s_FPTickCount % 60 == 0) app.DebugPrintf("[FP] tick #%d exitcode=%u STILL_ACTIVE=%u\n", s_FPTickCount, exitcode, (DWORD)STILL_ACTIVE); + s_FPTickCount++; + //app.DebugPrintf("CScene_FullscreenProgress Timer %d\n",pTimer->nId); if( exitcode != STILL_ACTIVE ) diff --git a/Minecraft.Client/Build/Common/UI/UIScene_Intro.cpp b/Minecraft.Client/Build/Common/UI/UIScene_Intro.cpp index 866c3fbc4..25b57cc40 100644 --- a/Minecraft.Client/Build/Common/UI/UIScene_Intro.cpp +++ b/Minecraft.Client/Build/Common/UI/UIScene_Intro.cpp @@ -5,7 +5,6 @@ #ifdef __linux__ static int s_introTickCount = 0; #endif -#include UIScene_Intro::UIScene_Intro(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) { diff --git a/Minecraft.Client/Build/Common/UI/UIScene_MainMenu.cpp b/Minecraft.Client/Build/Common/UI/UIScene_MainMenu.cpp index f9b825499..624dddfdb 100644 --- a/Minecraft.Client/Build/Common/UI/UIScene_MainMenu.cpp +++ b/Minecraft.Client/Build/Common/UI/UIScene_MainMenu.cpp @@ -1806,6 +1806,7 @@ void UIScene_MainMenu::tick() { static int s_mainMenuTickCount = 0; s_mainMenuTickCount++; + if(s_mainMenuTickCount % 60 == 1) { fprintf(stderr, "[MM] tick %d\n", s_mainMenuTickCount); fflush(stderr); } if(s_mainMenuTickCount == 90) // ~3 seconds at 30fps { fprintf(stderr, "[Linux] Auto-starting trial world from MainMenu after %d ticks\n", s_mainMenuTickCount); diff --git a/Minecraft.Client/MinecraftServer.cpp b/Minecraft.Client/MinecraftServer.cpp index 196dd6fe1..d63fb7933 100644 --- a/Minecraft.Client/MinecraftServer.cpp +++ b/Minecraft.Client/MinecraftServer.cpp @@ -257,6 +257,7 @@ bool MinecraftServer::initServer(__int64 seed, NetworkGameInitData *initData, DW // logger.info("Preparing level \"" + levelName + "\""); m_bLoaded = loadLevel(new McRegionLevelStorageSource(File(L".")), levelName, seed, pLevelType, initData); // logger.info("Done (" + (System.nanoTime() - levelNanoTime) + "ns)! For help, type \"help\" or \"?\""); + app.DebugPrintf("[SRV] loadLevel returned %d\n", m_bLoaded); // 4J delete passed in save data now - this is only required for the tutorial which is loaded by passing data directly in rather than using the storage manager if( initData->saveData ) @@ -266,7 +267,9 @@ bool MinecraftServer::initServer(__int64 seed, NetworkGameInitData *initData, DW initData->saveData->fileSize = 0; } + app.DebugPrintf("[SRV] Signaling ServerReady\n"); g_NetworkManager.ServerReady(); // 4J added + app.DebugPrintf("[SRV] ServerReady signaled, returning m_bLoaded=%d\n", m_bLoaded); return m_bLoaded; } @@ -508,8 +511,7 @@ bool MinecraftServer::loadLevel(LevelStorageSource *storageSource, const wstring // 4J - Make a new thread to do post processing InitializeCriticalSection(&m_postProcessCS); - // 4J-PB - fix for 108310 - TCR #001 BAS Game Stability: TU12: Code: Compliance: Crash after creating world on "journey" seed. - // Stack gets very deep with some sand tower falling, so increased the stacj to 256K from 128k on other platforms (was already set to that on PS3 and Orbis) + app.DebugPrintf("[SRV] Starting post-processing thread\n"); m_postUpdateThread = new C4JThread(runPostUpdate, this, "Post processing", 256*1024); @@ -517,6 +519,7 @@ bool MinecraftServer::loadLevel(LevelStorageSource *storageSource, const wstring m_postUpdateThread->SetProcessor(CPU_CORE_POST_PROCESSING); m_postUpdateThread->SetPriority(THREAD_PRIORITY_ABOVE_NORMAL); m_postUpdateThread->Run(); + app.DebugPrintf("[SRV] Post-processing thread started\n"); __int64 startTime = System::currentTimeMillis(); @@ -589,9 +592,11 @@ bool MinecraftServer::loadLevel(LevelStorageSource *storageSource, const wstring #else __int64 lastStorageTickTime = System::currentTimeMillis(); Pos *spawnPos = level->getSharedSpawnPos(); + app.DebugPrintf("[SRV] dim=%d spawn=(%d,%d) r=%d\n", i, spawnPos->x, spawnPos->z, r); int twoRPlusOne = r*2 + 1; int total = twoRPlusOne * twoRPlusOne; + int chunksDone = 0; for (int x = -r; x <= r && running; x += 16) { for (int z = -r; z <= r && running; z += 16) @@ -617,6 +622,8 @@ bool MinecraftServer::loadLevel(LevelStorageSource *storageSource, const wstring PIXBeginNamedEvent(0,"Creating %d ", (count++)%8); level->cache->create((spawnPos->x + x) >> 4, (spawnPos->z + z) >> 4, true); // 4J - added parameter to disable postprocessing here PIXEndNamedEvent(); + chunksDone++; + if(chunksDone % 50 == 0) app.DebugPrintf("[SRV] dim=%d chunk %d/%d\n", i, chunksDone, total); // while (level->updateLights() && running) // ; if( System::currentTimeMillis() - lastStorageTickTime > 50 ) @@ -649,10 +656,12 @@ bool MinecraftServer::loadLevel(LevelStorageSource *storageSource, const wstring } // printf("Main thread complete at %dms\n",System::currentTimeMillis() - startTime); + app.DebugPrintf("[SRV] All chunk loops done, waiting for postProcess\n"); // Wait for post processing, then lighting threads, to end (post-processing may make more lighting changes) m_postUpdateTerminate = true; postProcessTerminate(mcprogress); + app.DebugPrintf("[SRV] postProcessTerminate done\n"); // stronghold position? @@ -713,14 +722,18 @@ bool MinecraftServer::loadLevel(LevelStorageSource *storageSource, const wstring if( levels[0]->isNew ) { + app.DebugPrintf("[SRV] Saving level 0...\n"); levels[0]->save(true, mcprogress); + app.DebugPrintf("[SRV] Level 0 saved\n"); } if( s_bServerHalted || !g_NetworkManager.IsInSession() ) return false; if( levels[0]->isNew || levels[1]->isNew || levels[2]->isNew ) { + app.DebugPrintf("[SRV] Saving to disc...\n"); levels[0]->saveToDisc(mcprogress, false); + app.DebugPrintf("[SRV] saveToDisc done\n"); } if( s_bServerHalted || !g_NetworkManager.IsInSession() ) return false; diff --git a/Minecraft.Client/Platform/Linux/Linux_Minecraft.cpp b/Minecraft.Client/Platform/Linux/Linux_Minecraft.cpp index a9d58a3b6..39d2c705f 100644 --- a/Minecraft.Client/Platform/Linux/Linux_Minecraft.cpp +++ b/Minecraft.Client/Platform/Linux/Linux_Minecraft.cpp @@ -6,6 +6,29 @@ #include //#include #include +#ifdef __linux__ +#include +#include +#include +static void sigsegv_handler(int sig) { + const char msg[] = "\n=== SIGNAL CAUGHT: "; + write(STDERR_FILENO, msg, sizeof(msg)-1); + char signum[8]; + int len = 0; + int s = sig; + if (s == 0) { signum[len++] = '0'; } + else { char tmp[8]; int tl = 0; while(s > 0) { tmp[tl++] = '0' + (s%10); s /= 10; } for(int i = tl-1; i >= 0; i--) signum[len++] = tmp[i]; } + write(STDERR_FILENO, signum, len); + const char msg1b[] = " ===\n"; + write(STDERR_FILENO, msg1b, sizeof(msg1b)-1); + void *array[64]; + int size = backtrace(array, 64); + backtrace_symbols_fd(array, size, STDERR_FILENO); + const char msg2[] = "=== END BACKTRACE ===\n"; + write(STDERR_FILENO, msg2, sizeof(msg2)-1); + _exit(139); +} +#endif #include "../Windows64/GameConfig/Minecraft.spa.h" #include "../../MinecraftServer.h" #include "../../Player/LocalPlayer.h" @@ -552,6 +575,16 @@ int StartMinecraftThreadProc( void* lpParameter ) int main(int argc, const char *argv[] ) { +#ifdef __linux__ + struct sigaction sa; + sa.sa_handler = sigsegv_handler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESETHAND; + sigaction(SIGSEGV, &sa, NULL); + sigaction(SIGABRT, &sa, NULL); + sigaction(SIGBUS, &sa, NULL); + sigaction(SIGTRAP, &sa, NULL); +#endif app.DebugPrintf("---main()\n"); #if 0 diff --git a/Minecraft.Client/Platform/Linux/Stubs/winapi_stubs.h b/Minecraft.Client/Platform/Linux/Stubs/winapi_stubs.h index 7e5ab1315..7fc8f0891 100644 --- a/Minecraft.Client/Platform/Linux/Stubs/winapi_stubs.h +++ b/Minecraft.Client/Platform/Linux/Stubs/winapi_stubs.h @@ -808,10 +808,9 @@ static inline BOOL ResetEvent(HANDLE hEvent) { #define WAIT_FAILED ((DWORD)0xFFFFFFFF) #define INFINITE 0xFFFFFFFF +#define HANDLE_TYPE_THREAD 0x54485200 -static inline DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds) { - Event* ev = (Event*)hHandle; - if (!ev) return WAIT_FAILED; +static inline DWORD _WaitForEvent(Event* ev, DWORD dwMilliseconds) { pthread_mutex_lock(&ev->mutex); if (dwMilliseconds == INFINITE) { while (!ev->signaled) pthread_cond_wait(&ev->cond, &ev->mutex); @@ -835,6 +834,18 @@ static inline DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds) { return WAIT_OBJECT_0; } +struct LinuxThread; +static inline DWORD _WaitForThread(struct LinuxThread* lt, DWORD dwMilliseconds); + +static inline DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds) { + if (!hHandle) return WAIT_FAILED; + // Check if this is a thread handle (LinuxThread has magic number as first field) + if (*(int*)hHandle == HANDLE_TYPE_THREAD) { + return _WaitForThread((struct LinuxThread*)hHandle, dwMilliseconds); + } + return _WaitForEvent((Event*)hHandle, dwMilliseconds); +} + static inline DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAll, DWORD dwMilliseconds) { if (bWaitAll) { for (DWORD i = 0; i < nCount; i++) WaitForSingleObject(lpHandles[i], dwMilliseconds); @@ -862,6 +873,7 @@ static inline void CloseHandle_Event(HANDLE hEvent) { typedef DWORD (*LPTHREAD_START_ROUTINE)(void*); struct LinuxThread { + int handleType; pthread_t thread; LPTHREAD_START_ROUTINE func; void* param; @@ -870,6 +882,9 @@ struct LinuxThread { int suspended; pthread_mutex_t suspendMutex; pthread_cond_t suspendCond; + pthread_mutex_t completionMutex; + pthread_cond_t completionCond; + int completed; }; static inline void* _linux_thread_entry(void* arg) { @@ -878,20 +893,58 @@ static inline void* _linux_thread_entry(void* arg) { while (lt->suspended) pthread_cond_wait(<->suspendCond, <->suspendMutex); pthread_mutex_unlock(<->suspendMutex); lt->exitCode = lt->func(lt->param); + // Signal completion + pthread_mutex_lock(<->completionMutex); + lt->completed = 1; + pthread_cond_broadcast(<->completionCond); + pthread_mutex_unlock(<->completionMutex); return NULL; } +static inline DWORD _WaitForThread(struct LinuxThread* lt, DWORD dwMilliseconds) { + pthread_mutex_lock(<->completionMutex); + if (lt->completed) { + pthread_mutex_unlock(<->completionMutex); + return WAIT_OBJECT_0; + } + if (dwMilliseconds == 0) { + pthread_mutex_unlock(<->completionMutex); + return WAIT_TIMEOUT; + } + if (dwMilliseconds == INFINITE) { + while (!lt->completed) pthread_cond_wait(<->completionCond, <->completionMutex); + } else { + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += dwMilliseconds / 1000; + ts.tv_nsec += (dwMilliseconds % 1000) * 1000000; + if (ts.tv_nsec >= 1000000000) { ts.tv_sec++; ts.tv_nsec -= 1000000000; } + while (!lt->completed) { + if (pthread_cond_timedwait(<->completionCond, <->completionMutex, &ts) != 0) { + pthread_mutex_unlock(<->completionMutex); + return WAIT_TIMEOUT; + } + } + } + pthread_mutex_unlock(<->completionMutex); + return WAIT_OBJECT_0; +} + static DWORD g_nextThreadId = 1000; static inline HANDLE CreateThread(void*, SIZE_T stackSize, LPTHREAD_START_ROUTINE lpStartAddress, void* lpParameter, DWORD dwCreationFlags, DWORD* lpThreadId) { LinuxThread* lt = (LinuxThread*)calloc(1, sizeof(LinuxThread)); + lt->handleType = HANDLE_TYPE_THREAD; lt->func = lpStartAddress; lt->param = lpParameter; lt->exitCode = STILL_ACTIVE; lt->suspended = (dwCreationFlags & CREATE_SUSPENDED) ? 1 : 0; + lt->completed = 0; lt->threadId = __sync_fetch_and_add(&g_nextThreadId, 1); pthread_mutex_init(<->suspendMutex, NULL); pthread_cond_init(<->suspendCond, NULL); + pthread_mutex_init(<->completionMutex, NULL); + pthread_cond_init(<->completionCond, NULL); if (lpThreadId) *lpThreadId = lt->threadId; pthread_attr_t attr; pthread_attr_init(&attr); diff --git a/Minecraft.World/Build/stlHaEcC b/Minecraft.World/Build/stlHaEcC new file mode 100644 index 000000000..8b277f0dd --- /dev/null +++ b/Minecraft.World/Build/stlHaEcC @@ -0,0 +1 @@ +! diff --git a/Minecraft.World/Network/Connection.cpp b/Minecraft.World/Network/Connection.cpp index 6b5304664..757d53257 100644 --- a/Minecraft.World/Network/Connection.cpp +++ b/Minecraft.World/Network/Connection.cpp @@ -20,11 +20,9 @@ int Connection::writeSizes[256]; void Connection::_init() { // printf("Con:0x%x init\n",this); -#if !defined(__linux__) InitializeCriticalSection(&writeLock); InitializeCriticalSection(&threadCounterLock); InitializeCriticalSection(&incoming_cs); -#endif running = true; quitting = false; @@ -51,11 +49,9 @@ Connection::~Connection() // may get stuck whilst blocking waiting on a read readThread->WaitForCompletion(INFINITE); writeThread->WaitForCompletion(INFINITE); -#if defined(__linux__) DeleteCriticalSection(&writeLock); DeleteCriticalSection(&threadCounterLock); DeleteCriticalSection(&incoming_cs); -#endif // __linux__ delete m_hWakeReadThread; delete m_hWakeWriteThread;