Hello, developers! I’ve attempted to create a 2-item crafting system for my game, which works perfectly in the studio, but in-game, it randomly stops working without any given errors. It usually only happens when my brother is on console and tries to use it. I’ve tested it with two players in studio, and it worked great. So I assume it’s something to do with the client or a logic error in my code I can’t seem to find.
Server:
-- # Services
local ServerStorage = game:GetService("ServerStorage")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- # Objects
local CraftingTable = workspace.Map.Cabin.CraftingTable
local Pos = CraftingTable.Pos
local Pos2 = CraftingTable.Pos2
local ProximityPrompt = CraftingTable.Part.ProximityPrompt
local Items_Folder = ReplicatedStorage.Items
-- # Remotes
local StartCrafting = ReplicatedStorage.Remotes.StartCrafting
local CheckItems = ReplicatedStorage.Remotes.CheckItems
local ItemAdded = ReplicatedStorage.Remotes.ItemAdded
local ItemCrafted = ReplicatedStorage.Remotes.ItemCrafted
local ClearTable = ReplicatedStorage.Remotes.ClearTable
--local CraftingStatus = Pos.CraftingStatus.TextLabel
-- # Tables, etc.
local Items = {
"Log",
"Rope",
"Stick",
"Rock"
}
local Recipes = {
Bow = {"Log", "Rope"},
Axe = {"Stick", "Rock"}
}
local function changePlayerSpeed(player,speed)
local char = player.Character or player.CharacterAdded:Wait()
local humanoid = char:FindFirstChildWhichIsA("Humanoid")
humanoid.WalkSpeed = speed
end
ProximityPrompt.Triggered:Connect(function(player)
StartCrafting:FireClient(player)
changePlayerSpeed(player,0)
end)
local function CheckForItem(Character)
if not Character then
warn(Character)
return
end
local hasTool = Character:FindFirstChildWhichIsA("Tool")
if hasTool then
if table.find(Items,hasTool.Name) then
return true
end
end
return false
end
CheckItems.OnServerEvent:Connect(function(player,posLocation)
local Character = player.Character or player.CharacterAdded:Wait()
if Character then
if CheckForItem(Character) then
-- Has tool
local hasTool = Character:FindFirstChildWhichIsA("Tool")
ItemAdded:FireClient(player,hasTool,posLocation)
end
end
end)
local playerItem1 = {}
local playerItem2 = {}
local function isRecipeThenCraft(player)
for result,v in pairs(Recipes) do
local item1 = playerItem1[player]
local item2 = playerItem2[player]
if (
(item1 == v[1] and item2 == v[2]) or
(item1 == v[2] and item2 == v[1])
)
then
return result
end
end
return nil
end
ItemAdded.OnServerEvent:Connect(function(player:Player,Item:Tool,PosLocation:Part)
if table.find(Items,Item.Name) and PosLocation.Name == Pos.Name then
playerItem1[player] = Item.Name
Item:Destroy()
elseif table.find(Items,Item.Name) and PosLocation.Name == Pos2.Name then
playerItem2[player] = Item.Name
Item:Destroy()
local foundItem = isRecipeThenCraft(player)
if foundItem then
local newItem = Items_Folder:FindFirstChild(foundItem):Clone()
newItem.Parent = player.Backpack
ItemCrafted:FireClient(player)
playerItem1[player] = nil
playerItem2[player] = nil
changePlayerSpeed(player,16)
--warn("PlayerItem1:",playerItem1,"PlayerItem2:",playerItem2)
end
end
end)
ClearTable.OnServerEvent:Connect(function(player)
changePlayerSpeed(player,16)
if playerItem1[player] ~= nil then
local returnItem = Items_Folder:FindFirstChild(playerItem1[player]):Clone()
returnItem.Parent = player.Backpack
end
if playerItem2[player] ~= nil then
local returnItem = Items_Folder:FindFirstChild(playerItem2[player]):Clone()
returnItem.Parent = player.Backpack
end
playerItem1[player] = nil
playerItem2[player] = nil
--warn("PlayerItem1:",playerItem1,"PlayerItem2:",playerItem2)
end)
Client:
-- # Services
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local TweenService = game:GetService("TweenService")
local players = game:GetService("Players")
-- # Player
local Player = players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
repeat task.wait() until Character~= nil
if Character then
warn("Character loaded")
end
local humanoid = Character:WaitForChild("Humanoid")
local PlayerGui = Player.PlayerGui
-- # UI
local CraftingScreen = PlayerGui:WaitForChild("CraftingScreen")
local Container = CraftingScreen:WaitForChild("Container")
local Leave = Container:WaitForChild("Leave")
-- # Camera
local CurrentCamera = workspace.CurrentCamera
-- # Objects
local Cabin = workspace.Map.Cabin
local CraftingTable = Cabin:WaitForChild("CraftingTable")
local Pos = CraftingTable:WaitForChild("Pos")
local Pos2 = CraftingTable:WaitForChild("Pos2")
local CamPos = CraftingTable:WaitForChild("CameraPos")
local Items_Folder = ReplicatedStorage.Items
-- # Remotes
local StartCrafting = ReplicatedStorage.Remotes.StartCrafting
local CheckItems = ReplicatedStorage.Remotes.CheckItems
local ItemAdded = ReplicatedStorage.Remotes.ItemAdded
local ItemCrafted = ReplicatedStorage.Remotes.ItemCrafted
local ClearTable = ReplicatedStorage.Remotes.ClearTable
-- # Prompts
local TablePrompt = CraftingTable:WaitForChild("Part"):WaitForChild("ProximityPrompt")
local PosPrompt = Pos:WaitForChild("ProximityPrompt")
local Pos2Prompt = Pos2:WaitForChild("ProximityPrompt")
-- # Sets when player joins
local DefaultWalkSpeed = humanoid.WalkSpeed
local function moveCamera(Object,Reset)
if not Reset and Object then
CurrentCamera.CameraType = Enum.CameraType.Scriptable
TweenService:Create(
CurrentCamera,
TweenInfo.new(1),
{CFrame = Object.CFrame}
):Play()
elseif Reset and Object.Name == "Head" then
TweenService:Create(
CurrentCamera,
TweenInfo.new(1),
{CFrame = Object.CFrame}
):Play()
task.delay(1,function()
CurrentCamera.CameraType = Enum.CameraType.Custom
end)
elseif Reset and not Object then
CurrentCamera.CameraType = Enum.CameraType.Custom
end
end
StartCrafting.OnClientEvent:Connect(function(isCrafting)
--humanoid.WalkSpeed = 0
CraftingScreen.Enabled = true
TablePrompt.Enabled = false
PosPrompt.Enabled = true
moveCamera(CamPos,false)
end)
PosPrompt.Triggered:Connect(function()
CheckItems:FireServer(Pos)
end)
Pos2Prompt.Triggered:Connect(function()
CheckItems:FireServer(Pos2)
end)
local function CheckForExistingDisplay(PosLocation)
for _,isItem in pairs(PosLocation:GetChildren()) do
if isItem:IsA("Tool") then
return true
end
end
return false
end
local function placeDisplay(PosLocation,Item)
-- Place Display item
local success, Error = pcall(function()
local DisplayItem = Items_Folder:FindFirstChild(Item.Name):Clone()
DisplayItem.Parent = PosLocation
if DisplayItem:FindFirstChild("Handle") then
DisplayItem.Handle.CFrame = PosLocation.CFrame
DisplayItem.Handle.Anchored = true
DisplayItem.RequiresHandle = false
end
end)
if Error then
warn("Issue with Display Item")
end
end
local function enableOtherPrompt(PosLocation)
for _,v in pairs(CraftingTable:GetChildren()) do
local posName = string.match(v.Name, "Pos")
if v:IsA("Part") and posName and v.Name ~= PosLocation.Name then
if not CheckForExistingDisplay(v) then
local prompt = v:FindFirstChildWhichIsA("ProximityPrompt")
if prompt then
prompt.Enabled = true
end
end
end
end
end
local function clearDisplays()
for _,v in pairs(CraftingTable:GetChildren()) do
local posName = string.match(v.Name, "Pos")
if v:IsA("Part") and posName then
if CheckForExistingDisplay(v) then
local tool = v:FindFirstChildWhichIsA("Tool")
if tool then
tool:Destroy()
end
end
end
end
end
local function disablePOSPrompts()
for _,v in pairs(CraftingTable:GetChildren()) do
local posName = string.match(v.Name, "Pos")
if v:IsA("Part") and posName then
if not CheckForExistingDisplay(v) then
local prompt = v:FindFirstChildWhichIsA("ProximityPrompt")
if prompt then
prompt.Enabled = false
end
end
end
end
end
local function visual(part)
for _,v in pairs(part:GetChildren()) do
if v:IsA("ParticleEmitter") then
v:Emit(7)
elseif v:IsA("Sound") then
v.PlaybackSpeed = math.random(8,10)/10
v:Play()
end
end
end
ItemAdded.OnClientEvent:Connect(function(Item,PosLocation)
if Items_Folder:FindFirstChild(Item.Name) then
if not CheckForExistingDisplay(PosLocation) then
-- Disable Prompt
PosLocation:FindFirstChildWhichIsA("ProximityPrompt").Enabled = false
visual(PosLocation)
enableOtherPrompt(PosLocation)
placeDisplay(PosLocation,Item)
ItemAdded:FireServer(Item,PosLocation)
end
end
end)
local function endCrafting()
if Character:FindFirstChild("Head") then
local head = Character:FindFirstChild("Head")
moveCamera(head,true)
else
moveCamera(nil,true)
end
--humanoid.WalkSpeed = DefaultWalkSpeed
clearDisplays()
disablePOSPrompts()
CraftingScreen.Enabled = false
TablePrompt.Enabled = true
end
ItemCrafted.OnClientEvent:Connect(function()
endCrafting()
visual(CraftingTable:WaitForChild("Part"))
end)
Leave.MouseButton1Down:Connect(function()
ClearTable:FireServer()
endCrafting()
end)
Player.CharacterRemoving:Connect(function()
ClearTable:FireServer()
endCrafting()
end)
players.PlayerRemoving:Connect(function(player)
if player == Player then
ClearTable:FireServer()
endCrafting()
end
end)
