Jump to content

[HELP] DX Login, freezing


..:D&G:..

Recommended Posts

So I made this login panel with DX, but after a few seconds having the window (renderLoginWindow()) open and clicking the buttons a few times, my game freezes but it doesn't go into "not responding".

loginMod = 0 
local rustFont = dxCreateFont(":Main/files/Rust.ttf", 30) 
function build_loginWin() 
    loginMod = 1 
    dxDrawText("Login", s[1]*161/1920, s[2]*635/1080, s[1]*357/1920, s[2]*718/1080, tocolor(255, 255, 255, 255), 1.00, rustFont, "center", "center", false, false, false, false, false) 
    dxDrawText("Register", s[1]*136/1920, s[2]*728/1080, s[1]*380/1920, s[2]*799/1080, tocolor(255, 255, 255, 255), 1.00, rustFont, "center", "center", false, false, false, false, false) 
    dxDrawText("Quit", s[1]*161/1920, s[2]*809/1080, s[1]*347/1920, s[2]*886/1080, tocolor(255, 255, 255, 255), 1.00, rustFont, "center", "center", false, false, false, false, false) 
    showChat(false) 
    showCursor(true) 
    guiSetInputMode("no_binds_when_editing") 
end 
  
function showLoginOnJoin() 
    addEventHandler("onClientRender",root,build_loginWin) 
    addEventHandler("onClientClick", getRootElement(), onLoginButtonsClick ) 
end 
addEventHandler("onClientPlayerJoin", getRootElement(), showLoginOnJoin) 
  
function showLoginOnStartup() 
    showLoginOnJoin() 
end 
addEventHandler("onClientResourceStart", getRootElement(), showLoginOnJoin) 
  
function renderLoginWindow() 
    createLoginEditBoxes() 
    loginMod = 2 
  
    dxDrawText("Close", s[1]*1130/1920, s[2]*613/1080, s[1]*1260/1920, s[2]*662/1080, tocolor(255, 255, 255, 255), 1.00, lRustFont1, "center", "center", false, false, false, false, false) 
    dxDrawText("Login", s[1]*931/1920, s[2]*613/1080, s[1]*1109/1920, s[2]*662/1080, tocolor(255, 255, 255, 255), 1.00, lRustFont1, "center", "center", false, false, false, false, false) 
end 
  
function onLoginButtonsClick() 
    if clickLoginClose and (getElementData(getLocalPlayer(), "loggedin") == false) and (loginMod == 2) then 
        removeEventHandler("onClientRender",getRootElement(),renderLoginWindow)  
        loginMod = 1 
    elseif clickLoginButt and (getElementData(getLocalPlayer(), "loggedin") == false) and (loginMod == 2) then 
        -- LOGIN FUNCTION 
    elseif clickLogin and (getElementData(getLocalPlayer(), "loggedin") == false) and (loginMod == 1) then 
        addEventHandler("onClientRender",root,renderLoginWindow) 
    elseif clickRegister and (getElementData(getLocalPlayer(), "loggedin") == false) and (loginMod == 1) then 
        outputDebugString("Clicked register") 
        --addEventHandler("onClientRender",root,renderRegisterWindow) 
    elseif clickQuit and (getElementData(getLocalPlayer(), "loggedin") == false) and (loginMod == 1) then 
        outputDebugString("Quit") 
        --addEventHandler("onClientRender",root,renderQuitWindow) 
    end 
end 

Thanks.

Link to comment

That's simply to heavy to run, remember that onClientRender already uses a large amount of system resources just being executed. You're also using two events to trigger the client render (onClientPlayerJoin) and (onClientResourceStart) of which one of them triggers as soon another player joins.

You have multiple GUI's drawing on top of each others, on line 39 you're also adding another onClientRender to draw yet another GUI instead of removing it which would have been the logical choice. This means you won't need many clicks on the login button until your game freezes.

Link to comment

I sorted it out now, now it removes the handler for the old function before adding it to a new one, and now there is only 1 function for the buttons. But now after a few seconds, the font just failes and turns to a boolean, and when I click a "button", it clicks 2 times instead of once...

Link to comment

You'll need to read the function and event descriptions more thoroughly. All the answers you're looking are there.

1. Render events are run with every frame, so whatever you do here need to be done carefully. As stated before, you were probably creating new GUI elements with every frame. This would mean 30-60 new GUI elements per second. No wonder it stops responding, eh? :P

2. The reason onClientClick is triggering twice is because you're not checking whether it was pressed down or released. It triggers for both of those.

Example;

function ExampleCode(theButton, theState) 
    if(theButton == "left" and theState == "down") then 
        -- Left mouse button was pressed down 
    end 
end 

Link to comment
You'll need to read the function and event descriptions more thoroughly. All the answers you're looking are there.

1. Render events are run with every frame, so whatever you do here need to be done carefully. As stated before, you were probably creating new GUI elements with every frame. This would mean 30-60 new GUI elements per second. No wonder it stops responding, eh? :P

2. The reason onClientClick is triggering twice is because you're not checking whether it was pressed down or released. It triggers for both of those.

Example;

function ExampleCode(theButton, theState) 
    if(theButton == "left" and theState == "down") then 
        -- Left mouse button was pressed down 
    end 
end 

Fucking finally someone to point me in the right direction! Now that I fixed the double clicking, what other event should I use?

Link to comment

[quote name=..:D&G:..]:o finally someone to point me in the right direction! Now that I fixed the double clicking, what other event should I use?

For what? For the above you use onClientClick. Or are you referring to the rendering? What you're doing should work just fine just make sure stuff like createLoginEditBoxes() is only run once when needed. You can do so by either using an if statement or simply executing it when they click a button instead - which would be the logical way to go.

Edit:

Just noticed that you're trying to use onClientClick on GUI elements. For this you'll want to use onClientGUIClick instead.

Edit2:

I was bored, so I re-wrote your code a bit to show how I personally would write it. Of course, nothing is tested so don't copy and paste it and expect it to work. It's very likely I may have missed something :P It's just to give you an idea of how it could be better organized.

local rustFont = dxCreateFont(":Main/files/Rust", 30) 
  
-- Use this table to control what is being rendered, thus, you can keep it all undere one drawing function. Add entires as you want, remember to add a new elseif statement to DX_MenuDrawing! 
local activeMenu = { 
    ["MainMenu"] = true, 
    ["LoginMenu"] = false, 
    ["RegisterMenu"] = false 
} 
  
function DX_MenuDrawing() 
    if(activeMenu["MainMenu"] == true) then 
        -- Main menu is currently true, so draw any necessary DX stuff here. 
        dxDrawText("Login", s[1]*161/1920, s[2]*635/1080, s[1]*357/1920, s[2]*718/1080, tocolor(255, 255, 255, 255), 1.00, rustFont, "center", "center", false, false, false, false, false) 
        dxDrawText("Register", s[1]*136/1920, s[2]*728/1080, s[1]*380/1920, s[2]*799/1080, tocolor(255, 255, 255, 255), 1.00, rustFont, "center", "center", false, false, false, false, false) 
        dxDrawText("Quit", s[1]*161/1920, s[2]*809/1080, s[1]*347/1920, s[2]*886/1080, tocolor(255, 255, 255, 255), 1.00, rustFont, "center", "center", false, false, false, false, false) 
    elseif(activeMenu["LoginMenu"] == true) then 
        -- Login menu is currently true, so draw any necessary DX stuff here. 
        dxDrawText("Close", s[1]*1130/1920, s[2]*613/1080, s[1]*1260/1920, s[2]*662/1080, tocolor(255, 255, 255, 255), 1.00, lRustFont1, "center", "center", false, false, false, false, false) 
        dxDrawText("Login", s[1]*931/1920, s[2]*613/1080, s[1]*1109/1920, s[2]*662/1080, tocolor(255, 255, 255, 255), 1.00, lRustFont1, "center", "center", false, false, false, false, false) 
    elseif(activeMenu["RegisterMenu"] == true) then 
        -- Register menu is currently true, so draw any necessary DX stuff here. 
    end 
end 
  
function DetectMenuClicks_Handler(theButton, theState) 
    if(theButton == "left" and theState == "up") then 
        if(source == clickLoginClose) then 
            -- 
        elseif(source == clickLoginButt) then 
            -- 
        elseif(source == clickLogin and activeMenu["LoginMenu"] == false and getElementData(localPlayer, "loggedin") == false) then -- Make sure that the new menu is not already showing, to avoid clicking things not currently visible. 
            -- Since now after you've clicked it, it's active - so update the status 
            activeMenu["MainMenu"] = false -- Make sure the previous stage stops rendering 
            activeMenu["LoginMenu"] = true 
            createLoginEditBoxes() -- Alternatively you can create them on start and just use guiSetVisible. 
        elseif(source == clickRegister and activeMenu["RegisterMenu"] == false and getElementData(localPlayer, "loggedin") == false) then 
            activeMenu["MainMenu"] = false -- Make sure the previous stage stops rendering 
            activeMenu["RegisterMenu"] = true 
        elseif(source == clickQuit) then 
            -- Make sure you stop drawing, not necessary if the player quits the server, obviously. 
            removeEventHandler("onClientRender", root, DX_MenuDrawing) 
        end 
    end 
end 
addEventHandler("onClientGUIClick", root, DetectMenuClicks_Handler) 
  
function OnStart_Handler() 
    -- Stuff like these only need to be run once, instead of with every frame. 
    showChat(false) 
    showCursor(true) 
    guiSetInputMode("no_binds_when_editing") 
    -- 
    addEventHandler("onClientRender", root, DX_MenuDrawing) 
end 
addEventHandler("onClientResourceStart", resourceRoot, OnStart_Handler) 

Also to further optimize it, you'll want to avoid doing hardcoded math when drawing frames if necessary. For example, you're doing this to make your drawings relative; s[1]*161/1920 you could instead do this s[1]*0.0838541666666667.

Yes, it looks uglier, but it's one calculation less. And this is a calculation you'll be doing every frame. While the difference may not be noticeable at all, it's good to keep such things in mind as optimization is very important.

To speed the process up you can use this;

I use a website where you can run Lua code to make the process very fast and straight forward, since doing it all manually is a very tedious process. Especially with DX functions.

Simply paste this code(into the website linked above) and enter the appropriate values. Then copy the output and you're golden.

local sX, sY, wX, hY = 480, 240, 969, 570; -- Paste the absolute values here 
local sourceWidth = 1920;    -- Change those to the source values. 
local sourceHeight = 1080;   -- Change those to the source values. 
local nSX, nSY, nWX, nHY = (sX/sourceWidth), (sY/sourceHeight), (wX/sourceWidth), (hY/sourceHeight); 
  
for i=0, 47 do 
   print(""); -- This is just to clear the print window, so you don't confused what to copy. 
end 
  
print(tostring(nSX).."*screenX, "..tostring(nSY).."*screenY, "..tostring(nWX).."*screenX, "..tostring(nHY).."*screenY"); 

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...