local UGCValidationService = game:GetService("UGCValidationService") local root = script.Parent.Parent local Constants = require(root.Constants) local DEFAULT_OFFSET = Vector3.new(0, 0, 0) local function pointInBounds(worldPos, boundsCF, boundsSize) local objectPos = boundsCF:pointToObjectSpace(worldPos) return objectPos.X >= -boundsSize.X/2 and objectPos.X <= boundsSize.X/2 and objectPos.Y >= -boundsSize.Y/2 and objectPos.Y <= boundsSize.Y/2 and objectPos.Z >= -boundsSize.Z/2 and objectPos.Z <= boundsSize.Z/2 end local function getAttachment(parent, names) for _, name in pairs(names) do local result = parent:FindFirstChild(name) if result then return result end end return nil end local function validateMeshBounds(isAsync, instance, assetTypeEnum) local assetInfo = Constants.ASSET_TYPE_INFO[assetTypeEnum] -- these are guaranteed to exist thanks to validateInstanceTree being called beforehand local handle = instance.Handle local mesh = handle:FindFirstChildOfClass("SpecialMesh") local attachment = getAttachment(handle, assetInfo.attachmentNames) if mesh.MeshId == "" then return false, { "Mesh must contain valid MeshId" } end local success, verts = pcall(function() if isAsync then return UGCValidationService:GetMeshVerts(mesh.MeshId) else return UGCValidationService:GetMeshVertsSync(mesh.MeshId) end end) if not success then return false, { "Failed to read mesh" } end local boundsInfo = assert(assetInfo.bounds[attachment.Name], "Could not find bounds for " .. attachment.Name) local boundsSize = boundsInfo.size local boundsOffset = boundsInfo.offset or DEFAULT_OFFSET local boundsCF = handle.CFrame * attachment.CFrame * CFrame.new(boundsOffset) for _, vertPos in pairs(verts) do local worldPos = handle.CFrame:pointToWorldSpace(vertPos * mesh.Scale) if not pointInBounds(worldPos, boundsCF, boundsSize) then return false, { "Mesh is too large!", string.format("Max size for type %s is ( %s )", assetTypeEnum.Name, tostring(boundsSize)), "Use SpecialMesh.Scale if needed" } end end return true end return validateMeshBounds