Asset Dictionary | A fast and easy way to get IDs

This module will run a loop and append any IDs it finds to a table corresponding to the asset type.


Module link: Asset Dictionary
Documentation: Asset Dictionary Documentation
GitHub: bloodbonnieking/Roblox-Asset-Dictionary


Updates

V1.1:

  • Added different tables for every asset
  • Fixed the 2nd argument not doing anything
  • Changed the elseifs to cases (table)
  • Added some exceptions and errors

V1.2:

  • Fixed a coding oversight that would only sort AssetDictionary, DecalDictionary and TextureDictionary
  • Added a new optional boolean “Reverse”. Read more in the documentation.

V1.3:

  • Added pants and shirt support

V1.4:

  • Fixed supported assets getting skipped over for “not being supported”
  • Switched to numeric for loop to hopefully speed stuff up
  • Switched to using typeof() for exceptions

V1.5:

  • Added a few memory related functions (read more in the documentation)
  • Changed the AssetDictionary table to GeneralDictionary, and finally deprecated it. (REMOVED COMPLETELY IN V1.6)

V1.6:
- Removed GeneralDictionary (it was useless and it made the script unreadable)

  • Added type notations (tried to add type notations before in a few unreleased versions because I didn’t know that ? makes it optional)
  • Removed nil checks
  • Made errors tell you the argument name instead
  • Added a new argument, read more in the documentation

V1.7:

  • Moved documentation (and made it better)
  • Moved animation dictionary to above image labels, this does not affect anything and is merely tidying up the code a bit
  • Changed . to : for functions for slight consistency
  • Video support
  • ClearTable now needs the asset type name to avoid accidental clearing of non-related tables
  • Errors are now level 2 errors
  • Added a print argument for debugging

V1.8:

  • Cleaned up the code, got rid of useless things and improved it a bit
  • Moved dictionaries into ModuleDictionary.Dictionaries. This isn’t a big change, but possibly a tedious one.
  • Got rid of “temporary tables” which were the tables that weren’t share across scripts.
  • Created a new argument, ClearTables which will clear all of the tables before appending the ids (default is true)
  • Removed some useless exceptions
  • Script uses native Luau now (from my testing, it used to take a solid second without native and now it takes like less than half a second) (read more here: Luau Native Code Generation Preview [Studio Beta])
  • Made ClearTable WAY more compact
  • ClearTable now accepts strings with “Dictionary”, not just without
    V1.8.1 (not wasting a version number)
  • The GetDictionary scope no longer ends before the return (that wasn’t intentional)
  • Print will now print a benchmark (note: the time starts as soon as the function is called and the print happens at the end, which means other if statements may change the result.)
    V1.9
  • Added support for particle emitters
  • that’s it

What’s supported:

  • Decals
  • Textures
  • Sounds
  • Meshes
  • Animations
  • Image labels
  • Image buttons
  • Video frames
  • Shirts
  • Pants
  • Particle emitters

Here is the code if you don’t want to open it in a place:

--!native

local ModuleDictionary = {}
ModuleDictionary.Dictionaries = {
	GeneralDictionary = {};
	DecalDictionary = {};
	TextureDictionary = {};
	SoundDictionary = {};
	MeshDictionary = {};
	AnimationDictionary = {};
	VideoDictionary = {};
	ImageLabelDictionary = {};
	ImageButtonDictionary = {};
	ShirtDictionary = {};
	PantsDictionary = {};
	ParticleDictionary = {}
}
local Dictionaries = ModuleDictionary.Dictionaries

--//main functions

local function AddToTable(Target, Print)
	local Start = os.clock()
	for index = 1, #Target do
		local Cases = {
			["Decal"] = function ()
				table.insert(Dictionaries.DecalDictionary, Target[index].Texture)
				table.insert(Dictionaries.GeneralDictionary, Target[index].Texture)
			end,
			["Texture"] = function ()
				table.insert(Dictionaries.TextureDictionary, Target[index].Texture)
				table.insert(Dictionaries.GeneralDictionary, Target[index].Texture)
			end,
			["Sound"] = function ()
				table.insert(Dictionaries.TextureDictionary, Target[index].SoundId)
				table.insert(Dictionaries.GeneralDictionary, Target[index].SoundId)
			end,
			["Mesh"] = function ()
				table.insert(Dictionaries.MeshDictionary, Target[index].MeshId)
				table.insert(Dictionaries.GeneralDictionary, Target[index].MeshId)
			end,
			["Animation"] = function ()
				table.insert(Dictionaries.AnimationDictionary, Target[index].AnimationId)
				table.insert(Dictionaries.GeneralDictionary, Target[index].AnimationId)
			end,
			["VideoFrame"] = function ()
				table.insert(Dictionaries.VideoDictionary, Target[index].Video)
				table.insert(Dictionaries.GeneralDictionary, Target[index].Video)
			end,
			["ImageLabel"] = function ()
				table.insert(Dictionaries.ImageLabelDictionary, Target[index].Image)
				table.insert(Dictionaries.GeneralDictionary, Target[index].Image)
			end,
			["ImageButton"] = function ()
				table.insert(Dictionaries.ImageButtonDictionary, Target[index].Image)
				table.insert(Dictionaries.GeneralDictionary, Target[index].Image)
			end,
			["Shirt"] = function ()
				table.insert(Dictionaries.ShirtDictionary, Target[index].ShirtTemplate)
				table.insert(Dictionaries.GeneralDictionary, Target[index].ShirtTemplate)
			end,
			["Pants"] = function ()
				table.insert(Dictionaries.PantsDictionary, Target[index].PantsTemplate)
				table.insert(Dictionaries.GeneralDictionary, Target[index].PantsTemplate)
			end,
			["ParticleEmitter"] = function ()
				table.insert(Dictionaries.ParticleDictionary, Target[index].Texture)
				table.insert(Dictionaries.GeneralDictionary, Target[index].Texture)
			end,
		}
		if Print then
			print(`Name: {Target[index]} ClassName: {Target[index].ClassName}`)
		end
		local success, err = pcall(function()
			Cases[Target[index].ClassName]()
		end)
		if not success and Print then
			warn("Instance is not supported. Expected a downloadable or supported asset, got "..tostring(Target[index].ClassName))
		end
	end
	local End = os.clock()
	if Print then
		print(`For loop took: {End - Start}`)
	end
end



function ModuleDictionary:GetDictionary(Target: Instance, Descendants: boolean?, ClearTables: boolean?, Sort: boolean?, Reverse: boolean?, DeleteTarget: boolean?, Print: boolean?)

	local StartTime = os.clock()
	if typeof(Target) ~= "Instance" then error(`GetDictionary expects Target to be an instance, got {tostring(Target)}`) end	
	if typeof(Descendants) ~= "boolean" then Descendants = false end
	if typeof(ClearTables) ~= "boolean" then ClearTables = true end
	if typeof(DeleteTarget) ~= "boolean" then DeleteTarget = false end
	if typeof(Sort) ~= "boolean" then Sort = true end
	if typeof(Reverse) ~= "boolean" then Reverse = true end
	if typeof(Print) ~= "boolean" then Print = false end

	if ClearTables == true then
		for _, tables in pairs(Dictionaries) do
			table.clear(tables)
		end	
	end

	if Descendants == false then
		AddToTable(Target:GetChildren(), Print)
	elseif Descendants == true then
		AddToTable(Target:GetDescendants(), Print)
	end


	local function ReverseTable(ID1, ID2)
		pcall(function()
			--print(ID1, ID2)
			return ID1 > ID2
		end)
	end


	if Reverse == false and Sort == true then
		for _, tables in pairs(Dictionaries) do
			table.sort(tables)
		end
	elseif Reverse == true and Sort == true then
		for _, tables in pairs(Dictionaries) do
			print(tables)
			table.sort(tables, ReverseTable)
		end
	end


	if DeleteTarget == true then
		Target:Destroy()
	end

	if Print == true then
		print("General:", Dictionaries.GeneralDictionary)
		print("Decals:", Dictionaries.DecalDictionary)
		print("Textures:", Dictionaries.TextureDictionary)
		print("Sounds:", Dictionaries. SoundDictionary)
		print("Meshes:", Dictionaries.MeshDictionary)
		print("Animations:", Dictionaries.AnimationDictionary)
		print("Videos:", Dictionaries.VideoDictionary)
		print("Image Labels:", Dictionaries.ImageLabelDictionary)
		print("Image Buttons:", Dictionaries.ImageButtonDictionary)
		print("Shirts:", Dictionaries.ShirtDictionary)
		print("Pants:", Dictionaries.PantsDictionary)
		print("Particles:", Dictionaries.ParticleDictionary)
		local EndTime = os.clock()
		print(`Took: {EndTime - StartTime}`)
	end
end

--//memory freeing functions

function ModuleDictionary:ClearTable(Table: string)
	if typeof(Table) == "string" then
		local success, err = pcall(function()
			print(Table)
			if Table:find("Dictionary") then
				table.clear(Dictionaries[Table])
			else
				table.clear(Dictionaries[Table.. "Dictionary"])
			end
		end)
		if not success then
			error("ClearTable expects the string to be a supported asset, got "..Table, 2)
		end
	end
end

function ModuleDictionary:ClearAllTables() --//no arguments needed, and will only clear asset dictionary tables.
	for _, tables in pairs (Dictionaries) do
		table.clear(tables)
	end
end

task.spawn(function()
	while task.wait(1) do
	print(Dictionaries)
	end
end)

return ModuleDictionary
15 Likes

why is it uploaded to the “Vulkano Studios” group?

2 Likes

edit: the module is no longer uploaded to that group.

Why are you asking?
I’ve asked the people who i work with if i should upload it under the group and they said yes. We have agreed to upload it under the group.
that probably came off ruder than i wanted lol

7 Likes

I’m not rude (sorry if I sounded rude)

but I like your module!

3 Likes

I’ll add a change soon. I’ll add another argument for if you want to reverse the tables or not. Default is true.

1 Like

Nah don’t worry i was a little confused by the tone. Glad you like it!

4 Likes

Alright patch is out:
fixed supported assets being skipped over even though they are supported
switched to numeric for loop for a slight performance increase (micro-optimizing i know)
switched to typeof() for exceptions
if you have any ideas please tell me. the code looks like a mess ngl

1 Like

Released a new update. I recommend you use this new version. sorry for weird post formatting lol

1 Like

Updated it again, you should use this version since it’s cleaner (i think) and i finally just deleted GeneralDictionary lol

2 Likes

well not anymore lmao since i do not work with them anymore. that version is now deprecated since i can’t maintain it.

2 Likes

V1.7!!! Now there is video support, moved documentation, also changed groups due to the fact i do not work with Vulkano Studios anymore. That version is now deprecated since i cannot maintain it. Please use the new one from now on. check changelogs for other changes!

1 Like

You did a mistake here

anyways I joined the linked group but the game in the group is broken

2 Likes

whoops my bad, also dark forest? that’s a very old project i am not really working on at the moment lol. right now i’m working on another horror game since dark forest was very poorly written lmao.

2 Likes

If you find bugs (which you probably will since i suck at coding) please leave a detailed report here. Also, if you have feedback, suggestions or improvement feel free to leave them here!

1 Like

We’ve come a long way, (oh also V1.8 came out and you need to use this since it is way better) from 36 lines and like one table and nearly nothing, to the current 149 lines.

V1 code (release)

local ModuleDictionary = {}
local AssetDictionary = {}
local function AddToTable(Target)
    for _, instance in pairs(Target:GetChildren()) do
        if instance:IsA("Decal", "Texture") then
            table.insert(AssetDictionary, instance.Texture)
        elseif instance:IsA("Sound") then
            table.insert(AssetDictionary, instance.SoundId)
        elseif instance:IsA("Mesh") then
            table.insert(AssetDictionary, instance.MeshId)
        elseif instance:IsA("ImageLabel", "ImageButton") then
            table.insert(AssetDictionary, instance.ImageId)
        elseif instance:IsA("Animation") then
            table.insert(AssetDictionary, instance.AnimationId)
        end
    end
end
function ModuleDictionary.GetDictionary(Target, Descendants, DeleteTarget)
    if Descendants == false or Descendants == nil then
        AddToTable(Target)
    elseif Descendants == true then
        AddToTable(Target)
    elseif Descendants ~= true and Descendants ~= false and Descendants ~= nil then
        error("GetDictionary expects the second argument to be a boolean, got".. " "..tostring(Descendants))    
    end
    local function ReverseTable(ID1, ID2)
        return ID1 > ID2
    end
    table.sort(AssetDictionary, ReverseTable)
    ModuleDictionary.Dictionary = AssetDictionary
    print(AssetDictionary)
    if DeleteTarget == true then
        Target:Destroy()
    end
end
return ModuleDictionary

current code:

--!native

local ModuleDictionary = {}
ModuleDictionary.Dictionaries = {
	DecalDictionary = {};
	TextureDictionary = {};
	SoundDictionary = {};
	MeshDictionary = {};
	AnimationDictionary = {};
	VideoDictionary = {};
	ImageLabelDictionary = {};
	ImageButtonDictionary = {};
	ShirtDictionary = {};
	PantsDictionary = {};
}
local Dictionaries = ModuleDictionary.Dictionaries

--//functions

local function AddToTable(Target)
	for index = 1, #Target do
		local Cases = {
			["Decal"] = function ()
				table.insert(Dictionaries.DecalDictionary, Target[index].Texture)
			end,
			["Texture"] = function ()
				table.insert(Dictionaries.TextureDictionary, Target[index].Texture)
			end,
			["Sound"] = function ()
				table.insert(Dictionaries.TextureDictionary, Target[index].SoundId)
			end,
			["Mesh"] = function ()
				table.insert(Dictionaries.MeshDictionary, Target[index].MeshId)
			end,
			["Animation"] = function ()
				table.insert(Dictionaries.AnimationDictionary, Target[index].AnimationId)
			end,
			["VideoFrame"] = function ()
				table.insert(Dictionaries.VideoDictionary, Target[index].Video)
			end,
			["ImageLabel"] = function ()
				table.insert(Dictionaries.ImageLabelDictionary, Target[index].Image)
			end,
			["ImageButton"] = function ()
				table.insert(Dictionaries.ImageButtonDictionary, Target[index].Image)
			end,
			["Shirt"] = function ()
				table.insert(Dictionaries.ShirtDictionary, Target[index].ShirtTemplate)
			end,
			["Pants"] = function ()
				table.insert(Dictionaries.PantsDictionary, Target[index].PantsTemplate)
			end,
		}
		--print(Target[index], Target[index].ClassName)
		local success, err = pcall(function()
			Cases[Target[index].ClassName]()
		end)
		if not success then
			warn("Instance is not supported. Expected a downloadable or supported asset, got "..tostring(Target[index].ClassName))
		end
	end
end



function ModuleDictionary:GetDictionary(Target: Instance, Descendants: boolean?, ClearTables: boolean?, DeleteTarget: boolean?, Sort: boolean?, Reverse: boolean?, Print: boolean?)

	if Descendants == nil then Descendants = false end
	if ClearTables == nil then ClearTables = true end
	if DeleteTarget == nil then DeleteTarget = false end
	if Sort == nil then Sort = true end
	if Reverse == nil then Reverse = true end
	if Print == nil then Print = false end

	if ClearTables == true then
		for _, tables in pairs(Dictionaries) do
			table.clear(tables)
		end	
	end

	if Descendants == false then
		AddToTable(Target:GetChildren())
	elseif Descendants == true then
		AddToTable(Target:GetDescendants())
	end


	local function ReverseTable(ID1, ID2)
		pcall(function()
			--print(ID1, ID2)
			return ID1 > ID2
		end)
	end


	if Reverse == false and Sort == true then
		for _, tables in pairs(Dictionaries) do
			table.sort(tables)
		end
	elseif Reverse == true and Sort == true then
		for _, tables in pairs(Dictionaries) do
			table.sort(tables, ReverseTable)
		end
	end


	if DeleteTarget == true then
		Target:Destroy()
	end

	if Print == true then
		print("Decals:", Dictionaries.DecalDictionary)
		print("Textures:", Dictionaries.TextureDictionary)
		print("Sounds:", Dictionaries. SoundDictionary)
		print("Meshes:", Dictionaries.MeshDictionary)
		print("Animations:", Dictionaries.AnimationDictionary)
		print("Videos:", Dictionaries.VideoDictionary)
		print("Image Labels:", Dictionaries.ImageLabelDictionary)
		print("Image Buttons:", Dictionaries.ImageButtonDictionary)
		print("Shirts:", Dictionaries.ShirtDictionary)
		print("Pants:", Dictionaries.PantsDictionary)
	end

	--//memory freeing functions

	function ModuleDictionary:ClearTable(Table: string)
		if typeof(Table) == "string" then
			local success, err = pcall(function()
				print(Table)
				if Table:find("Dictionary") then
					table.clear(Dictionaries[Table])
				else
					table.clear(Dictionaries[Table.. "Dictionary"])
				end
			end)
			if not success then
				error("ClearTable expects the string to be a supported asset, got "..Table, 2)
			end
		end
	end

	function ModuleDictionary:ClearAllTables() --//no arguments needed, and will only clear asset dictionary tables.
		for _, tables in pairs (Dictionaries) do
			table.clear(tables)
		end
	end
end

return ModuleDictionary

I just think it’s a fun comparison. anyways use v1.8!!!11111

1 Like

small update: GetDictionary’s scope ends at the correct place now and print prints a benchmark. the time starts as soon as the function is called. should i change this?

  • Keep it this way
  • Start the time as soon as the AddToTable function is called and end it after it stops
  • Start the time as soon as the AddToTable function is called and end it before you print the benchmark

0 voters

1 Like

mr @VSCPlays what do you think (you’re the only invested person also totally choose the 2nd option/j)

Tidied up documentation. I’ll probably release an update later today moving the cases table to a nested function so it isn’t redeclared over and over for every iteration.

Also moving delete target to after Reverse because there’s like barely any uses for it and it’s annoying

i unfortunately could not do this since it looked messier.

unlogged update since it’s small:
this

and i added another benchmark for the for loop. yes, it does check for print.

Hippidy hoppidy your code is now my property :slightly_smiling_face:

Im using this for a studio plugin

1 Like