diff --git a/resources/iw2/_codxe/codxe.json b/_codxe/iw2/codxe.json
similarity index 100%
rename from resources/iw2/_codxe/codxe.json
rename to _codxe/iw2/codxe.json
diff --git a/resources/iw2/_codxe/mods/example/maps/_minefields.gsc b/_codxe/iw2/mods/example/maps/_minefields.gsc
similarity index 100%
rename from resources/iw2/_codxe/mods/example/maps/_minefields.gsc
rename to _codxe/iw2/mods/example/maps/_minefields.gsc
diff --git a/resources/iw2/_codxe/mods/example/maps/custom.gsc b/_codxe/iw2/mods/example/maps/custom.gsc
similarity index 100%
rename from resources/iw2/_codxe/mods/example/maps/custom.gsc
rename to _codxe/iw2/mods/example/maps/custom.gsc
diff --git a/resources/iw2/_codxe/mods/example/maps/mp/gametypes/_clientids.gsc b/_codxe/iw2/mods/example/maps/mp/gametypes/_clientids.gsc
similarity index 100%
rename from resources/iw2/_codxe/mods/example/maps/mp/gametypes/_clientids.gsc
rename to _codxe/iw2/mods/example/maps/mp/gametypes/_clientids.gsc
diff --git a/resources/iw2/_codxe/mods/example/maps/mp/gametypes/custom_mp.gsc b/_codxe/iw2/mods/example/maps/mp/gametypes/custom_mp.gsc
similarity index 100%
rename from resources/iw2/_codxe/mods/example/maps/mp/gametypes/custom_mp.gsc
rename to _codxe/iw2/mods/example/maps/mp/gametypes/custom_mp.gsc
diff --git a/resources/iw3/_codxe/internal/maps/ac130.d3dbsp.ents b/_codxe/iw3/internal/maps/ac130.d3dbsp.ents
similarity index 100%
rename from resources/iw3/_codxe/internal/maps/ac130.d3dbsp.ents
rename to _codxe/iw3/internal/maps/ac130.d3dbsp.ents
diff --git a/resources/iw3/_codxe/internal/maps/ac130.gsc b/_codxe/iw3/internal/maps/ac130.gsc
similarity index 100%
rename from resources/iw3/_codxe/internal/maps/ac130.gsc
rename to _codxe/iw3/internal/maps/ac130.gsc
diff --git a/resources/iw3/_codxe/internal/maps/aftermath.d3dbsp.ents b/_codxe/iw3/internal/maps/aftermath.d3dbsp.ents
similarity index 100%
rename from resources/iw3/_codxe/internal/maps/aftermath.d3dbsp.ents
rename to _codxe/iw3/internal/maps/aftermath.d3dbsp.ents
diff --git a/resources/iw3/_codxe/internal/maps/aftermath.gsc b/_codxe/iw3/internal/maps/aftermath.gsc
similarity index 100%
rename from resources/iw3/_codxe/internal/maps/aftermath.gsc
rename to _codxe/iw3/internal/maps/aftermath.gsc
diff --git a/resources/iw3/_codxe/internal/maps/airlift.d3dbsp.ents b/_codxe/iw3/internal/maps/airlift.d3dbsp.ents
similarity index 100%
rename from resources/iw3/_codxe/internal/maps/airlift.d3dbsp.ents
rename to _codxe/iw3/internal/maps/airlift.d3dbsp.ents
diff --git a/resources/iw3/_codxe/internal/maps/airlift.gsc b/_codxe/iw3/internal/maps/airlift.gsc
similarity index 100%
rename from resources/iw3/_codxe/internal/maps/airlift.gsc
rename to _codxe/iw3/internal/maps/airlift.gsc
diff --git a/resources/iw3/_codxe/internal/maps/airplane.d3dbsp.ents b/_codxe/iw3/internal/maps/airplane.d3dbsp.ents
similarity index 100%
rename from resources/iw3/_codxe/internal/maps/airplane.d3dbsp.ents
rename to _codxe/iw3/internal/maps/airplane.d3dbsp.ents
diff --git a/resources/iw3/_codxe/internal/maps/airplane.gsc b/_codxe/iw3/internal/maps/airplane.gsc
similarity index 100%
rename from resources/iw3/_codxe/internal/maps/airplane.gsc
rename to _codxe/iw3/internal/maps/airplane.gsc
diff --git a/resources/iw3/_codxe/internal/maps/ambush.d3dbsp.ents b/_codxe/iw3/internal/maps/ambush.d3dbsp.ents
similarity index 100%
rename from resources/iw3/_codxe/internal/maps/ambush.d3dbsp.ents
rename to _codxe/iw3/internal/maps/ambush.d3dbsp.ents
diff --git a/resources/iw3/_codxe/internal/maps/ambush.gsc b/_codxe/iw3/internal/maps/ambush.gsc
similarity index 100%
rename from resources/iw3/_codxe/internal/maps/ambush.gsc
rename to _codxe/iw3/internal/maps/ambush.gsc
diff --git a/resources/iw3/_codxe/internal/maps/armada.d3dbsp.ents b/_codxe/iw3/internal/maps/armada.d3dbsp.ents
similarity index 100%
rename from resources/iw3/_codxe/internal/maps/armada.d3dbsp.ents
rename to _codxe/iw3/internal/maps/armada.d3dbsp.ents
diff --git a/resources/iw3/_codxe/internal/maps/armada.gsc b/_codxe/iw3/internal/maps/armada.gsc
similarity index 100%
rename from resources/iw3/_codxe/internal/maps/armada.gsc
rename to _codxe/iw3/internal/maps/armada.gsc
diff --git a/resources/iw3/_codxe/internal/maps/blackout.d3dbsp.ents b/_codxe/iw3/internal/maps/blackout.d3dbsp.ents
similarity index 100%
rename from resources/iw3/_codxe/internal/maps/blackout.d3dbsp.ents
rename to _codxe/iw3/internal/maps/blackout.d3dbsp.ents
diff --git a/resources/iw3/_codxe/internal/maps/blackout.gsc b/_codxe/iw3/internal/maps/blackout.gsc
similarity index 100%
rename from resources/iw3/_codxe/internal/maps/blackout.gsc
rename to _codxe/iw3/internal/maps/blackout.gsc
diff --git a/resources/iw3/_codxe/internal/maps/bog_a.d3dbsp.ents b/_codxe/iw3/internal/maps/bog_a.d3dbsp.ents
similarity index 100%
rename from resources/iw3/_codxe/internal/maps/bog_a.d3dbsp.ents
rename to _codxe/iw3/internal/maps/bog_a.d3dbsp.ents
diff --git a/resources/iw3/_codxe/internal/maps/bog_a.gsc b/_codxe/iw3/internal/maps/bog_a.gsc
similarity index 100%
rename from resources/iw3/_codxe/internal/maps/bog_a.gsc
rename to _codxe/iw3/internal/maps/bog_a.gsc
diff --git a/resources/iw3/_codxe/internal/maps/bog_b.d3dbsp.ents b/_codxe/iw3/internal/maps/bog_b.d3dbsp.ents
similarity index 100%
rename from resources/iw3/_codxe/internal/maps/bog_b.d3dbsp.ents
rename to _codxe/iw3/internal/maps/bog_b.d3dbsp.ents
diff --git a/resources/iw3/_codxe/internal/maps/bog_b.gsc b/_codxe/iw3/internal/maps/bog_b.gsc
similarity index 100%
rename from resources/iw3/_codxe/internal/maps/bog_b.gsc
rename to _codxe/iw3/internal/maps/bog_b.gsc
diff --git a/resources/iw3/_codxe/internal/maps/cargoship.d3dbsp.ents b/_codxe/iw3/internal/maps/cargoship.d3dbsp.ents
similarity index 100%
rename from resources/iw3/_codxe/internal/maps/cargoship.d3dbsp.ents
rename to _codxe/iw3/internal/maps/cargoship.d3dbsp.ents
diff --git a/resources/iw3/_codxe/internal/maps/cargoship.gsc b/_codxe/iw3/internal/maps/cargoship.gsc
similarity index 100%
rename from resources/iw3/_codxe/internal/maps/cargoship.gsc
rename to _codxe/iw3/internal/maps/cargoship.gsc
diff --git a/resources/iw3/_codxe/internal/maps/coup.d3dbsp.ents b/_codxe/iw3/internal/maps/coup.d3dbsp.ents
similarity index 100%
rename from resources/iw3/_codxe/internal/maps/coup.d3dbsp.ents
rename to _codxe/iw3/internal/maps/coup.d3dbsp.ents
diff --git a/resources/iw3/_codxe/internal/maps/coup.gsc b/_codxe/iw3/internal/maps/coup.gsc
similarity index 100%
rename from resources/iw3/_codxe/internal/maps/coup.gsc
rename to _codxe/iw3/internal/maps/coup.gsc
diff --git a/resources/iw3/_codxe/internal/maps/hunted.d3dbsp.ents b/_codxe/iw3/internal/maps/hunted.d3dbsp.ents
similarity index 100%
rename from resources/iw3/_codxe/internal/maps/hunted.d3dbsp.ents
rename to _codxe/iw3/internal/maps/hunted.d3dbsp.ents
diff --git a/resources/iw3/_codxe/internal/maps/hunted.gsc b/_codxe/iw3/internal/maps/hunted.gsc
similarity index 100%
rename from resources/iw3/_codxe/internal/maps/hunted.gsc
rename to _codxe/iw3/internal/maps/hunted.gsc
diff --git a/resources/iw3/_codxe/internal/maps/icbm.d3dbsp.ents b/_codxe/iw3/internal/maps/icbm.d3dbsp.ents
similarity index 100%
rename from resources/iw3/_codxe/internal/maps/icbm.d3dbsp.ents
rename to _codxe/iw3/internal/maps/icbm.d3dbsp.ents
diff --git a/resources/iw3/_codxe/internal/maps/icbm.gsc b/_codxe/iw3/internal/maps/icbm.gsc
similarity index 100%
rename from resources/iw3/_codxe/internal/maps/icbm.gsc
rename to _codxe/iw3/internal/maps/icbm.gsc
diff --git a/resources/iw3/_codxe/internal/maps/jeepride.d3dbsp.ents b/_codxe/iw3/internal/maps/jeepride.d3dbsp.ents
similarity index 100%
rename from resources/iw3/_codxe/internal/maps/jeepride.d3dbsp.ents
rename to _codxe/iw3/internal/maps/jeepride.d3dbsp.ents
diff --git a/resources/iw3/_codxe/internal/maps/jeepride.gsc b/_codxe/iw3/internal/maps/jeepride.gsc
similarity index 100%
rename from resources/iw3/_codxe/internal/maps/jeepride.gsc
rename to _codxe/iw3/internal/maps/jeepride.gsc
diff --git a/resources/iw3/_codxe/internal/maps/killhouse.d3dbsp.ents b/_codxe/iw3/internal/maps/killhouse.d3dbsp.ents
similarity index 100%
rename from resources/iw3/_codxe/internal/maps/killhouse.d3dbsp.ents
rename to _codxe/iw3/internal/maps/killhouse.d3dbsp.ents
diff --git a/resources/iw3/_codxe/internal/maps/killhouse.gsc b/_codxe/iw3/internal/maps/killhouse.gsc
similarity index 100%
rename from resources/iw3/_codxe/internal/maps/killhouse.gsc
rename to _codxe/iw3/internal/maps/killhouse.gsc
diff --git a/resources/iw3/_codxe/internal/maps/launchfacility_a.d3dbsp.ents b/_codxe/iw3/internal/maps/launchfacility_a.d3dbsp.ents
similarity index 100%
rename from resources/iw3/_codxe/internal/maps/launchfacility_a.d3dbsp.ents
rename to _codxe/iw3/internal/maps/launchfacility_a.d3dbsp.ents
diff --git a/resources/iw3/_codxe/internal/maps/launchfacility_a.gsc b/_codxe/iw3/internal/maps/launchfacility_a.gsc
similarity index 100%
rename from resources/iw3/_codxe/internal/maps/launchfacility_a.gsc
rename to _codxe/iw3/internal/maps/launchfacility_a.gsc
diff --git a/resources/iw3/_codxe/internal/maps/launchfacility_b.d3dbsp.ents b/_codxe/iw3/internal/maps/launchfacility_b.d3dbsp.ents
similarity index 100%
rename from resources/iw3/_codxe/internal/maps/launchfacility_b.d3dbsp.ents
rename to _codxe/iw3/internal/maps/launchfacility_b.d3dbsp.ents
diff --git a/resources/iw3/_codxe/internal/maps/launchfacility_b.gsc b/_codxe/iw3/internal/maps/launchfacility_b.gsc
similarity index 100%
rename from resources/iw3/_codxe/internal/maps/launchfacility_b.gsc
rename to _codxe/iw3/internal/maps/launchfacility_b.gsc
diff --git a/resources/iw3/_codxe/internal/maps/scoutsniper.d3dbsp.ents b/_codxe/iw3/internal/maps/scoutsniper.d3dbsp.ents
similarity index 100%
rename from resources/iw3/_codxe/internal/maps/scoutsniper.d3dbsp.ents
rename to _codxe/iw3/internal/maps/scoutsniper.d3dbsp.ents
diff --git a/resources/iw3/_codxe/internal/maps/scoutsniper.gsc b/_codxe/iw3/internal/maps/scoutsniper.gsc
similarity index 100%
rename from resources/iw3/_codxe/internal/maps/scoutsniper.gsc
rename to _codxe/iw3/internal/maps/scoutsniper.gsc
diff --git a/resources/iw3/_codxe/internal/maps/sniperescape.d3dbsp.ents b/_codxe/iw3/internal/maps/sniperescape.d3dbsp.ents
similarity index 100%
rename from resources/iw3/_codxe/internal/maps/sniperescape.d3dbsp.ents
rename to _codxe/iw3/internal/maps/sniperescape.d3dbsp.ents
diff --git a/resources/iw3/_codxe/internal/maps/sniperescape.gsc b/_codxe/iw3/internal/maps/sniperescape.gsc
similarity index 100%
rename from resources/iw3/_codxe/internal/maps/sniperescape.gsc
rename to _codxe/iw3/internal/maps/sniperescape.gsc
diff --git a/resources/iw3/_codxe/internal/maps/village_assault.d3dbsp.ents b/_codxe/iw3/internal/maps/village_assault.d3dbsp.ents
similarity index 100%
rename from resources/iw3/_codxe/internal/maps/village_assault.d3dbsp.ents
rename to _codxe/iw3/internal/maps/village_assault.d3dbsp.ents
diff --git a/resources/iw3/_codxe/internal/maps/village_assault.gsc b/_codxe/iw3/internal/maps/village_assault.gsc
similarity index 100%
rename from resources/iw3/_codxe/internal/maps/village_assault.gsc
rename to _codxe/iw3/internal/maps/village_assault.gsc
diff --git a/resources/iw3/_codxe/internal/maps/village_defend.d3dbsp.ents b/_codxe/iw3/internal/maps/village_defend.d3dbsp.ents
similarity index 100%
rename from resources/iw3/_codxe/internal/maps/village_defend.d3dbsp.ents
rename to _codxe/iw3/internal/maps/village_defend.d3dbsp.ents
diff --git a/resources/iw3/_codxe/internal/maps/village_defend.gsc b/_codxe/iw3/internal/maps/village_defend.gsc
similarity index 100%
rename from resources/iw3/_codxe/internal/maps/village_defend.gsc
rename to _codxe/iw3/internal/maps/village_defend.gsc
diff --git a/resources/iw3/_codxe/mods/codjumper/README.md b/_codxe/iw3/mods/codjumper/README.md
similarity index 100%
rename from resources/iw3/_codxe/mods/codjumper/README.md
rename to _codxe/iw3/mods/codjumper/README.md
diff --git a/resources/iw3/_codxe/mods/codjumper/buttons_default.cfg b/_codxe/iw3/mods/codjumper/buttons_default.cfg
similarity index 100%
rename from resources/iw3/_codxe/mods/codjumper/buttons_default.cfg
rename to _codxe/iw3/mods/codjumper/buttons_default.cfg
diff --git a/resources/iw3/_codxe/mods/codjumper/fixed_fps.cfg b/_codxe/iw3/mods/codjumper/fixed_fps.cfg
similarity index 100%
rename from resources/iw3/_codxe/mods/codjumper/fixed_fps.cfg
rename to _codxe/iw3/mods/codjumper/fixed_fps.cfg
diff --git a/resources/iw3/_codxe/mods/codjumper/images/~weapon_rpg7_spec-rgb&weapon_~06163c5b.dds b/_codxe/iw3/mods/codjumper/images/~weapon_rpg7_spec-rgb&weapon_~06163c5b.dds
similarity index 100%
rename from resources/iw3/_codxe/mods/codjumper/images/~weapon_rpg7_spec-rgb&weapon_~06163c5b.dds
rename to _codxe/iw3/mods/codjumper/images/~weapon_rpg7_spec-rgb&weapon_~06163c5b.dds
diff --git a/resources/iw3/_codxe/mods/codjumper/maps/mp/gametypes/_globallogic.gsc b/_codxe/iw3/mods/codjumper/maps/mp/gametypes/_globallogic.gsc
similarity index 100%
rename from resources/iw3/_codxe/mods/codjumper/maps/mp/gametypes/_globallogic.gsc
rename to _codxe/iw3/mods/codjumper/maps/mp/gametypes/_globallogic.gsc
diff --git a/resources/iw3/_codxe/mods/codjumper/maps/mp/gametypes/_rank.gsc b/_codxe/iw3/mods/codjumper/maps/mp/gametypes/_rank.gsc
similarity index 100%
rename from resources/iw3/_codxe/mods/codjumper/maps/mp/gametypes/_rank.gsc
rename to _codxe/iw3/mods/codjumper/maps/mp/gametypes/_rank.gsc
diff --git a/resources/iw3/_codxe/mods/codjumper/maps/mp/gametypes/cj.gsc b/_codxe/iw3/mods/codjumper/maps/mp/gametypes/cj.gsc
similarity index 100%
rename from resources/iw3/_codxe/mods/codjumper/maps/mp/gametypes/cj.gsc
rename to _codxe/iw3/mods/codjumper/maps/mp/gametypes/cj.gsc
diff --git a/resources/iw3/_codxe/mods/codjumper/maps/mp/gametypes/dm.gsc b/_codxe/iw3/mods/codjumper/maps/mp/gametypes/dm.gsc
similarity index 100%
rename from resources/iw3/_codxe/mods/codjumper/maps/mp/gametypes/dm.gsc
rename to _codxe/iw3/mods/codjumper/maps/mp/gametypes/dm.gsc
diff --git a/resources/iw3/_codxe/mods/codjumper/maps/mp/gametypes/war.gsc b/_codxe/iw3/mods/codjumper/maps/mp/gametypes/war.gsc
similarity index 100%
rename from resources/iw3/_codxe/mods/codjumper/maps/mp/gametypes/war.gsc
rename to _codxe/iw3/mods/codjumper/maps/mp/gametypes/war.gsc
diff --git a/resources/iw3/_codxe/mods/codjumper/pc_fps.cfg b/_codxe/iw3/mods/codjumper/pc_fps.cfg
similarity index 100%
rename from resources/iw3/_codxe/mods/codjumper/pc_fps.cfg
rename to _codxe/iw3/mods/codjumper/pc_fps.cfg
diff --git a/resources/iw3/_codxe/mods/example/maps/_cagedchickens.gsc b/_codxe/iw3/mods/example/maps/_cagedchickens.gsc
similarity index 100%
rename from resources/iw3/_codxe/mods/example/maps/_cagedchickens.gsc
rename to _codxe/iw3/mods/example/maps/_cagedchickens.gsc
diff --git a/resources/iw3/_codxe/mods/example/maps/example.gsc b/_codxe/iw3/mods/example/maps/example.gsc
similarity index 100%
rename from resources/iw3/_codxe/mods/example/maps/example.gsc
rename to _codxe/iw3/mods/example/maps/example.gsc
diff --git a/resources/iw4/_codxe/codxe.json b/_codxe/iw4/codxe.json
similarity index 100%
rename from resources/iw4/_codxe/codxe.json
rename to _codxe/iw4/codxe.json
diff --git a/resources/iw4/_codxe/mods/codjumper/maps/_names.gsc b/_codxe/iw4/mods/codjumper/maps/_names.gsc
similarity index 100%
rename from resources/iw4/_codxe/mods/codjumper/maps/_names.gsc
rename to _codxe/iw4/mods/codjumper/maps/_names.gsc
diff --git a/resources/iw4/_codxe/mods/codjumper/maps/cj.gsc b/_codxe/iw4/mods/codjumper/maps/cj.gsc
similarity index 100%
rename from resources/iw4/_codxe/mods/codjumper/maps/cj.gsc
rename to _codxe/iw4/mods/codjumper/maps/cj.gsc
diff --git a/resources/iw4/_codxe/mods/codjumper/maps/codxe_utility.gsc b/_codxe/iw4/mods/codjumper/maps/codxe_utility.gsc
similarity index 100%
rename from resources/iw4/_codxe/mods/codjumper/maps/codxe_utility.gsc
rename to _codxe/iw4/mods/codjumper/maps/codxe_utility.gsc
diff --git a/resources/iw4/_codxe/mods/codjumper/maps/mp/gametypes/_codxe_utility.gsc b/_codxe/iw4/mods/codjumper/maps/mp/gametypes/_codxe_utility.gsc
similarity index 100%
rename from resources/iw4/_codxe/mods/codjumper/maps/mp/gametypes/_codxe_utility.gsc
rename to _codxe/iw4/mods/codjumper/maps/mp/gametypes/_codxe_utility.gsc
diff --git a/resources/iw4/_codxe/mods/codjumper/maps/mp/gametypes/cj_hud.gsc b/_codxe/iw4/mods/codjumper/maps/mp/gametypes/cj_hud.gsc
similarity index 100%
rename from resources/iw4/_codxe/mods/codjumper/maps/mp/gametypes/cj_hud.gsc
rename to _codxe/iw4/mods/codjumper/maps/mp/gametypes/cj_hud.gsc
diff --git a/resources/iw4/_codxe/mods/codjumper/maps/mp/gametypes/cj_mp.gsc b/_codxe/iw4/mods/codjumper/maps/mp/gametypes/cj_mp.gsc
similarity index 100%
rename from resources/iw4/_codxe/mods/codjumper/maps/mp/gametypes/cj_mp.gsc
rename to _codxe/iw4/mods/codjumper/maps/mp/gametypes/cj_mp.gsc
diff --git a/resources/iw4/_codxe/mods/codjumper/maps/mp/gametypes/menu.gsc b/_codxe/iw4/mods/codjumper/maps/mp/gametypes/menu.gsc
similarity index 100%
rename from resources/iw4/_codxe/mods/codjumper/maps/mp/gametypes/menu.gsc
rename to _codxe/iw4/mods/codjumper/maps/mp/gametypes/menu.gsc
diff --git a/resources/iw4/_codxe/mods/codjumper/maps/mp/gametypes/war.gsc b/_codxe/iw4/mods/codjumper/maps/mp/gametypes/war.gsc
similarity index 100%
rename from resources/iw4/_codxe/mods/codjumper/maps/mp/gametypes/war.gsc
rename to _codxe/iw4/mods/codjumper/maps/mp/gametypes/war.gsc
diff --git a/resources/iw4/_codxe/mods/example/maps/_cagedchickens.gsc b/_codxe/iw4/mods/example/maps/_cagedchickens.gsc
similarity index 100%
rename from resources/iw4/_codxe/mods/example/maps/_cagedchickens.gsc
rename to _codxe/iw4/mods/example/maps/_cagedchickens.gsc
diff --git a/resources/iw4/_codxe/mods/example/maps/codxe_utility.gsc b/_codxe/iw4/mods/example/maps/codxe_utility.gsc
similarity index 100%
rename from resources/iw4/_codxe/mods/example/maps/codxe_utility.gsc
rename to _codxe/iw4/mods/example/maps/codxe_utility.gsc
diff --git a/resources/iw4/_codxe/mods/example/maps/example_sp.gsc b/_codxe/iw4/mods/example/maps/example_sp.gsc
similarity index 100%
rename from resources/iw4/_codxe/mods/example/maps/example_sp.gsc
rename to _codxe/iw4/mods/example/maps/example_sp.gsc
diff --git a/resources/iw5/_codxe/codxe.json b/_codxe/iw5/codxe.json
similarity index 100%
rename from resources/iw5/_codxe/codxe.json
rename to _codxe/iw5/codxe.json
diff --git a/resources/iw5/_codxe/mods/codjumper/maps/mp/gametypes/cj.gsc b/_codxe/iw5/mods/codjumper/maps/mp/gametypes/cj.gsc
similarity index 100%
rename from resources/iw5/_codxe/mods/codjumper/maps/mp/gametypes/cj.gsc
rename to _codxe/iw5/mods/codjumper/maps/mp/gametypes/cj.gsc
diff --git a/resources/iw5/_codxe/mods/codjumper/maps/mp/gametypes/cj.gscbin b/_codxe/iw5/mods/codjumper/maps/mp/gametypes/cj.gscbin
similarity index 100%
rename from resources/iw5/_codxe/mods/codjumper/maps/mp/gametypes/cj.gscbin
rename to _codxe/iw5/mods/codjumper/maps/mp/gametypes/cj.gscbin
diff --git a/resources/iw5/_codxe/mods/codjumper/maps/mp/gametypes/war.gsc b/_codxe/iw5/mods/codjumper/maps/mp/gametypes/war.gsc
similarity index 100%
rename from resources/iw5/_codxe/mods/codjumper/maps/mp/gametypes/war.gsc
rename to _codxe/iw5/mods/codjumper/maps/mp/gametypes/war.gsc
diff --git a/resources/iw5/_codxe/mods/codjumper/maps/mp/gametypes/war.gscbin b/_codxe/iw5/mods/codjumper/maps/mp/gametypes/war.gscbin
similarity index 100%
rename from resources/iw5/_codxe/mods/codjumper/maps/mp/gametypes/war.gscbin
rename to _codxe/iw5/mods/codjumper/maps/mp/gametypes/war.gscbin
diff --git a/resources/qos/_codxe/codxe.json b/_codxe/qos/codxe.json
similarity index 100%
rename from resources/qos/_codxe/codxe.json
rename to _codxe/qos/codxe.json
diff --git a/resources/qos/_codxe/mods/example/maps/mp/gametypes/_clientids.gsc b/_codxe/qos/mods/example/maps/mp/gametypes/_clientids.gsc
similarity index 100%
rename from resources/qos/_codxe/mods/example/maps/mp/gametypes/_clientids.gsc
rename to _codxe/qos/mods/example/maps/mp/gametypes/_clientids.gsc
diff --git a/resources/qos/_codxe/mods/example/maps/mp/gametypes/example_mp.gsc b/_codxe/qos/mods/example/maps/mp/gametypes/example_mp.gsc
similarity index 100%
rename from resources/qos/_codxe/mods/example/maps/mp/gametypes/example_mp.gsc
rename to _codxe/qos/mods/example/maps/mp/gametypes/example_mp.gsc
diff --git a/resources/t4/_codxe/codxe.json b/_codxe/t4/codxe.json
similarity index 100%
rename from resources/t4/_codxe/codxe.json
rename to _codxe/t4/codxe.json
diff --git a/resources/t4/_codxe/mods/codjumper/maps/mp/gametypes/cj.gsc b/_codxe/t4/mods/codjumper/maps/mp/gametypes/cj.gsc
similarity index 100%
rename from resources/t4/_codxe/mods/codjumper/maps/mp/gametypes/cj.gsc
rename to _codxe/t4/mods/codjumper/maps/mp/gametypes/cj.gsc
diff --git a/resources/t4/_codxe/mods/codjumper/maps/mp/gametypes/menu.gsc b/_codxe/t4/mods/codjumper/maps/mp/gametypes/menu.gsc
similarity index 100%
rename from resources/t4/_codxe/mods/codjumper/maps/mp/gametypes/menu.gsc
rename to _codxe/t4/mods/codjumper/maps/mp/gametypes/menu.gsc
diff --git a/resources/t4/_codxe/mods/codjumper/maps/mp/gametypes/tdm.gsc b/_codxe/t4/mods/codjumper/maps/mp/gametypes/tdm.gsc
similarity index 100%
rename from resources/t4/_codxe/mods/codjumper/maps/mp/gametypes/tdm.gsc
rename to _codxe/t4/mods/codjumper/maps/mp/gametypes/tdm.gsc
diff --git a/resources/t4/_codxe/mods/example/maps/_music.gsc b/_codxe/t4/mods/example/maps/_music.gsc
similarity index 100%
rename from resources/t4/_codxe/mods/example/maps/_music.gsc
rename to _codxe/t4/mods/example/maps/_music.gsc
diff --git a/resources/t4/_codxe/mods/example/maps/custom.gsc b/_codxe/t4/mods/example/maps/custom.gsc
similarity index 100%
rename from resources/t4/_codxe/mods/example/maps/custom.gsc
rename to _codxe/t4/mods/example/maps/custom.gsc
diff --git a/resources/t4/_codxe/mods/example/maps/mp/gametypes/_clientids.gsc b/_codxe/t4/mods/example/maps/mp/gametypes/_clientids.gsc
similarity index 100%
rename from resources/t4/_codxe/mods/example/maps/mp/gametypes/_clientids.gsc
rename to _codxe/t4/mods/example/maps/mp/gametypes/_clientids.gsc
diff --git a/resources/t4/_codxe/mods/example/maps/mp/gametypes/custom.gsc b/_codxe/t4/mods/example/maps/mp/gametypes/custom.gsc
similarity index 100%
rename from resources/t4/_codxe/mods/example/maps/mp/gametypes/custom.gsc
rename to _codxe/t4/mods/example/maps/mp/gametypes/custom.gsc
diff --git a/resources/t5/_codxe/codxe.json b/_codxe/t5/codxe.json
similarity index 100%
rename from resources/t5/_codxe/codxe.json
rename to _codxe/t5/codxe.json
diff --git a/resources/t5/_codxe/mods/example/maps/mp/gametypes/_clientids.gsc b/_codxe/t5/mods/example/maps/mp/gametypes/_clientids.gsc
similarity index 100%
rename from resources/t5/_codxe/mods/example/maps/mp/gametypes/_clientids.gsc
rename to _codxe/t5/mods/example/maps/mp/gametypes/_clientids.gsc
diff --git a/resources/t5/_codxe/mods/example/maps/mp/gametypes/example_mp.gsc b/_codxe/t5/mods/example/maps/mp/gametypes/example_mp.gsc
similarity index 100%
rename from resources/t5/_codxe/mods/example/maps/mp/gametypes/example_mp.gsc
rename to _codxe/t5/mods/example/maps/mp/gametypes/example_mp.gsc
diff --git a/build.py b/build.py
index 4fefd013..722c560f 100644
--- a/build.py
+++ b/build.py
@@ -9,6 +9,7 @@
BINARY_PATH = r"build\Release\bin\codxe.xex"
STAGING_DIR = r"build\staging"
RESOURCES_PATH = r"resources"
+DATA_PATH = r"_codxe"
VERSION_HEADER_PATH = r"build\Release\obj\git_version.h"
@@ -56,6 +57,13 @@ def read_git_version():
print(f"Resources directory not found at {RESOURCES_PATH}")
exit(1)
+if os.path.isdir(DATA_PATH):
+ shutil.copytree(DATA_PATH, os.path.join(STAGING_DIR, "_codxe"), dirs_exist_ok=True)
+ print("CoD Xe data directory copied successfully")
+else:
+ print(f"CoD Xe data directory not found at {DATA_PATH}")
+ exit(1)
+
print("Copying binary to all title ID directories...")
plugins_dir = os.path.join(STAGING_DIR, "xenia", "plugins")
if os.path.exists(plugins_dir):
diff --git a/codxe.vcxproj b/codxe.vcxproj
index 902aba34..a2a1bfa4 100644
--- a/codxe.vcxproj
+++ b/codxe.vcxproj
@@ -85,6 +85,7 @@
+
@@ -235,6 +236,7 @@
+
diff --git a/docs/features.md b/docs/features.md
index 36e67186..5f262317 100644
--- a/docs/features.md
+++ b/docs/features.md
@@ -6,7 +6,13 @@ The raw GSC loader enables loading `.gsc` scripts directly from the mod director
### Setup
-Create a `_codxe\mods` folder in your game directory, and place a `codxe.json` in `_codxe` to define which mod is active.
+Create a `_codxe\\mods` folder in your game directory, and place a `codxe.json` in `_codxe\` to define which mod is active. Use `iw2`, `iw3`, `iw4`, `iw5`, `t4`, `t5`, or `qos` for the game ID.
+
+The repository and release archive contain one top-level [`_codxe`](/_codxe) folder with a subdirectory for each game. Copy that folder into your game directory or a USB/HDD root, preserving `_codxe\\...`. All supported games that use CoD Xe data share this layout. Title updates and Xenia files remain separate from the game data.
+
+CoD Xe selects one data root at startup. If `_codxe\` exists, all config, mod, fastfile, usermap, internal asset, dump, and player stats paths use that root. Missing files never fall back to the legacy `_codxe` root. The old layout remains supported when the nested directory does not exist. Keep all data for a game together when migrating.
+
+On Xbox hardware, when neither local directory exists, CoD Xe searches `Usb0:\_codxe\` through `Usb4:\_codxe\`, then `Hdd1:\_codxe\`. The first existing directory becomes the only active root for reads and writes. USB/HDD roots only accept the nested layout. If no existing root is found, new files use the local `_codxe\` directory. Xenia uses the local directories.
In `codxe.json`, set `"active_mod"` to the name of your mod folder:
@@ -19,7 +25,7 @@ In `codxe.json`, set `"active_mod"` to the name of your mod folder:
Once configured, the engine will redirect script lookups to:
```text
-game:\_codxe\mods\my_mod\
+game:\_codxe\\mods\my_mod\
```
Example tree structure:
@@ -27,14 +33,15 @@ Example tree structure:
```text
game:.
`-- _codxe
- |-- codxe.json
- `-- mods
- `-- my_mod
- `-- maps
- `-- mp
- `-- gametypes
- |-- _callbacksetup.gsc
- `-- custom_logic.gsc
+ `--
+ |-- codxe.json
+ `-- mods
+ `-- my_mod
+ `-- maps
+ `-- mp
+ `-- gametypes
+ |-- _callbacksetup.gsc
+ `-- custom_logic.gsc
```
The underscore keeps the folder at the top of file listings and separates CoD Xe system files from the game's core content.
@@ -46,7 +53,7 @@ The loader operates using a virtual filesystem. All `.gsc` scripts, whether load
For example:
- A file in `common_mp.ff/maps/mp/gametypes/_callbacksetup.gsc`
-- Can be overridden by `game:\_codxe\mods\my_mod\maps\mp\gametypes\_callbacksetup.gsc`
+- Can be overridden by `game:\_codxe\\mods\my_mod\maps\mp\gametypes\_callbacksetup.gsc`
Your version will take precedence over the copy embedded in the original fastfile. You can also add new scripts and call them from overridden entry points such as `_callbacksetup.gsc`.
diff --git a/docs/t4.md b/docs/t4.md
index c817d595..834bdbb8 100644
--- a/docs/t4.md
+++ b/docs/t4.md
@@ -220,7 +220,7 @@ self.god = false;
## Example Mods
-Example T4 mods are available under [`resources/t4/_codxe/mods`](/resources/t4/_codxe/mods):
+Example T4 mods are available under [`_codxe/t4/mods`](/_codxe/t4/mods):
- `example` - Basic script examples for singleplayer and multiplayer.
- `codjumper` - Codjumper-oriented scripts and menu examples.
diff --git a/src/common/config.cpp b/src/common/config.cpp
index f780173a..a30f30f2 100644
--- a/src/common/config.cpp
+++ b/src/common/config.cpp
@@ -9,35 +9,18 @@
#define INVALID_FILE_SIZE ((DWORD) - 1)
#endif
-const char *CONFIG_PATH = "game:\\_codxe\\codxe.json";
-const char *MOD_DIR = "game:\\_codxe\\mods";
-const char *DUMP_DIR = "game:\\_codxe\\dump";
-
// Default values
char Config::active_mod[MAX_PATH] = {};
bool Config::dump_rawfile = false;
bool Config::dump_map_ents = false;
-char Config::mod_base_path[MAX_PATH] = {};
std::string Config::data_root;
-bool Config::shared_layout_enabled = false;
std::vector Config::mounted_links;
namespace
{
const char *CONFIG_DEVICE_LINK_NAME = "codxe:";
const char *CONFIG_DEVICE_LINK_PATH = "codxe:\\";
-
-const char *GetGameDirectoryName(Config::GameId gameId)
-{
- switch (gameId)
- {
- case Config::GAME_T4:
- return "t4";
- case Config::GAME_NONE:
- default:
- return nullptr;
- }
-}
+const char *const DEVICE_LINK_NAMESPACES[] = {"\\System??\\", "\\??\\"};
bool StartsWith(const std::string &value, const char *prefix)
{
@@ -65,30 +48,41 @@ bool TryGetDeviceRoot(const std::string &path, std::string &device_root)
return true;
}
-bool MountDevice(const char *link_name, const char *device_path)
+void UnmountDevice(const char *link_name)
{
- const DWORD process_type = KeGetCurrentProcessType();
- const std::string link_path = std::string(process_type == PROC_TYPE_SYSTEM ? "\\System??\\" : "\\??\\") + link_name;
+ for (size_t i = 0; i < ARRAYSIZE(DEVICE_LINK_NAMESPACES); ++i)
+ {
+ const std::string link_path = std::string(DEVICE_LINK_NAMESPACES[i]) + link_name;
+ STRING link = {};
+ RtlInitAnsiString(&link, link_path.c_str());
+ ObDeleteSymbolicLink(&link);
+ }
+}
- STRING link = {};
+bool MountDevice(const char *link_name, const char *device_path)
+{
STRING device = {};
- RtlInitAnsiString(&link, link_path.c_str());
RtlInitAnsiString(&device, device_path);
- const NTSTATUS delete_status = ObDeleteSymbolicLink(&link);
- const NTSTATUS create_status = ObCreateSymbolicLink(&link, &device);
- UNREFERENCED_PARAMETER(delete_status);
-
- return NT_SUCCESS(create_status);
-}
+ // Plugin setup runs in the system process; game reads and writes run in the title process.
+ // DOS device links are namespace-specific, so both must point to the same selected device.
+ for (size_t i = 0; i < ARRAYSIZE(DEVICE_LINK_NAMESPACES); ++i)
+ {
+ const std::string link_path = std::string(DEVICE_LINK_NAMESPACES[i]) + link_name;
+ STRING link = {};
+ RtlInitAnsiString(&link, link_path.c_str());
+ ObDeleteSymbolicLink(&link);
+ const NTSTATUS status = ObCreateSymbolicLink(&link, &device);
+ if (!NT_SUCCESS(status))
+ {
+ DbgPrint("[codxe][Config] Failed to mount %s -> %s: status=0x%08X\n", link_path.c_str(), device_path,
+ status);
+ UnmountDevice(link_name);
+ return false;
+ }
+ }
-void UnmountDevice(const char *link_name)
-{
- const DWORD process_type = KeGetCurrentProcessType();
- const std::string link_path = std::string(process_type == PROC_TYPE_SYSTEM ? "\\System??\\" : "\\??\\") + link_name;
- STRING link = {};
- RtlInitAnsiString(&link, link_path.c_str());
- ObDeleteSymbolicLink(&link);
+ return true;
}
bool BuildMountedConfigPath(const std::string &device_config_path, std::string &mounted_config_path)
@@ -166,14 +160,12 @@ bool ReadFileToString(const char *path, std::string &outString)
return true;
}
-Config::Config(GameId gameId)
+Config::Config(GameId::Type gameId)
{
data_root = "game:\\_codxe";
mounted_links.clear();
- const char *gameDirectoryName = GetGameDirectoryName(gameId);
- shared_layout_enabled = gameDirectoryName != nullptr;
-
- std::string config_path = CONFIG_PATH;
+ const char *gameDirectoryName = GameId::ToString(gameId);
+ std::string config_path = filesystem::JoinPath(data_root.c_str(), "codxe.json");
if (xbox::GetEnvironment() != xbox::ENVIRONMENT_XENIA)
{
@@ -192,7 +184,7 @@ Config::Config(GameId gameId)
if (slash != std::string::npos)
{
// On hardware Config is constructed before game: is retargeted to the new title.
- // Only the config file load needs this early executable-relative path.
+ // Root selection and config loading need this early executable-relative path.
config_path = full_path.substr(0, slash) + "\\_codxe\\codxe.json";
std::string mounted_config_path;
@@ -207,7 +199,7 @@ Config::Config(GameId gameId)
}
}
- if (shared_layout_enabled)
+ if (gameDirectoryName != nullptr)
{
// Config loads before game: is retargeted on hardware, so inspect the
// executable-relative path while choosing the single active root.
@@ -225,7 +217,9 @@ Config::Config(GameId gameId)
}
else
{
- data_root.clear();
+ // If no existing root is found, new files use the local nested layout.
+ data_root = std::string("game:\\_codxe\\") + gameDirectoryName;
+ config_path = filesystem::JoinPath(nested_local_directory.c_str(), "codxe.json");
if (xbox::GetEnvironment() != xbox::ENVIRONMENT_XENIA)
{
// Only the game directory accepts the legacy layout.
@@ -275,11 +269,9 @@ Config::~Config()
{
// Reset to defaults on cleanup
active_mod[0] = '\0';
- mod_base_path[0] = '\0';
dump_rawfile = false;
dump_map_ents = false;
data_root.clear();
- shared_layout_enabled = false;
for (size_t i = 0; i < mounted_links.size(); ++i)
UnmountDevice(mounted_links[i].c_str());
mounted_links.clear();
@@ -341,13 +333,6 @@ bool Config::LoadFromJson(const char *jsonBuffer, DWORD bufferSize)
DbgPrint(" Dump Raw Scripts: %s\n", dump_rawfile ? "true" : "false");
DbgPrint(" Dump Map Entities: %s\n", dump_map_ents ? "true" : "false");
- if (active_mod[0] != '\0')
- {
- // Config loads before game: is guaranteed to point at the new executable root on hardware.
- // Keep the intended path and let later game-lifecycle file accesses validate it naturally.
- _snprintf_s(mod_base_path, ARRAYSIZE(mod_base_path), _TRUNCATE, "%s\\%s", MOD_DIR, active_mod);
- }
-
return true;
}
@@ -373,16 +358,19 @@ const char *Config::GetActiveMod()
std::string Config::ResolveModPath(const char *relativePath)
{
- if (!relativePath || !*relativePath || !mod_base_path[0])
+ if (!relativePath || !*relativePath || !active_mod[0])
return std::string();
- if (shared_layout_enabled)
- {
- const std::string mod_path = filesystem::JoinPath("mods", active_mod);
- return ResolveDataPath(filesystem::JoinPath(mod_path.c_str(), relativePath).c_str());
- }
+ const std::string mod_path = filesystem::JoinPath("mods", active_mod);
+ return BuildDataPath(filesystem::JoinPath(mod_path.c_str(), relativePath).c_str());
+}
+
+std::string Config::BuildDataPath(const char *relativePath)
+{
+ if (!relativePath || data_root.empty())
+ return std::string();
- return filesystem::JoinPath(mod_base_path, relativePath);
+ return filesystem::JoinPath(data_root.c_str(), relativePath);
}
std::string Config::ResolveDataPath(const char *relativePath)
@@ -390,7 +378,7 @@ std::string Config::ResolveDataPath(const char *relativePath)
if (!relativePath || !*relativePath || data_root.empty())
return std::string();
- const std::string path = filesystem::JoinPath(data_root.c_str(), relativePath);
+ const std::string path = BuildDataPath(relativePath);
return filesystem::FileExists(path.c_str()) ? path : std::string();
}
@@ -399,7 +387,7 @@ std::string Config::ResolveDataDirectory(const char *relativePath)
if (!relativePath || !*relativePath || data_root.empty())
return std::string();
- const std::string path = filesystem::JoinPath(data_root.c_str(), relativePath);
+ const std::string path = BuildDataPath(relativePath);
return filesystem::DirectoryExists(path.c_str()) ? path : std::string();
}
diff --git a/src/common/config.h b/src/common/config.h
index b94a509a..9a0fcbd2 100644
--- a/src/common/config.h
+++ b/src/common/config.h
@@ -1,23 +1,14 @@
#pragma once
#include "pch.h"
-
-extern const char *CONFIG_PATH;
-extern const char *MOD_DIR;
-extern const char *DUMP_DIR;
+#include "game_id.h"
bool ReadFileToString(const char *path, std::string &outString);
class Config : public Module
{
public:
- enum GameId
- {
- GAME_NONE,
- GAME_T4,
- };
-
- explicit Config(GameId gameId = GAME_NONE);
+ explicit Config(GameId::Type gameId);
~Config();
static bool dump_rawfile;
@@ -25,15 +16,15 @@ class Config : public Module
static const char *GetActiveMod();
static std::string ResolveModPath(const char *relativePath);
+ // Build paths within the root selected at startup, including files that do not exist yet.
+ static std::string BuildDataPath(const char *relativePath);
static std::string ResolveDataPath(const char *relativePath);
static std::string ResolveDataDirectory(const char *relativePath);
static std::string ResolveDataPathForGameFile(const char *relativePath);
private:
static char active_mod[MAX_PATH];
- static char mod_base_path[MAX_PATH];
static std::string data_root;
- static bool shared_layout_enabled;
static std::vector mounted_links;
bool LoadFromJson(const char *jsonBuffer, DWORD bufferSize);
diff --git a/src/common/game_id.cpp b/src/common/game_id.cpp
new file mode 100644
index 00000000..357aad11
--- /dev/null
+++ b/src/common/game_id.cpp
@@ -0,0 +1,28 @@
+#include "pch.h"
+#include "game_id.h"
+
+namespace GameId
+{
+const char *ToString(Type gameId)
+{
+ switch (gameId)
+ {
+ case IW2:
+ return "iw2";
+ case IW3:
+ return "iw3";
+ case IW4:
+ return "iw4";
+ case IW5:
+ return "iw5";
+ case T4:
+ return "t4";
+ case T5:
+ return "t5";
+ case QOS:
+ return "qos";
+ default:
+ return nullptr;
+ }
+}
+} // namespace GameId
diff --git a/src/common/game_id.h b/src/common/game_id.h
new file mode 100644
index 00000000..c2064aae
--- /dev/null
+++ b/src/common/game_id.h
@@ -0,0 +1,17 @@
+#pragma once
+
+namespace GameId
+{
+enum Type
+{
+ IW2,
+ IW3,
+ IW4,
+ IW5,
+ T4,
+ T5,
+ QOS,
+};
+
+const char *ToString(Type gameId);
+} // namespace GameId
diff --git a/src/common/gsc_loader.cpp b/src/common/gsc_loader.cpp
index 0043cd5e..967f3e91 100644
--- a/src/common/gsc_loader.cpp
+++ b/src/common/gsc_loader.cpp
@@ -52,7 +52,7 @@ void DumpSource(const char *scriptPath, const char *contents)
if (!scriptPath || !contents)
return;
- const std::string dumpPath = filesystem::JoinPath(DUMP_DIR, scriptPath);
+ const std::string dumpPath = Config::BuildDataPath(filesystem::JoinPath("dump", scriptPath).c_str());
if (dumpPath.empty())
return;
diff --git a/src/filesystem.cpp b/src/filesystem.cpp
index 8d1c6732..890844f4 100644
--- a/src/filesystem.cpp
+++ b/src/filesystem.cpp
@@ -43,12 +43,10 @@ void CreateDirectories(const char *path)
NormalizePathSeparators(&directory[0]);
char *p = &directory[0];
- const bool hasDrivePrefix = directory.size() >= 3 && p[1] == ':' && p[2] == '\\';
- const bool hasGamePrefix = directory.size() >= 6 && strncmp(p, "game:\\", 6) == 0;
-
- // Skip leading drive letter (e.g., "C:\") or "game:\" prefix
- if (hasDrivePrefix || hasGamePrefix)
- p += (hasDrivePrefix ? 3 : 6); // Move past "C:\" or "game:\"
+ const size_t rootSeparator = directory.find('\\');
+ // Skip the device root, including multi-character links such as game: and codxeusb0:.
+ if (rootSeparator != std::string::npos && rootSeparator > 0 && directory[rootSeparator - 1] == ':')
+ p += rootSeparator + 1;
for (; *p; p++)
{
@@ -75,10 +73,9 @@ void CreateParentDirectories(const char *path)
if (lastSeparator == std::string::npos)
return;
- const bool isDriveRoot = lastSeparator == 2 && directory.size() > 1 && directory[1] == ':';
- const bool isGameRoot =
- lastSeparator == 5 && directory.size() >= 6 && strncmp(directory.c_str(), "game:\\", 6) == 0;
- if (isDriveRoot || isGameRoot)
+ const bool isDeviceRoot =
+ lastSeparator > 0 && directory[lastSeparator - 1] == ':' && directory.find('\\') == lastSeparator;
+ if (isDeviceRoot)
{
return;
}
diff --git a/src/game/iw2/mp/main.cpp b/src/game/iw2/mp/main.cpp
index 7626f32f..211c0ee9 100644
--- a/src/game/iw2/mp/main.cpp
+++ b/src/game/iw2/mp/main.cpp
@@ -11,7 +11,7 @@ namespace mp
IW2_MP_Plugin::IW2_MP_Plugin()
{
- RegisterModule(new Config());
+ RegisterModule(new Config(GameId::IW2));
RegisterModule(new GSC());
RegisterModule(new scr_parser());
RegisterModule(new PlayerMovement());
diff --git a/src/game/iw2/sp/main.cpp b/src/game/iw2/sp/main.cpp
index f1f31740..2463753f 100644
--- a/src/game/iw2/sp/main.cpp
+++ b/src/game/iw2/sp/main.cpp
@@ -9,7 +9,7 @@ namespace sp
IW2_SP_Plugin::IW2_SP_Plugin()
{
- RegisterModule(new Config());
+ RegisterModule(new Config(GameId::IW2));
RegisterModule(new scr_parser());
}
diff --git a/src/game/iw3/mp/components/cmds.cpp b/src/game/iw3/mp/components/cmds.cpp
index 797ec078..ac920405 100644
--- a/src/game/iw3/mp/components/cmds.cpp
+++ b/src/game/iw3/mp/components/cmds.cpp
@@ -16,7 +16,7 @@ void Cmd_Dumpraw_f()
for (int i = 0; i < count; i++)
{
auto rawfile = files[i].rawfile;
- const std::string dumpPath = filesystem::JoinPath(DUMP_DIR, rawfile->name);
+ const std::string dumpPath = Config::BuildDataPath(filesystem::JoinPath("dump", rawfile->name).c_str());
filesystem::WriteFileToDisk(dumpPath.c_str(), rawfile->buffer, rawfile->len);
}
}
diff --git a/src/game/iw3/mp/components/fastfiles.cpp b/src/game/iw3/mp/components/fastfiles.cpp
index f7697b90..c64db992 100644
--- a/src/game/iw3/mp/components/fastfiles.cpp
+++ b/src/game/iw3/mp/components/fastfiles.cpp
@@ -14,8 +14,8 @@ const char *const MOD_ZONE = "mod";
const char *const MOD_FASTFILE = "mod.ff";
const char *const CODXE_COMMON_ZONE = "codxe_common_mp";
const char *const CODXE_UI_ZONE = "codxe_ui_mp";
-const char *const CODXE_ZONE_DIRECTORY = "game:\\_codxe\\zone";
-const char *const USERMAPS_DIRECTORY = "game:\\_codxe\\usermaps";
+const char *const CODXE_ZONE_DIRECTORY = "zone";
+const char *const USERMAPS_DIRECTORY = "usermaps";
const char *const FASTFILE_EXTENSION = ".ff";
bool IsSafeZoneName(const char *name)
@@ -39,7 +39,7 @@ std::string GetCodxeZoneFastfilePath(const char *zoneName)
return std::string();
const std::string filename = std::string(zoneName) + FASTFILE_EXTENSION;
- return filesystem::JoinPath(CODXE_ZONE_DIRECTORY, filename.c_str());
+ return Config::BuildDataPath(filesystem::JoinPath(CODXE_ZONE_DIRECTORY, filename.c_str()).c_str());
}
bool ContainsZone(const XZoneInfo *zoneInfo, unsigned int zoneCount, const char *name)
@@ -109,9 +109,9 @@ std::string FastFiles::GetModFastfilePath()
return ModList::ResolvePath(MOD_FASTFILE);
}
-const char *FastFiles::GetUsermapsDirectory()
+std::string FastFiles::GetUsermapsDirectory()
{
- return USERMAPS_DIRECTORY;
+ return Config::BuildDataPath(USERMAPS_DIRECTORY);
}
std::string FastFiles::GetUsermapFastfilePath(const char *zoneName)
@@ -128,7 +128,7 @@ std::string FastFiles::GetUsermapFastfilePath(const char *zoneName)
directory.erase(directory.length() - 5);
const std::string usermapDirectory = filesystem::JoinPath(USERMAPS_DIRECTORY, directory.c_str());
- return filesystem::JoinPath(usermapDirectory.c_str(), (filename + ".ff").c_str());
+ return Config::BuildDataPath(filesystem::JoinPath(usermapDirectory.c_str(), (filename + ".ff").c_str()).c_str());
}
int FastFiles::DB_BuildOSPath_Hook(const char *zoneName, unsigned int size, char *filename)
diff --git a/src/game/iw3/mp/components/fastfiles.h b/src/game/iw3/mp/components/fastfiles.h
index 6ef3fc3d..5c44d2bf 100644
--- a/src/game/iw3/mp/components/fastfiles.h
+++ b/src/game/iw3/mp/components/fastfiles.h
@@ -12,7 +12,7 @@ class FastFiles : public Module
FastFiles();
~FastFiles();
- static const char *GetUsermapsDirectory();
+ static std::string GetUsermapsDirectory();
static std::string GetUsermapFastfilePath(const char *zoneName);
static void ReloadModZone();
diff --git a/src/game/iw3/mp/components/image_loader.cpp b/src/game/iw3/mp/components/image_loader.cpp
index 77203175..9f0a626d 100644
--- a/src/game/iw3/mp/components/image_loader.cpp
+++ b/src/game/iw3/mp/components/image_loader.cpp
@@ -412,7 +412,7 @@ std::string GetImageDumpPath(const char *imageName)
sanitizedName.erase(std::remove_if(sanitizedName.begin(), sanitizedName.end(), [](char c) { return c == '*'; }),
sanitizedName.end());
const std::string relativePath = GetImageRelativePath(sanitizedName.c_str());
- return filesystem::JoinPath(DUMP_DIR, relativePath.c_str());
+ return Config::BuildDataPath(filesystem::JoinPath("dump", relativePath.c_str()).c_str());
}
bool ReadBinaryFile(const std::string &path, std::vector *data)
@@ -685,7 +685,7 @@ void Cmd_imagedump()
ImageList imageList;
R_GetImageList(&imageList);
- const std::string imageDumpDirectory = filesystem::JoinPath(DUMP_DIR, "images");
+ const std::string imageDumpDirectory = Config::BuildDataPath(filesystem::JoinPath("dump", "images").c_str());
filesystem::CreateDirectories(imageDumpDirectory.c_str());
for (unsigned int i = 0; i < imageList.count; ++i)
diff --git a/src/game/iw3/mp/components/mods.cpp b/src/game/iw3/mp/components/mods.cpp
index 8c614cf9..d7627eb7 100644
--- a/src/game/iw3/mp/components/mods.cpp
+++ b/src/game/iw3/mp/components/mods.cpp
@@ -11,7 +11,6 @@ namespace mp
namespace
{
const float MODS_FEEDER_ID = 9.0f;
-const char *const MODS_DIRECTORY = "game:\\_codxe\\mods";
const char *const FS_GAME_PREFIX = "mods/";
bool IsSafeModName(const char *name)
@@ -85,7 +84,7 @@ std::string ModList::GetActiveName()
std::string ModList::GetActivePath()
{
const std::string name = GetActiveName();
- return name.empty() ? std::string() : filesystem::JoinPath(MODS_DIRECTORY, name.c_str());
+ return name.empty() ? std::string() : Config::BuildDataPath(filesystem::JoinPath("mods", name.c_str()).c_str());
}
std::string ModList::ResolvePath(const char *relativePath)
@@ -102,7 +101,7 @@ bool ModList::RunMod(const char *name)
if (!fs_game || !IsSafeModName(name))
return false;
- const std::string modPath = filesystem::JoinPath(MODS_DIRECTORY, name);
+ const std::string modPath = Config::BuildDataPath(filesystem::JoinPath("mods", name).c_str());
if (!filesystem::DirectoryExists(modPath.c_str()))
{
Com_PrintError(CON_CHANNEL_ERROR, "Mod directory does not exist: %s\n", modPath.c_str());
@@ -139,12 +138,13 @@ void ModList::ScanMods()
ModsScanned = true;
UIFeeder::SetSelectedIndex(MODS_FEEDER_ID, CurrentMod);
- const std::string searchPattern = filesystem::JoinPath(MODS_DIRECTORY, "*");
+ const std::string modsDirectory = Config::BuildDataPath("mods");
+ const std::string searchPattern = filesystem::JoinPath(modsDirectory.c_str(), "*");
WIN32_FIND_DATAA findData;
HANDLE findHandle = FindFirstFileA(searchPattern.c_str(), &findData);
if (findHandle == INVALID_HANDLE_VALUE)
{
- DbgPrint("[codxe][IW3][ModList] Mod directory is unavailable: %s\n", MODS_DIRECTORY);
+ DbgPrint("[codxe][IW3][ModList] Mod directory is unavailable: %s\n", modsDirectory.c_str());
return;
}
@@ -156,7 +156,7 @@ void ModList::ScanMods()
FeederEntry entry;
entry.name = name;
- const std::string directory = filesystem::JoinPath(MODS_DIRECTORY, name.c_str());
+ const std::string directory = Config::BuildDataPath(filesystem::JoinPath("mods", name.c_str()).c_str());
entry.displayName = ReadDisplayName(filesystem::JoinPath(directory.c_str(), "description.txt"), name);
Mods.push_back(entry);
} while (FindNextFileA(findHandle, &findData) != 0);
@@ -176,7 +176,8 @@ void ModList::ScanMods()
UIFeeder::SetSelectedIndex(MODS_FEEDER_ID, CurrentMod);
- DbgPrint("[codxe][IW3][ModList] Found %u mod(s) in %s\n", static_cast(Mods.size()), MODS_DIRECTORY);
+ DbgPrint("[codxe][IW3][ModList] Found %u mod(s) in %s\n", static_cast(Mods.size()),
+ modsDirectory.c_str());
}
void ModList::EnsureModsScanned()
diff --git a/src/game/iw3/mp/components/mpsp.cpp b/src/game/iw3/mp/components/mpsp.cpp
index 5cdd45db..0a32a47b 100644
--- a/src/game/iw3/mp/components/mpsp.cpp
+++ b/src/game/iw3/mp/components/mpsp.cpp
@@ -114,7 +114,7 @@ namespace Asset
std::string get_load_dir()
{
- return "game:\\_codxe\\internal";
+ return Config::BuildDataPath("internal");
}
namespace MapEnts_
{
diff --git a/src/game/iw3/mp/components/stats.cpp b/src/game/iw3/mp/components/stats.cpp
index 6ff68b63..af285b17 100644
--- a/src/game/iw3/mp/components/stats.cpp
+++ b/src/game/iw3/mp/components/stats.cpp
@@ -398,7 +398,7 @@ std::string GetStatsPath(unsigned int controllerIndex)
_snprintf_s(filename, ARRAYSIZE(filename), _TRUNCATE, "controller_%u.stat", controllerIndex);
}
- return filesystem::JoinPath("game:\\_codxe\\players", filename);
+ return Config::BuildDataPath(filesystem::JoinPath("players", filename).c_str());
}
bool LoadStats(unsigned int controllerIndex)
diff --git a/src/game/iw3/mp/components/ui_feeder.cpp b/src/game/iw3/mp/components/ui_feeder.cpp
index 51310abc..021b848f 100644
--- a/src/game/iw3/mp/components/ui_feeder.cpp
+++ b/src/game/iw3/mp/components/ui_feeder.cpp
@@ -78,14 +78,14 @@ void ScanUsermaps()
usermapsScanned = true;
UIFeeder::SetSelectedIndex(USERMAPS_FEEDER_ID, selectedUsermap);
- const char *usermapsDirectory = FastFiles::GetUsermapsDirectory();
- const std::string searchPattern = filesystem::JoinPath(usermapsDirectory, "*");
+ const std::string usermapsDirectory = FastFiles::GetUsermapsDirectory();
+ const std::string searchPattern = filesystem::JoinPath(usermapsDirectory.c_str(), "*");
WIN32_FIND_DATAA findData;
HANDLE findHandle = FindFirstFileA(searchPattern.c_str(), &findData);
if (findHandle == INVALID_HANDLE_VALUE)
{
UpdateUsermapCounter();
- DbgPrint("[codxe][IW3][UIFeeder] Usermap directory is unavailable: %s\n", usermapsDirectory);
+ DbgPrint("[codxe][IW3][UIFeeder] Usermap directory is unavailable: %s\n", usermapsDirectory.c_str());
return;
}
@@ -104,7 +104,7 @@ void ScanUsermaps()
FeederEntry entry;
entry.name = name;
- const std::string directory = filesystem::JoinPath(usermapsDirectory, name.c_str());
+ const std::string directory = filesystem::JoinPath(usermapsDirectory.c_str(), name.c_str());
entry.displayName = ReadDisplayName(filesystem::JoinPath(directory.c_str(), "description.txt"), name);
usermaps.push_back(entry);
} while (FindNextFileA(findHandle, &findData) != 0);
@@ -126,7 +126,7 @@ void ScanUsermaps()
UpdateUsermapCounter();
DbgPrint("[codxe][IW3][UIFeeder] Found %u usermap(s) in %s\n", static_cast(usermaps.size()),
- usermapsDirectory);
+ usermapsDirectory.c_str());
}
void EnsureUsermapsScanned()
diff --git a/src/game/iw3/mp/main.cpp b/src/game/iw3/mp/main.cpp
index a59008cd..0b8132d3 100644
--- a/src/game/iw3/mp/main.cpp
+++ b/src/game/iw3/mp/main.cpp
@@ -38,6 +38,7 @@ IW3_MP_Plugin::IW3_MP_Plugin()
// Special modules need to be registered first
RegisterModule(new Patches());
+ RegisterModule(new Config(GameId::IW3));
RegisterModule(new Events());
RegisterModule(new command());
RegisterModule(new UIScript());
diff --git a/src/game/iw3/sp/main.cpp b/src/game/iw3/sp/main.cpp
index c90a2da6..7fbd73e8 100644
--- a/src/game/iw3/sp/main.cpp
+++ b/src/game/iw3/sp/main.cpp
@@ -84,7 +84,7 @@ void Load_MapEntsPtr_Hook()
// Dump stock map ents if enabled (numEntityChars includes the null terminator, which is not written)
if (Config::dump_map_ents && mapEnts->numEntityChars > 0)
{
- const std::string dumpPath = map_ents::BuildPath(DUMP_DIR, mapEnts->name);
+ const std::string dumpPath = map_ents::BuildPath(Config::BuildDataPath("dump").c_str(), mapEnts->name);
if (!dumpPath.empty())
{
filesystem::WriteFileToDisk(dumpPath.c_str(), mapEnts->entityString, mapEnts->numEntityChars - 1);
@@ -138,7 +138,7 @@ void Cmd_Dumpraw_f()
for (int i = 0; i < count; i++)
{
auto rawfile = files[i].rawfile;
- const std::string dumpPath = filesystem::JoinPath(DUMP_DIR, rawfile->name);
+ const std::string dumpPath = Config::BuildDataPath(filesystem::JoinPath("dump", rawfile->name).c_str());
filesystem::WriteFileToDisk(dumpPath.c_str(), rawfile->buffer, rawfile->len);
}
}
@@ -146,7 +146,7 @@ void Cmd_Dumpraw_f()
IW3_SP_Plugin::IW3_SP_Plugin()
{
DbgPrint("IW3 SP: Plugin loaded\n");
- RegisterModule(new Config());
+ RegisterModule(new Config(GameId::IW3));
RegisterModule(new Events());
RegisterModule(new command());
RegisterModule(new scr_parser());
diff --git a/src/game/iw4/mp/components/fastfiles.cpp b/src/game/iw4/mp/components/fastfiles.cpp
index 1a9bfe18..fe4c02d9 100644
--- a/src/game/iw4/mp/components/fastfiles.cpp
+++ b/src/game/iw4/mp/components/fastfiles.cpp
@@ -8,16 +8,8 @@ namespace mp
namespace
{
const char *const CODXE_PATCH_ZONE = "codxe_patch_mp";
-const char *const CODXE_PATCH_FILENAME = "codxe_patch_mp.ff";
-const char *const CODXE_PATCH_RELATIVE_PATH = "_codxe\\zone\\codxe_patch_mp.ff";
-const char *const CODXE_PATCH_PATH = "game:\\_codxe\\zone\\codxe_patch_mp.ff";
const char *const CODXE_UI_ZONE = "codxe_ui_mp";
-const char *const CODXE_UI_FILENAME = "codxe_ui_mp.ff";
-const char *const CODXE_UI_RELATIVE_PATH = "_codxe\\zone\\codxe_ui_mp.ff";
-const char *const CODXE_UI_PATH = "game:\\_codxe\\zone\\codxe_ui_mp.ff";
-const char *const CODXE_ZONE_RELATIVE_DIRECTORY = "_codxe\\zone\\";
const char *const CODXE_IMAGEFILE_FILENAME = "imagefile5.pak";
-const char *const GAME_DEVICE_PREFIX = "game:\\";
const char *const FASTFILE_EXTENSION = ".ff";
const unsigned int MAX_ZONE_COUNT = 32;
@@ -79,8 +71,8 @@ bool IsSafeFastfileName(const char *filename)
void DB_LoadXAssets_Hook(XZoneInfo *zoneInfo, unsigned int zoneCount, int sync)
{
auto original = DB_LoadXAssets_Detour.GetOriginal();
- const bool patchFileExists = filesystem::FileExists(CODXE_PATCH_PATH);
- const bool uiFileExists = filesystem::FileExists(CODXE_UI_PATH);
+ const bool patchFileExists = !Config::ResolveDataPath("zone\\codxe_patch_mp.ff").empty();
+ const bool uiFileExists = !Config::ResolveDataPath("zone\\codxe_ui_mp.ff").empty();
const XZoneInfo *stockPatchZone = FindZone(zoneInfo, zoneCount, "patch_mp");
const XZoneInfo *stockUiZone = FindZone(zoneInfo, zoneCount, "ui_mp");
const bool injectPatch = patchFileExists && stockPatchZone;
@@ -126,28 +118,18 @@ int Sys_CreateFile_Hook(const char *dir, const char *filename)
{
auto original = Sys_CreateFile_Detour.GetOriginal();
- if (filename && std::strcmp(filename, CODXE_PATCH_FILENAME) == 0)
- return original(dir, CODXE_PATCH_RELATIVE_PATH);
-
- if (filename && std::strcmp(filename, CODXE_UI_FILENAME) == 0)
- return original(dir, CODXE_UI_RELATIVE_PATH);
-
- if (filename && std::strcmp(filename, CODXE_IMAGEFILE_FILENAME) == 0)
+ if (filename && (std::strcmp(filename, CODXE_IMAGEFILE_FILENAME) == 0 || IsSafeFastfileName(filename)))
{
- const std::string relativePath = std::string(CODXE_ZONE_RELATIVE_DIRECTORY) + filename;
- const std::string devicePath = std::string(GAME_DEVICE_PREFIX) + relativePath;
-
- if (filesystem::FileExists(devicePath.c_str()))
- return original(dir, relativePath.c_str());
- }
-
- if (IsSafeFastfileName(filename))
- {
- const std::string relativePath = std::string(CODXE_ZONE_RELATIVE_DIRECTORY) + filename;
- const std::string devicePath = std::string(GAME_DEVICE_PREFIX) + relativePath;
-
- if (filesystem::FileExists(devicePath.c_str()))
- return original(dir, relativePath.c_str());
+ const std::string path = Config::ResolveDataPath(filesystem::JoinPath("zone", filename).c_str());
+ // Sys_CreateFile prepends the title directory, so pass a title-relative filename.
+ if (path.compare(0, 6, "game:\\") == 0)
+ return original(dir, path.substr(6).c_str());
+
+ // External roots use a device link directly, with the stock async/unbuffered read flags.
+ if (!path.empty())
+ return reinterpret_cast(CreateFileA(path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr,
+ OPEN_EXISTING, FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING,
+ nullptr));
}
return original(dir, filename);
diff --git a/src/game/iw4/mp/main.cpp b/src/game/iw4/mp/main.cpp
index d5844ee3..5198da6b 100644
--- a/src/game/iw4/mp/main.cpp
+++ b/src/game/iw4/mp/main.cpp
@@ -13,6 +13,7 @@ namespace mp
IW4_MP_Plugin::IW4_MP_Plugin()
{
+ RegisterModule(new Config(GameId::IW4));
RegisterModule(new Events());
RegisterModule(new fastfiles());
RegisterModule(new Branding());
diff --git a/src/game/iw4/mp_tu6/components/fastfiles.cpp b/src/game/iw4/mp_tu6/components/fastfiles.cpp
index 24c1c816..29c6b41f 100644
--- a/src/game/iw4/mp_tu6/components/fastfiles.cpp
+++ b/src/game/iw4/mp_tu6/components/fastfiles.cpp
@@ -8,16 +8,8 @@ namespace mp_tu6
namespace
{
const char *const CODXE_PATCH_ZONE = "codxe_patch_mp";
-const char *const CODXE_PATCH_FILENAME = "codxe_patch_mp.ff";
-const char *const CODXE_PATCH_RELATIVE_PATH = "_codxe\\zone\\codxe_patch_mp.ff";
-const char *const CODXE_PATCH_PATH = "game:\\_codxe\\zone\\codxe_patch_mp.ff";
const char *const CODXE_UI_ZONE = "codxe_ui_mp";
-const char *const CODXE_UI_FILENAME = "codxe_ui_mp.ff";
-const char *const CODXE_UI_RELATIVE_PATH = "_codxe\\zone\\codxe_ui_mp.ff";
-const char *const CODXE_UI_PATH = "game:\\_codxe\\zone\\codxe_ui_mp.ff";
-const char *const CODXE_ZONE_RELATIVE_DIRECTORY = "_codxe\\zone\\";
const char *const CODXE_IMAGEFILE_FILENAME = "imagefile5.pak";
-const char *const GAME_DEVICE_PREFIX = "game:\\";
const char *const FASTFILE_EXTENSION = ".ff";
const unsigned int MAX_ZONE_COUNT = 32;
@@ -86,8 +78,8 @@ bool IsSafeFastfileName(const char *filename)
void DB_LoadXAssets_Hook(XZoneInfo *zoneInfo, unsigned int zoneCount, int sync)
{
auto original = DB_LoadXAssets_Detour.GetOriginal();
- const bool patchFileExists = filesystem::FileExists(CODXE_PATCH_PATH);
- const bool uiFileExists = filesystem::FileExists(CODXE_UI_PATH);
+ const bool patchFileExists = !Config::ResolveDataPath("zone\\codxe_patch_mp.ff").empty();
+ const bool uiFileExists = !Config::ResolveDataPath("zone\\codxe_ui_mp.ff").empty();
const XZoneInfo *stockPatchZone = FindZone(zoneInfo, zoneCount, "patch_mp");
const XZoneInfo *stockUiZone = FindZone(zoneInfo, zoneCount, "ui_mp");
const bool injectPatch = patchFileExists && stockPatchZone;
@@ -133,28 +125,21 @@ SysFile Sys_CreateFile_Hook(const char *dir, const char *filename)
{
auto original = Sys_CreateFile_Detour.GetOriginal();
- if (filename && std::strcmp(filename, CODXE_PATCH_FILENAME) == 0)
- return original(dir, CODXE_PATCH_RELATIVE_PATH);
-
- if (filename && std::strcmp(filename, CODXE_UI_FILENAME) == 0)
- return original(dir, CODXE_UI_RELATIVE_PATH);
-
- if (filename && std::strcmp(filename, CODXE_IMAGEFILE_FILENAME) == 0)
- {
- const std::string relativePath = std::string(CODXE_ZONE_RELATIVE_DIRECTORY) + filename;
- const std::string devicePath = std::string(GAME_DEVICE_PREFIX) + relativePath;
-
- if (filesystem::FileExists(devicePath.c_str()))
- return original(dir, relativePath.c_str());
- }
-
- if (IsSafeFastfileName(filename))
+ if (filename && (std::strcmp(filename, CODXE_IMAGEFILE_FILENAME) == 0 || IsSafeFastfileName(filename)))
{
- const std::string relativePath = std::string(CODXE_ZONE_RELATIVE_DIRECTORY) + filename;
- const std::string devicePath = std::string(GAME_DEVICE_PREFIX) + relativePath;
+ const std::string path = Config::ResolveDataPath(filesystem::JoinPath("zone", filename).c_str());
+ // Sys_CreateFile prepends the title directory, so pass a title-relative filename.
+ if (path.compare(0, 6, "game:\\") == 0)
+ return original(dir, path.substr(6).c_str());
- if (filesystem::FileExists(devicePath.c_str()))
- return original(dir, relativePath.c_str());
+ // External roots use a device link directly, with the stock async/unbuffered read flags.
+ if (!path.empty())
+ {
+ SysFile file = {CreateFileA(path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING,
+ FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING, nullptr),
+ 0};
+ return file;
+ }
}
return original(dir, filename);
diff --git a/src/game/iw4/mp_tu6/main.cpp b/src/game/iw4/mp_tu6/main.cpp
index 28585c60..873088fd 100644
--- a/src/game/iw4/mp_tu6/main.cpp
+++ b/src/game/iw4/mp_tu6/main.cpp
@@ -22,7 +22,7 @@ namespace mp_tu6
IW4_MP_TU6_Plugin::IW4_MP_TU6_Plugin()
{
- RegisterModule(new Config());
+ RegisterModule(new Config(GameId::IW4));
RegisterModule(new Events()); // Must be registered first to ensure hooks are in place
RegisterModule(new fastfiles());
RegisterModule(new cg());
diff --git a/src/game/iw4/sp/components/clipmap.cpp b/src/game/iw4/sp/components/clipmap.cpp
index 4e295b3f..ee025d96 100644
--- a/src/game/iw4/sp/components/clipmap.cpp
+++ b/src/game/iw4/sp/components/clipmap.cpp
@@ -20,7 +20,7 @@ void Load_clipMap_t_Hook(bool atStreamStart)
// Dump map entities if enabled
if (Config::dump_map_ents)
{
- const std::string dumpPath = map_ents::BuildPath(DUMP_DIR, mapEnts->name);
+ const std::string dumpPath = map_ents::BuildPath(Config::BuildDataPath("dump").c_str(), mapEnts->name);
if (!dumpPath.empty())
{
filesystem::WriteFileToDisk(dumpPath.c_str(), mapEnts->entityString, mapEnts->numEntityChars - 1);
diff --git a/src/game/iw4/sp/main.cpp b/src/game/iw4/sp/main.cpp
index a5aaebaa..48e472aa 100644
--- a/src/game/iw4/sp/main.cpp
+++ b/src/game/iw4/sp/main.cpp
@@ -33,7 +33,7 @@ IW4_SP_Plugin::IW4_SP_Plugin()
RemoveIdleGunSway();
- RegisterModule(new Config());
+ RegisterModule(new Config(GameId::IW4));
RegisterModule(new cg());
RegisterModule(new clipmap());
RegisterModule(new GSCFields());
diff --git a/src/game/iw5/mp/main.cpp b/src/game/iw5/mp/main.cpp
index ccf809da..f5bf38c7 100644
--- a/src/game/iw5/mp/main.cpp
+++ b/src/game/iw5/mp/main.cpp
@@ -219,7 +219,7 @@ bool DB_IsXAssetDefault_Hook(XAssetType type, const char *name)
IW5_MP_Plugin::IW5_MP_Plugin()
{
- RegisterModule(new Config());
+ RegisterModule(new Config(GameId::IW5));
RegisterModule(new Events());
RegisterModule(new Branding());
RegisterModule(new patches());
diff --git a/src/game/qos/mp/main.cpp b/src/game/qos/mp/main.cpp
index c9f14f9c..98705e67 100644
--- a/src/game/qos/mp/main.cpp
+++ b/src/game/qos/mp/main.cpp
@@ -14,7 +14,7 @@ namespace mp
QOS_MP_Plugin::QOS_MP_Plugin()
{
DbgPrint("QOS SP: Registering modules\n");
- RegisterModule(new Config());
+ RegisterModule(new Config(GameId::QOS));
RegisterModule(new Events());
RegisterModule(new clipmap());
RegisterModule(new GSC());
diff --git a/src/game/qos/sp/main.cpp b/src/game/qos/sp/main.cpp
index 844b9e8a..761495e8 100644
--- a/src/game/qos/sp/main.cpp
+++ b/src/game/qos/sp/main.cpp
@@ -9,7 +9,7 @@ namespace sp
QOS_SP_Plugin::QOS_SP_Plugin()
{
DbgPrint("QOS SP: Registering modules\n");
- RegisterModule(new Config());
+ RegisterModule(new Config(GameId::QOS));
RegisterModule(new scr_parser());
}
diff --git a/src/game/t4/mp/components/map.cpp b/src/game/t4/mp/components/map.cpp
index ed120e0c..273832f4 100644
--- a/src/game/t4/mp/components/map.cpp
+++ b/src/game/t4/mp/components/map.cpp
@@ -68,7 +68,7 @@ void Load_clipMap_t_Hook(bool atStreamStart)
// Dump map entities if enabled
if (Config::dump_map_ents)
{
- const std::string dumpPath = map_ents::BuildPath(DUMP_DIR, mapEnts->name);
+ const std::string dumpPath = map_ents::BuildPath(Config::BuildDataPath("dump").c_str(), mapEnts->name);
if (!dumpPath.empty())
{
filesystem::WriteFileToDisk(dumpPath.c_str(), mapEnts->entityString, mapEnts->numEntityChars - 1);
diff --git a/src/game/t4/mp/main.cpp b/src/game/t4/mp/main.cpp
index 80db9204..67b9863b 100644
--- a/src/game/t4/mp/main.cpp
+++ b/src/game/t4/mp/main.cpp
@@ -27,7 +27,7 @@ T4_MP_Plugin::T4_MP_Plugin()
RegisterModule(new Debug());
#endif
- RegisterModule(new Config());
+ RegisterModule(new Config(GameId::T4));
RegisterModule(new Events()); // Must be registered before modules that subscribe to engine events.
RegisterModule(new Branding());
RegisterModule(new BrushCollision());
diff --git a/src/game/t4/sp/components/clipmap.cpp b/src/game/t4/sp/components/clipmap.cpp
index c07da257..23d6cd17 100644
--- a/src/game/t4/sp/components/clipmap.cpp
+++ b/src/game/t4/sp/components/clipmap.cpp
@@ -68,7 +68,7 @@ void Load_clipMap_t_Hook(bool atStreamStart)
// Dump map entities if enabled
if (Config::dump_map_ents)
{
- const std::string dumpPath = map_ents::BuildPath(DUMP_DIR, mapEnts->name);
+ const std::string dumpPath = map_ents::BuildPath(Config::BuildDataPath("dump").c_str(), mapEnts->name);
if (!dumpPath.empty())
{
filesystem::WriteFileToDisk(dumpPath.c_str(), mapEnts->entityString, mapEnts->numEntityChars - 1);
diff --git a/src/game/t4/sp/main.cpp b/src/game/t4/sp/main.cpp
index 375607b6..84ed9200 100644
--- a/src/game/t4/sp/main.cpp
+++ b/src/game/t4/sp/main.cpp
@@ -61,7 +61,7 @@ T4_SP_Plugin::T4_SP_Plugin()
// Default ui_autoContinue on so level loads do not wait for input in solo or split-screen.
*(volatile uint8_t *)0x82279B07 = 0x01;
- RegisterModule(new Config(Config::GAME_T4));
+ RegisterModule(new Config(GameId::T4));
RegisterModule(new Events()); // Must be registered before modules that subscribe to engine events.
RegisterModule(new FastFiles());
RegisterModule(new clipmap());
diff --git a/src/game/t5/mp/main.cpp b/src/game/t5/mp/main.cpp
index bfb0dec3..0f604ec4 100644
--- a/src/game/t5/mp/main.cpp
+++ b/src/game/t5/mp/main.cpp
@@ -10,7 +10,7 @@ namespace mp
T5_MP_Plugin::T5_MP_Plugin()
{
DbgPrint("T5 MP: Registering modules\n");
- RegisterModule(new Config());
+ RegisterModule(new Config(GameId::T5));
RegisterModule(new scr_parser());
}
diff --git a/src/game/t5/sp/main.cpp b/src/game/t5/sp/main.cpp
index dcb73bd3..27a53ac2 100644
--- a/src/game/t5/sp/main.cpp
+++ b/src/game/t5/sp/main.cpp
@@ -10,7 +10,7 @@ namespace sp
T5_SP_Plugin::T5_SP_Plugin()
{
DbgPrint("T5 SP: Registering modules\n");
- RegisterModule(new Config());
+ RegisterModule(new Config(GameId::T5));
RegisterModule(new scr_parser());
}