Roblox · Песочница · урок 6
Верстак: E — меню рецептов, выбираешь предмет, видишь ингредиенты, «Скрафтить» — сервер забирает ресурсы и выдаёт предмет.
Синим — что добавляем на этом уроке.
Workspace └─ Workbench (Model) └─ Table (Part) └─ ProximityPrompt (ProximityPrompt) — «Крафт» └─ OpenCraft (Script) ReplicatedStorage ├─ CraftOpenEvent (RemoteEvent) └─ CraftFunction (RemoteFunction) ServerStorage └─ Tools (Folder) — Pickaxe, Axe, Shovel — образцы для крафта ServerScriptService └─ CraftServer (Script) StarterGui └─ CraftGui (ScreenGui) — ResetOnSpawn выкл. └─ MainFrame (Frame) — Visible выкл. ├─ Workbench (TextLabel) — заголовок ├─ CloseButton (TextButton) ├─ RecipesFrame (ScrollingFrame) — UIListLayout, Sample (TextButton, Visible выкл.) ├─ CraftFrame (Frame) — Object, Ingredients, Message, CraftButton, BackButton; Visible выкл. └─ CraftLocal (LocalScript)
Где: Workspace → Workbench → Table → ProximityPrompt · Script
Зачем: Открывает меню.
-- общее хранилище
local RS = game:GetService("ReplicatedStorage")
-- ProximityPrompt верстака
local prompt = script.Parent
-- открыть меню крафта
local openEvent = RS:WaitForChild("CraftOpenEvent")
-- игрок нажал E у верстака
prompt.Triggered:Connect(function(player)
-- меню открывается только у него
openEvent:FireClient(player)
-- конец функции
end)Где: StarterGui → CraftGui → MainFrame · LocalScript
Зачем: Меню крафта.
-- общее хранилище
local RS = game:GetService("ReplicatedStorage")
-- рецепты и названия
local Items = require(RS:WaitForChild("Items"))
-- верстак позвал
local openEvent = RS:WaitForChild("CraftOpenEvent")
-- попросить сервер скрафтить
local craftFunction = RS:WaitForChild("CraftFunction")
-- окно крафта
local mainFrame = script.Parent
-- список рецептов
local recipesFrame = mainFrame:WaitForChild("RecipesFrame")
-- шаблон кнопки рецепта
local sample = recipesFrame:WaitForChild("Sample")
-- один рецепт
local craftFrame = mainFrame:WaitForChild("CraftFrame")
-- что сейчас крафтим
local selected = nil
-- открыть рецепт
local function Show(item)
-- запоминаем
selected = item
-- название
craftFrame.Object.Text = Items.Names[item] or item
-- строчки ингредиентов
local parts = {}
-- каждый ингредиент
for name, amount in pairs(Items.Recipes[item]) do
-- «Дерево × 2»
table.insert(parts, (Items.Names[name] or name) .. " × " .. amount)
-- конец перебора
end
-- список
craftFrame.Ingredients.Text = "Нужно: " .. table.concat(parts, ", ")
-- без старых сообщений
craftFrame.Message.Text = ""
-- прячем список
recipesFrame.Visible = false
-- показываем рецепт
craftFrame.Visible = true
-- конец функции
end
-- кнопка на каждый рецепт — сама
for item in pairs(Items.Recipes) do
-- копия шаблона
local button = sample:Clone()
-- имя
button.Name = item
-- название по-русски
button.Text = Items.Names[item] or item
-- шаблон был скрыт
button.Visible = true
-- в список
button.Parent = recipesFrame
-- клик — рецепт
button.MouseButton1Click:Connect(function() Show(item) end)
-- конец перебора
end
-- «Скрафтить» — подписка одна
craftFrame.CraftButton.MouseButton1Click:Connect(function()
-- ничего не выбрано
if not selected then return end
-- сервер проверит и скрафтит
local _, text = craftFunction:InvokeServer(selected)
-- «Создано» или «Не хватает»
craftFrame.Message.Text = text
-- конец функции
end)
-- назад к рецептам
craftFrame.BackButton.MouseButton1Click:Connect(function()
-- прячем рецепт
craftFrame.Visible = false
-- показываем список
recipesFrame.Visible = true
-- конец функции
end)
-- закрыть
mainFrame.CloseButton.MouseButton1Click:Connect(function() mainFrame.Visible = false end)
-- верстак позвал
openEvent.OnClientEvent:Connect(function()
-- сначала список
craftFrame.Visible = false
-- рецептов
recipesFrame.Visible = true
-- открываем
mainFrame.Visible = true
-- конец функции
end)Где: ServerScriptService · Script
Зачем: Крафт с проверкой.
-- общее хранилище
local RS = game:GetService("ReplicatedStorage")
-- образцы инструментов
local SS = game:GetService("ServerStorage")
-- рецепты
local Items = require(RS:WaitForChild("Items"))
-- инвентарь
local Inventory = require(game:GetService("ServerScriptService"):WaitForChild("Inventory"))
-- запрос крафта
local craftFunction = RS:WaitForChild("CraftFunction")
-- инструменты, которые можно скрафтить
local tools = SS:WaitForChild("Tools")
-- игрок нажал «Скрафтить»
craftFunction.OnServerInvoke = function(player, item)
-- рецепт
local recipe = typeof(item) == "string" and Items.Recipes[item]
-- нет
if not recipe then return false, "Нет такого рецепта" end
-- проверяем каждый ингредиент
for name, amount in pairs(recipe) do
-- не хватает
if Inventory.Count(player, name) < amount then
-- ответ
return false, "Не хватает: " .. (Items.Names[name] or name)
-- конец проверки
end
-- конец перебора
end
-- забираем ингредиенты
for name, amount in pairs(recipe) do Inventory.Take(player, name, amount) end
-- это инструмент?
local tool = tools:FindFirstChild(item)
-- да
if tool then
-- в рюкзак
tool:Clone().Parent = player.Backpack
-- блок
else
-- в инвентарь
Inventory.Add(player, item, 1)
-- конец проверки
end
-- ответ
return true, "Создано: " .. (Items.Names[item] or item)
-- конец функции
endЗапусти Play (или Run) и убедись: