SetNetworkOwner issues

i’m making a game with my friend, this piece of code completely bricks our replication on test dummies.

this a ragdoll setup function, when v:SetNetworkOwner(nil) is not commented out, the network owner should in theory be set to the server. althought when we damage the dummies on our client, it replicates to the server. we are confident that it is this line messing with the replication, since when we had it commented out, the issue stopped.

here are two pov’s that show our issue accurately

please note that the replication of the health only happens when the client touches the dummy

this is the piece of code which handles hits on the client:

the ragdoll module is not made by me or my friend, i found it in #resources:community-resources
here’s the full ragdoll module code:

--!nonstrict
--[[

made 2/11/2024

]]

-- variables
local ragdoll = {}
ragdoll.__index = ragdoll

-- services
local players = game:GetService("Players")
local run = game:GetService("RunService")
local physics = game:GetService("PhysicsService")

-- types
type ragdollSettings = {
	impulse: boolean, -- give initial impulse on :ragdoll()
	makeRagdollValue: boolean, -- make a value in the character that when changed will ragdoll/unragdoll depending on the value
	ragdollTimer: boolean | number, -- automatically undo ragdoll after x amount of time
}

-- creating ragdoll collisiongroup
if run:IsServer() then
	physics:RegisterCollisionGroup("ragdoll")
	physics:CollisionGroupSetCollidable("ragdoll", "ragdoll", true)
end

-- settings setup
function ragdoll.new(options: ragdollSettings)
	local self = setmetatable({}, ragdoll)
	
	-- type checking
	self.options = options or {}
	self.options.impulse = typeof(self.options.impulse) == "boolean" and self.options.impulse or false
	self.options.makeRagdollValue = typeof(self.options.makeRagdollValue) == "boolean" and self.options.makeRagdollValue or false
	self.options.ragdollTimer = typeof(self.options.ragdollTimer) == "number" and self.options.ragdollTimer or false

	return self
end

function ragdoll:setup(character: Model)
	-- references
	local ragdollParts = script.RagdollParts:Clone()
	
	-- fixing ragdollParts table
	local newrdp = {}
	for _, object in pairs(ragdollParts:GetChildren()) do
		newrdp[object.Name] = object
	end
	
	-- variables
	local isPlayer = players:GetPlayerFromCharacter(character)
	
	-- references
	local humanoid = character:FindFirstChild("Humanoid")
	local head = character:FindFirstChild("Head")
	
	-- checks
	if not humanoid then return end
	if tostring(humanoid.RigType.Name) ~= "R6" then error("ragdoll module: rig is not R6") return end
	if not head then return end
	
	-- humanoid
	humanoid.BreakJointsOnDeath = false
	humanoid.RequiresNeck = false
	
	-- npc check
	if not isPlayer then
		
		-- folder
		local socketsFolder = Instance.new("Folder")
		socketsFolder.Name = "Sockets"
		socketsFolder.Parent = character
		
		-- unachoring baseparts (setnetworkowner is seperate to prevent welding errors)
		for _, basePart in pairs(character:GetChildren()) do
			if basePart:IsA("BasePart") then
				basePart.Anchored = false
			end
		end
		
		for _, basePart in pairs(character:GetChildren()) do
			if basePart:IsA("BasePart") then
				basePart:SetNetworkOwner(nil)
			end
		end
		
		-- heads are not always 1x1x1, resize just in case
		head.Size = Vector3.one
		
		-- ragdoll parts
		for _, instance in pairs(newrdp) do
			if instance:IsA("Attachment") then
				instance.Parent = character:FindFirstChild(instance:GetAttribute("Parent"))
			elseif instance:IsA("BallSocketConstraint") then
				instance.Attachment0 = newrdp[instance:GetAttribute("0")]
				instance.Attachment1 = newrdp[instance:GetAttribute("1")]
				instance.Parent = socketsFolder
			end
		end
	end
	
	-- ragdoll value
	if self.options.makeRagdollValue then
		
		-- value
		local bool = Instance.new("BoolValue")
		bool.Name = "Ragdolled"
		bool.Parent = character
		
		-- ragdoll value
		bool:GetPropertyChangedSignal("Value"):Connect(function()
			local value = bool.Value
			if value then
				self:ragdoll(character)
			else
				self:unragdoll(character)
			end
		end)
	end
end

function ragdoll:ragdoll(character: Model, force: Vector3)
	-- variables
	local isPlayer = players:GetPlayerFromCharacter(character)
	
	-- references
	local humanoid = character:FindFirstChild("Humanoid")
	local root = character:FindFirstChild("HumanoidRootPart")
	local torso = character:FindFirstChild("Torso")
	
	-- checks
	if not humanoid then return end
	if tostring(humanoid.RigType.Name) ~= "R6" then error("ragdoll module: rig is not R6") return end
	if not root then return end
	if not torso then return end
	
	-- setup
	humanoid:ChangeState(Enum.HumanoidStateType.Physics)
	humanoid.AutoRotate = false
	
	-- disabling motors
	for _, motor in pairs(torso:GetChildren()) do
		if motor:IsA("Motor6D") then
			motor.Enabled = false
		end
	end
	
	-- collision group
	for _, basepart in pairs(character:GetChildren()) do
		if basepart:IsA("BasePart") then
			basepart.CollisionGroup = "ragdoll"
		end
	end
	
	-- impulse
	if self.options.impulse then
		root:ApplyAngularImpulse(Vector3.new(-90, 0, 0))
	end
	
	-- force
	if force and typeof(force) == "Vector3" then
		root.Velocity += force
	end
	
	-- ragdoll timer
	if self.options.ragdollTimer then 
		task.spawn(function()

			-- wait
			task.wait(self.options.ragdollTimer)
			
			-- unragdoll
			if character then
				self:unragdoll(character)
			end
		end)
	end
end

function ragdoll:unragdoll(character: Model)
	-- variables
	local player = players:GetPlayerFromCharacter(character)
	
	-- references
	local humanoid = character:FindFirstChild("Humanoid")
	local root = character:FindFirstChild("HumanoidRootPart")
	local torso = character:FindFirstChild("Torso")

	-- checks
	if not humanoid then return end
	if tostring(humanoid.RigType.Name) ~= "R6" then error("ragdoll module: rig is not R6") return end
	if not root then return end
	if not torso then return end

	-- setup
	humanoid:ChangeState(Enum.HumanoidStateType.GettingUp)
	humanoid.AutoRotate = true
	
	-- enabling motors
	for _, motor in pairs(torso:GetChildren()) do
		if motor:IsA("Motor6D") then
			motor.Enabled = true
		end
	end
	
	-- collision group
	for _, basepart in pairs(character:GetChildren()) do
		if basepart:IsA("BasePart") then
			basepart.CollisionGroup = "Default"
		end
	end
end

return ragdoll

for anyone wondering, the module:Ragdoll() function is called from the server, not clients.

any help is greatly appreciated !

Are you only damaging the rig on the client and don’t want it to replicate the damage to the server?