Why My Voxel Modules Delele Random Parts

Here what It should be like

Here what I get

the image for “Here what It should be like” is my old version without queue so It gonna be like that

--[[ 
	CAUTION : THIS MODULE IS IN ALPHA!!!
	
	THX TO : wackz for insp and shatterbox for optimize tips!!!

    Version: 1
]]

local blockBuster = {}

--remotes
local replicate = script.Replicate

--modules
local Subdivide = require(script.Subdivide)
local Encapsulates = require(script.Encapsulates)
local PartSen = require(script.PartSen)
--Setup
local tempBlockBusterFolder = Instance.new("Folder",workspace)
tempBlockBusterFolder.Name = ""

local server = Instance.new("Folder",workspace)
server.Name = "server_blockBuster"

local client = Instance.new("Folder",workspace)
client.Name = "client_blockBuster"

--Service and stuff
local runService = game:GetService("RunService")
local blockBusterQueue = {}
local currentId = 0

blockBuster.destroyableTag = "Destroyable"
--optimize stuff
blockBuster.maxDividePerFrame = 100

blockBuster.defaultVoxelSize = 1 --defalut voxel size change this if you like!!!

--this is default overlapParams bc why not
blockBuster.defaultOverlapParams = OverlapParams.new()
blockBuster.defaultOverlapParams.FilterType = Enum.RaycastFilterType.Exclude
blockBuster.defaultOverlapParams.FilterDescendantsInstances = {}

blockBuster.partDestroy = function(part) -- you can change behivor of this to make what you like (when destroy voxels btw) this get replicate to client too so IF you want 2 behavior using rs in the function
	part:Destroy()
end

function destroy(part,isVoxel,destroyFunction) -- this is for the replicate Stuff

	if isVoxel then
		destroyFunction(part)
	else
		part:Destroy()
	end
end

function divideable(part: BasePart, allowTemp)
	if not part:IsA("BasePart") then return false end
	if part.Shape ~= Enum.PartType.Block then return false end
	if not part:HasTag(blockBuster.destroyableTag) then return false end
	if not allowTemp and part.Parent == tempBlockBusterFolder then return false end
	return true
end

function blockBuster.partToHitbox(hitbox : BasePart, voxelSize : number, overlapParams : OverlapParams, voxelHandler)
	replicate:FireAllClients()
	local parts

	voxelSize = voxelSize or blockBuster.defaultVoxelSize
	overlapParams = overlapParams or blockBuster.defaultOverlapParams
	voxelHandler = voxelHandler or blockBuster.partDestroy

	if overlapParams == blockBuster.defaultOverlapParams then
		overlapParams.FilterDescendantsInstances = {hitbox,tempBlockBusterFolder}
	end

	repeat
		parts = workspace:GetPartsInPart(hitbox, overlapParams)

		local remainingParts = {}
		local processedParts = {}
	
		if #parts == 0 then break end

		local maxProcess = math.min(#parts, blockBuster.maxDividePerFrame)

		for i = 1, maxProcess do
			local part = parts[i]
			
			if divideable(part) then
				local subdivide = Subdivide.subdivide(part, voxelSize,hitbox)
				if subdivide then
					for _, sub in pairs(subdivide) do
						--create a part in client
						local size = sub.Size
					
						local clonePart = part:Clone()
						clonePart.Anchored = true	
						clonePart.CFrame = sub.CFrame
						clonePart.Size = size
						clonePart.Parent = server
					end
					
					destroy(part,false)
				else
					destroy(part,true,voxelHandler)
				end

				table.insert(processedParts,part)
			end
		end

		for _, part in pairs(parts) do
			if not table.find(processedParts,part) then
				table.insert(remainingParts, part)
			end
		end

		if #remainingParts > 0 then
			for _, part in pairs(remainingParts) do
				blockBusterQueue[part] = {
					voxelSize = voxelSize,
					voxelHandler = voxelHandler,
					parent = server,
					hitbox = hitbox,
				}
				
				part.Parent = tempBlockBusterFolder
			end
		end

	until #parts == 0
	
end

runService.Heartbeat:Connect(function()

	for part, data in pairs(blockBusterQueue) do
		--if divideCount >= blockBuster.maxDividePerFrame then
		--	break
		--end
		
		local voxelSize = data.voxelSize
		local hitbox = data.hitbox
		local handler = data.voxelHandler

		if divideable(part,true) then
			local subdivide = Subdivide.subdivide(part, voxelSize)
			if subdivide then

				for _, sub in pairs(subdivide) do
					local size = sub.Size

					local clonePart = part:Clone()
					clonePart.Anchored = true
					clonePart.CFrame = sub.CFrame
					clonePart.Size = size
					clonePart.Parent = server

					if not Subdivide.isVoxel(size,voxelSize) then
						blockBusterQueue[clonePart] = {
							voxelSize = voxelSize,
							voxelHandler = handler,
							parent = server,
							hitbox = hitbox,
						}

						clonePart.Parent = tempBlockBusterFolder
					end
				end
				
				local isIn,Point = Encapsulates(part,hitbox.CFrame,hitbox.Size)
				
				if Point > 0 then
					destroy(part,false)
					blockBusterQueue[part] = nil
				elseif Point <= 0 then
					blockBusterQueue[part] = nil
				end
			else
				destroy(part,true,handler)
				blockBusterQueue[part] = nil
			end
		else
			blockBusterQueue[part] = nil
		end
	end
end)

return blockBuster

I believe this issue is more suitable for the category Scripting Support since it involves scripting.
This category is for assisting those that are using the platform.

I’m new to devforum thanks I changed it

1 Like

figure it out I need to mod the Encapsulates check