diff --git a/arma/server/addons/store/README.md b/arma/server/addons/store/README.md index 367ab28..10787a9 100644 --- a/arma/server/addons/store/README.md +++ b/arma/server/addons/store/README.md @@ -42,12 +42,14 @@ class CfgStore { patches[] = {"rhs_main", "rhsusf_main"}; addons[] = {"rhs_", "rhsusf_", "rhsgref_", "rhsafrf_"}; prefixes[] = {"rhs_", "rhsusf_", "rhsgref_", "rhsafrf_"}; + dlcs[] = {}; }; class ace3 { patches[] = {"ace_main"}; addons[] = {"ace_"}; prefixes[] = {"ace_"}; + dlcs[] = {}; }; }; @@ -76,9 +78,10 @@ uses the same prices and descriptions the UI displays. filtering. `allowlist` only keeps generated entries that match one of the configured `mods[]`; `denylist` removes matching entries. Each `ModSources` child can define `patches[]` to detect whether the mod is loaded, `addons[]` -for exact config source addon/source mod names, and `prefixes[]` for classname, -source addon, or source mod prefixes. If a mod source defines no patches, it is -treated as available and only the source/prefix checks are used. +for exact config source addon/source mod names, `prefixes[]` for classname, +source addon, or source mod prefixes, and `dlcs[]` for DLC/source/author labels +used by Creator DLC content. If a mod source defines no patches, it is treated +as available and only the source/prefix/DLC checks are used. `units[]` follows the same `dynamic`, `allowlist`, and `denylist` behavior as item and vehicle categories. Unit purchases are immediate spawn grants, not diff --git a/arma/server/addons/store/functions/fnc_initCatalogService.sqf b/arma/server/addons/store/functions/fnc_initCatalogService.sqf index 796152e..0865b0f 100644 --- a/arma/server/addons/store/functions/fnc_initCatalogService.sqf +++ b/arma/server/addons/store/functions/fnc_initCatalogService.sqf @@ -87,6 +87,28 @@ GVAR(StoreCatalogServiceBaseClass) = compileFinal createHashMapFromArray [ _loaded }], + ["describeMissionStoreModSources", compileFinal { + params [["_mods", [], [[]]]]; + + _mods apply { + private _modID = _x; + private _patches = _self call ["getMissionStoreModSourceValues", [_modID, "patches"]]; + private _addons = _self call ["getMissionStoreModSourceValues", [_modID, "addons"]]; + private _prefixes = _self call ["getMissionStoreModSourceValues", [_modID, "prefixes"]]; + private _dlcs = _self call ["getMissionStoreModSourceValues", [_modID, "dlcs"]]; + private _loaded = _self call ["isMissionStoreModLoaded", [_modID]]; + + format [ + "%1 loaded=%2 patches=%3 addons=%4 prefixes=%5 dlcs=%6", + _modID, + _loaded, + _patches, + _addons, + _prefixes, + _dlcs + ] + } + }], ["doesValueMatchAnyPrefix", compileFinal { params [["_value", "", [""]], ["_prefixes", [], [[]]]]; @@ -109,12 +131,19 @@ GVAR(StoreCatalogServiceBaseClass) = compileFinal createHashMapFromArray [ private _className = _item getOrDefault ["className", ""]; private _sourceAddons = (_item getOrDefault ["sourceAddons", []]) apply { toLowerANSI _x }; private _sourceMod = _item getOrDefault ["sourceMod", ""]; + private _sourceDLC = _item getOrDefault ["sourceDLC", ""]; + private _sourceAuthor = _item getOrDefault ["sourceAuthor", ""]; private _addons = (_self call ["getMissionStoreModSourceValues", [_modID, "addons"]]) apply { toLowerANSI _x }; private _prefixes = (_self call ["getMissionStoreModSourceValues", [_modID, "prefixes"]]) apply { toLowerANSI _x }; + private _dlcs = (_self call ["getMissionStoreModSourceValues", [_modID, "dlcs"]]) apply { toLowerANSI _x }; private _matchPrefixes = _addons + _prefixes; private _sourceModLower = toLowerANSI _sourceMod; + private _sourceDLCLower = toLowerANSI _sourceDLC; + private _sourceAuthorLower = toLowerANSI _sourceAuthor; if (_sourceModLower in _addons) exitWith { true }; + if (_sourceDLCLower in _dlcs) exitWith { true }; + if (_sourceAuthorLower in _dlcs) exitWith { true }; private _sourceAddonMatched = false; { if (_x in _addons) exitWith { _sourceAddonMatched = true; }; @@ -123,6 +152,8 @@ GVAR(StoreCatalogServiceBaseClass) = compileFinal createHashMapFromArray [ if (_sourceAddonMatched) exitWith { true }; if (_self call ["doesValueMatchAnyPrefix", [_className, _matchPrefixes]]) exitWith { true }; if (_self call ["doesValueMatchAnyPrefix", [_sourceMod, _matchPrefixes]]) exitWith { true }; + if (_self call ["doesValueMatchAnyPrefix", [_sourceDLC, _dlcs]]) exitWith { true }; + if (_self call ["doesValueMatchAnyPrefix", [_sourceAuthor, _dlcs]]) exitWith { true }; false }], @@ -141,9 +172,18 @@ GVAR(StoreCatalogServiceBaseClass) = compileFinal createHashMapFromArray [ private _mode = _self call ["getMissionStoreModMode", []]; private _mods = _self call ["getMissionStoreModList", []]; - if (_mode isEqualTo "dynamic" || { _mods isEqualTo [] }) exitWith { +_items }; + private _beforeCount = count _items; + if (_mode isEqualTo "dynamic" || { _mods isEqualTo [] }) exitWith { + ["INFO", format [ + "Store mod filter skipped. Mode=%1 Mods=%2 Items=%3", + _mode, + _mods, + _beforeCount + ]] call EFUNC(common,log); + +_items + }; - switch (_mode) do { + private _filteredItems = switch (_mode) do { case "allowlist": { _items select { _self call ["doesItemMatchMissionStoreMods", [_x, _mods]] } }; @@ -153,7 +193,18 @@ GVAR(StoreCatalogServiceBaseClass) = compileFinal createHashMapFromArray [ default { +_items }; - } + }; + + ["INFO", format [ + "Store mod filter applied. Mode=%1 Mods=%2 Items=%3 -> %4 Sources=[%5]", + _mode, + _mods, + _beforeCount, + count _filteredItems, + (_self call ["describeMissionStoreModSources", [_mods]]) joinString "; " + ]] call EFUNC(common,log); + + _filteredItems }], ["getMissionStoreCategoryList", compileFinal { params [["_category", "", [""]]]; @@ -304,6 +355,8 @@ GVAR(StoreCatalogServiceBaseClass) = compileFinal createHashMapFromArray [ private _displayName = getText (_cfg >> "displayName"); private _sourceAddons = configSourceAddonList _cfg; private _sourceMod = configSourceMod _cfg; + private _sourceDLC = getText (_cfg >> "DLC"); + private _sourceAuthor = getText (_cfg >> "author"); private _picture = getText (_cfg >> _imageField); if (_picture isEqualTo "" && { _imageField isNotEqualTo "picture" }) then { _picture = getText (_cfg >> "picture"); @@ -321,7 +374,9 @@ GVAR(StoreCatalogServiceBaseClass) = compileFinal createHashMapFromArray [ ["image", _picture], ["type", _typeLabel], ["sourceAddons", _sourceAddons], - ["sourceMod", _sourceMod] + ["sourceMod", _sourceMod], + ["sourceDLC", _sourceDLC], + ["sourceAuthor", _sourceAuthor] ] }], ["appendCfgWeaponsByItemInfoType", compileFinal { diff --git a/docs/STORE_USAGE_GUIDE.md b/docs/STORE_USAGE_GUIDE.md index 5648e7f..338a1a5 100644 --- a/docs/STORE_USAGE_GUIDE.md +++ b/docs/STORE_USAGE_GUIDE.md @@ -42,12 +42,14 @@ class CfgStore { patches[] = {"rhs_main", "rhsusf_main"}; addons[] = {"rhs_", "rhsusf_", "rhsgref_", "rhsafrf_"}; prefixes[] = {"rhs_", "rhsusf_", "rhsgref_", "rhsafrf_"}; + dlcs[] = {}; }; class ace3 { patches[] = {"ace_main"}; addons[] = {"ace_"}; prefixes[] = {"ace_"}; + dlcs[] = {}; }; }; @@ -76,9 +78,10 @@ server-side and are used by both the UI payload and checkout validation. filtering. `allowlist` only keeps generated entries that match one of the configured `mods[]`; `denylist` removes matching entries. Each `ModSources` child can define `patches[]` to detect whether the mod is loaded, `addons[]` -for exact config source addon/source mod names, and `prefixes[]` for classname, -source addon, or source mod prefixes. If a mod source defines no patches, it is -treated as available and only the source/prefix checks are used. +for exact config source addon/source mod names, `prefixes[]` for classname, +source addon, or source mod prefixes, and `dlcs[]` for DLC/source/author labels +used by Creator DLC content. If a mod source defines no patches, it is treated +as available and only the source/prefix/DLC checks are used. For example, to show only RHS-sourced generated inventory: @@ -91,6 +94,17 @@ The matching `class rhs` must exist under `ModSources`. Category `mode` is still applied afterward, so leave `mode = "dynamic"` if the mod filter should be the only inventory filter. +For Creator DLCs such as RF or WS, prefer both prefixes and DLC labels: + +```cpp +class rf { + patches[] = {}; + addons[] = {"lxrf_", "rf_"}; + prefixes[] = {"lxrf_", "rf_"}; + dlcs[] = {"rf", "reactionforces", "reaction forces"}; +}; +``` + The current filter is global for the mission. Revisit per-store profile support if individual vendors need different inventories.