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