Sistema Dual de Moedas Roblox: Soft Currency e Robux
Gere um sistema profissional de economia dupla para Roblox: uma moeda soft obtida durante o gameplay e uma moeda premium adquirida exclusivamente por compras com Robux. O prompt orienta a implementação correta do fluxo de Developer Products, evitando o erro comum de tentar manipular o saldo de Robux do jogador diretamente.
Ideal para jogos com lojas, upgrades, cosméticos, boosts, pacotes de gemas e economia persistente. O resultado solicitado inclui arquitetura servidor-autoritativa, DataStore, RemoteEvents validados, prevenção contra duplicação de recompensas e instruções práticas para configurar e testar tudo no Roblox Studio.
Atue como um desenvolvedor Roblox sênior, especialista em Luau, economias de jogo, DataStoreService e monetização segura com MarketplaceService. Crie um sistema completo, seguro e pronto para produção de moeda dupla: uma soft currency obtida no jogo e uma premium currency comprada com Robux por Developer Products. Antes de escrever o código, considere o contexto específico do meu projeto abaixo. Se algum item estiver vazio ou não existir, adote nomes seguros e explique onde devo criá-lo. Preserve e integre-se aos objetos existentes sempre que possível, sem renomear ou apagar recursos do meu jogo. CONTEXTO DO MEU JOGO (vou preencher): - Nome da soft currency: [ex.: Coins] - Nome da premium currency: [ex.: Gems] - Estrutura atual no Explorer: [cole aqui] - RemoteEvents/RemoteFunctions já existentes e suas finalidades: [cole aqui] - Produtos de desenvolvedor e IDs: [ex.: 123456 = 100 Gems; 123457 = 500 Gems] - Itens/loja que consomem soft currency ou premium currency: [descreva] - Existe sistema de DataStore próprio? [sim/não; cole detalhes] - Já existe MarketplaceService.ProcessReceipt em outro script? [sim/não; cole o código ou descreva] - Regras adicionais de recompensa, limites e preços: [descreva] IMPORTANTE SOBRE ROBUX: trate Robux corretamente. O jogo não pode ler, armazenar, transferir nem alterar o saldo real de Robux do jogador. Portanto, a hard/premium currency deve ser uma moeda virtual do jogo, como Gems, concedida somente após a confirmação de compra de Developer Product pelo MarketplaceService. Use PromptProductPurchase para iniciar a compra e MarketplaceService.ProcessReceipt no servidor para confirmar e conceder a recompensa. Não use PromptGamePassPurchase para pacotes consumíveis; explique brevemente quando Game Pass seria apropriado, mas implemente Developer Products neste sistema. Gere a implementação principal como um Script de servidor chamado CurrencyService.server.lua, para ser colocado em ServerScriptService. Ele deve ser autocontido e criar automaticamente, se estiverem ausentes, os RemoteEvents necessários em ReplicatedStorage dentro de uma pasta organizada, por exemplo ReplicatedStorage/Remotes/Currency. Caso a arquitetura recomendada exija código auxiliar, você pode incluir no máximo um ModuleScript complementar, identificando claramente seu nome, tipo e localização exata no Explorer. Não entregue pseudocódigo nem trechos incompletos. O Script deve implementar, no mínimo: 1. Carregamento, criação e salvamento persistente dos saldos de soft e premium currency com DataStoreService, usando UpdateAsync quando apropriado, pcall, tentativas controladas e tratamento de falhas sem sobrescrever dados válidos. 2. Uma estrutura de dados por jogador no servidor e valores replicados apenas para interface, preferencialmente em leaderstats ou em uma pasta PlayerData claramente identificada. Os valores replicados nunca devem ser a fonte de verdade. 3. APIs internas claras, como AddSoftCurrency, SpendSoftCurrency, AddPremiumCurrency e SpendPremiumCurrency. Gastos devem ser atômicos no contexto do servidor: nunca permitir saldo negativo, dupla cobrança ou concessão duplicada. 4. Um RemoteEvent para o cliente solicitar compra de item com moeda interna. O cliente deve enviar apenas um identificador de item; preço, tipo de moeda, saldo, propriedade e efeito da compra devem ser definidos e validados exclusivamente no servidor por uma tabela de catálogo. Inclua exemplos de itens com ambos os tipos de moeda e deixe comentários indicando onde editar. 5. Um RemoteEvent para solicitar a abertura de compra de um Developer Product. O cliente jamais deve informar quantas Gems receberá ou o preço; ele só pode enviar um ProductId permitido. Valide o ProductId em uma tabela de recompensas no servidor antes de chamar PromptProductPurchase. 6. Uma implementação robusta de MarketplaceService.ProcessReceipt que conceda Gems somente uma vez por PurchaseId. Persista recibos processados em DataStore, retorne PurchaseGranted apenas quando a concessão estiver confirmada e retorne NotProcessedYet em falhas temporárias para que a Roblox tente novamente. Considere a possibilidade de o jogador estar offline durante a entrega e explique, em comentários, a estratégia adotada para isso. 7. Eventos de atualização para a UI e respostas de sucesso/erro que não exponham dados sensíveis. Todo input de RemoteEvent deve passar por validação de tipo, limite de tamanho, rate limit básico por jogador e verificações de estado. 8. PlayerAdded e PlayerRemoving, salvamento em BindToClose e limpeza de conexões/cache para reduzir perda de dados e memory leaks. Siga práticas de segurança Roblox rigorosamente: o servidor é autoritativo; nunca confie no cliente para dano, moeda, inventário, preços, IDs não permitidos ou confirmação de pagamento; valide todos os argumentos recebidos por RemoteEvent/RemoteFunction; não use loadstring; não exponha chaves, tokens ou serviços externos. Não use DataStore em LocalScript. Caso ProcessReceipt já exista no contexto informado, não sobrescreva silenciosamente o callback: mostre uma estratégia explícita de integração por roteador/dispatcher de produtos. Entregue a resposta nesta ordem: (1) uma visão rápida da arquitetura e dos objetos criados; (2) o código Luau completo, comentado e pronto para colar, obrigatoriamente dentro de bloco markdown ```lua; (3) uma lista objetiva de IDs, tabelas e nomes que preciso personalizar; (4) instruções passo a passo para testar no Roblox Studio, incluindo publicação em experiência de teste, configuração de Developer Products, ativação de API Services para DataStore em ambiente adequado e como simular a compra sem conceder moedas manualmente pelo cliente. Garanta compatibilidade com Luau atual e priorize legibilidade, tipagem opcional e manutenção profissional.