Fluxos in-game
Esta página junta tudo: pega cada gesto que o jogador faz no jogo e o segue até a plataforma e de volta. São cinco fluxos, e todos compartilham o mesmo esqueleto — o client pede pelo opcode 221, o servidor valida e delega ao Agent, a plataforma responde, o servidor devolve pelo opcode 220. O que muda é o que cada um pede e o que a UI faz com a resposta.
Vale reler antes a arquitetura, porque os opcodes e o papel do Agent aparecem em todos os fluxos abaixo.
Fluxo 1 — Vínculo do personagem
Seção intitulada “Fluxo 1 — Vínculo do personagem”Antes de anunciar ou comprar, o personagem precisa estar vinculado a uma conta Lootfy. O módulo detecta a falta de vínculo pela elegibilidade e encurta a jornada abrindo o navegador sozinho.
-
O gatilho. A elegibilidade volta com
blocker == 'NOT_LINKED'. A UI mostra o botão “Vincular personagem” e, se alguma janela Lootfy está visível, dispara o auto-vínculo — uma vez por sessão, para o navegador não abrir com nada na tela. -
O pedido. A função
requestLink()mandalink@{}no opcode 221. Os botões “Vincular personagem” fazem o mesmo, manualmente e sem trava de uma-vez-por-sessão. -
O servidor. O
opcode.luainicia o vínculo (vincular personagem,POST /v1/api/character-links) sempre sobre o personagem docidda sessão — ignora qualquer ref no payload. O Agent chama a plataforma, que devolve um link de uso único. -
A volta. O servidor manda
link@<url>no opcode 220. O módulo abre a URL no navegador do jogador, onde ele confirma o vínculo logado na conta Lootfy.
Fluxo 2 — Elegibilidade
Seção intitulada “Fluxo 2 — Elegibilidade”A elegibilidade é a pré-checagem que destrava (ou tranca) as ações Lootfy. Ela roda ao abrir a janela de venda ou de compra e alimenta o checkbox e o botão.
-
O gatilho. Abrir a janela de venda (
venda) ou de compra (showConfimarWindowDone) dispararequestEligibility(). -
O cache. O resultado é cacheado por 60 segundos por sessão. O botão “Atualizar” força a reconsulta (ignora o cache) — útil para reavaliar depois de vincular ou cadastrar recebimento sem fechar e reabrir a janela.
-
O pedido. Manda
elig@{}no opcode 221; o servidor respondeelig@<json>no 220 com{allowed, linked, message, blocker}. -
A aplicação, assimétrica. Na venda, o checkbox destrava por
allowed— que exige recebedor aprovado, porque o vendedor vai receber dinheiro. Na compra, o botão destrava só porlinked— o comprador só precisa estar vinculado; recebedor é regra do vendedor, não dele.
Fluxo 3 — Anúncio registrar anúncio
Seção intitulada “Fluxo 3 — Anúncio ”O anúncio publica na Lootfy uma oferta que o jogador acabou de criar no market do jogo. A ordem entre criar a oferta e anunciá-la é o que faz funcionar.
-
O gesto. No
ConfVendembrulhado (o botão Vender), o módulo lê antes de tudo se o checkbox “Anunciar na Lootfy” está marcado e habilitado, e sanitiza o preço em reais (só dígitos, vírgula e ponto). -
A oferta nasce no jogo. O
ConfVendoriginal roda e cria a oferta de market in-game, do jeito normal do jogo. -
O anúncio. Se estava anunciando e o preço não é vazio, o módulo manda
announce@{"brl":"<preço>"}no opcode 221. Preço vazio aborta com um aviso, sem anunciar. -
O Agent lista. Na mesma sessão TCP, a criação da oferta e o
announce@chegam ao servidor em ordem. O Agent pega a oferta recém-criada pela chave estávelplayer_id + timee a registra na Lootfy (registrar anúncio,POST /v1/api/market/listings,signature-only).
Fluxo 4 — Compra criar transação
Seção intitulada “Fluxo 4 — Compra ”A compra cria uma transação a partir da oferta que o comprador selecionou e devolve a ele uma página de pagamento Pix.
-
O gesto. O clique no botão “Comprar na Lootfy (R$)” resolve a oferta selecionada no market e lê a quantidade do campo da janela.
-
O pedido. Manda
buy@{"seller":..,"clientId":..,"count":..,"qty":..}no opcode 221. Ele envia o clientId do item (o servidor casa porgetItemInfo().clientId, id exato, porque o nome de exibição poderia divergir) e o count total da oferta como desempate — para quando o vendedor tem mais de um anúncio do mesmo item. -
O debounce. O botão se desabilita no clique e só reabilita quando chega o
checkout@ou após 5 segundos. Cada clique é umjtinovo, uma transação nova — o debounce evita que um duplo clique vire duas compras. -
O servidor e o Agent. O
opcode.luavalida contra ocid, monta a oferta de compra (item, personagem, quantidade — sem preço, que a plataforma já conhece do anúncio) e o Agent fazPOST /v1/api/transactions(criar transação,signature-only). Ojtiaqui é chave de idempotência: um retry reusa o mesmo. -
A volta. A plataforma devolve o
checkoutUrl; o servidor mandacheckout@<url>no opcode 220 e o módulo abre a página de pagamento no navegador do jogador. O debounce solta.
Fluxo 5 — Entrega server-side
Seção intitulada “Fluxo 5 — Entrega ”A entrega acontece depois e fora do client — é toda server-side, disparada pelo webhook de pagamento. O jogador não faz nada; ele só recebe o item.
-
O pagamento confirma. O comprador paga o Pix no navegador. O PSP confirma e a Lootfy dispara o webhook de entrega
transfer_order, assinado com a chave da plataforma. -
O Agent verifica. O Agent valida a assinatura do webhook (chave PLATFORM) e aciona o Lua de entrega do servidor.
-
A engine entrega. O Lua chama
doLootfyDeliver(sellerId, offerTime, count, buyerName)— o patch de engine. A oferta é encontrada pela chave estável, o estoque é consumido na memória e realinhado no banco, e o item vai para a bag (comprador online) ou o depot (offline). Nenhum dinheiro do jogo se move. -
A confirmação. O Lua lê o
(code, remaining)retornado:0confirma a entrega à plataforma viaPOST /v1/api/transactions/{transactionId}/delivery(confirmar entrega);2(estoque insuficiente) ou1(oferta sumiu) reportam a falha viaPOST /v1/api/transactions/{transactionId}/delivery-failure(reportar falha de entrega), e a plataforma trata (estorno ou reenfileiramento).