IGCN物品代码大编号小编号物品查询

USE MuOnline;
GO

-- ==========================================
-- 1. 设置搜索目标 (在此修改编号)
-- ==========================================
DECLARE @SearchGroup INT = 12;  -- 目标大编号
DECLARE @SearchIndex INT = 261; -- 目标小编号

-- ==========================================
-- 2. 预计算 S16 物品特征值
-- ==========================================

-- [A] 计算第1个字节 (小编号低位)
-- 对应 Hex 字符串的第 1-2 位
-- SQL SUBSTRING 位置: 1
DECLARE @Byte0_Val INT = @SearchIndex % 256;

-- [B] 计算第8个字节 (小编号高位进位标识)
-- 对应 Hex 字符串的第 15-16 位 (下标7)
-- SQL SUBSTRING 位置: 8
-- 如果小编号 > 255,该字节的 0x80 位必须为 1
DECLARE @Byte7_FlagMask INT = CASE WHEN @SearchIndex >= 256 THEN 0x80 ELSE 0x00 END;

-- [C] 计算第10个字节 (大编号信息)
-- 对应 Hex 字符串的第 19-20 位 (下标9)
-- SQL SUBSTRING 位置: 10
-- S16规则: Group = (Byte9高4位) + (Byte9最低位 * 16)
DECLARE @Byte9_HighNibble INT = @SearchGroup % 16; -- 基础大编号 (0-15)
DECLARE @Byte9_LowBit     INT = @SearchGroup / 16; -- 扩展大编号 (16+)

-- ==========================================
-- 3. 生成物品栏游标 (通用CTE)
-- ==========================================
-- 生成 1, 33, 65... 的序列,用于切割 varbinary
-- 覆盖背包(7648)和仓库(通常3840)的长度
WITH ItemSlots AS (
    SELECT 1 AS Pos
    UNION ALL
    SELECT Pos + 32 
    FROM ItemSlots 
    WHERE Pos + 32 <= 7648 
)
-- ==========================================
-- 4. 执行联合查询 (UNION ALL)
-- ==========================================
SELECT 
    AccountID,
    RoleName,      -- 角色名 或 [公共仓库]
    SourceType,    -- 来源类型 (背包/仓库)
    FoundItemHex,  -- 物品Hex代码
    StorageSlot    -- 所在字节位置
FROM (
    -- >>> 第一部分: 查询角色背包 Character <<<
    SELECT 
        C.AccountID,
        C.Name AS RoleName,
        '角色背包' AS SourceType,
        sys.fn_varbintohexstr(SUBSTRING(C.Inventory, T.Pos, 32)) AS FoundItemHex, -- 将二进制转为文本
        T.Pos AS StorageSlot,
        C.Inventory AS DataBlock
    FROM Character C
    CROSS JOIN ItemSlots T
    WHERE C.Inventory IS NOT NULL 
      AND DATALENGTH(C.Inventory) >= T.Pos + 31

    UNION ALL

    -- >>> 第二部分: 查询战盟/仓库 Warehouse <<<
    SELECT 
        W.AccountID,
        '[仓库]' AS RoleName, -- 仓库没有角色名,手动标记
        '仓库' AS SourceType,
        sys.fn_varbintohexstr(SUBSTRING(W.Items, T.Pos, 32)) AS FoundItemHex,
        T.Pos AS StorageSlot,
        W.Items AS DataBlock
    FROM warehouse W
    CROSS JOIN ItemSlots T
    WHERE W.Items IS NOT NULL 
      AND DATALENGTH(W.Items) >= T.Pos + 31
) AS CombinedData
WHERE 
    -- [核心匹配逻辑] 必须同时满足以下3点
    
    -- 1. 匹配小编号低位 (Byte 0)
    (CAST(SUBSTRING(DataBlock, StorageSlot, 1) AS INT) = @Byte0_Val)
    
    AND 
    
    -- 2. 匹配小编号高位进位 (Byte 7 & 0x80)
    -- 注意: 这里只检查第8位是否符合进位要求,不检查该字节的其他属性(如卓越属性)
    ((CAST(SUBSTRING(DataBlock, StorageSlot + 7, 1) AS INT) & 0x80) = @Byte7_FlagMask)
    
    AND 
    
    -- 3. 匹配大编号 (Byte 9)
    -- 检查高4位 (0xF0) 是否等于 Group%16
    (((CAST(SUBSTRING(DataBlock, StorageSlot + 9, 1) AS INT) & 0xF0) / 16) = @Byte9_HighNibble)
    AND
    -- 检查最低位 (0x01) 是否等于 Group/16
    ((CAST(SUBSTRING(DataBlock, StorageSlot + 9, 1) AS INT) & 0x01) = @Byte9_LowBit)

OPTION (MAXRECURSION 300); -- 允许递归深度

PHP查询

<?php

class MuItemDecoderS16 {
    /**
     * 解析S16物品代码
     * @param string $hexString 32位或更长的16进制字符串 (例如: F7000100000000800041...)
     * @return array
     */
    public static function decode($hexString) {
        // 1. 清理输入,移除空格并转大写
        $hex = strtoupper(str_replace([' ', '0x'], '', $hexString));

        // 2. 基础校验
        if (strlen($hex) < 32) {
            return ['error' => '代码长度不足,至少需要32位字符(16字节)'];
        }

        // --- 提取关键字节 ---
        
        // 第1字节 (1-2位): 基础索引 (Index Low Byte)
        $byte0 = hexdec(substr($hex, 0, 2));

        // 第8字节 (15-16位): 卓越/扩展位 (用于判断 Index +256)
        // 注意:对应你描述中的"15-16位",在字符串中下标是14
        $byte7 = hexdec(substr($hex, 14, 2));

        // 第10字节 (19-20位): 大类信息 (Group) 和 大类扩展
        // 注意:对应你描述中的"19-20位",在字符串中下标是18
        $byte9 = hexdec(substr($hex, 18, 2));

        // --- 计算逻辑 (S16公式) ---

        // 1. 计算小编号 (Index)
        // 逻辑:基础值(Byte0) + 进位值
        // 进位判定:如果第8字节(Byte7)包含 0x80 (即128, 二进制10000000),则小编号+256
        $index = $byte0;
        if (($byte7 & 0x80) == 0x80) {
            $index += 256;
        }

        // 2. 计算大编号 (Group)
        // 逻辑:由第10字节(Byte9)的高4位和最低位决定
        // 高4位 (0xF0): 基础大编号 (0-15)
        // 最低位 (0x01): 如果是奇数,代表大编号 +16
        $groupBase = ($byte9 & 0xF0) >> 4; // 取高4位
        $groupExtra = ($byte9 & 0x01);     // 取最低位 (0或1)
        
        $group = $groupBase + ($groupExtra * 16);

        // 3. 计算S16总编号 (可选: Group * 512 + Index)
        $totalID = ($group * 512) + $index;

        return [
            'hex_input' => substr($hex, 0, 32),
            'group'     => $group,    // 大编号
            'index'     => $index,    // 小编号
            'total_id'  => $totalID   // 物品总ID
        ];
    }
}

// --- 测试区域 ---

// 1. 你的目标物品
$targetItem = "0104DC0000000000005100FFFFFFFFFF261E9EEDFFFFFFFFFFFFFFFFFFFFFFFF";
$result = MuItemDecoderS16::decode($targetItem);

echo "============== 计算结果 ==============n";
echo "物品代码: " . substr($targetItem, 0, 32) . "...n";
echo "大编号 (Group): " . $result['group'] . "n";
echo "小编号 (Index): " . $result['index'] . "n";
echo "=====================================nn";


/* // --- 验证你的其他样本 (用于自检) ---
echo "--- 样本验证 ---n";

$samples = [
    "暗黑之翼" => "0600C8000000000000C000FFFFFFFFFF", // 预期: 12, 6
    "强化恶魔" => "4000FF000000000000D000FFFFFFFFFF", // 预期: 13, 64
    "超级国王" => "5600F20000000000000105FFFFFFFFFF", // 预期: 16, 86
    "幸运宝石" => "F800010000000080004100FFFFFFFFFF", // 预期: 20, 504
];

foreach ($samples as $name => $code) {
    $res = MuItemDecoderS16::decode($code);
    echo "{$name}: 大编号={$res['group']}, 小编号={$res['index']}n";
} */
?>

 

阅读剩余
THE END