Crafting Seguro por Combinação de Materiais Roblox
Gere um sistema de crafting robusto para Roblox em que jogadores combinam materiais do inventário para criar itens definidos por receitas. O prompt orienta a IA a produzir uma implementação servidor-autoritativa, evitando exploits comuns como criação indevida de itens, valores negativos e requisições repetidas de RemoteEvent.
Ideal para RPGs, simuladores, survival, tycoons e jogos de coleta que já possuem ou planejam possuir um inventário baseado em Folder, IntValues, Attributes ou ModuleScript. Antes de gerar o código, o usuário poderá informar a estrutura real do Explorer, os nomes dos materiais, receitas, RemoteEvents existentes e o formato de inventário usado no projeto.
A resposta esperada inclui um Script Luau completo, comentado e pronto para colar no ServerScriptService, com configuração de receitas, validação de dados, rate limit por jogador, consumo atômico de materiais e retorno estruturado de sucesso ou erro para o cliente.
Atue como um desenvolvedor Roblox Luau sênior, especializado em sistemas multiplayer seguros, inventários persistentes e arquitetura servidor-autoritativa. Crie um sistema completo de crafting por combinação de materiais em um único Script de servidor, pronto para ser colado no Roblox Studio. O TIPO obrigatório é `Script` (não LocalScript e não ModuleScript). O local obrigatório é `ServerScriptService`, com o nome sugerido `CraftingService.server.lua`. O script deve ser responsável pela lógica autoritativa de crafting. Ele deve receber solicitações do cliente por um `RemoteEvent` em `ReplicatedStorage`, mas jamais confiar em quantidades, materiais, resultados ou qualquer outro dado vindo do cliente. Caso o RemoteEvent configurado não exista e o contexto abaixo autorize sua criação, o script poderá criá-lo no servidor. Não crie interface gráfica nem entregue código de cliente neste pedido. Antes de escrever o código, analise e respeite o contexto do meu jogo abaixo. Se algum campo estiver como `[PREENCHER]`, use uma convenção segura, claramente marcada em comentários, e explique brevemente a suposição após o código. Preserve nomes já existentes no meu projeto quando eles forem informados. === CONTEXTO DO MEU JOGO === - Estrutura e nomes relevantes no Explorer: [COLE AQUI] - Local e formato do inventário do jogador (ex.: Player.Inventory com IntValues; Attributes; Profile/Data module): [COLE AQUI] - RemoteEvent existente para pedidos de crafting, se houver, e seu caminho: [COLE AQUI] - RemoteEvent existente para resposta/atualização ao cliente, se houver, e seu caminho: [COLE AQUI] - Materiais disponíveis e nomes exatos usados no inventário: [COLE AQUI] - Itens fabricáveis e receitas desejadas (resultado, quantidade produzida e ingredientes): [COLE AQUI] - Limites especiais, como quantidade máxima por pedido, nível necessário, bancada, gamepass ou moeda: [COLE AQUI] - Como o cliente enviará o pedido (ex.: apenas recipeId e quantidade): [COLE AQUI] - Regras adicionais e integrações existentes: [COLE AQUI] === FIM DO CONTEXTO === Implemente uma tabela de receitas no servidor usando IDs internos estáveis, por exemplo `wooden_sword`, separados dos nomes exibidos ao jogador. Cada receita deve definir ingredientes, quantidade de saída e, quando aplicável, requisitos opcionais. O cliente deve enviar somente um identificador de receita e uma quantidade solicitada; o servidor deve buscar toda a composição da receita localmente. Nunca aceite uma tabela de ingredientes, nome do item de resultado, saldo de inventário ou preço enviado pelo cliente. O Script precisa: localizar com segurança o inventário de cada jogador; validar tipos Luau de todos os argumentos recebidos pelo RemoteEvent; rejeitar IDs inexistentes, strings excessivamente longas, quantidades não numéricas, NaN, infinito, valores fracionários, negativos, zero e valores acima do limite configurado; confirmar que o jogador possui todos os ingredientes antes de alterar qualquer valor; descontar os ingredientes e adicionar o resultado de forma consistente; impedir saldo negativo; e impedir que uma falha parcial deixe o inventário corrompido. Faça uma pré-validação completa de capacidade e materiais antes de qualquer alteração. Se o formato de inventário não suportar criar um item ausente, retorne um erro explícito e documente o ponto de adaptação. Adicione rate limit por jogador usando `os.clock()` ou equivalente no servidor, com limpeza de estado em `Players.PlayerRemoving`. Proteja chamadas com `pcall` quando houver risco de erro por objetos ausentes ou integração externa. O sistema deve responder ao cliente com um payload simples e seguro por um RemoteEvent de resultado, contendo `success`, `code`, `recipeId`, `craftedAmount` e uma mensagem curta. Não envie o inventário inteiro sem necessidade. Use códigos de erro previsíveis, como `INVALID_REQUEST`, `INVALID_RECIPE`, `RATE_LIMITED`, `INVENTORY_NOT_READY`, `INSUFFICIENT_MATERIALS`, `INVENTORY_FULL` e `CRAFT_FAILED`. Inclua comentários úteis no código explicando: configuração de receitas, caminho do inventário, criação/localização dos RemoteEvents, validação de requisição, rate limit, checagem prévia de materiais e atualização atômica. Use APIs Roblox atuais, `WaitForChild` apenas quando fizer sentido e sem waits infinitos desnecessários. Não use `loadstring`, DataStore diretamente para cada craft, nem lógica de segurança no cliente. Caso exista um sistema de salvamento externo no contexto, altere somente os valores/objetos que ele já observa ou indique um ponto de integração seguro. Sua resposta deve conter, nesta ordem: 1) uma seção curta com a arquitetura assumida e os caminhos no Explorer; 2) exatamente um bloco de código markdown identificado como `lua`, contendo o Script Luau completo e sem pseudocódigo, pronto para colar em `ServerScriptService`; 3) uma lista objetiva de instruções para testar no Roblox Studio, incluindo teste com dois jogadores em `Test > Start`, materiais suficientes/insuficientes, receita inválida, spam do RemoteEvent e confirmação de que o cliente não consegue definir o resultado do craft. Não omita trechos essenciais e não substitua código por reticências.