Contributor Amun 1923 Posted January 22, 2023 Contributor Share Posted January 22, 2023 (edited) Skip this part, you don't need it anymore. Scroll down. The game loop freezes when dragging/resizing the window. This is an attempt at fixing that. We'll open a thread and call "Process()" from there when we receive WM_ENTERSIZEMOVE and then shut it down when receiving WM_EXITSIZEMOVE, continuing our main game loop. There's also the option of creating a timer when entering WM_ENTERSIZEMOVE, calling "Process()" when receiving WM_TIMER and killing it when receiving WM_EXITSIZEMOVE, but there's quite a big delay till the timer starts and it's also not very reliable, so.. Note: This is HIGHLY experimental, and it might result in data races and crash the client. Even though I tested it as good as I could and tried to make sure the main thread's loop doesn't resume before ending the future, it's still a possibility for that to happen when you least expect it. Video: Code: This is the hidden content, please Sign In or Sign Up or This is the hidden content, please Sign In or Sign Up Many thanks to @limefor taking the time to test it. Good luck! UPDATE: Forget everything I gave you the last time, here's the complete fix: UPDATE2: Blocked right click as well, thanks @ CORKY If there's anything else that needs blocking/changing, let me know and I'll update the topic. Spoiler // PythonApplication.cpp // Search m_dwLastIdleTime(0), // Add m_IsMovingMainWindow(false), // Search #ifndef _DEBUG SetEterExceptionHandler(); #endif // Add m_InitialMouseMovingPoint = {}; // Search void CPythonApplication::Loop() { ... } // Add before: void CPythonApplication::SetUserMovingMainWindow(bool flag) { if (flag && !GetCursorPos(&m_InitialMouseMovingPoint)) return; m_IsMovingMainWindow = flag; } bool CPythonApplication::IsUserMovingMainWindow() const { return m_IsMovingMainWindow; } void CPythonApplication::UpdateMainWindowPosition() { POINT finalPoint{}; if (GetCursorPos(&finalPoint)) { LONG xDiff = finalPoint.x - m_InitialMouseMovingPoint.x; LONG yDiff = finalPoint.y - m_InitialMouseMovingPoint.y; RECT r{}; GetWindowRect(&r); SetPosition(r.left + xDiff, r.top + yDiff); m_InitialMouseMovingPoint = finalPoint; } } // Search void CPythonApplication::Loop() { #ifdef PROFILING Profiler::Instance().beginSession("session1"); #endif while (1) { // Add if (IsUserMovingMainWindow()) UpdateMainWindowPosition(); // Looks like this: while (1) { if (IsUserMovingMainWindow()) UpdateMainWindowPosition(); if (IsMessage()) { if (!MessageProcess()) break; } else { if (!Process()) break; m_dwLastIdleTime = ELTimer_GetMSec(); } } Spoiler // PythonApplication.h // Find void Loop(); // Add bool IsUserMovingMainWindow() const; void SetUserMovingMainWindow(bool flag); void UpdateMainWindowPosition(); // Go to the end and protected: bool m_IsMovingMainWindow;//add this POINT m_InitialMouseMovingPoint; // and this int m_iCursorNum; Spoiler // PythonApplicationProcedure.cpp // Find case WM_EXITSIZEMOVE: { ... } // Add case WM_NCLBUTTONDOWN: { switch (wParam) { case HTMAXBUTTON: case HTSYSMENU: return 0; case HTMINBUTTON: ShowWindow(hWnd, SW_MINIMIZE); return 0; case HTCLOSE: RunPressExitKey(); return 0; case HTCAPTION: if (!IsUserMovingMainWindow()) SetUserMovingMainWindow(true); return 0; } break; } case WM_NCLBUTTONUP: { if (IsUserMovingMainWindow()) SetUserMovingMainWindow(false); break; } case WM_NCRBUTTONDOWN: case WM_NCRBUTTONUP: case WM_CONTEXTMENU: return 0; Edited January 22 by Amun Added full fix 118 1 21 2 48 Link to comment Share on other sites More sharing options...
Active Member lime 248 Posted January 22, 2023 Active Member Share Posted January 22, 2023 Agreed, works fine for me. Be careful while implementing it. Thanks, @ Amun! 2 Link to comment Share on other sites More sharing options...
Premium CORKY 259 Posted January 25, 2023 Premium Share Posted January 25, 2023 Great release, but I also want to point out that the freezing will also happen when holding right click on the bar or opening the context menu. Adding case WM_CONTEXTMENU: return 0; break; into the CPythonApplication::WindowProcedure message switch will stop the context menu from opening. 2 1 Link to comment Share on other sites More sharing options...
Premium Intel 765 Posted February 27, 2023 Premium Share Posted February 27, 2023 On 1/25/2023 at 2:56 AM, dumita123 said: Great release, but I also want to point out that the freezing will also happen when holding right click on the bar or opening the context menu. Adding case WM_CONTEXTMENU: return 0; break; into the CPythonApplication::WindowProcedure message switch will stop the context menu from opening. This still won't fix the problem when left clicking on the bar (and keeping the left click down, same with the right click). When moving, the player will keep moving in background and the window will also unfreeze, but not when auto attacking and pressing the spacebar, or moving pressing W (basically pressing any button while keeping the menubar clicked fucks it up. I still haven't found a solution for that but I also don't know if it causes to fly bug an enemy character). 1 Link to comment Share on other sites More sharing options...
Contributor Amun 1923 Posted February 27, 2023 Author Contributor Share Posted February 27, 2023 (edited) 15 hours ago, xXIntelXx said: This still won't fix the problem when left clicking on the bar (and keeping the left click down, same with the right click). When moving, the player will keep moving in background and the window will also unfreeze, but not when auto attacking and pressing the spacebar, or moving pressing W (basically pressing any button while keeping the menubar clicked fucks it up. I still haven't found a solution for that but I also don't know if it causes to fly bug an enemy character). Actually, it does. I can use the keyboard normally(move, attack, write) while dragging/keeping the window(left click). I've not thought about fixing the right click as well(for some reason). Also, I was extremely busy, so I've not checked to see if Dumita's change will help in that regard. These being said, however, you can trigger/close the thread when entering and exiting the context menu. I don't see why you wouldn't be able to use the same solution for the right click as well. Edit: Just noticed(forgot about it) I also have a video of me moving when dragging the client: Regards, Amun Edited February 27, 2023 by Amun + video Link to comment Share on other sites More sharing options...
Premium CORKY 259 Posted February 27, 2023 Premium Share Posted February 27, 2023 14 minutes ago, Amun said: Actually, it does. I can use the keyboard normally(move, attack, write) while dragging/keeping the window(left click). I've not thought about fixing the right click as well(for some reason). Also, I was extremely busy, so I've not checked to see if Dumita's change will help in that regard. These being said, however, you can trigger/close the thread when entering and exiting the context menu. I don't see why you wouldn't be able to use the same solution for the right click as well. Edit: Just noticed(forgot about it) I also have a video of me moving when dragging the client: Regards, Amun What Intel was saying is that if you're holding the left/right click on the bar without moving the mouse at all, the game will still freeze for around 300-500ms. My post was only related to the context menu (because it was freezing the client while it was opened) so it just removes that option since no one was using it anyway. Link to comment Share on other sites More sharing options...
Contributor Amun 1923 Posted February 27, 2023 Author Contributor Share Posted February 27, 2023 4 minutes ago, dumita123 said: What Intel was saying is that if you're holding the left/right click on the bar without moving the mouse at all, the game will still freeze for around 300-500ms. My post was only related to the context menu (because it was freezing the client while it was opened) so it just removes that option since no one was using it anyway. Ah, yes, I just noticed now. If you want the transition to be done instantly, keep the thread opened at all times and just let it know when it can and can't call Process, instead of triggering a new future whenever you click the bar. ez Link to comment Share on other sites More sharing options...
Premium Intel 765 Posted February 27, 2023 Premium Share Posted February 27, 2023 (edited) 48 minutes ago, dumita123 said: What Intel was saying is that if you're holding the left/right click on the bar without moving the mouse at all, the game will still freeze for around 300-500ms. My post was only related to the context menu (because it was freezing the client while it was opened) so it just removes that option since no one was using it anyway. 34 minutes ago, Amun said: Ah, yes, I just noticed now. If you want the transition to be done instantly, keep the thread opened at all times and just let it know when it can and can't call Process, instead of triggering a new future whenever you click the bar. ez The problem is not the transition to be done instantly (it's irrelevant as long as the client is still processing in the background) This is what happens when moving with W (so W pressed and left click on the bar at the same time without releasing it): https://metin2.download/picture/577iCuT4g8a26z941R9dHO817H5tNf35/.gif This is what happens when moving just clicking left click once: https://metin2.download/picture/N4ZAQcgKtYRoABf9YdU43WgjBRK24RpY/.gif Side note when I was banging my head to the wall, I stumbled upon a post saying:"Your application is most likely "freezing" because it has a WinMain loop similar to this: while (true) { if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } else { TickGame(); } } Guess what do we have here.. void CPythonApplication::Loop() { while (1) { if (IsMessage()) { if (!MessageProcess()) break; } else { if (!Process()) break; m_dwLastIdleTime=ELTimer_GetMSec(); } } } bool CMSApplication::IsMessage() { MSG msg; if (!PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) return false; return true; } bool CMSApplication::MessageProcess() { MSG msg; if (!GetMessage(&msg, NULL, 0, 0)) return false; TranslateMessage(&msg); DispatchMessage(&msg); return true; } Edited February 27, 2023 by Metin2 Dev Core X - External 2 Internal Link to comment Share on other sites More sharing options...
Contributor Amun 1923 Posted February 27, 2023 Author Contributor Share Posted February 27, 2023 (edited) Spoiler 16 minutes ago, xXIntelXx said: The problem is not the transition to be done instantly (it's irrelevant as long as the client is still processing in the background) This is what happens when moving with W (so W pressed and left click on the bar at the same time without releasing it): https://metin2.download/picture/577iCuT4g8a26z941R9dHO817H5tNf35/.gif This is what happens when moving just clicking left click once: https://metin2.download/picture/N4ZAQcgKtYRoABf9YdU43WgjBRK24RpY/.gif Side note when I was banging my head to the wall, I stumbled upon a post saying:"Your application is most likely "freezing" because it has a WinMain loop similar to this: while (true) { if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } else { TickGame(); } } Guess what do we have here.. void CPythonApplication::Loop() { while (1) { if (IsMessage()) { if (!MessageProcess()) break; } else { if (!Process()) break; m_dwLastIdleTime=ELTimer_GetMSec(); } } } bool CMSApplication::IsMessage() { MSG msg; if (!PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) return false; return true; } bool CMSApplication::MessageProcess() { MSG msg; if (!GetMessage(&msg, NULL, 0, 0)) return false; TranslateMessage(&msg); DispatchMessage(&msg); return true; } Ah, yes, I see what you mean. It does, indeed, freeze when keeping the button pressed and then clicking the window. Also, yeah, I went through all of those forum topics/stackoverflow questions/docs.. It's been a while, but I remember there were many things to take into consideration when making the game loop. I will fix this(button thingy) as well at some point, but I can't promise anything because I won't have a lot of free time for the next month or so. Edited February 27, 2023 by Metin2 Dev Core X - External 2 Internal 1 Link to comment Share on other sites More sharing options...
Premium CORKY 259 Posted January 18 Premium Share Posted January 18 (edited) I've fixed it entirely by creating a separate detached thread for the process function. I've tested it for about 1 hour doing duels/killing mobs, trying to fuck it up. If you want to try this method, revert the changes done from the main post and do the following: PythonApplication.cpp // Add #include <thread> if you don't have it already. // Replace CPythonApplication:Loop() with the following: void CPythonApplication::Loop() { static bool m_started = false; while (true) { if (IsMessage()) { if (!MessageProcess()) break; } else { if (!m_started) { std::thread process_thread([this]() { while (1) { if (!Process()) break; } }); m_started = true; process_thread.detach(); } } } } The result (I've spammed clicks on the window bar, moved it, constantly calling the message): Spoiler Edited January 18 by CORKY typo Link to comment Share on other sites More sharing options...
Contributor Amun 1923 Posted January 19 Author Contributor Share Posted January 19 6 hours ago, CORKY said: I've fixed it entirely by creating a separate detached thread for the process function. I've tested it for about 1 hour doing duels/killing mobs, trying to fuck it up. If you want to try this method, revert the changes done from the main post and do the following: PythonApplication.cpp // Add #include <thread> if you don't have it already. // Replace CPythonApplication:Loop() with the following: void CPythonApplication::Loop() { static bool m_started = false; while (true) { if (IsMessage()) { if (!MessageProcess()) break; } else { if (!m_started) { std::thread process_thread([this]() { while (1) { if (!Process()) break; } }); m_started = true; process_thread.detach(); } } } } The result (I've spammed clicks on the window bar, moved it, constantly calling the message): Reveal hidden contents Thank you, Corky, but maybe next time ask why none of us, the plebs, ever came forward with that solution. 2 1 1 Link to comment Share on other sites More sharing options...
Filachilla 29 Posted January 19 Share Posted January 19 1 hour ago, Amun said: Thank you, Corky, but maybe next time ask why none of us, the plebs, ever came forward with that solution. Maybe because its experimental so far who wanna share perfect code?.. Im glad when anyone share some fragment ideas 1 Link to comment Share on other sites More sharing options...
Premium Intel 765 Posted January 19 Premium Share Posted January 19 (edited) 11 hours ago, Amun said: Thank you, Corky, but maybe next time ask why none of us, the plebs, ever came forward with that solution. ahah I remember I talked with Amun about this and told me that this might happen. I've tested again Amun's way and at the end, it's the same as I had it. It's fine in 99.99% cases but a friend of mine told me the client apparently can't freeze, ever, even if in the background it's still "rendering" (so after the freeze you'll see your actual position), because with that freeze players can get out of the "fly" (with the original client, it can even execute some skills multiple times. Basically, you get stuck with sword hits, then you freeze the client and do like the warrior's three way skill. You'll be "unstuck" from the hits, and that skill might even do double/triple or more damage. I LOVE THIS GAME BTW.). Edited January 19 by Intel 1 Link to comment Share on other sites More sharing options...
Contributor Amun 1923 Posted January 20 Author Contributor Share Posted January 20 (edited) Topic updated, added full fix. I don't even know why I spent 6 hours reading docs and 100 forum pages from 2006 when I could've done this from the beginning, but whatever. Fuck you and I'll see you tomorrow Edit 1: Added checks for right click Edit 2: Proper function and variable names. GitHub and download links updated Edited January 20 by Amun 1 1 Link to comment Share on other sites More sharing options...
Premium Intel 765 Posted January 20 Premium Share Posted January 20 Amun's had enough 2 Link to comment Share on other sites More sharing options...
Premium Speachless 767 Posted January 20 Premium Share Posted January 20 (edited) Right click remains stuck when you use it as soon as the client opens, before it fully loads. As a quick fix, I enabled your solution only after the login is initialized. I did not found any other bug, nor my players reported any. Thank you for the fix! Edited January 20 by Speachless 1 Link to comment Share on other sites More sharing options...
guckemal 0 Posted January 20 Share Posted January 20 (edited) I have a problem when I compile my client source it tells me this error Marty 5.7 Source "InitialMousePoint" undeclared identifier Edited January 20 by guckemal Link to comment Share on other sites More sharing options...
Contributor Amun 1923 Posted January 20 Author Contributor Share Posted January 20 (edited) 1 hour ago, Speachless said: Bug: If you try to drag the client before it's fully loaded (when you start if for the first time) it remains suck on "drag mode" Ok, thanks, I'll add a fix later tonight. As far as I know, most applications have a "fucking stop" type of deal when clicking the escape key. We'll see. 1 hour ago, guckemal said: I have a problem when I compile my client source it tells me this error Marty 5.7 Source "InitialMousePoint" undeclared identifier Ah damn, yeah, it should be m_InitialMouseMovingPoint in CPythonApplication::UpdateMainWindowPosition(). I'll update it now, thanks Update: From what I see, you can manage to get it stuck in "drag mode" if you: start dragging in loading phase and, while it's loading, you drag your mouse out of the window and release really fast But as soon as the app is done processing it'll snap right under your mouse, and a simple click will just take it out of "drag mode", which is default behavior for most applications you're using today, so I don't see that as a problem. Waiting for Speachless to answer my DM and tell me exactly how to get it stuck with right click, because I tried 20 times and couldn't. Edited January 20 by Amun 1 Link to comment Share on other sites More sharing options...
guckemal 0 Posted January 21 Share Posted January 21 (edited) If I move my metin window so that I only see half the metin window (half out of the monitor area) or move it to another monitor and then move it back to normal position, I get a black screen where the metin window is not visible including a short lag. This happens since the FIX https://metin2.download/picture/47k70pKv53Fv3jcnKZ9jixtK4UYlw2Vp/.gif Edited January 21 by Metin2 Dev International Core X - External 2 Internal Link to comment Share on other sites More sharing options...
Contributor Amun 1923 Posted January 21 Author Contributor Share Posted January 21 6 hours ago, guckemal said: If I move my metin window so that I only see half the metin window (half out of the monitor area) or move it to another monitor and then move it back to normal position, I get a black screen where the metin window is not visible including a short lag. This happens since the FIX https://metin2.download/picture/47k70pKv53Fv3jcnKZ9jixtK4UYlw2Vp/.gif That's the default behavior for the app, you just didn't get the chance to see it yet. If you can't see that part of the screen, then it won't render it(hence the black part), and when you take it back, it'll start rendering it again(sometimes with a slight delay, which is why get the chance to see the black part for a few ms). Link to comment Share on other sites More sharing options...
Active Member ReFresh 2353 Posted January 21 Active Member Share Posted January 21 (edited) Ah, you didn't update the github repo since now. Didn't see it was already metioned. Edited January 22 by Metin2 Dev International Core X - External 2 Internal 1 I'll be always helpful! Link to comment Share on other sites More sharing options...
Contributor Amun 1923 Posted January 21 Author Contributor Share Posted January 21 (edited) 3 hours ago, ReFresh said: Ah, you didn't update the github repo since now. Didn't see it was already metioned. Done, updated repo and the download link, thanks for reminding me! Edited January 22 by Metin2 Dev International Core X - External 2 Internal 1 Link to comment Share on other sites More sharing options...
Refuse1337 0 Posted January 22 Share Posted January 22 11 hours ago, Amun said: Done, updated repo and the download link, thanks for reminding me! I found 1 bug, if press or hold in right corner on the top (where is close, minimize etc..), the client still freezing 1 Link to comment Share on other sites More sharing options...
Premium CORKY 259 Posted January 22 Premium Share Posted January 22 (edited) 12 hours ago, Refuse1337 said: I found 1 bug, if press or hold in right corner on the top (where is close, minimize etc..), the client still freezing You need to handle manually the min/max/close buttons. You can do it like the following: case WM_NCLBUTTONDOWN: { switch (wParam) { case HTMINBUTTON: ShowWindow(hWnd, SW_MINIMIZE); return 0; case HTMAXBUTTON: case HTSYSMENU: return 0; case HTCLOSE: RunPressExitKey(); return 0; case HTCAPTION: if (!IsUserMovingMainWindow()) SetUserMovingMainWindow(true); return 0; } break; } Additionally, I've also blocked the HTSYSMENU param, otherwise, the players can click on the application icon that's in the non-client area and it'll pop up the system menu, which will, again, freeze the application. Edited January 22 by CORKY Added HTSYSMENU 1 1 Link to comment Share on other sites More sharing options...
Contributor Amun 1923 Posted January 22 Author Contributor Share Posted January 22 (edited) [EDITED OUT] Corky will update his message, no point in writing the same thing twice. Will update the repository and the archive in a few min. Edit: Topic, repository and archive are up to date Edit2: In case it helps any of you. Speachless answered and said he can still get it to freeze in the very beginning, but it's because he's loading some things before the window is fully loaded, which means it's a custom problem that I will not handle for you. Not exactly a problem if you ask me, but his fix was to only enable the window moving part after the player logged in(should be fine if you enable it right before the game ::Loop() starts as well). Edited January 22 by Amun 3 Link to comment Share on other sites More sharing options...
Recommended Posts