Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Y
YGOMobile
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
fallenstardust
YGOMobile
Commits
3cd073dd
Commit
3cd073dd
authored
Nov 18, 2025
by
fallenstardust
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
注释部分函数
parent
7c60c104
Changes
3
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
693 additions
and
406 deletions
+693
-406
Classes/gframe/duelclient.cpp
Classes/gframe/duelclient.cpp
+82
-19
Classes/gframe/event_handler.cpp
Classes/gframe/event_handler.cpp
+469
-289
Classes/gframe/game.cpp
Classes/gframe/game.cpp
+142
-98
No files found.
Classes/gframe/duelclient.cpp
View file @
3cd073dd
...
...
@@ -1231,39 +1231,86 @@ void DuelClient::HandleSTOCPacketLan(unsigned char* data, int len) {
}
}
// Analyze STOC_GAME_MSG packet
/**
* @brief 分析并处理来自服务器的游戏消息包
*
* 该函数负责解析从服务器接收到的STOC_GAME_MSG类型数据包,根据消息类型执行相应的游戏逻辑处理。
* 主要功能包括:
* 1. 读取消息类型并保存到游戏信息中
* 2. 保存最后一次成功处理的消息用于错误恢复
* 3. 隐藏当前显示的菜单界面
* 4. 处理非重播模式下的界面清理工作
* 5. 处理观战者视角切换
* 6. 根据不同的消息类型分发到对应的处理逻辑
*
* @param msg 指向消息数据包的指针
* @param len 消息数据包的长度
* @return bool 处理成功返回true,失败返回false
*
* @note 该函数是游戏核心逻辑处理函数,负责处理所有游戏过程中服务器发送的消息
* @note 对于MSG_RETRY消息会进行特殊处理,尝试恢复上一次成功的操作
* @note 在处理过程中会根据需要锁定和解锁图形界面互斥锁以保证线程安全
*/
bool
DuelClient
::
ClientAnalyze
(
unsigned
char
*
msg
,
int
len
)
{
// 定义一个指针,用于遍历消息数据
unsigned
char
*
pbuf
=
msg
;
// 定义一个宽字符缓冲区,用于存储文本信息
wchar_t
textBuffer
[
256
];
// 从消息数据中读取当前消息类型,并存储到游戏信息结构中
mainGame
->
dInfo
.
curMsg
=
BufferIO
::
Read
<
uint8_t
>
(
pbuf
);
// 如果当前消息不是重试消息,则将当前消息保存为最后成功处理的消息
if
(
mainGame
->
dInfo
.
curMsg
!=
MSG_RETRY
)
{
// 复制消息数据到last_successful_msg缓冲区
std
::
memcpy
(
last_successful_msg
,
msg
,
len
);
// 记录消息长度
last_successful_msg_length
=
len
;
}
// 隐藏当前显示的游戏菜单
mainGame
->
dField
.
HideMenu
();
// 如果不是回放模式,且当前消息不是等待或卡片选择消息
if
(
!
mainGame
->
dInfo
.
isReplay
&&
mainGame
->
dInfo
.
curMsg
!=
MSG_WAITING
&&
mainGame
->
dInfo
.
curMsg
!=
MSG_CARD_SELECTED
)
{
// 重置等待帧计数器
mainGame
->
waitFrame
=
-
1
;
// 隐藏提示信息显示
mainGame
->
stHintMsg
->
setVisible
(
false
);
// 如果卡片选择窗口当前可见
if
(
mainGame
->
wCardSelect
->
isVisible
())
{
// 锁定图形界面互斥锁
mainGame
->
gMutex
.
lock
();
// 隐藏卡片选择窗口
mainGame
->
HideElement
(
mainGame
->
wCardSelect
);
// 解锁图形界面互斥锁
mainGame
->
gMutex
.
unlock
();
// 等待11帧确保界面操作完成
mainGame
->
WaitFrameSignal
(
11
);
}
// 如果选项窗口当前可见
if
(
mainGame
->
wOptions
->
isVisible
())
{
// 锁定图形界面互斥锁
mainGame
->
gMutex
.
lock
();
// 隐藏选项窗口
mainGame
->
HideElement
(
mainGame
->
wOptions
);
// 解锁图形界面互斥锁
mainGame
->
gMutex
.
unlock
();
// 等待11帧确保界面操作完成
mainGame
->
WaitFrameSignal
(
11
);
}
}
// 如果当前计时玩家是玩家1,则将计时玩家设置为2(无)
if
(
mainGame
->
dInfo
.
time_player
==
1
)
mainGame
->
dInfo
.
time_player
=
2
;
// 如果正在进行视角交换
if
(
is_swapping
)
{
// 锁定图形界面互斥锁
mainGame
->
gMutex
.
lock
();
// 执行回放视角交换操作
mainGame
->
dField
.
ReplaySwap
();
// 解锁图形界面互斥锁
mainGame
->
gMutex
.
unlock
();
// 重置视角交换标志
is_swapping
=
false
;
}
// 根据消息类型分发到相应的处理函数
switch
(
mainGame
->
dInfo
.
curMsg
)
{
case
MSG_RETRY
:
{
if
(
last_successful_msg_length
)
{
...
...
@@ -3168,23 +3215,39 @@ bool DuelClient::ClientAnalyze(unsigned char* msg, int len) {
return
true
;
}
case
MSG_SUMMONING
:
{
// 从消息缓冲区读取召唤的卡片密码
unsigned
int
code
=
BufferIO
::
Read
<
int32_t
>
(
pbuf
);
// 读取控制者位置(被注释掉,未使用)
/*int cc = */
mainGame
->
LocalPlayer
(
BufferIO
::
Read
<
uint8_t
>
(
pbuf
));
// 读取召唤位置(被注释掉,未使用)
/*int cl = */
BufferIO
::
Read
<
uint8_t
>
(
pbuf
);
// 读取召唤区域序列(被注释掉,未使用)
/*int cs = */
BufferIO
::
Read
<
uint8_t
>
(
pbuf
);
// 读取召唤位置(被注释掉,未使用)
/*int cp = */
BufferIO
::
Read
<
uint8_t
>
(
pbuf
);
// 如果不是回放模式或者不是跳过回放,则执行以下操作
if
(
!
mainGame
->
dInfo
.
isReplay
||
!
mainGame
->
dInfo
.
isReplaySkiping
)
{
// 尝试播放在sound/chants/{code}.mp3 该卡片id相同文件名所在的音效,如果失败则播放普通召唤音效
if
(
!
mainGame
->
soundManager
->
PlayChant
(
code
))
mainGame
->
soundManager
->
PlaySoundEffect
(
SoundManager
::
SFX
::
SUMMON
);
// 构造召唤事件字符串,显示"召唤了xxx",会打印在消息记录窗口中
myswprintf
(
event_string
,
dataManager
.
GetSysString
(
1603
),
dataManager
.
GetName
(
code
));
// 设置要显示的卡片密码
mainGame
->
showcardcode
=
code
;
// 设置卡片显示差异参数为0
mainGame
->
showcarddif
=
0
;
// 设置卡片显示位置参数为0
mainGame
->
showcardp
=
0
;
// 设置显示卡片类型为7(召唤动画)
mainGame
->
showcard
=
7
;
// 等待30帧显示召唤动画
mainGame
->
WaitFrameSignal
(
30
);
// 重置显示卡片类型
mainGame
->
showcard
=
0
;
// 再等待11帧
mainGame
->
WaitFrameSignal
(
11
);
}
// 返回true表示处理成功
return
true
;
}
case
MSG_SUMMONED
:
{
...
...
Classes/gframe/event_handler.cpp
View file @
3cd073dd
This diff is collapsed.
Click to expand it.
Classes/gframe/game.cpp
View file @
3cd073dd
...
...
@@ -1903,16 +1903,30 @@ void Game::SaveConfig() {
// android::saveIntSetting(appMain, "control_mode", gameConf.control_mode);
}
/**
* @brief 显示指定卡牌的信息。
*
* 此函数用于在游戏界面中显示一张卡牌的详细信息,包括图像、名称、类型、种族、属性、攻击力/守备力等,
* 并根据卡牌是否有效(存在于数据表中)以及其具体类型(怪兽卡、魔法卡、陷阱卡等)进行不同的处理。
* 同时会设置文本区域以展示卡牌描述,并调整控件位置与缩放。
*
* @param code 卡牌编号,用作查找卡牌数据的关键字。
*/
void
Game
::
ShowCardInfo
(
int
code
)
{
// 定义格式化缓冲区和获取卡牌数据表引用
wchar_t
formatBuffer
[
256
];
auto
&
_datas
=
dataManager
.
GetDataTable
();
auto
cit
=
_datas
.
find
(
code
);
bool
is_valid
=
(
cit
!=
_datas
.
end
());
// 设置卡片图片并启用自动缩放
imgCard
->
setImage
(
imageManager
.
GetTexture
(
code
));
imgCard
->
setScaleImage
(
true
);
// 根据卡牌是否存在决定如何显示名称:若存在且是替代卡则使用别名
if
(
is_valid
)
{
auto
&
cd
=
cit
->
second
;
if
(
is_alternative
(
cd
.
code
,
cd
.
alias
))
if
(
is_alternative
(
cd
.
code
,
cd
.
alias
))
myswprintf
(
formatBuffer
,
L"%ls[%08d]"
,
dataManager
.
GetName
(
cd
.
alias
),
cd
.
alias
);
else
myswprintf
(
formatBuffer
,
L"%ls[%08d]"
,
dataManager
.
GetName
(
code
),
code
);
...
...
@@ -1920,20 +1934,26 @@ void Game::ShowCardInfo(int code) {
else
{
myswprintf
(
formatBuffer
,
L"%ls[%08d]"
,
dataManager
.
GetName
(
code
),
code
);
}
// 设置名称标签文本及提示工具文本(当文字超出宽度时)
stName
->
setText
(
formatBuffer
);
if
((
int
)
guiFont
->
getDimension
(
formatBuffer
).
Width
>
stName
->
getRelativePosition
().
getWidth
()
-
gameConf
.
textfontsize
)
if
((
int
)
guiFont
->
getDimension
(
formatBuffer
).
Width
>
stName
->
getRelativePosition
().
getWidth
()
-
gameConf
.
textfontsize
)
stName
->
setToolTipText
(
formatBuffer
);
else
stName
->
setToolTipText
(
nullptr
);
// 字段名显示逻辑
int
offset
=
0
;
if
(
is_valid
&&
!
gameConf
.
hide_setname
)
{
auto
&
cd
=
cit
->
second
;
auto
target
=
cit
;
// 若当前卡有同名卡并且该同名卡存在于数据库中,则使用该同名卡对应的数据
if
(
cd
.
alias
&&
_datas
.
find
(
cd
.
alias
)
!=
_datas
.
end
())
{
target
=
_datas
.
find
(
cd
.
alias
);
}
// 如果目标卡具有字段码,则构造并显示字段名
if
(
target
->
second
.
setcode
[
0
])
{
offset
=
23
;
// *yScale;
offset
=
23
;
// 固定偏移量用于布局调整
const
auto
&
setname
=
dataManager
.
FormatSetName
(
target
->
second
.
setcode
);
myswprintf
(
formatBuffer
,
L"%ls%ls"
,
dataManager
.
GetSysString
(
1329
),
setname
.
c_str
());
stSetName
->
setText
(
formatBuffer
);
...
...
@@ -1944,61 +1964,85 @@ void Game::ShowCardInfo(int code) {
else
{
stSetName
->
setText
(
L""
);
}
if
(
is_valid
&&
cit
->
second
.
type
&
TYPE_MONSTER
)
{
// 怪物卡信息处理分支
if
(
is_valid
&&
cit
->
second
.
type
&
TYPE_MONSTER
)
{
auto
&
cd
=
cit
->
second
;
// 构造并显示怪物卡的基本信息(类型、种族、属性)
const
auto
&
type
=
dataManager
.
FormatType
(
cd
.
type
);
const
auto
&
race
=
dataManager
.
FormatRace
(
cd
.
race
);
const
auto
&
attribute
=
dataManager
.
FormatAttribute
(
cd
.
attribute
);
myswprintf
(
formatBuffer
,
L"[%ls] %ls/%ls"
,
type
.
c_str
(),
race
.
c_str
(),
attribute
.
c_str
());
stInfo
->
setText
(
formatBuffer
);
// 判断文本长度是否需要换行偏移
int
offset_info
=
0
;
irr
::
core
::
dimension2d
<
unsigned
int
>
dtxt
=
guiFont
->
getDimension
(
formatBuffer
);
if
(
dtxt
.
Width
>
(
300
*
xScale
-
13
)
-
15
)
if
(
dtxt
.
Width
>
(
300
*
xScale
-
13
)
-
15
)
offset_info
=
15
;
const
wchar_t
*
form
=
L"\u2605"
;
// 准备等级符号和攻防数值字符串
const
wchar_t
*
form
=
L"\u2605"
;
// 默认星数标记
wchar_t
adBuffer
[
64
]{};
wchar_t
scaleBuffer
[
16
]{};
if
(
!
(
cd
.
type
&
TYPE_LINK
))
{
if
(
cd
.
type
&
TYPE_XYZ
)
form
=
L"\u2606"
;
if
(
cd
.
attack
<
0
&&
cd
.
defense
<
0
)
// 非连接卡处理
if
(
!
(
cd
.
type
&
TYPE_LINK
))
{
if
(
cd
.
type
&
TYPE_XYZ
)
form
=
L"\u2606"
;
// XYZ卡使用不同标记
// 攻击力/防御力未知情况下的特殊处理
if
(
cd
.
attack
<
0
&&
cd
.
defense
<
0
)
myswprintf
(
adBuffer
,
L"?/?"
);
else
if
(
cd
.
attack
<
0
)
else
if
(
cd
.
attack
<
0
)
myswprintf
(
adBuffer
,
L"?/%d"
,
cd
.
defense
);
else
if
(
cd
.
defense
<
0
)
else
if
(
cd
.
defense
<
0
)
myswprintf
(
adBuffer
,
L"%d/?"
,
cd
.
attack
);
else
myswprintf
(
adBuffer
,
L"%d/%d"
,
cd
.
attack
,
cd
.
defense
);
}
else
{
}
// 连接卡处理
else
{
form
=
L"LINK-"
;
const
auto
&
link_marker
=
dataManager
.
FormatLinkMarker
(
cd
.
link_marker
);
if
(
cd
.
attack
<
0
)
if
(
cd
.
attack
<
0
)
myswprintf
(
adBuffer
,
L"?/- %ls"
,
link_marker
.
c_str
());
else
myswprintf
(
adBuffer
,
L"%d/- %ls"
,
cd
.
attack
,
link_marker
.
c_str
());
}
if
(
cd
.
type
&
TYPE_PENDULUM
)
{
// 摆钟卡额外显示左右刻度
if
(
cd
.
type
&
TYPE_PENDULUM
)
{
myswprintf
(
scaleBuffer
,
L" %d/%d"
,
cd
.
lscale
,
cd
.
rscale
);
}
// 组合最终数据信息并设置到界面上
myswprintf
(
formatBuffer
,
L"[%ls%d] %ls%ls"
,
form
,
cd
.
level
,
adBuffer
,
scaleBuffer
);
stDataInfo
->
setText
(
formatBuffer
);
// 调整控件的位置
stSetName
->
setRelativePosition
(
Resize
(
10
,
83
,
250
,
106
));
stText
->
setRelativePosition
(
Resize
(
10
,
83
+
offset
,
251
,
340
));
scrCardText
->
setRelativePosition
(
Resize
(
255
,
83
+
offset
,
258
,
340
));
}
else
{
}
else
{
// 非怪物卡或无效卡处理
if
(
is_valid
)
{
const
auto
&
type
=
dataManager
.
FormatType
(
cit
->
second
.
type
);
myswprintf
(
formatBuffer
,
L"[%ls]"
,
type
.
c_str
());
}
else
myswprintf
(
formatBuffer
,
L"[%ls]"
,
dataManager
.
unknown_string
);
stInfo
->
setText
(
formatBuffer
);
stDataInfo
->
setText
(
L""
);
// 调整控件位置适应非怪物卡布局
stSetName
->
setRelativePosition
(
Resize
(
10
,
60
,
250
,
106
));
stText
->
setRelativePosition
(
Resize
(
10
,
60
+
offset
,
251
,
340
));
scrCardText
->
setRelativePosition
(
Resize
(
255
,
60
+
offset
,
258
,
340
));
}
// 获取并初始化卡牌描述文本
showingtext
=
dataManager
.
GetText
(
code
);
const
auto
&
tsize
=
stText
->
getRelativePosition
();
InitStaticText
(
stText
,
tsize
.
getWidth
(),
tsize
.
getHeight
(),
textFont
,
showingtext
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment