  货币类 vs 代币类 — 核心区别

  ┌───────────────────────┬──────────────────────────────┬───────────────────────────────────────┐
  │                       │       货币（Currency）       │             代币（Token）             │
  ├───────────────────────┼──────────────────────────────┼───────────────────────────────────────┤
  │ 举例                  │ 钻石(1)、金币(5)、友情点(15) │ 迷宫币(9)、血战筹码(12)、悬赏点(35)   │
  ├───────────────────────┼──────────────────────────────┼───────────────────────────────────────┤
  │ 存储位置              │ RoleData 字段（专用字段）    │ RoleItemData.Items 背包（通用道具格） │
  ├───────────────────────┼──────────────────────────────┼───────────────────────────────────────┤
  │ 不进背包              │ ✅ 加入 ItemsNotInPackage    │ ❌ 不用加                             │
  ├───────────────────────┼──────────────────────────────┼───────────────────────────────────────┤
  │ 需要改 CurrencyModule │ ✅ 必须加                    │ ❌ 不需要                             │
  ├───────────────────────┼──────────────────────────────┼───────────────────────────────────────┤
  │ 需要改 RoleData       │ ✅ 需要加字段                │ ❌ 不需要                             │
  ├───────────────────────┼──────────────────────────────┼───────────────────────────────────────┤
  │ 客户端同步            │ 通过 SyncClientRoleDataType  │ 通过背包增量同步                      │
  └───────────────────────┴──────────────────────────────┴───────────────────────────────────────┘

  ---
  一、新增货币类道具（如新货币）

  步骤 1：item.xlsx 新增一行

  Id=36, ItemType=1(Currency), ItemName=XX货币, Stack=0, AutoUse=0

  步骤 2：iteminstance.xlsx 新增捆绑实例

  InstanceId=3600, ItemId=36, ItemType=1

  步骤 3：ItemDefines.cs 新增 ID 常量 + 加入 ItemsNotInPackage

  文件：server/src/server/OpenCards.Server.Logic/Module/Item/ItemDefines.cs

  public static int NewCurrencyItemId = 36; // 新货币

  public static List<int> ItemsNotInPackage = new List<int>(){
      DiamondItemId, FreeDiamondItemId, CoinItemId, VipExpItemId,
      FreeVipExpItemId, HeroExpItemId, FriendPointId, RoleExpId,
      NewCurrencyItemId  // ← 加这里
  };

  步骤 4：RoleData.cs 新增存储字段

  文件：server/src/core/OpenCards.Core/ORM/RoleData.cs

  [PersistField]
  [SyncClientData(SyncClientRoleDataType.NewCurrency)]  // 如需客户端实时同步
  public int NewCurrency;

  步骤 5：0x35300.Logic.Role.cs 新增同步枚举值

  文件：server/src/core/OpenCards.Core/Protocol/Client/0x35300.Logic.Role.cs

  public enum SyncClientRoleDataType
  {
      // ... 现有值 ...
      PresetHeroSelect2 = 45,
      NewCurrency = 46,  // ← 新增
  }

  步骤 6：CurrencyModule.cs 新增增删查逻辑

  文件：server/src/server/OpenCards.Server.Logic/Module/CurrencyModule.cs

  在 OnEventAddItemImp 中加：
  else if (itemInstance.ItemId == ItemDefines.NewCurrencyItemId)
  {
      if (ItemDefines.ItemsNotInPackage.Contains(itemInstance.ItemId))
      {
          beforeItemJObject.Add(EventTrackPropertyDefines.ResourceID, itemInstance.ItemId);
          beforeItemJObject.Add(EventTrackPropertyDefines.ResourceName, itemName);
          beforeItemJObject.Add(EventTrackPropertyDefines.ResourceNum, roleModule.roleDataMapping.NewCurrency);
          needDig = true;
      }
      roleModule.roleDataMapping.NewCurrency += itemInstance.Count;
  }

  在 OnEventRemoveItem 中加：
  else if (itemid == ItemDefines.NewCurrencyItemId)
  {
      if (ItemDefines.ItemsNotInPackage.Contains(itemid))
          beforeItemJObject.Add(EventTrackPropertyDefines.ResourceNum, roleDataMapping.NewCurrency);
      if (roleModule.roleDataMapping.NewCurrency < count)
          success.value = false;
      else
      {
          roleModule.roleDataMapping.NewCurrency -= count;
          success.value = true;
      }
  }

  在 OnEventGetItemCount 中加：
  else if (itemid == ItemDefines.NewCurrencyItemId)
  {
      count.value = roleDataMapping.NewCurrency;
  }

  ---
  二、新增代币类道具（不进背包，但走通用背包存储）

  代币比货币简单得多，只需要配置表 + 常量，不需要改 CurrencyModule 和 RoleData。

  步骤 1：item.xlsx 新增一行

  Id=37, ItemType=3(Token), ItemName=XX代币, Stack=999999, AutoUse=0

  步骤 2：iteminstance.xlsx 新增捆绑实例

  InstanceId=3700, ItemId=37, ItemType=1

  步骤 3：ItemDefines.cs 新增 ID 常量（不加 ItemsNotInPackage）

  public static int NewTokenItemId = 37; // 新代币（走背包存储）

  步骤 4：业务代码中使用

  发放：
  DispatchEvent(EventDefines.EventAddItem,
      新的ItemInstanceId,  // iteminstance.xlsx 中的 InstanceId
      count,
      AddItemReason.YourReason, 0, LogicUtils.FileLine);

  查询数量：
  Ref<long> count = new Ref<long>();
  DispatchEvent(EventDefines.EventGetItemCount, ItemDefines.NewTokenItemId, count);

  扣除：
  Ref<bool> success = new Ref<bool>();
  DispatchEvent(EventDefines.EventRemoveItem, ItemDefines.NewTokenItemId,
      amount, RemoveItemReason.YourReason, 0, LogicUtils.FileLine, success);

  ---
  总结对比

  ┌────────────────────────┬───────────────┬───────────┐
  │         修改点         │    货币类     │  代币类   │
  ├────────────────────────┼───────────────┼───────────┤
  │ item.xlsx              │ ✅            │ ✅        │
  ├────────────────────────┼───────────────┼───────────┤
  │ iteminstance.xlsx      │ ✅            │ ✅        │
  ├────────────────────────┼───────────────┼───────────┤
  │ ItemDefines.cs 常量    │ ✅            │ ✅        │
  ├────────────────────────┼───────────────┼───────────┤
  │ ItemsNotInPackage      │ ✅ 必须加     │ ❌ 不加   │
  ├────────────────────────┼───────────────┼───────────┤
  │ RoleData.cs 新字段     │ ✅ 必须加     │ ❌ 不需要 │
  ├────────────────────────┼───────────────┼───────────┤
  │ SyncClientRoleDataType │ ✅ 新增枚举   │ ❌ 不需要 │
  ├────────────────────────┼───────────────┼───────────┤
  │ CurrencyModule.cs      │ ✅ 三处加逻辑 │ ❌ 不需要 │
  └────────────────────────┴───────────────┴───────────┘
