-- src/ServerScriptService/CraftingManager.server.lua local Players = game:GetService("Players") local ReplicatedStorage = game:GetService("ReplicatedStorage") local CraftingConfig = require(ReplicatedStorage:WaitForChild("Shared"):WaitForChild("CraftingConfig")) local ChoppingConfig = require(ReplicatedStorage:WaitForChild("Shared"):WaitForChild("ChoppingConfig")) local CraftEvent = ReplicatedStorage:WaitForChild("Events"):WaitForChild("CraftEvent") local NotificationEvent = ReplicatedStorage:WaitForChild("Events"):WaitForChild("NotificationEvent") local ShopEvent = ReplicatedStorage:WaitForChild("Events"):WaitForChild("ShopEvent") local SoundEvent = ReplicatedStorage:WaitForChild("Events"):WaitForChild("SoundEvent") local function getPlayerResources(player) local data = _G.GetPlayerData(player) if not data then return {} end if not data.Resources then data.Resources = {} end return data.Resources end local function canCraft(player, recipeId) local recipe = CraftingConfig.Recipes[recipeId] if not recipe then return false, "Unknown recipe" end local resources = getPlayerResources(player) for material, requiredAmount in pairs(recipe.Materials) do local have = resources[material] or 0 if have < requiredAmount then return false, "Need " .. tostring(requiredAmount) .. " " .. material .. " (have " .. tostring(have) .. ")" end end -- Check if player already owns this tool if ChoppingConfig.AxeTypes[recipeId] and _G.HasInInventory and _G.HasInInventory(player, "Tools", recipeId) then return false, "You already own " .. (recipe.Name or recipeId) end return true, "OK" end local function craftItem(player, recipeId) -- Anti-cheat if _G.IsRateLimited and _G.IsRateLimited(player, "Craft") then return end local canDo, reason = canCraft(player, recipeId) if not canDo then NotificationEvent:FireClient(player, "Error", reason) SoundEvent:FireClient(player, "PurchaseFail", nil) return end local recipe = CraftingConfig.Recipes[recipeId] local resources = getPlayerResources(player) -- Deduct materials for material, requiredAmount in pairs(recipe.Materials) do resources[material] = resources[material] - requiredAmount end -- Add tool to inventory if _G.AddToInventory then _G.AddToInventory(player, "Tools", recipeId) end -- Auto-equip if it is an axe if ChoppingConfig.AxeTypes[recipeId] then local data = _G.GetPlayerData(player) if data then data.EquippedAxe = recipeId player:SetAttribute("EquippedAxe", recipeId) if player.Character then player.Character:SetAttribute("EquippedAxe", recipeId) end end end NotificationEvent:FireClient(player, "Crafted", "Crafted " .. (recipe.Name or recipeId) .. "!") SoundEvent:FireClient(player, "ConstructComplete", nil) -- Send updated inventory to client local data = _G.GetPlayerData(player) if data then ShopEvent:FireClient(player, "InventoryUpdate", data.Inventory) CraftEvent:FireClient(player, "ResourceUpdate", data.Resources) end end -- Handle resource query from client local function onCraftEvent(player, action, data) if action == "Craft" then craftItem(player, data) elseif action == "QueryResources" then local resources = getPlayerResources(player) CraftEvent:FireClient(player, "ResourceUpdate", resources) end end CraftEvent.OnServerEvent:Connect(onCraftEvent) print("Crafting Manager initialized")