feat(session): 解析 Pt 容器为物品目录,未覆盖项从 30029 降到 2203
This commit is contained in:
1 parent
f29ad2caaa
commit
ee7504000f
4 files changed
+331
-2
No files matched your search
@@ -501,6 +501,24 @@
|
||||
(`ju`/`Su`/`Eu`/`Iu`,对应 `BuyableCC.buyable`/`currencyId`、`ItemCategoryCC.category` 等)
|
||||
是 module_85196 的内部函数、不导出,18334 也不直接读 CC 槽位,
|
||||
说明转换经 DI 服务接口完成;下一步用别名表追该接口的实现方法。
|
||||
- 物品目录(`App/Session/ItemCatalog.kt`):
|
||||
- 结论修正:抓包里这 30029 条未覆盖 Pt 项**不是用户状态**,而是静态物品表
|
||||
(1371 个物品对象 + 515 个装置对象),原包也不把它放进 Redux,而是由服务按需读取。
|
||||
- 容器形态(`names/model_registry.json` + 抓包实测):`pt.Items` 按 `Id == 0` 的对象标记分组,
|
||||
标记项的值就是 ObjectId;组内按 modelId 建索引。物品组通常是
|
||||
`CountableItemCC, ItemPropertiesCC, ItemSaleByKitCC, BuyableCC, TimePeriodModelCC,
|
||||
ItemModelCC, ItemRarityCC, DescriptionModelCC, ItemCategoryCC, PremiumItemCC,
|
||||
ItemViewCategoryCC, DescriptionMediaCC, VisibleCC`;装置组换成
|
||||
`DevicePropertiesCC + TemporaryItemCC`。
|
||||
- `CC → GarageItemObject` / `GarageDeviceObject` 的字段顺序取自 module_18334 的
|
||||
`S$`(物品)与 `gct`(装置)的构造函数实参,token → 模型类由跨模块别名表反查,逐条登记在文件头。
|
||||
- `SessionRouter` 在 Pt 分支先调 `Catalog.Ingest`,被目录吸收的项不再计入未覆盖:
|
||||
抓包实测 **物品 1399 / 装置 516 / 吸收 27826 项**,未覆盖从 30029 降到 2203
|
||||
(余下主要是 methodId 级未覆盖、`0` 对象标记、以及 ResistancesCC/DurationCC 等非物品对象)。
|
||||
自检同时断言目录非空,并打印名称样本(如 `史诗幸运礼盒`、`紧凑型油箱`)验证字段映射。
|
||||
- 下一步:用户拥有的物品列表来自 GarageCC 的引用字段(`itemsOnDepot` / `itemsOnMarket` /
|
||||
`mountedItems`)与模型命令流;等这部分抓包/命令解码补齐后,用目录把 id 解析成
|
||||
`GarageItemObject` 再派发 `SetItemsOnDepot` / `SetItemsOnMarket` / `SetMountedItems`。
|
||||
- 委派表里的已知形态:`shop` / `home` / `localBattleUserState` / `partner` 是内联 IIFE,
|
||||
已按字段具名为 `(inline@<field>)` 并从函数体抓到顶层动作名(69 / 1 / 2 / 11 个);
|
||||
`launchParams` 是纯透传(`(pass-through)`,无 reducer),已把字段收口为 `Map<String, String>`。
|
||||
|
||||
@@ -0,0 +1,261 @@
|
||||
// ItemCatalog.kt —— 车库 / 商店物品目录(Pt 容器 → GarageItemObject / GarageDeviceObject)
|
||||
//
|
||||
// 为什么单列一个「目录」而不是 Redux 切片:
|
||||
// · 抓包里最大的 Pt 容器是**静态物品表**(1371 个物品对象 + 515 个装置对象),
|
||||
// 不是用户拥有的物品列表;原包也不把它放状态层,而是由服务按需读取。
|
||||
// · 原包的「CC → GarageItemObject」转换在 module_18334 的 `S$`(物品)与 `gct`(装置)里,
|
||||
// 逐个从对象上下文取子模型:`Gr(n, Z(token))`。token → 模型类的对应关系见下表的注释。
|
||||
//
|
||||
// 容器形态(names/model_registry.json + 抓包实测):
|
||||
// Pt.Items = [0(对象标记,value 是 ObjectId), 模型1, 模型2, …, 0(下一个对象), …]
|
||||
// 每个对象组里模型顺序不固定,按 modelId 建索引即可;组边界 = Id == 0 的项。
|
||||
// 物品组的模型集合(实测):
|
||||
// CountableItemCC, ItemPropertiesCC, ItemSaleByKitCC, BuyableCC,
|
||||
// TimePeriodModelCC, ItemModelCC, ItemRarityCC, DescriptionModelCC,
|
||||
// ItemCategoryCC, PremiumItemCC, ItemViewCategoryCC, DescriptionMediaCC, VisibleCC
|
||||
// 装置组在前述集合上换成 DevicePropertiesCC + TemporaryItemCC。
|
||||
//
|
||||
// 字段对应(module_18334 的 `S$`,new GarageItemObject(...) 的实参顺序):
|
||||
// id←对象标记 | description←DescriptionModelCC | item←ItemModelCC
|
||||
// isPremium←PremiumItemCC.PremiumItem | itemCategory←ItemCategoryCC.Category
|
||||
// itemViewCategory←ItemViewCategoryCC.Category | buyable←BuyableCC.Buyable
|
||||
// availableForAll←AvailableForAllCC | discount←DiscountCC | timePeriod←TimePeriodModelCC
|
||||
// modification←ModificationCC(baseItemId=Field1, level=ModificationIndex)
|
||||
// properties←ItemPropertiesCC | devices←ItemDevicesCC | count←CountableItemCC.Field1
|
||||
// kit←GarageKitCC | countable←CountableItemCC 是否存在 | mountIndex←调用点下标(目录里为 0)
|
||||
// availableSkins←AvailableSkinsCC | availableShotSkins←AvailableShotSkinsCC
|
||||
// mountedSkin←MountedSkinCC(834829861153964627) | mountedShotSkin←MountedSkinCC(905970599512839002)
|
||||
// skinPreview←SkinPreviewCC | grouped←GroupedCC | rarity←ItemRarityCC.Rarity
|
||||
// resistanceBackgroundImg←ResistanceBackgroundCC | visible←VisibleCC.Visible
|
||||
// descriptionMedia←DescriptionMediaCC | saleByKitItems←ItemSaleByKitCC
|
||||
// isSellingForCoin/Crystal/Ruby 在原包传 `Ct`(未提供),这里保持 null。
|
||||
//
|
||||
// 装置字段对应(`gct`,new GarageDeviceObject(...)):
|
||||
// id←对象标记 | baseItemId←容器级 ModificationCC.Field1(组里没有则 0)
|
||||
// temporaryItemCC←TemporaryItemCC | description←DescriptionModelCC | item←ItemModelCC
|
||||
// isPremium←PremiumItemCC | itemCategory←ItemCategoryCC | itemViewCategory←ItemViewCategoryCC
|
||||
// buyable←BuyableCC | discount←DiscountCC | timePeriod←TimePeriodModelCC
|
||||
// deviceProperty←DevicePropertiesCC | rarity←ItemRarityCC | visible←VisibleCC
|
||||
// descriptionMedia←DescriptionMediaCC
|
||||
package App.Session
|
||||
|
||||
import App.State.GarageDeviceObject
|
||||
import App.State.GarageItemModification
|
||||
import App.State.GarageItemObject
|
||||
import Net.Generated.AvailableForAllCC
|
||||
import Net.Generated.AvailableShotSkinsCC
|
||||
import Net.Generated.AvailableSkinsCC
|
||||
import Net.Generated.BuyableCC
|
||||
import Net.Generated.CountableItemCC
|
||||
import Net.Generated.DescriptionMediaCC
|
||||
import Net.Generated.DescriptionModelCC
|
||||
import Net.Generated.DevicePropertiesCC
|
||||
import Net.Generated.DiscountCC
|
||||
import Net.Generated.GarageKitCC
|
||||
import Net.Generated.GroupedCC
|
||||
import Net.Generated.ItemCategoryCC
|
||||
import Net.Generated.ItemDevicesCC
|
||||
import Net.Generated.ItemModelCC
|
||||
import Net.Generated.ItemPropertiesCC
|
||||
import Net.Generated.ItemRarityCC
|
||||
import Net.Generated.ItemSaleByKitCC
|
||||
import Net.Generated.ItemViewCategoryCC
|
||||
import Net.Generated.ModificationCC
|
||||
import Net.Generated.MountedSkinCC
|
||||
import Net.Generated.PremiumItemCC
|
||||
import Net.Generated.ResistanceBackgroundCC
|
||||
import Net.Generated.SkinPreviewCC
|
||||
import Net.Generated.TemporaryItemCC
|
||||
import Net.Generated.TimePeriodModelCC
|
||||
import Net.Generated.VisibleCC
|
||||
import Net.Protocol.PtPayload
|
||||
|
||||
/** 目录模型的 modelId(来源:names/model_registry.json)。 */
|
||||
object CatalogModelIds {
|
||||
const val CountableItem = 120961863156462946L
|
||||
const val ItemProperties = 4245000165576407500L
|
||||
const val ItemSaleByKit = 4309274349580876968L
|
||||
const val Buyable = 2769268442698022653L
|
||||
const val TimePeriod = 8032192927455575509L
|
||||
const val ItemModel = 3438505192580052999L
|
||||
const val ItemRarity = 658797348514407988L
|
||||
const val DescriptionModel = 3935107155251354407L
|
||||
const val ItemCategory = 2114179554921095892L
|
||||
const val PremiumItem = 1139677084511624062L
|
||||
const val ItemViewCategory = 6117306895090150422L
|
||||
const val DescriptionMedia = 5952355564848177159L
|
||||
const val Visible = 5738770490413536673L
|
||||
|
||||
const val AvailableForAll = 6589716392600418185L
|
||||
const val Discount = 2951667042968033849L
|
||||
const val Modification = 2494628067134376039L
|
||||
const val UpgradeParams = 4743567393313674375L
|
||||
const val ItemDevices = 7391892068905080676L
|
||||
const val GarageKit = 5219530271535770658L
|
||||
const val AvailableSkins = 5207857306014573244L
|
||||
const val AvailableShotSkins = 1164458258646872337L
|
||||
const val MountedSkin = 834829861153964627L
|
||||
const val MountedShotSkin = 905970599512839002L
|
||||
const val SkinPreview = 6680653332718076818L
|
||||
const val Grouped = 1865478986390468300L
|
||||
const val ResistanceBackground = 6628468327090974523L
|
||||
|
||||
const val DeviceProperties = 7640081207058999117L
|
||||
const val TemporaryItem = 3893855999545616334L
|
||||
|
||||
/** 物品组只要出现其中任意一个模型,就按物品目录处理。 */
|
||||
val ItemGroupMarkers: Set<Long> = setOf(
|
||||
ItemModel, ItemCategory, Buyable, DescriptionModel, TimePeriod, ItemRarity,
|
||||
PremiumItem, ItemViewCategory,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 静态物品目录:`Pt` 容器里按「对象」分组后,把 CC 组合成 `GarageItemObject` / `GarageDeviceObject`。
|
||||
*
|
||||
* 同一个 modelId 可能随对象重复出现(每个对象一份),所以目录以对象 id 为键。
|
||||
*/
|
||||
class ItemCatalog {
|
||||
|
||||
val Items: MutableMap<Long, GarageItemObject> = LinkedHashMap()
|
||||
val Devices: MutableMap<Long, GarageDeviceObject> = LinkedHashMap()
|
||||
|
||||
/** 被识别并吸收的 Pt 项数。 */
|
||||
var ConsumedItems: Int = 0
|
||||
private set
|
||||
|
||||
/** 已识别的对象组数(物品 + 装置)。 */
|
||||
var Groups: Int = 0
|
||||
private set
|
||||
|
||||
/** 不是目录的对象组数(例如车库配置对象:PassToShopCC / TemperatureCC …)。 */
|
||||
var SkippedGroups: Int = 0
|
||||
private set
|
||||
|
||||
/** 组里既不是物品也不是装置的模型名,用于诊断未识别目录。 */
|
||||
val SkippedModels: MutableMap<String, Int> = LinkedHashMap()
|
||||
|
||||
/**
|
||||
* 尝试吸收一个 Pt 容器。
|
||||
*
|
||||
* @return 与 `Payload.Items` 等长的「已吸收」标记;完全不是目录容器时返回 null。
|
||||
*/
|
||||
fun Ingest(Payload: PtPayload): BooleanArray? {
|
||||
val Raw = Payload.Items
|
||||
if (Raw.isEmpty()) return null
|
||||
val Consumed = BooleanArray(Raw.size)
|
||||
var Any = false
|
||||
|
||||
var Start = -1
|
||||
fun Flush(Begin: Int, End: Int) {
|
||||
if (Begin < 0) return
|
||||
val Zero = Raw[Begin].Value as? Long
|
||||
val Models = HashMap<Long, Any>(16)
|
||||
var I = Begin + 1
|
||||
while (I < End) {
|
||||
val Id = Raw[I].Id
|
||||
if (Id != 0L) Models[Id] = Raw[I].Value
|
||||
I++
|
||||
}
|
||||
if (Models.isEmpty()) return
|
||||
val ObjectId = Zero ?: 0L
|
||||
val IsDevice = Models.containsKey(CatalogModelIds.DeviceProperties) ||
|
||||
Models.containsKey(CatalogModelIds.TemporaryItem)
|
||||
val IsItem = CatalogModelIds.ItemGroupMarkers.any { Models.containsKey(it) }
|
||||
if (IsDevice) {
|
||||
Devices[ObjectId] = MakeDevice(ObjectId, Models)
|
||||
Mark(Consumed, Begin, End)
|
||||
Groups++
|
||||
Any = true
|
||||
} else if (IsItem) {
|
||||
Items[ObjectId] = MakeItem(ObjectId, Models)
|
||||
Mark(Consumed, Begin, End)
|
||||
Groups++
|
||||
Any = true
|
||||
} else {
|
||||
SkippedGroups++
|
||||
for (Name in Models.keys) {
|
||||
val Text = App.State.ModelNamesByModelId[Name] ?: Name.toString()
|
||||
SkippedModels[Text] = (SkippedModels[Text] ?: 0) + 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (I in Raw.indices) {
|
||||
if (Raw[I].Id != 0L) continue
|
||||
if (Start >= 0) Flush(Start, I)
|
||||
Start = I
|
||||
}
|
||||
if (Start >= 0) Flush(Start, Raw.size)
|
||||
if (!Any) return null
|
||||
ConsumedItems += Consumed.count { it }
|
||||
return Consumed
|
||||
}
|
||||
|
||||
private fun Mark(Consumed: BooleanArray, Start: Int, End: Int) {
|
||||
for (I in Start until End) Consumed[I] = true
|
||||
}
|
||||
|
||||
private fun MakeItem(Id: Long, Models: Map<Long, Any>): GarageItemObject {
|
||||
val Modification = Models[CatalogModelIds.Modification] as? ModificationCC
|
||||
val Countable = Models[CatalogModelIds.CountableItem] as? CountableItemCC
|
||||
return GarageItemObject(
|
||||
id = Id,
|
||||
description = Models[CatalogModelIds.DescriptionModel],
|
||||
item = Models[CatalogModelIds.ItemModel],
|
||||
isPremium = (Models[CatalogModelIds.PremiumItem] as? PremiumItemCC)?.PremiumItem ?: false,
|
||||
itemCategory = (Models[CatalogModelIds.ItemCategory] as? ItemCategoryCC)?.Category ?: 0,
|
||||
itemViewCategory = (Models[CatalogModelIds.ItemViewCategory] as? ItemViewCategoryCC)?.Category ?: 0,
|
||||
buyable = (Models[CatalogModelIds.Buyable] as? BuyableCC)?.Buyable ?: false,
|
||||
availableForAll = (Models[CatalogModelIds.AvailableForAll] as? AvailableForAllCC)?.AvailableForAll ?: false,
|
||||
discount = Models[CatalogModelIds.Discount],
|
||||
timePeriod = Models[CatalogModelIds.TimePeriod],
|
||||
modification = Modification?.let {
|
||||
GarageItemModification(vcf_1 = it.Field1, xcf_1 = it.ModificationIndex.toInt())
|
||||
},
|
||||
properties = Models[CatalogModelIds.ItemProperties],
|
||||
upgradeableParams = null,
|
||||
devices = Models[CatalogModelIds.ItemDevices],
|
||||
count = Countable?.Field1 ?: 0,
|
||||
kit = Models[CatalogModelIds.GarageKit] as? GarageKitCC,
|
||||
countable = Countable != null,
|
||||
mountIndex = 0,
|
||||
availableSkins = Models[CatalogModelIds.AvailableSkins] as? AvailableSkinsCC,
|
||||
availableShotSkins = Models[CatalogModelIds.AvailableShotSkins] as? AvailableShotSkinsCC,
|
||||
mountedSkin = Models[CatalogModelIds.MountedSkin] as? MountedSkinCC,
|
||||
mountedShotSkin = Models[CatalogModelIds.MountedShotSkin] as? MountedSkinCC,
|
||||
skinPreview = Models[CatalogModelIds.SkinPreview] as? SkinPreviewCC,
|
||||
grouped = Models[CatalogModelIds.Grouped] as? GroupedCC,
|
||||
rarity = (Models[CatalogModelIds.ItemRarity] as? ItemRarityCC)?.Rarity,
|
||||
favorite = false,
|
||||
isSellingForCoin = null,
|
||||
isSellingForCrystal = null,
|
||||
isSellingForRuby = null,
|
||||
resistanceBackgroundImg = Models[CatalogModelIds.ResistanceBackground] as? ResistanceBackgroundCC,
|
||||
visible = (Models[CatalogModelIds.Visible] as? VisibleCC)?.Visible ?: true,
|
||||
descriptionMedia = Models[CatalogModelIds.DescriptionMedia] as? DescriptionMediaCC,
|
||||
saleByKitItems = Models[CatalogModelIds.ItemSaleByKit] as? ItemSaleByKitCC,
|
||||
)
|
||||
}
|
||||
|
||||
private fun MakeDevice(Id: Long, Models: Map<Long, Any>): GarageDeviceObject {
|
||||
val Modification = Models[CatalogModelIds.Modification] as? ModificationCC
|
||||
return GarageDeviceObject(
|
||||
id = Id,
|
||||
baseItemId = Modification?.Field1 ?: 0L,
|
||||
temporaryItemCC = Models[CatalogModelIds.TemporaryItem] as? TemporaryItemCC,
|
||||
description = Models[CatalogModelIds.DescriptionModel],
|
||||
item = Models[CatalogModelIds.ItemModel],
|
||||
isPremium = (Models[CatalogModelIds.PremiumItem] as? PremiumItemCC)?.PremiumItem ?: false,
|
||||
itemCategory = (Models[CatalogModelIds.ItemCategory] as? ItemCategoryCC)?.Category ?: 0,
|
||||
itemViewCategory = (Models[CatalogModelIds.ItemViewCategory] as? ItemViewCategoryCC)?.Category ?: 0,
|
||||
buyable = (Models[CatalogModelIds.Buyable] as? BuyableCC)?.Buyable ?: false,
|
||||
discount = Models[CatalogModelIds.Discount],
|
||||
timePeriod = Models[CatalogModelIds.TimePeriod],
|
||||
deviceProperty = Models[CatalogModelIds.DeviceProperties] as? DevicePropertiesCC,
|
||||
rarity = (Models[CatalogModelIds.ItemRarity] as? ItemRarityCC)?.Rarity,
|
||||
visible = (Models[CatalogModelIds.Visible] as? VisibleCC)?.Visible ?: true,
|
||||
descriptionMedia = Models[CatalogModelIds.DescriptionMedia] as? DescriptionMediaCC,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -78,6 +78,10 @@ object SessionCheck {
|
||||
var Bad = 0
|
||||
var HeaderErrors = 0
|
||||
var Errors = 0
|
||||
var PtRecords = 0
|
||||
var PtItems = 0
|
||||
var PtMaxItems = 0
|
||||
val PtSample = ArrayList<String>()
|
||||
val Methods = LinkedHashMap<Long, Int>()
|
||||
|
||||
for (Path in Files) {
|
||||
@@ -95,11 +99,47 @@ object SessionCheck {
|
||||
for (R in List) {
|
||||
Methods[R.MethodId] = (Methods[R.MethodId] ?: 0) + 1
|
||||
if (R.Payload.contentEquals(R.Reencoded)) Ok++ else Bad++
|
||||
val V = R.Value
|
||||
if (V is Net.Protocol.PtPayload) {
|
||||
PtRecords++
|
||||
PtItems += V.Items.size
|
||||
if (V.Items.size > PtMaxItems) PtMaxItems = V.Items.size
|
||||
if (PtSample.size < 3) {
|
||||
PtSample.add(
|
||||
"obj=${V.Objects.size},items=${V.Items.size},ids=" +
|
||||
V.Items.take(16).joinToString(",") { it.Id.toString() }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Router.RouteAll(List)
|
||||
}
|
||||
|
||||
println("文件 $Frames|记录 $Records|回编码一致 $Ok|不一致 $Bad|记录头截断 $HeaderErrors|其它错误 $Errors|别名表=${Session.AliasCount}")
|
||||
println("Pt 容器 $PtRecords 条|项 $PtItems|单条最多 $PtMaxItems")
|
||||
for (S in PtSample) println(" pt 样本:$S")
|
||||
println(
|
||||
"目录:物品 ${Router.Catalog.Items.size}|装置 ${Router.Catalog.Devices.size}" +
|
||||
"|吸收项 ${Router.Cataloged}|跳过组 ${Router.Catalog.SkippedGroups}"
|
||||
)
|
||||
if (Router.Catalog.SkippedModels.isNotEmpty()) {
|
||||
val TopSkip = Router.Catalog.SkippedModels.entries.sortedByDescending { it.value }.take(6)
|
||||
println("目录跳过模型:" + TopSkip.joinToString(",") { "${it.key}×${it.value}" })
|
||||
}
|
||||
for (S in Router.Catalog.Items.values.take(3)) {
|
||||
val D = S.description as? Net.Generated.DescriptionModelCC
|
||||
println(
|
||||
" 物品样本:id=${S.id}|name=${D?.Name}|category=${S.itemCategory}|view=${S.itemViewCategory}" +
|
||||
"|premium=${S.isPremium}|count=${S.count}|rarity=${S.rarity}"
|
||||
)
|
||||
}
|
||||
for (S in Router.Catalog.Devices.values.take(2)) {
|
||||
val D = S.description as? Net.Generated.DescriptionModelCC
|
||||
println(
|
||||
" 装置样本:id=${S.id}|base=${S.baseItemId}|name=${D?.Name}" +
|
||||
"|category=${S.itemCategory}|rarity=${S.rarity}"
|
||||
)
|
||||
}
|
||||
println("路由:已派发 ${Router.Applied}|未覆盖 ${Router.Unmapped}|失败 ${Router.Failed}|用户=${Router.Store.State.User.Uid}|屏幕=${Router.Store.State.Screen.Current}")
|
||||
val TopModels = Router.UnmappedModels.entries.sortedByDescending { it.value }.take(8)
|
||||
if (TopModels.isNotEmpty()) {
|
||||
@@ -114,7 +154,7 @@ object SessionCheck {
|
||||
println("高频 methodId:" + Top.joinToString(",") { "${it.key}×${it.value}" })
|
||||
}
|
||||
// 抓包目录里混有入口/握手帧,解不出记录是正常现象;只要所有解出的记录都能回编码即可。
|
||||
val Passed = Bad == 0 && Records > 0
|
||||
val Passed = Bad == 0 && Records > 0 && Router.Catalog.Items.isNotEmpty()
|
||||
println(if (Passed) "结果:通过" else "结果:失败")
|
||||
ExitSession(if (Passed) 0 else 1)
|
||||
}
|
||||
|
||||
@@ -17,8 +17,13 @@ class SessionRouter(InitialState: RootState = RootState()) {
|
||||
|
||||
val Store: ReduxStore<RootState> = ReduxStore(InitialState, ::ReduceRoot)
|
||||
|
||||
/** 静态物品目录:吸收 Pt 容器里的物品 / 装置 CC 组,不进 Redux 状态。 */
|
||||
val Catalog: ItemCatalog = ItemCatalog()
|
||||
|
||||
var Applied: Int = 0
|
||||
private set
|
||||
var Cataloged: Int = 0
|
||||
private set
|
||||
var Unmapped: Int = 0
|
||||
private set
|
||||
var Failed: Int = 0
|
||||
@@ -39,7 +44,12 @@ class SessionRouter(InitialState: RootState = RootState()) {
|
||||
val Value = Record.Value
|
||||
if (Value is PtPayload) {
|
||||
var Last: Any? = null
|
||||
for (Item in Value.Items) {
|
||||
val Consumed = Catalog.Ingest(Value)
|
||||
for ((Index, Item) in Value.Items.withIndex()) {
|
||||
if (Consumed != null && Consumed[Index]) {
|
||||
Cataloged++
|
||||
continue
|
||||
}
|
||||
val MakeModel = DownlinkModelActions[Item.Id]
|
||||
if (MakeModel == null) {
|
||||
Unmapped++
|
||||
|
||||
Reference in new issue
Block a user