I’m trying to make an item system that allows a player to pick up an item and drag it around. Only the “owner” of this item should be able to move it, but at the moment anyone can move the item.
On the client side, a cursor part is cloned from the replicated storage. When the player joins the game. When the player clicks on an object the script checks to see if the object is moveable and if it is it welds the cursor to the object. Then the cursor moves around and unwelds when the player lets go of the grab button. This works fine.
On the server side, the network ownership of the object is set to the first player who picks it up.
The issue is the network ownership updates again whenever another player tries to pick up the object. I am not changing the network ownership of the part this time, but it still updates. Why is this happening?
Client-side item movement script.
local UserInputService = game:GetService("UserInputService")
local ContextActionService = game:GetService("ContextActionService")
local Players = game:GetService("Players")
local Player = Players.LocalPlayer
local Mouse = game.Players.LocalPlayer:GetMouse()
local RequestOwnership = game.ReplicatedStorage.Remote.RequestOwnership
local setPosConnection
local MaxDist = 30
local currentDist = MaxDist
local cursor = game.ReplicatedStorage.Cursor:Clone()
cursor.Parent = game.Workspace
local weld = cursor.WeldConstraint
local playerconfig = require(game:GetService("Players").LocalPlayer.PlayerScripts:WaitForChild("PlayerModule"))
local ctrls = playerconfig:GetControls()
local function SetPosition()
local character = Player.Character
-- Calculate the position in front of the player's head
local headPosition = character:WaitForChild("Head").Position
local cursorPosition = Mouse.Hit.p
local direction = (cursorPosition - headPosition).unit
local positionInFront = headPosition + direction * currentDist
cursor.AlignPosition.Position = positionInFront
end
local function FindTopLevelModel(part:Part)
local model
if not part then
return nil
end
if part.Parent ~= game.Workspace and part.Parent:IsA("Model") then
model = part.Parent
else
return false
end
while true do
wait(0.01)
if model.Parent ~= game.Workspace and model.Parent:IsA("Model") then
model = model.Parent
else
break
end
end
return model
end
local function handleManipulation(actionName, inputState, inputObject)
if actionName == "AdjustDist" then
if inputState == Enum.UserInputState.Change then
if inputObject.Position.Z == 1 then
currentDist = math.clamp(currentDist + 5, 5, MaxDist)
elseif inputObject.Position.Z == -1 then
currentDist = math.clamp(currentDist - 5, 5, MaxDist)
end
elseif inputState == Enum.UserInputState.Begin then
if inputObject.KeyCode == Enum.KeyCode.DPadUp then
currentDist = math.clamp(currentDist + 5, 5, MaxDist)
else
currentDist = math.clamp(currentDist - 5, 5, MaxDist)
end
end
end
end
local function StartGrab()
currentDist = MaxDist
ContextActionService:BindAction("AdjustDist",handleManipulation,false,Enum.UserInputType.MouseWheel ,Enum.KeyCode.DPadUp,Enum.KeyCode.DPadDown)
setPosConnection = game:GetService("RunService").Heartbeat:Connect(function()
SetPosition()
end)
local topmodel:Model = FindTopLevelModel(Mouse.Target)
if topmodel then
RequestOwnership:FireServer(topmodel)
end
print(topmodel)
if topmodel and topmodel:GetAttribute("Moveable") and Player:DistanceFromCharacter(topmodel.PrimaryPart.Position) <= MaxDist then
currentDist = Player:DistanceFromCharacter(topmodel.PrimaryPart.Position)
cursor.Position = Mouse.Hit.Position
print("Welding", topmodel.PrimaryPart)
weld.Part1 = topmodel.PrimaryPart
end
cursor.Transparency = 0.5
cursor.Trail.Enabled = true
end
local function StopGrab()
if setPosConnection and setPosConnection.Connected then
setPosConnection:Disconnect()
end
ContextActionService:UnbindAction("AdjustDist")
weld.Part1 = nil
cursor.Transparency = 1
cursor.Trail.Enabled = false
end
local function handleAction(actionName, inputState, inputObject)
if actionName == "GrabItem" then
if inputState == Enum.UserInputState.Begin then
StartGrab()
elseif inputState == Enum.UserInputState.End then
StopGrab()
end
elseif actionName == "AdjustDist" then
print(inputObject)
end
end
ContextActionService:BindAction("GrabItem",handleAction,false,Enum.UserInputType.MouseButton1,Enum.KeyCode.ButtonR2)
Server-side ownership script.
local RequestOwnership = game.ReplicatedStorage.Remote.RequestOwnership
local function setOwnership(player :Player ,Model :Model)
if Model:IsA("Model") == true and Model:GetAttribute("Moveable") == true then
print("debug 0")
if Model:GetAttribute("OwnerId") == nil or Model:GetAttribute("OwnerId") == player.UserId then
print("debug 1")
if Model.PrimaryPart then
print("debug 2")
Model:SetAttribute("OwnerId",player.UserId)
Model.PrimaryPart:SetNetworkOwner(player)
print("updated ownership")
end
end
end
end
RequestOwnership.OnServerEvent:Connect(setOwnership)
The ownership is only set by the server-side script to the first player to interact with it, but the network ownership of the object still updates when another player tries to pick it up. I have checked and the server-side script is working like it is meant to, but something else is causing the network ownership to change. What could it be?