ygopro-msg-encode 1.1.17 → 1.1.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/OPPONENTVIEW_FIXES.md +131 -0
- package/dist/index.cjs +16 -42
- package/dist/index.cjs.map +2 -2
- package/dist/index.mjs +16 -42
- package/dist/index.mjs.map +2 -2
- package/dist/src/protos/msg/proto/confirm-decktop.d.ts +0 -1
- package/dist/src/protos/msg/proto/confirm-extratop.d.ts +0 -1
- package/dist/src/protos/msg/proto/deck-top.d.ts +0 -1
- package/package.json +1 -1
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# OpponentView 实现修复总结
|
|
2
|
+
|
|
3
|
+
## 已修复的问题
|
|
4
|
+
|
|
5
|
+
### 1. MSG_SHUFFLE_EXTRA (shuffle-extra.ts)
|
|
6
|
+
|
|
7
|
+
**问题**:只遮掩了非公开的卡片(没有 0x80000000 标记的)
|
|
8
|
+
|
|
9
|
+
**正确实现**:应该全部遮掩,无论是否有公开标记
|
|
10
|
+
|
|
11
|
+
**对照源码**:`single_duel.cpp` 第 1163-1179 行
|
|
12
|
+
```cpp
|
|
13
|
+
for (int i = 0; i < count; ++i)
|
|
14
|
+
BufferIO::Write<int32_t>(pbuf, 0); // 全部遮掩
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
**修复**:
|
|
18
|
+
```typescript
|
|
19
|
+
// 修复前
|
|
20
|
+
view.cards = view.cards.map((card) => {
|
|
21
|
+
if (!(card & 0x80000000)) {
|
|
22
|
+
return 0;
|
|
23
|
+
}
|
|
24
|
+
return card;
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// 修复后
|
|
28
|
+
view.cards = view.cards.map(() => 0); // 全部遮掩
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
### 2. MSG_TAG_SWAP (tag-swap.ts)
|
|
34
|
+
|
|
35
|
+
**问题**:`handCards` 全部遮掩,但应该只遮掩非公开的(类似 `extraCards`)
|
|
36
|
+
|
|
37
|
+
**正确实现**:手牌和额外卡组都应该只遮掩没有 0x80000000 标记的卡片
|
|
38
|
+
|
|
39
|
+
**对照源码**:`tag_duel.cpp` 第 1932-1960 行
|
|
40
|
+
```cpp
|
|
41
|
+
// 对手牌的处理
|
|
42
|
+
for (int i = 0; i < hcount; ++i) {
|
|
43
|
+
if(!(pbufw[3] & 0x80)) // 检查 0x80000000
|
|
44
|
+
BufferIO::Write<int32_t>(pbufw, 0); // 非公开的遮掩
|
|
45
|
+
else
|
|
46
|
+
pbufw += 4; // 公开的保留
|
|
47
|
+
}
|
|
48
|
+
// 对额外卡组的处理(同样逻辑)
|
|
49
|
+
for (int i = 0; i < ecount; ++i) {
|
|
50
|
+
if(!(pbufw[3] & 0x80))
|
|
51
|
+
BufferIO::Write<int32_t>(pbufw, 0);
|
|
52
|
+
else
|
|
53
|
+
pbufw += 4;
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**修复**:
|
|
58
|
+
```typescript
|
|
59
|
+
// 修复前
|
|
60
|
+
view.handCards = view.handCards.map(() => 0); // 全部遮掩
|
|
61
|
+
|
|
62
|
+
// 修复后
|
|
63
|
+
view.handCards = view.handCards.map((card) => {
|
|
64
|
+
if (!(card & 0x80000000)) {
|
|
65
|
+
return 0; // 只遮掩非公开的
|
|
66
|
+
}
|
|
67
|
+
return card; // 保留公开的
|
|
68
|
+
});
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## 其他修复
|
|
74
|
+
|
|
75
|
+
### 3. MSG_CONFIRM_DECKTOP / MSG_CONFIRM_EXTRATOP / MSG_DECK_TOP
|
|
76
|
+
|
|
77
|
+
**问题**:项目中实现了 `opponentView` 遮掩逻辑,但 YGOPro 源码中这些消息不做遮掩
|
|
78
|
+
|
|
79
|
+
**正确实现**:移除 `opponentView` 方法,使用基类的默认实现(不遮掩)
|
|
80
|
+
|
|
81
|
+
**对照源码**:`single_duel.cpp` 第 1089-1224 行
|
|
82
|
+
|
|
83
|
+
这些消息在源码中**直接发给所有人,不做遮掩**:
|
|
84
|
+
```cpp
|
|
85
|
+
// MSG_CONFIRM_DECKTOP
|
|
86
|
+
NetServer::SendBufferToPlayer(players[0], STOC_GAME_MSG, offset, pbuf - offset);
|
|
87
|
+
NetServer::ReSendToPlayer(players[1]); // 直接转发,无遮掩
|
|
88
|
+
|
|
89
|
+
// MSG_CONFIRM_EXTRATOP (相同处理)
|
|
90
|
+
// MSG_DECK_TOP (相同处理)
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**原因**:ocgcore 在生成这些消息时,已经通过 `0x80000000` 标记控制了哪些内容是公开的。网络层直接转发,不需要额外遮掩。
|
|
94
|
+
|
|
95
|
+
**修复**:移除了这些消息的 `opponentView` 方法,使用基类的默认实现(直接返回 copy)。
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## 0x80000000 标记的语义
|
|
100
|
+
|
|
101
|
+
在 YGOPro 中,`0x80000000` 标记用于表示"公开"状态:
|
|
102
|
+
|
|
103
|
+
- **有标记**:这张卡是公开的,所有人都能看到
|
|
104
|
+
- **无标记**:这张卡是非公开的,需要根据玩家身份决定是否遮掩
|
|
105
|
+
|
|
106
|
+
**源码示例**(ocgcore/field.cpp):
|
|
107
|
+
```cpp
|
|
108
|
+
pduel->write_buffer32(pcard->data.code | (pcard->is_position(POS_FACEUP) ? 0x80000000 : 0));
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## 验证方法
|
|
114
|
+
|
|
115
|
+
对照 YGOPro 源代码:
|
|
116
|
+
- **单人决斗**:`/home/nanahira/ygo/ygopro/gframe/single_duel.cpp`
|
|
117
|
+
- **TAG 决斗**:`/home/nanahira/ygo/ygopro/gframe/tag_duel.cpp`
|
|
118
|
+
- **核心逻辑**:`/home/nanahira/ygo/ygopro/ocgcore/`
|
|
119
|
+
|
|
120
|
+
关键函数:
|
|
121
|
+
- `RefreshHand()`: 刷新手牌
|
|
122
|
+
- `RefreshMzone()`: 刷新怪兽区
|
|
123
|
+
- `RefreshSzone()`: 刷新魔陷区
|
|
124
|
+
- `RefreshExtra()`: 刷新额外卡组
|
|
125
|
+
- `RefreshSingle()`: 刷新单张卡片
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## 修复日期
|
|
130
|
+
|
|
131
|
+
2026-02-14
|
package/dist/index.cjs
CHANGED
|
@@ -3363,19 +3363,9 @@ __decorateClass([
|
|
|
3363
3363
|
], _YGOProMsgConfirmDeckTop_CardInfo.prototype, "sequence", 2);
|
|
3364
3364
|
var YGOProMsgConfirmDeckTop_CardInfo = _YGOProMsgConfirmDeckTop_CardInfo;
|
|
3365
3365
|
var _YGOProMsgConfirmDeckTop = class _YGOProMsgConfirmDeckTop extends YGOProMsgBase {
|
|
3366
|
-
//
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
view.cards = view.cards.map((card) => {
|
|
3370
|
-
const c = { ...card };
|
|
3371
|
-
if (!(c.code & 2147483648)) {
|
|
3372
|
-
c.code = 0;
|
|
3373
|
-
}
|
|
3374
|
-
return c;
|
|
3375
|
-
});
|
|
3376
|
-
return view;
|
|
3377
|
-
}
|
|
3378
|
-
// confirm-decktop 使用基类的 playerView (基于 player 字段)
|
|
3366
|
+
// MSG_CONFIRM_DECKTOP 在 single_duel.cpp 中不做遮掩,直接发给所有人
|
|
3367
|
+
// ocgcore 通过 0x80000000 标记控制公开状态
|
|
3368
|
+
// 因此使用基类的默认实现(不遮掩)
|
|
3379
3369
|
};
|
|
3380
3370
|
__name(_YGOProMsgConfirmDeckTop, "YGOProMsgConfirmDeckTop");
|
|
3381
3371
|
_YGOProMsgConfirmDeckTop.identifier = OcgcoreCommonConstants.MSG_CONFIRM_DECKTOP;
|
|
@@ -3408,19 +3398,9 @@ __decorateClass([
|
|
|
3408
3398
|
], _YGOProMsgConfirmExtraTop_CardInfo.prototype, "sequence", 2);
|
|
3409
3399
|
var YGOProMsgConfirmExtraTop_CardInfo = _YGOProMsgConfirmExtraTop_CardInfo;
|
|
3410
3400
|
var _YGOProMsgConfirmExtraTop = class _YGOProMsgConfirmExtraTop extends YGOProMsgBase {
|
|
3411
|
-
//
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
view.cards = view.cards.map((card) => {
|
|
3415
|
-
const c = { ...card };
|
|
3416
|
-
if (!(c.code & 2147483648)) {
|
|
3417
|
-
c.code = 0;
|
|
3418
|
-
}
|
|
3419
|
-
return c;
|
|
3420
|
-
});
|
|
3421
|
-
return view;
|
|
3422
|
-
}
|
|
3423
|
-
// confirm-extratop 使用基类的 playerView (基于 player 字段)
|
|
3401
|
+
// MSG_CONFIRM_EXTRATOP 在 single_duel.cpp 中不做遮掩,直接发给所有人
|
|
3402
|
+
// ocgcore 通过 0x80000000 标记控制公开状态
|
|
3403
|
+
// 因此使用基类的默认实现(不遮掩)
|
|
3424
3404
|
};
|
|
3425
3405
|
__name(_YGOProMsgConfirmExtraTop, "YGOProMsgConfirmExtraTop");
|
|
3426
3406
|
_YGOProMsgConfirmExtraTop.identifier = OcgcoreCommonConstants.MSG_CONFIRM_EXTRATOP;
|
|
@@ -3476,15 +3456,9 @@ var YGOProMsgDamageStepStart = _YGOProMsgDamageStepStart;
|
|
|
3476
3456
|
|
|
3477
3457
|
// src/protos/msg/proto/deck-top.ts
|
|
3478
3458
|
var _YGOProMsgDeckTop = class _YGOProMsgDeckTop extends YGOProMsgBase {
|
|
3479
|
-
//
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
if (!(view.code & 2147483648)) {
|
|
3483
|
-
view.code = 0;
|
|
3484
|
-
}
|
|
3485
|
-
return view;
|
|
3486
|
-
}
|
|
3487
|
-
// deck-top 使用基类的 playerView (基于 player 字段)
|
|
3459
|
+
// MSG_DECK_TOP 在 single_duel.cpp 中不做遮掩,直接发给所有人
|
|
3460
|
+
// ocgcore 通过 0x80000000 标记控制公开状态
|
|
3461
|
+
// 因此使用基类的默认实现(不遮掩)
|
|
3488
3462
|
};
|
|
3489
3463
|
__name(_YGOProMsgDeckTop, "YGOProMsgDeckTop");
|
|
3490
3464
|
_YGOProMsgDeckTop.identifier = OcgcoreCommonConstants.MSG_DECK_TOP;
|
|
@@ -5295,12 +5269,7 @@ var _YGOProMsgShuffleExtra = class _YGOProMsgShuffleExtra extends YGOProMsgBase
|
|
|
5295
5269
|
// 对方视角需要隐藏额外卡组信息
|
|
5296
5270
|
opponentView() {
|
|
5297
5271
|
const view = this.copy();
|
|
5298
|
-
view.cards = view.cards.map((
|
|
5299
|
-
if (!(card & 2147483648)) {
|
|
5300
|
-
return 0;
|
|
5301
|
-
}
|
|
5302
|
-
return card;
|
|
5303
|
-
});
|
|
5272
|
+
view.cards = view.cards.map(() => 0);
|
|
5304
5273
|
return view;
|
|
5305
5274
|
}
|
|
5306
5275
|
};
|
|
@@ -5675,7 +5644,12 @@ var _YGOProMsgTagSwap = class _YGOProMsgTagSwap extends YGOProMsgBase {
|
|
|
5675
5644
|
// 对方和队友视角需要隐藏手牌和额外卡组信息
|
|
5676
5645
|
opponentView() {
|
|
5677
5646
|
const view = this.copy();
|
|
5678
|
-
view.handCards = view.handCards.map(() =>
|
|
5647
|
+
view.handCards = view.handCards.map((card) => {
|
|
5648
|
+
if (!(card & 2147483648)) {
|
|
5649
|
+
return 0;
|
|
5650
|
+
}
|
|
5651
|
+
return card;
|
|
5652
|
+
});
|
|
5679
5653
|
view.extraCards = view.extraCards.map((card) => {
|
|
5680
5654
|
if (!(card & 2147483648)) {
|
|
5681
5655
|
return 0;
|