I see no obvious easy solution to this. There’s always going to be false positives with whatever method you choose.
What you said here is probably the best:
My recomendation however is to forget about it and move onto something else. I think its more beneficial to allocate more resources into developing the main crux of your game.
Failed completely just because I can’t detect layered clothing because layered clothing is actually on top of the character not where it is on the character.
Okay, so. Just got back from the gym and made whatever this abomination is:
NOTE THIS DOESN’T WORK WITH LAYERED CLOTHING
local test_list = {Enum.AccessoryType.Back,Enum.AccessoryType.Front,Enum.AccessoryType.Unknown}
local min_accuracy = 0.8
local ray_params = RaycastParams.new()
ray_params.FilterType = Enum.RaycastFilterType.Include
for _,child in pairs(script.Parent.Victim:GetChildren()) do
if child:IsA("Accessory") then
test = false
for _,acc_type in pairs(test_list) do
if child.AccessoryType == acc_type then
test = true
end
end
if test then
local fake_accessory = game:GetService("AssetService"):CreateMeshPartAsync(child.Handle.SpecialMesh.MeshId)
fake_accessory.Name = "FakeAccessory"
fake_accessory.Anchored = true
fake_accessory.Parent = workspace
fake_accessory.CFrame = script.Parent.FakeTorso.CFrame*script.Parent.Victim.Torso.CFrame:ToObjectSpace(child.Handle.CFrame)
ray_params.FilterDescendantsInstances = {fake_accessory}
local rays_hit = 0
local rays_not_hit = 0
local rays_should_have_hit = 0
local rays_should_not_have_hit = 0
for _,attachment in pairs(script.Parent.FakeTorso:GetChildren()) do
local new_ray = workspace:Raycast(attachment.WorldPosition,attachment.WorldCFrame.LookVector,ray_params)
if attachment.Name == "True" then
rays_should_have_hit += 1
if new_ray then
print("W")
rays_hit += 1
end
elseif attachment.Name == "False" then
rays_should_not_have_hit += 1
if not new_ray then
rays_not_hit += 1
end
end
end
local precent = (rays_hit+rays_not_hit)/(rays_should_have_hit+rays_should_not_have_hit)
if precent > min_accuracy then
print(child.Name.." CONFIDENCE:"..tostring(math.round(precent*100)).."%")
end
fake_accessory:Destroy()
end
end
end
I create a “fake accessory” using MeshPart, which allows me to check if it’s a certain shape.
Obviously, knowing that not all Chest accessories are the same shape, we use a “minimum confidence” variable, which I found that a 0.8/80% works good for both 1.0 and 3.0 Chests. Granted, I’ll have to make a large scale test to check how much of the accessories it detects later.
I made this thing in response to this post like an hour ago based off some other avatar related shenanigans i was doing a while ago:
local blacklistcreators = {"."}--Defaults filter everything.
local blacklistnames = {"."}
local blacklistdescriptors = {"."}
local function maincheck(info)
local val = false
local splitname = string.split(info["Name"],"%s%p")
for r = 1, #splitname do
for t = 1, #blacklistnames do
if string.match(splitname[r],blacklistnames[t]) then
val = true
end
end
end
for t = 1, #blacklistcreators do
if string.match(info["Creator"]["Name"],blacklistcreators[t]) then
val = true
end
end
local splitdescription = string.split(info["Description"],"%s%p")
for r = 1, #splitdescription do
for t = 1, #blacklistdescriptors do
if string.match(splitdescription[r],blacklistdescriptors[t]) then
val = true
end
end
end
return val
end
local plydesc = script.Parent:WaitForChild("Humanoid"):WaitForChild("HumanoidDescription")
if tonumber(plydesc.Torso) and tonumber(plydesc.Torso) ~= 0 and maincheck(game:GetService("MarketplaceService"):GetProductInfo(tonumber(plydesc.Torso))) == true then
plydesc.Torso = "0"
end
if tonumber(plydesc.Pants) and tonumber(plydesc.Pants) ~= 0 and maincheck(game:GetService("MarketplaceService"):GetProductInfo(tonumber(plydesc.Pants))) == true then
plydesc.Pants = "14862393678" -- This id is just a random image i uploaded for a custom reflection cubemaps test.
end
if tonumber(plydesc.Shirt) and tonumber(plydesc.Shirt) ~= 0 and maincheck(game:GetService("MarketplaceService"):GetProductInfo(tonumber(plydesc.Shirt))) == true then
plydesc.Shirt = "14858194613" -- same as other one
end
task.wait(0.05)--Extra wait to make sure the AccessoryDescriptions have loaded in.
local extradescs = plydesc:GetChildren()
for i = 1, #extradescs do
if extradescs[i].ClassName == "AccessoryDescription" and maincheck(game:GetService("MarketplaceService"):GetProductInfo(tonumber(extradescs[i].AssetId))) == true then
extradescs[i]:Destroy()
end
end
script.Parent.Humanoid:ApplyDescriptionReset(plydesc)
Works with layered clothing, 2d clothing, accessories and torsos doesnt do anything with the shape though, You put it in StarterCharacterScripts as a script(RunContext: server or Legacy).
Might be a bit too many attachments, but this is the system that I’ve decided on.
I use a singular raycast per attachment that is parallel to the torso that are in the shape of a chest.
I am not sure how many false positives this system may give with the “is air” and “is filled” system.
MUST BE AIR:
MUST BE FILLED:
BOTH:
As you can see, the system works surprisingly well once tweaked to work as necessary.
And it doesn’t limit you from only doing side checks eithers, since it uses the direction of the attachment! Of course, you still have to consider the performance impact, although I doubt that doing one check every time a character changes should cost too much. Especially since this is only done on Front, Back and Unknown accessories.
if you guys are so bothered about this. probs the best thing to do would be to use Pythonanywhere to create our own API, this would allow for 2 interaction - 1: submit asset id fro blacklisting, and 2 check where an item id is blacklisted.
I def could def put this together for you for free, but hostings costs would cost about $5 a month.
so basically when a player join you get all the asset ides for their stuff send them to pythonanywhere server and it tell you if someone has marked them to be blacklisted.
Don’t know if anyone’s said this yet but the best way to make sure this doesn’t happen is to put a custom character creator in your game. A lot of people don’t like doing this for obvious reasons but unfortunately it’s the only way to totally control what people wear in your game.
If you don’t want to go full nuclear, you can have a script check a user’s hats and only remove items that are not uploaded by Roblox. However since everyone wears UGC now it’s likely to cause a lot of confusion and upset your players.
I’ve decided that I’d probably prefer this to be community driven.
To be more exact, players are able to submit inappropriate UGC items and using some sort of online hosted API the suggestions are sent to a select few moderators and they may either accept them or decline them, making so that we both avoid having false-positives using other methods and that we are able to blacklist a lot more inappropriate UGC items than just Chests.
If anyone is interested in helping with this I’d be glad to take suggestions, but ultimately, this is the approach I want to take. If roblox won’t moderate it’s platform, as developers, I feel like we should do something about it instead.
to be honest, the simplest method/s would be to let players decide if they want to see front/back accessories or just disable front/back accessories entirely
i doubt anyone would want to actively moderate some roblox melon reports
dont even bother having moderators, just let people submit items and then return the number of times they have been submitted. so if you want super good standards block any items that return a value of 1 or greater and then if you want less moderation pick items that are >2 etc
Hmm I think I might have a solution. When a front accessory is submitted you could load it (preferably on the client of who uploaded it to make it less laggy) somewhere in the game and create 3 raycast, 2 of which should start a couple studs in front of each melon. The third raycast should also be a couple studs infront of the accessory but below and in the middle of the other 2 raycast (the ray casts should face towards the accessory). Then check the distance it took for the ray casts to hit a part on the accessory, if the difference between the 2 raycast and the 3rd is greater that let’s say 2 studs you can deem the accessory inappropriate.
I think this is an awesome idea personally and I would even pay for a service like this if it works. It’s unfortunate that WE are the ones who have to be responsible and clean up Roblox’s mess but I’m running out of feasible options to deal with this.
No, I refuse to.
Like I said, I have a very personal stance against these types of UGCs.
Also. I did not spend almost a week learning about Rest API, hosting and other stuff to stop now.
I WILL do it and NOBODY can stop me.
There are already enough people bothered to do so.
Even then, I can always just look through the UGC’s myself and sort of scrape the inappropriate stuff by hand.
I will put an end to those degens by hand if I must.
I’ll keep y’all updated on the progress btw.
Honestly? The most efficient way is hand filtering. Make a big list of all the IDs, adding them in as you go. It’s how people blacklisted audios when boomboxes were around, and how people blacklisted large accessories from games where it may be a disruption.