Sign in to follow this  
Lord Henry

Micro-dúvida em relação ao desempenho

Recommended Posts

Eae pessoal. Estou com uma dúvida rápida aqui.
Estou fazendo um sistema de level, nesse sistema existe um verificador server-side que verifica todos os jogadores a cada 1 segundo procurando por players AFK para pausar o Up do level.
Até então sem problemas, mas estou querendo colocar o tempo do up de cada jogador aparecer na tela deles, qual procedimento a seguir é MAIS LEVE para fazer isso?

  1. cria uma variável, salva o tempo nela e triggerClientEvent a cada 1 segundo, para enviar essa variável atualizada ao cliente.
  2. setElementData no jogador a cada 1 segundo, então o client irá sempre mostrar essa data na tela dele.
  3. setAccountData no jogador a cada 1 segundo. [Já vi que é inviável fazer assim, até porque não há como receber esse valor client-side]
  4. fazer o próprio client calcular o tempo de up?

A propósito, o timer em si é este: (server-side)

Spoiler

globalTimer = setTimer (function () -- Executa isso tudo a cada 1 segundo.
	for theKey, thePlayer in ipairs (getElementsByType ("player")) do -- Para cada jogador no server, faz isso:
		if not getElementData (thePlayer, "AFK") then -- Se o jogador não estiver AFK, então:
			local now = getTickCount () -- variável now, recebe o momento atual.
			local account = getPlayerAccount (thePlayer) -- variável account recebe a conta do jogador logado atualmente.
			if not isGuestAccount (account) then -- Se a conta dele não for deslogado, então:
				if (getPlayerIdleTime(thePlayer) >= 300000) then -- 5 min. Se o jogador estiver parado por mais de 5 minutos, então:
					triggerClientEvent (thePlayer, "showAFK", getRootElement()) -- Mostra mensagem de AFK na tela do jogador. (e lá, seta data "AFK" no jogador)
					setAccountData (account, "levelTimeLapsed", (getTickCount() - playerExpStart[thePlayer]) + getAccountData (account, "levelTimeLapsed")) -- Salva o up atual na conta do jogador. (momento atual - momento que começou a upar + tanto de tempo up que ele já tinha na conta)
				else -- Se o jogador não estiver AFK, então:
					playerLapsed[thePlayer] = now - playerExpStart[thePlayer] + getAccountData (account, "levelTimeLapsed") -- variável playerLapsed recebe o momento atual - o momento que começou a upar + o que ele já tem upado na conta.
					if playerLapsed[thePlayer] >= (60000 * tonumber (get ("minuteExp"))) then -- 720000 -- Se o tempo upado ao total passar de 12 minutos, então: (minuteExp = 12 na configuração)
						if playerExp[thePlayer] < 5 then -- O jogador upa de level ao atingir 5 de Exp, se o Exp atual for menor que 5, então:
							playerExp[thePlayer] = playerExp[thePlayer] + 1 -- Aumenta o Exp em 1 e mostra mensagem pra ele dizendo quanto de Exp ele tem agora.
							outputChatBox ("Você ganhou #00FF00+1 de Experiência#FFFFFF. Você tem agora #00FF00"..playerExp[thePlayer].."#FFFFFF /#00FF00 5#FFFFFF pontos de experiência.", thePlayer, 255, 255, 255, true)
						end
						if playerExp[thePlayer] == 5 then -- Se logo depois dele receber o Exp ele ficar com 5, então:
							playerExp[thePlayer] = 0 -- Zera o Exp dele.
							playerLevel[thePlayer] = playerLevel[thePlayer] + 1 -- Aumenta o level dele em 1.
							setElementData (thePlayer, "level", playerLevel[thePlayer]) -- Salva o novo level na conta do jogador. (isso acontece a cada 1 hora por padrão)
							outputChatBox ("Você avançou de nível! Seu nível agora é "..playerLevel[thePlayer]..".", thePlayer, 0, 255, 0, true) -- Avisa isso pra ele, dizendo quanto de level ele tem agora.
						end
						playerExpStart[thePlayer] = now -- Recomeça o tempo Up, setando o momento atual.
						setAccountData (account, "levelTimeLapsed", 0) -- Salva o tempo de Up em 0 na conta do jogador, já que ele está começando a upar um novo Exp.
					end
				end
			end
		end
	end
end, 1000, 0)

function continueUp () -- Executa isso no jogador depois q ele sai do AFK. 
	playerExpStart[client] = getTickCount() -- playerExpStart passa a ser o momento atual. (não é 0)
end
addEvent ("restaureLapse", true)
addEventHandler ("restaureLapse", getRootElement(), continueUp)

 

No script client, deverá ter um onClientRender que deverá mostrar o playerLapsed ao jogador. (só que no client, irá formatar os milisegundos em minutos/segundos.)

Edited by Lord Henry

Share this post


Link to post

Pelo que eu vi, no loop, você verifica na 3ª linha se o jogador não está AFK para que o código prossiga. Por que você está fazendo outra checagem de 5 minutos inativo então? O AFK do element-data funciona de outra forma?

Dito isso, indo ao problema, creio que o que mais te impede de fazer o código de uma forma mais eficiente e organizada, é estar misturando essa verificação de AFK junto com o sistema de level dentro desse loop global.

Fiz aqui um código que você pode usar para a verificação da inatividade dos jogadores:

addEventHandler( "onResourceStart", resourceRoot, 
	function()
		setTimer( startMonitoringPlayers, 10000, 0 )
	end
)

function startMonitoringPlayers()
	for _, player in pairs( getElementsByType("player") ) do
		local acc = getPlayerAccount(player)
		if not isGuestAccount(acc) and isPlayerAFK( player ) and getElementData( player, "playerAFKState" ) ~= true then
			setElementData( player, "playerAFKState", true )
		elseif not isGuestAccount(acc) and isPlayerAFK( player ) ~= true and getElementData( player, "playerAFKState" ) then
			setElementData( player, "playerAFKState", false )
		end
	end
end

function isPlayerAFK( player )
	if isElement(player) then
		return ( getPlayerIdleTime( player ) >= 300000 )
	end
	return false
end

Com o element-data atualizado para sincronizar com o client, você pode usá-lo no outro lado pra caso precisse. Na pior das hipóteses, vai demorar 10 segundos pra detectar o estado do jogador, mas você poder colocar um tempo mais baixo se achar conveniente.

Percebi também que você pausa o progresso do level quando fica inativo por 5 minutos. Você pode colocar no lugar do setElementData uma tabela individual e quando detectar se o jogador ficou AFK ou voltou ao jogo você pode colocar o triggerClientEvent que você usou na linha 9 do seu código.

Nessa chamada ao client, você pode saber no lado do client quando ele fica AFK e quando volta, acho que com essas informações, você pode fazer o código do level no lado client.

 

Share this post


Link to post

Então... na verdade quando o jogador fica AFK. Ele ativa uma função no cliente do jogador que irá gerar um código e mostrar na tela do jogador para que ele digite pra poder sair do AFK. Quando ele usar o código, vai se movimentar 0.01 posição pro lado, para reiniciar o getPlayerIdleTime e então seta a data "AFK" false no jogador. O objetivo é justamente fazer o jogador não querer ficar AFK. Se o jogador se mover sem acertar o código, a data "AFK" vai continuar lá e ele vai continuar bloqueado de upar até que digite o código que está mostrando na tela.

E eu coloquei verificador duplo de AFK ali no timer pois não quero q ele fique ativando o cliente a cada segundo, ele só deve ativar 1 vez e esperar o jogador desativá-lo.

Edited by Lord Henry

Share this post


Link to post

Ah sim, agora entendi. Tem esta função útil que acredito que seja a mesma coisa que getPlayerIdleTime e você pode usar no lado client:

function isElementMoving (theElement )
   if isElement ( theElement ) then                                   -- First check if the given argument is an element
      return Vector3( getElementVelocity( theElement ) ).length ~= 0
   end
   return false
end

Como eu disse na outra resposta, você pode fazer o level no lado client também.

Share this post


Link to post

Mas e quando o jogador sair do servidor? Como eu vou fazer pra salvar os dados na conta dele? Faço um triggerClientEvent pra que o cliente envie os dados ao servidor usando um triggerServerEvent?

Estou usando isso para salvar os dados quando o resource para. Também faço isso quando o jogador da Quit ou desloga.
 

function saveAllLevels ()
	for theKey, thePlayer in ipairs (getElementsByType ("player")) do
		local acc = getPlayerAccount (thePlayer)
		if not isGuestAccount (acc) then
			setAccountData (acc, "level", playerLevel[thePlayer]) -- Variáveis que estou usando para guardar os dados o tempo todo.
			setAccountData (acc, "levelExp", playerExp[thePlayer])
			setAccountData (acc, "levelTimeLapsed", playerLapsed[thePlayer])
		end
	end
end
addEventHandler ("onResourceStop", getResourceRootElement(getThisResource()), saveAllLevels)

 

Share this post


Link to post

Sim. onClientResourceStop + triggerServerEvent e envia os dados pra serem salvos na conta. onClientResourceStop vai funcionar substituindo os dois eventos do lado server - onPlayerQuit e onResourceStop.

Quando sair da conta, você pode usar onPlayerLogout mesmo e chamar um evento no client para salvar os dados chamando outro evento do lado server.

Edited by DNL291

Share this post


Link to post

Ainda estou tentando fazer client-side.
Estou tendo que mudar a lógica de tudo, passar todas as variáveis pro client.

Edited by Lord Henry

Share this post


Link to post

fiz essa parte do client, só nao testei, nao tive tempo.

-- afk por ficar parado
local x,y = guiGetScreenSize()
local afk = {
	x = 0,
	y = 0,
	z = 0,
	tick = getTickCount(),
	state = false
}

function drawAfkMsg()
	dxDrawText("You Are AFK!",0,0,x,y,tocolor(255,255,255,255),1,"default","center","center",true)
end

function startAfk()
	local x,y,z = getElementPosition(localPlayer)
	if afk.x == x and afk.y == y and afk.z == z then
		local now = getTickCount() - afk.tick
		if now >= 10000 then
			if not afk.state then
				afk.state = true
				setElementData(localPlayer,"posAFK",true)
				removeEventHandler("onClientRender",root,drawAfkMsg)
				addEventHandler("onClientRender",root,drawAfkMsg)
			end
		end
	else
		clearAfk()
	end
end

function clearAfk()
    removeEventHandler("onClientRender",root,drawAfkMsg)
	local x,y,z = getElementPosition(localPlayer)
	setElementData(localPlayer,"posAFK",false)
	afk.x = x
	afk.y = y
	afk.z = z
    afk.tick = getTickCount()
	afk.state = false
end
setTimer(startAfk,1000,0)

-- afk por sair do jogo
addEventHandler("onClientMinimize",root,
function()
	setElementData(localPlayer,"tabAFK",true)
end
)

addEventHandler("onClientRestore",root,
function()
	setElementData(localPlayer,"tabAFK",false)
end
)

 

Share this post


Link to post

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
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.