ClosetCleaner2 | Out Of The Closet Edition

Eorzea Time
 
 
 
Language: JP EN FR DE
Ffxivpro Yellow Box
5290 users online
Forum » Windower » General » ClosetCleaner2 | Out of the Closet Edition
ClosetCleaner2 | Out of the Closet Edition
Offline
Posts: 15
By Exclore 2026-04-29 10:23:13
Link | Quote | Reply
 
ClosetCleaner2 is a new and improved take on the original concept of ClosetCleaner - an audit tool to see what gear is hanging around in your wardrobes and doesn't need to be there! Rather than loading your GearSwap Lua files, this version parses through your files and inventory to create a report file with the following info:

Unused Gear
This is gear that is in your inventory but not utilized by any of your GearSwap Lua files.

Gear In Use
Gear that is being utilized by a GearSwap and a list of which files.

Missing Gear
Gear listed in a GearSwap that is not present in your inventory. keep in mind that this does not currently check mog slips

Possible Misspellings
These are pieces of gear found in a Lua file that do not match any existing piece of gear by cross referencing the Windower resource files. It will also make its best guess as to what item you probably meant.

The most basic usage is simply //cc report which will give you a report based on the character you are logged in on and all GearSwap Lua files for all jobs it can find. There are several other features for specifying lists of jobs for specific characters, adding custom file patterns, and specifying what inventories to search - all of which can be found in the README.
[+]
Offline
Posts: 142
By Jhoo 2026-05-02 03:21:12
Link | Quote | Reply
 
Awesome !
 Carbuncle.Nynja
Offline
Server: Carbuncle
Game: FFXI
User: NynJa
Posts: 7474
By Carbuncle.Nynja 2026-05-02 09:01:58
Link | Quote | Reply
 
I never got OG CC to work, got this one to spit out a very easy to read report on one of my chars in 2 minutes. A++
 Shiva.Magified
Offline
Server: Shiva
Game: FFXI
User: magified
Posts: 13
By Shiva.Magified 2026-05-02 09:35:43
Link | Quote | Reply
 
got it to work after a few minutes of messing with patterns.

I guess I use a slightly weird pattern in gearswap files of:
{name}/{job}.lua

which isn't one of the defaults
 Bahamut.Navius
Offline
Server: Bahamut
Game: FFXI
User: phot0nic
Posts: 141
By Bahamut.Navius 2026-05-02 11:56:50
Link | Quote | Reply
 
I love this, it's incredibly useful and easy to use. One thing I noticed is that 'ranged' should be added to the luaParser in addition to 'range'. Once I added this, it picked up my ranged weapons/instruments correctly.

Would it be possible to report the number of times a specific item is found, and list this number in Section 2 of the report (and ideally let us sort by that number)? I love the idea of being able to see which pieces are only used in one or two job luas, but being able to quickly sort by which items are frequently used (even if it's one job lua) or rarely used could really help with inventory tidying. It's probably outside scope, but also getting some sort of indication of which items are jobs-specific could help too. Like, a piece of Empy gear is obviously only present in one job lua, but it could easily be a vital piece for that job. Being able to separate this from non-JSE pieces that are only present in one job lua could be helpful.
[+]
Offline
Posts: 351
By Sidiov 2026-05-02 14:55:20
Link | Quote | Reply
 
Great job!
small note, if Windower is on a samba share, the path starts with a single /, but needs a double //. Since lua doesn't seem to have a standard way to determine if a path is samba, maybe add a fallback in case of file not found to attempt //? Or I may be the only one playing like that!
Offline
Posts: 210
By zeta 2026-05-02 15:59:14
Link | Quote | Reply
 
I use a lot of table/variable references like shown below then i will do thinks like neck=DynaNeck, will it catch things like that? Also lot of set_combine()


Thanks.

EDIT:
Some more examples for RNG ammo and weapons

Offline
Posts: 15
By Exclore 2026-05-03 08:14:20
Link | Quote | Reply
 
As long as the file that has the gear definitions is referenced from the main file with the include function, such as include('job_gear_file.lua') the parser will recursively pull in that file when it checks for gear. Set_Combine() is also handled because ClosetCleaner2 just checks "Is that gear being used at all?" instead of trying to physically load the Lua.
Offline
Posts: 15
By Exclore 2026-05-03 08:34:57
Link | Quote | Reply
 
Bahamut.Navius said: »
I love this, it's incredibly useful and easy to use. One thing I noticed is that 'ranged' should be added to the luaParser in addition to 'range'. Once I added this, it picked up my ranged weapons/instruments correctly.

Thank you for catching the range/ranged bit, I've pushed up a fix for that.

Bahamut.Navius said: »
Would it be possible to report the number of times a specific item is found, and list this number in Section 2 of the report (and ideally let us sort by that number)? I love the idea of being able to see which pieces are only used in one or two job luas, but being able to quickly sort by which items are frequently used (even if it's one job lua) or rarely used could really help with inventory tidying.

I've had a few folks ask for different ways to sort/filter the data in a few ways, so I've added a new ReportMode setting that allows to switch from exporting the report in a text format to a CSV instead. Excel, Google Sheets, Open Office Calc, etc should be able to do some more advanced sorting/filtering.

Bahamut.Navius said: »
It's probably outside scope, but also getting some sort of indication of which items are jobs-specific could help too. Like, a piece of Empy gear is obviously only present in one job lua, but it could easily be a vital piece for that job. Being able to separate this from non-JSE pieces that are only present in one job lua could be helpful.

I'll have to think on this one, I do think that it would be helpful to have an indicator of what jobs gear is viable for, and I'm trying trying to keep the report clean-ish looking. Maybe I'll add it as a CSV only option.
[+]
Offline
Posts: 25
By neonrage 2026-05-04 07:36:50
Link | Quote | Reply
 
I am noticing if I define gear outside my sets such as:
Code
    --Erilaz
    EMPY = {}   
    EMPY.Head		=	"Erilaz Galea +3"
    EMPY.Body		=	"Erilaz Surcoat +3"
    EMPY.Hands		=	"Erilaz Gauntlets +3"
    EMPY.Legs		=	"Erilaz Leg Guards +3"
    EMPY.Feet		=	"Erilaz Greaves +3"


Then use the variable name in my sets, it's not detected as used in a set and is listed as unused in the report.

Such as:
Code
	sets.midcast['Refresh'] = set_combine(sets.midcast['Enhancing Magic'],{
		head    = EMPY.Head,
		waist   = "Gishdubar Sash",
	})

Code
 
Section 1: UNUSED GEAR (in inventory, not in any lua file)   [200 items]
 -------------------------------+-------------------------
  Name                           | Location                
  -------------------------------+-------------------------
  Eri. Leg Guards +3             | Wardrobe 5              
  Erilaz Galea +3                | Wardrobe 5              
  Erilaz Gauntlets +3            | Wardrobe 5              
  Erilaz Greaves +3              | Wardrobe 5              
  Erilaz Surcoat +3              | Wardrobe 5
[+]
Offline
Posts: 15
By Exclore 2026-05-04 09:43:12
Link | Quote | Reply
 
neonrage said: »
I am noticing if I define gear outside my sets such as:
Code
    --Erilaz
    EMPY = {}   
    EMPY.Head		=	"Erilaz Galea +3"
    EMPY.Body		=	"Erilaz Surcoat +3"
    EMPY.Hands		=	"Erilaz Gauntlets +3"
    EMPY.Legs		=	"Erilaz Leg Guards +3"
    EMPY.Feet		=	"Erilaz Greaves +3"


Then use the variable name in my sets, it's not detected as used in a set and is listed as unused in the report.

Such as:
Code
	sets.midcast['Refresh'] = set_combine(sets.midcast['Enhancing Magic'],{
		head    = EMPY.Head,
		waist   = "Gishdubar Sash",
	})

Code
 
Section 1: UNUSED GEAR (in inventory, not in any lua file)   [200 items]
 -------------------------------+-------------------------
  Name                           | Location                
  -------------------------------+-------------------------
  Eri. Leg Guards +3             | Wardrobe 5              
  Erilaz Galea +3                | Wardrobe 5              
  Erilaz Gauntlets +3            | Wardrobe 5              
  Erilaz Greaves +3              | Wardrobe 5              
  Erilaz Surcoat +3              | Wardrobe 5

Thank you for the very helpful examples, I've pushed up an update that better looks at assigned variables, if it sees a head=EMPY.Head it will assume EMPY.Head is a piece of gear and find the associated string to parse it.

I've also added the list of jobs that a piece of gear can be used by to the CSV version of the report.
[+]
Offline
Posts: 15
By Mekaider 2026-05-04 15:07:08
Link | Quote | Reply
 
Hello,

Cool addon, thank you for sharing it.

I had an issue getting it to read my lua files, even after setting the path with 'cc addpattern {name}/{job}_gear.lua'.

I think it was due to the sidecar pattern I use (based on Mote's - but my own hodge bodge version) where it's like this: WAR.lua > includes a lib file > lib loads a sidecar WAR_gear.lua

I got the report working by switching the order of extra_patterns and BASE_FILE_PATTERNS so that the right path was returned for me:
Code
closetCleaner2.lua:L438:local function resolve_job_lua(gs_path, job, char_name, extra_patterns)
...
    -- Make user supplied patterns take precedence
    local all_patterns = {}
    for _, p in ipairs(extra_patterns or {}) do
        all_patterns[#all_patterns + 1] = p
    end
    for _, p in ipairs(BASE_FILE_PATTERNS) do
        all_patterns[#all_patterns + 1] = p
    end
...


Not sure if that's right or wrong but my report output looks better now.

Might just be a me problem, due to my lib, but I thought worth raising because it could be the same for anyone using *_gear.lua sidecars with Mote libs.
Offline
Posts: 284
By Ranoutofspace 2026-05-05 04:15:03
Link | Quote | Reply
 
This is phenomenal. So easy to use.

What's the setting to hide 'misisng' gear if it's on a slip?
Offline
By Kadokawa 2026-05-05 07:18:59
Link | Quote | Reply
 
Could you make it work with Equipsets for Semi-vanila players?
Offline
Posts: 210
By zeta 2026-05-06 22:10:43
Link | Quote | Reply
 
Kadokawa said: »
Could you make it work with Equipsets for Semi-vanila players?

I dont see how that could work.
 Fenrir.Brimstonefox
Offline
Server: Fenrir
Game: FFXI
User: Brimstone
Posts: 462
By Fenrir.Brimstonefox 2026-05-07 16:56:20
Link | Quote | Reply
 
Bravo, I was too lazy to write a parser knowing its a bunch of effort (and I'll still miss things) so i just came up with a creative way to read all the data, of course what I never counted on was people having so much other stuff in their gearswap that it would cause other problems. Life is full of tradeoffs I guess.

Anyways the latest version is integrated into gearswap, so you probably should have forked this. I think it has some of the pathing issues to the job.lua files fixed and I changed print to add_to_chat because reading the console sucks.

If the windower team like this better it could be the default version (its certainly safer) although they could be integrated with a configuration to "load" or "parse" (with parse as the default because its safer) I started to work on a way to hierarchically dump the sets (for wiki, ffixah posts or the python simulator) its probably 90% done (you can get text files in debug mode, i just never formally tried to sort and dump in specific formats)

WRT using equipsets, everything is a mere matter of software. You would need to find them and then parse them, I think they're stored in the POL folder in some hex directory encoded from the character name (I think it the same for the same character on different systems) so if you can figure that out then you need to figure out the format those are in and parse them (I think they can be loaded by polutils if I'm not mistaken), but not sure how you go about doing that in lua (I although I suppose it might be possible to load the c(? - or w/e) libraries from polutils) its a huge headache I've had no desire to tackle. (I could be way off about something here but it seems theoretically possible, since the original wasn't parsing anything it was further removed from the concept)

Original Thread for reference.
 Fenrir.Brimstonefox
Offline
Server: Fenrir
Game: FFXI
User: Brimstone
Posts: 462
By Fenrir.Brimstonefox 2026-05-07 12:05:19
Link | Quote | Reply
 
Ranoutofspace said: »
This is phenomenal. So easy to use.

What's the setting to hide 'misisng' gear if it's on a slip?

Oh the original did not have one (so presumably this wouldn't), but I'm pretty sure there's some way to read slips. I might look into adding that.

Oh and i can fix range vs ranged too.

Bahamut.Navius said: »
Would it be possible to report the number of times a specific item is found, and list this number in Section 2 of the report (and ideally let us sort by that number)?

THe original included this and sorted it by ascending iirc (been a few months since I've looked at it/used it).
[+]
Offline
Posts: 33
By lildheyose 2026-05-07 17:56:08
Link | Quote | Reply
 
i use custom files is there a way to add those
Offline
Posts: 15
By Exclore 2026-05-07 13:40:10
Link | Quote | Reply
 
Fenrir.Brimstonefox said: »
Bravo, I was too lazy to write a parser knowing its a bunch of effort (and I'll still miss things) so i just came up with a creative way to read all the data, of course what I never counted on was people having so much other stuff in their gearswap that it would cause other problems. Life is full of tradeoffs I guess.

Anyways the latest version is integrated into gearswap, so you probably should have forked this. I think it has some of the pathing issues to the job.lua files fixed and I changed print to add_to_chat because reading the console sucks.

If the windower team like this better it could be the default version (its certainly safer) although they could be integrated with a configuration to "load" or "parse" (with parse as the default because its safer) I started to work on a way to hierarchically dump the sets (for wiki, ffixah posts or the python simulator) its probably 90% done (you can get text files in debug mode, i just never formally tried to sort and dump in specific formats)

WRT using equipsets, everything is a mere matter of software. You would need to find them and then parse them, I think they're stored in the POL folder in some hex directory encoded from the character name (I think it the same for the same character on different systems) so if you can figure that out then you need to figure out the format those are in and parse them (I think they can be loaded by polutils if I'm not mistaken), but not sure how you go about doing that in lua (I although I suppose it might be possible to load the c(? - or w/e) libraries from polutils) its a huge headache I've had no desire to tackle. (I could be way off about something here but it seems theoretically possible, since the original wasn't parsing anything it was further removed from the concept)

Original Thread for reference.

Heya, big fan of the original - I honestly think that loading the swap files is a more air tight way of getting the list of gear- but like you mentioned comes with downsides of random includes, people putting creative scripts in their swaps that fire off, etc. I actually took a swing at forking the original here: https://github.com/Gol-exe/closetCleaner with the intent of adding set_combine() recursion capability, and while it does work, after playing whack-a-mole with a ton of configs in various people's swaps I decided to do a ground up implementation using a text parse pattern instead.
[+]
Offline
Posts: 15
By Exclore 2026-05-07 14:29:44
Link | Quote | Reply
 
The most recent version I pushed up a few minutes ago will also support mog slips. Rather than showing up in the Missing Gear section, gear stored on slips will display in the Gear In Use section with a location indicating which slip it is stored on.
[+]
Offline
Posts: 36
By Broguypal 2026-05-07 16:17:13
Link | Quote | Reply
 
Exclore said: »
The most recent version I pushed up a few minutes ago will also support mog slips. Rather than showing up in the Missing Gear section, gear stored on slips will display in the Gear In Use section with a location indicating which slip it is stored on.


I really like this. On review of the code, I didn't even realize that windower had a 'slips' in its resources. Definitely going to use this!

Fantastic job!
[+]