Replicating Spawned Items | ReplicaService

  1. What do you want to achieve? Keep it simple and clear!
    I realize my system for spawning items is slow because i do every thing on the server, so i decided to take a look a replica service. I am currently using replica Service for the replication of the data. So if the player breaks the item or damages it, it will replicate for all other players ingame, also i want to load certain items either based on the current zone the player is in or, the zone around the player.

  2. What is the issue? Include screenshots / videos if possible!
    I have no clue what to do, when the item is clone withing the spawn item function, i create a new replica. But don’t know what to do from there, also i have other functions to have the player move to the item and start taking its health so the player can get a rewards from the item.

External Media
  1. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
    I Look on devForum and i only found replicating Data for like profile service
function module:startSearching(player, itemInstance, zoneName, position, orientation, parent)
	DataService:GetReplica(player):andThen(function(replica)
		foundItems[player] = {}
		-- Get the player's inventory and max bag size
		local Inventory = replica.Data.ItemInventory.Inventory
		local MaxBagSize = replica.Data.ItemInventory.MaxBagSize
		local itemCount = 0

		-- Count the number of items in the inventory
		for _ in pairs(Inventory) do
			itemCount = itemCount + 1
		end

		-- Check if the inventory is full
		if itemCount >= MaxBagSize then
			Network:FireClient(
				player,
				"Notify",
				"Your inventory is full! Auction or sell some thing to Clear it up.",
				3
			)
			playSound("Error", 1, workspace.Sounds)
			return -- Exit the function if the inventory is full
		end

		local billboardGui = itemInstance.PrimaryPart:FindFirstChild("PileBillBoard")
		local fillFrame = billboardGui and billboardGui.Frame.HealthBar
		billboardGui.PileName.Text = itemInstance.Name
		local health = itemInstance:GetAttribute("Health")

		if searchingPlayers[player.UserId] then
			return
		end
		searchingPlayers[player.UserId] = true

		-- Ensure the player has a character and the character has a Humanoid
		local character = player.Character
		local humanoid = character and character:FindFirstChildOfClass("Humanoid")
		local playerPosition = character.PrimaryPart.Position
		local pilePosition = itemInstance.PrimaryPart.Position
		local distance = (playerPosition - pilePosition).Magnitude
		local walkSpeed = humanoid and humanoid.WalkSpeed
		local timeToReach = distance / walkSpeed
		if not humanoid then
			searchingPlayers[player.UserId] = nil
			return
		end

		-- Move the player to the item
		local offset = Vector3.new(0, 0, 5)
		humanoid:MoveTo(itemInstance.PrimaryPart.Position + offset) -- Adjust the offset as needed
		task.wait(timeToReach - 1)

		playerPosition = character.PrimaryPart.Position
		distance = (playerPosition - pilePosition).Magnitude
		if distance > 32 then
			searchingPlayers[player.UserId] = nil
			return -- Exit the function if the player is not near the pile
		end

		while itemInstance:GetAttribute("Health") > 0 do
			Network:FireClient(player, "PlayDirtSound")
			local isCritical = math.random() < 0.1 -- 10% chance of a critical hit
			local healthReductionRate = isCritical and replica.Data.Damage * 1.5 or replica.Data.Damage
			Network:FireClient(player, "DealDamage", healthReductionRate, isCritical)
			itemInstance:SetAttribute("Health", itemInstance:GetAttribute("Health") - healthReductionRate)
			updateHealthBar(itemInstance, fillFrame, health)

			local scaleFactor = itemInstance:GetAttribute("Health") / health
			local newSize = itemInstance.PrimaryPart.Size * scaleFactor

			local tweenInfo = TweenInfo.new(0.3, Enum.EasingStyle.Linear, Enum.EasingDirection.Out)
			local tweenGoal = {}
			tweenGoal.Size = newSize
			local tween = TweenService:Create(itemInstance.PrimaryPart, tweenInfo, tweenGoal)
			tween:Play()
			tween.Completed:Wait()
		end

		module:finishSearching(player, itemInstance, zoneName, position, orientation, parent)
	end)
end

function module:finishSearching(player, itemInstance, zoneName, position, orientation, parent)
	DataService:GetReplica(player):andThen(function(replica)
		searchingPlayers[player.UserId] = nil
		if not replica then
			return
		end

		replica:SetValue(
			{ "JunkyardData", "TotalJunkPilesSearched" },
			replica.Data.JunkyardData.TotalJunkPilesSearched + 1
		)
		print("TotalJunkPilesSearched: " .. replica.Data.JunkyardData.TotalJunkPilesSearched)
		local MaxBagSize = replica.Data.ItemInventory.MaxBagSize
		local Inventory = replica.Data.ItemInventory.Inventory
		local itemCount = 0
		local itemName = itemInstance.Name
		local itemData = ItemsData[itemName].Items

		local itemsList = {}
		local spawnRate = itemData.SpawnRate or 0.5
		local respawnDelay = 1 / spawnRate

		if itemData then
			for _, itemInfo in pairs(itemData) do
				table.insert(itemsList, itemInfo)
			end
		else
			warn("Item data not found for item: " .. itemName)
		end

		for i = 1, 3 do
			local selectedItem = selectRandomItem(itemsList)
			if selectedItem then
				--- a way to add all three item to the foundItems[player] table
				if not foundItems[player] then
					foundItems[player] = {}
				end
				table.insert(foundItems[player], selectedItem)
			end
		end

		for _ in pairs(Inventory) do
			itemCount = itemCount + 1
		end

		if itemCount <= MaxBagSize then
			Network:FireClient(player, "FinishedSearching")
			Network:FireClient(player, "RewardsEvent", foundItems[player])
			for _, item in ipairs(foundItems[player]) do
				replica:ArrayInsert({ "ItemInventory", "Inventory" }, item)
			end
		else
			Network:FireClient(
				player,
				"Notify",
				"Your inventory is full! Auction or sell some thing to Clear it up.",
				3
			) 
			playSound("Error", 1, workspace.Sounds)
		end

		SetParticles(itemInstance)

		
		itemInstance:Destroy()
		

		Network:FireClient(player, "FinishedSearching")

		task.spawn(function()
			module:respawnIngredient(itemName, zoneName, position, orientation, parent, respawnDelay)
		end)
	end)
end

function module:spawnItem(itemName, zoneName, position, orientation, parent)
	local itemCount = itemInstances[itemName] or 0
	if itemCount >= 10 then
		handleError("Maximum limit reached for item: " .. itemName)
		return
	end

	local itemData = PilesData[itemName]
	if not itemData then
		handleError("No data found for item: " .. itemName)
		return
	end

	local itemModel = Items[zoneName]:FindFirstChild(itemName)
	if not itemModel then
		handleError("No model found for item: " .. itemName)
		return
	end

	local zonePart = parent.Parent
	local zoneSize = zonePart.Size

	local randomX = position.X + (math.random(-1, 1)) * zoneSize.X * .5
	local randomY = position.Y -- Adjust this if you have a height offset
	local randomZ = position.Z + (math.random(-1, 1)) * zoneSize.Z * .5

	local orientationX = math.rad(orientation.X)
	local orientationY = math.rad(orientation.Y)
	local orientationZ = math.rad(orientation.Z)

	local itemInstance = itemModel:Clone()
	itemInstance.Name = itemName

	local newItem = ReplicaService.NewReplica({
		ClassToken = ClassToken,
		Data = {
			IsDestoryed = false,
			Health = itemData.Health
		},
		Replication = "All"
	})


	local newCFrame = CFrame.new(Vector3.new(randomX, randomY, randomZ)) * CFrame.Angles(orientationX, orientationY, orientationZ)
	itemInstance:SetPrimaryPartCFrame(newCFrame)
	itemInstance.Parent = parent

	local primaryPart = itemInstance.PrimaryPart

	local billboardGui = primaryPart:FindFirstChild("PileBillBoard")
	billboardGui.PileName.Text = itemInstance.Name

	local health = itemData.Health or 100
	itemInstance:SetAttribute("Health", health)

	itemInstances[itemName] = itemCount + 1

	local fadeDuration = 2
	local tweenInfo = TweenInfo.new(fadeDuration, Enum.EasingStyle.Bounce, Enum.EasingDirection.Out)
	local tweenGoal = { Transparency = 0 }

	local descendants = itemInstance:GetDescendants()
	for _, child in ipairs(descendants) do
		if child:IsA("BasePart") then
			local tween = TweenService:Create(child, tweenInfo, tweenGoal)
			tween:Play()
		end
	end

	raycaseItem(itemInstance)
	module:setUpClickDetector(itemInstance, function(player)
		module:startSearching(player, itemInstance, zoneName, position, orientation, parent)
	end)
end