Jump to content

Soluções pra elemenData


Recommended Posts

mano tudo depende do quando voce usa por exemplo, se voce usa element data pra fazer um sistema no serverside tente emplementar ele usando tabelas, é uma alternativa, agora se voce usa elementdata que intergram client-server nao tem outra opção.

por exemplo uma data com nome 'cash' onde voce atualiza ela no serverside e mostra ela com um dx no client, é muito melhor usar o element mesmo do que uma função que fica atualizando.

Link to comment
3 hours ago, Gw8 said:

mano tudo depende do quando voce usa por exemplo, se voce usa element data pra fazer um sistema no serverside tente emplementar ele usando tabelas, é uma alternativa, agora se voce usa elementdata que intergram client-server nao tem outra opção.

por exemplo uma data com nome 'cash' onde voce atualiza ela no serverside e mostra ela com um dx no client, é muito melhor usar o element mesmo do que uma função que fica atualizando.

Entendi, é pq eu tava usando elementDate em algumas coisas mas era tanto uso q tava crashando meu servidor. Meio q fiquei sem opção.

Link to comment
  • Moderators

O maior erro é usar setElementData para qualquer tipo de armazenamento para um player/elemento. Isso é o que vejo em muitos scripts de amadores no assunto.

Aqui vai um exemplo do uso incorreto:

Spoiler

 


-- alterna a visibilidade do jogador entre 255 e 0
addCommandHandler( "setalpha", function()
	
	-- seta no element-data o alpha do ped do jogador
	if getElementData(localPlayer, "player-alpha") and getElementData(localPlayer, "player-alpha") == 0 then -- se já tiver invisivel faremos mostrar totalmente
		setElementAlpha( localPlayer, 255 ) -- mudar o alpha do ped
		setElementData( localPlayer, "player-alpha", 255 ) -- atualizar no element-data do player
	else
		setElementAlpha( localPlayer, 0 ) -- mudar o alpha do ped
		setElementData( localPlayer, "player-alpha", 0 ) -- atualizar no element-data do player
	end
end )

-- seta a visibilidade do jogador progressivamente de 255 até 0
addCommandHandler( "desaparecer", function()
	-- primeiro, verificamos se consta a data com o alpha em 255
	if getElementData(localPlayer, "player-alpha") and getElementData(localPlayer, "player-alpha") == 255 then
		local start = getTickCount()
	
		-- a cada 10ms irá setar a visibilidade do jogador;
		-- note que o setElementData também irá atualizar a cada execução
		setTimer( function()
	
			local duration = (start + 2000) - start
		
			alpha = interpolateBetween( 255, 0,0,0,0,0, (getTickCount() - start) / duration, "Linear" )
			setElementAlpha( localPlayer, alpha )
			setElementData( localPlayer, "player-alpha", alpha )
		
			-- verificar se a interpolação já terminou, então dar killtimer e parar a execução
			if alpha == 0 then
				killTimer(sourceTimer)
				alpha = nil
			end
		end, 10, 0 )
	else -- se a data com o alpha não existe ou não for 255, notificar o jogador
		outputChatBox( "Para usar este comando sua visibilidade deve ser 255!" )
	end
end )

-- seta a visibilidade do jogador progressivamente de 0 até 255
addCommandHandler( "aparecer", function()

	if getElementData(localPlayer, "player-alpha") and getElementData(localPlayer, "player-alpha") == 0 then
		local start = getTickCount()
	
		-- a cada 10ms irá setar a visibilidade do jogador;
		-- note que o setElementData também irá atualizar a cada execução
		setTimer( function()
	
			local duration = (start + 2000) - start
		
			alpha = interpolateBetween( 0, 0,0,255,0,0, (getTickCount() - start) / duration, "Linear" )
			setElementAlpha( localPlayer, alpha )
			setElementData( localPlayer, "player-alpha", alpha ) -- setar o alpha na data do player a cada 10ms (com sync ativada) (:noice:)
		
			-- verificar se a interpolação já terminou, então dar killtimer e parar a execução
			if alpha == 255 then
				killTimer(sourceTimer)
				alpha = nil
			end
		end, 10, 0 )
	else -- se a data com o alpha não existe ou não for 0, notificar o jogador
		outputChatBox( "Para usar este comando sua visibilidade deve ser 0!" )
	end
end )

Veja os comentários e tente entender a lógica do código!

  • 10 ms, como assim?

            ms = milisegundos;
            1000 ms é o mesmo que 1 segundo;
            Significa que, a cada 1 segundo será chamada a função 100 vezes (1000 / 10 = 100)

            O ponto é, a data "player-alpha" será sincronizada com o servidor nesse intervalo de tempo.

 

Código acima sem o setElementData:

Spoiler

local player_alpha

-- alterna a visibilidade do jogador entre 255 e 0
addCommandHandler( "setalpha", function()
	
	-- seta no element-data o alpha do ped do jogador
	if (player_alpha or -1) == 0 then -- se já tiver invisivel faremos mostrar totalmente
		setElementAlpha( localPlayer, 255 ) -- mudar o alpha do ped
		player_alpha = 255
	else
		setElementAlpha( localPlayer, 0 ) -- mudar o alpha do ped
		player_alpha = 0
	end
end )

-- seta a visibilidade do jogador progressivamente de 255 até 0
addCommandHandler( "desaparecer", function()
	-- primeiro, verificamos se consta a data com o alpha em 255
	if (player_alpha or -1) == 255 then
		local start = getTickCount()
	
		-- a cada 10ms irá setar a visibilidade do jogador;
		setTimer( function()
	
			local duration = (start + 2000) - start
		
			alpha = interpolateBetween( 255, 0,0,0,0,0, (getTickCount() - start) / duration, "Linear" )
			setElementAlpha( localPlayer, alpha )
			player_alpha = alpha
		
			-- verificar se a interpolação já terminou, então dar killtimer e parar a execução
			if alpha == 0 then
				killTimer(sourceTimer)
				alpha = nil
			end
		end, 10, 0 )
	else
		outputChatBox( "Para usar este comando sua visibilidade deve ser 255!" )
	end
end )

-- seta a visibilidade do jogador progressivamente de 0 até 255
addCommandHandler( "aparecer", function()

	if (player_alpha or -1) == 0 then
		local start = getTickCount()
	
		-- a cada 10ms irá setar a visibilidade do jogador;
		setTimer( function()
	
			local duration = (start + 2000) - start
		
			alpha = interpolateBetween( 0, 0,0,255,0,0, (getTickCount() - start) / duration, "Linear" )
			setElementAlpha( localPlayer, alpha )
			player_alpha = alpha
		
			-- verificar se a interpolação já terminou, então dar killtimer e parar a execução
			if alpha == 255 then
				killTimer(sourceTimer)
				alpha = nil
			end
		end, 10, 0 )
	else
		outputChatBox( "Para usar este comando sua visibilidade deve ser 0!" )
	end
end )

 

O erro que cometem com setElementData é usar de forma exagerada, e sem saber as consequências.

Exemplos disso é:

(1) Usar setElementData dentro do "onClientRender".

(2) A desinformação quanto ao atributo synchronize (muito por conta do baixo nível de entendimento na programação/scripting).

Há situações em que o scripter poderia simplesmente colocar false no 4º argumento, como em um caso que ele esteja usando element-data "no lugar de uma variável" (ou tabela). Ou seja, aquele element-data que não irá ter uso algum no lado server ou no lado cliente.

Imagine um cliente com 1 setElementData no "onClientRender", isso irá criar um tráfego na rede do servidor umas 50-60 vezes por segundo (vai depender do fps).

Claro que nem sempre terá esse tráfego todo na rede mesmo considerando a suposição acima, pois o element-data só é atualizado se ele for diferente do valor anterior (não posso afirmar isso com 100% de certeza mas acho que o MTA não iria deixar de fazer uma verificação antes, seria uma grande falha de otimização interna).

Você pode continuar usando setElementData no código acima se o mesmo tiver com sync desativada.  O mais otimizado, porém, continua sendo a versão com variável.

É válida uma alternativa com trigger events e tabelas como alternativa ao element-data.

Em resumo:

Saiba quando usar element-Data: 

Estude sobre tables (ou arrays); opte por table ou variável. O caminho mais fácil não significa que é o melhor, setElementData é prática mas tem seu custo.

Faça uso do argumento synchronize da função:

setElementData( element, key, value, synchronize )

Por padrão ele será true, então certifique-se de setar false caso o element-data não tiver a necessidade da atualização para o server ou para o cliente.

Saiba as consequências de usá-la:

Terá uma sincronização (se a sync tiver ativada) em todo o servidor e dependendo da quantidade do uso isso pode sobrecarregar o tráfego de rede. Além de que aumenta o uso de processamento.

Edited by DNL291
Corrigidos os outputChatBox para client-side; (EDIT) Termo synchronize corrigido
  • Like 1
Link to comment

Muito obrigado @DNL291, tem algumas coisas que eu utilizei elementData mas n tem nem necessidade. Mas agora me tira uma outra duvida, se eu fosse fazer um sistema igual esse que você me mandou qual seria a melhor forma pra eu salvar o valor do alpha do usuário pra por exemplo ele sair e ficar salvo, pois eu tenho bastante scripts q utilizo elementData mas n tem necessidade de salvar os dados quando o player desloga então posso fazer dessa forma q vc fez, mas os q precisam ser salvos depois q o cara deslogar eu teria q fazer em elemenData (com tables ou arrays é claro) ou teria uma forma melhor para isso sem precisar utilizar element?

 

Edited by Lord Henry
Removido quote desnecessário, colocado @mention no lugar.
Link to comment
  • Other Languages Moderators

@juaosilv elementData não salva entre as sessões de jogo. Se o jogador desconectar do servidor, todos os seus elementDatas são apagados da mesma forma. Para salvar entre as sessões, vc deve usar accountData, para salvar os dados permanentemente na conta do jogador. Depois quando o jogador voltar pro servidor e logar, carrega esses dados que estão salvos na conta dele. É aí que entram os sistemas de save/load.

Salvar com variáveis também não funciona entre as sessões, pois quando o jogador desconecta do servidor, os scripts client-side param de executar pra ele e suas variáveis apagadas. Se alguém der stop no resource enquanto o jogador está jogando, as variáveis também são resetadas e seus valores perdidos.

Edited by Lord Henry
Link to comment
9 hours ago, Lord Henry said:

@juaosilv elementData não salva entre as sessões de jogo. Se o jogador desconectar do servidor, todos os seus elementDatas são apagados da mesma forma. Para salvar entre as sessões, vc deve usar accountData, para salvar os dados permanentemente na conta do jogador. Depois quando o jogador voltar pro servidor e logar, carrega esses dados que estão salvos na conta dele. É aí que entram os sistemas de save/load.

Salvar com variáveis também não funciona entre as sessões, pois quando o jogador desconecta do servidor, os scripts client-side param de executar pra ele e suas variáveis apagadas. Se alguém der stop no resource enquanto o jogador está jogando, as variáveis também são resetadas e seus valores perdidos.

Eu utilizo um sistema de save q ele meio q faz isso com as elementData. Seria melhr eu usar logo accounData em algo q precise salvar doq elementData q utiliza um sistema de "save"(q no caso puxa os element e seta em account) p salvar?

Edited by juaosilv
Link to comment
42 minutes ago, juaosilv said:

Eu utilizo um sistema de save q ele meio q faz isso com as elementData. Seria melhr eu usar logo accounData em algo q precise salvar doq elementData q utiliza um sistema de "save"(q no caso puxa os element e seta em account) p salvar?

Obviamente... a não ser que você priorize facilidade na codificação ao invés de um bom desempenho do script na máquina/rede.

Link to comment
15 minutes ago, DNL291 said:

@juaosilv Se você quiser dizer, "substituir element-data por account-data usando acc data também para salvamento temporário", minha resposta é não, element-data é o ideal para o salvamento temporário, basta saber usar.

 

Vou re-formular, eu quis dizer que geralmente existem alguns scripts que save que fazem o seguinte:

 

Eles pegam quando você loga/deslogar o elementData exemplo:

 

saveAccount:

local banco = getElementData(source, "Banco")

setAccountData(source, "Banco", banco)

Ai eles meio q fazem isso e dps q vc loga eles fazem pegam a accountData e setam na element.

 

Isso q eu quis dizer, queria saber se é melhor usar direto accountData no sistema ou usar element mesmo com um sistema de save q faz essa função.

 

Link to comment
  • Moderators

Entendi.

A forma que você mencionou é correta.

Login > getAccountData > setElementData

Logout/Quit > getElementData > setAccountData

account-data : salvamento externo (no banco de dados do MTA)

element-data : salvamento temporário em um elemento

Se você criar um sistema próprio de armazenar você pode substituir pelo element-data, exemplo básico:

local elements = {}

function setElementCustomData( element, str, value )
	
	if not elements[element] then
		elements[element] = {}
	end
	elements[ element ][ str ] = value
end

function getElementCustomData( element, str )

	if elements[element] then
		return elements[element][str]

	end
	return false
end

-- exemplo
addEventHandler( "onPlayerChat", root, function( message )

	if not wasEventCancelled() then
		setElementCustomData( source, "lastChatMessage", message )
	end

end )

addCommandHandler( "lastmsg", function( thePlayer )

	local msg = getElementCustomData( thePlayer, "lastChatMessage" )
	outputChatBox( "Última mensagem: " .. (msg or "N/A"), thePlayer )
end )

Daí você também pode fazer a sincronização dos dados da tabela com triggerClientEvent, usando uma versão igual no clientside com os mesmos dados que no server.

Link to comment
17 hours ago, DNL291 said:

Entendi.

A forma que você mencionou é correta.

Login > getAccountData > setElementData

Logout/Quit > getElementData > setAccountData

account-data : salvamento externo (no banco de dados do MTA)

element-data : salvamento temporário em um elemento

Se você criar um sistema próprio de armazenar você pode substituir pelo element-data, exemplo básico:


local elements = {}

function setElementCustomData( element, str, value )
	
	if not elements[element] then
		elements[element] = {}
	end
	elements[ element ][ str ] = value
end

function getElementCustomData( element, str )

	if elements[element] then
		return elements[element][str]

	end
	return false
end

-- exemplo
addEventHandler( "onPlayerChat", root, function( message )

	if not wasEventCancelled() then
		setElementCustomData( source, "lastChatMessage", message )
	end

end )

addCommandHandler( "lastmsg", function( thePlayer )

	local msg = getElementCustomData( thePlayer, "lastChatMessage" )
	outputChatBox( "Última mensagem: " .. (msg or "N/A"), thePlayer )
end )

Daí você também pode fazer a sincronização dos dados da tabela com triggerClientEvent, usando uma versão igual no clientside com os mesmos dados que no server.

Entendi, mas n consegui entender se vc acha melhor utilizar logo accountData ou utilizar element com um sistema de save q faz esse papel de puxar o element e salvar em data.

Link to comment
  • Other Languages Moderators

A data é temporária ou permanente?

Ela é uma data que varia constantemente durante a partida do jogador? Ou é uma data constante que só muda quando ele faz uma ação específica?

Link to comment
2 hours ago, DNL291 said:

Tenho certeza que sua dúvida já foi respondida, mas parece que você não conseguiu assimilar as coisas. Ou então você se expressou muito mal e ninguém entendeu.

kkkkkkk verdade, li dnv e consegui entender. Obrigado novamente, esse tópico me ajudou pakas.

  • Like 1
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...