diff --git a/BetterGenshinImpact/App.xaml b/BetterGenshinImpact/App.xaml
index 5dd96ec7..3aedc8a1 100644
--- a/BetterGenshinImpact/App.xaml
+++ b/BetterGenshinImpact/App.xaml
@@ -20,6 +20,7 @@
+
diff --git a/BetterGenshinImpact/App.xaml.cs b/BetterGenshinImpact/App.xaml.cs
index 3f7acf19..abf1b719 100644
--- a/BetterGenshinImpact/App.xaml.cs
+++ b/BetterGenshinImpact/App.xaml.cs
@@ -73,6 +73,8 @@ public partial class App : Application
Log.Logger = loggerConfiguration.CreateLogger();
services.AddLogging(c => c.AddSerilog());
+ services.AddLocalization();
+
services.AddNavigationViewPageProvider();
// App Host
services.AddHostedService();
diff --git a/BetterGenshinImpact/Assets/Model/PaddleOCR/ch_ppocr_mobile_v2.0_cls/._inference.pdmodel b/BetterGenshinImpact/Assets/Model/PaddleOCR/ch_ppocr_mobile_v2.0_cls/._inference.pdmodel
deleted file mode 100644
index 87503bfd..00000000
Binary files a/BetterGenshinImpact/Assets/Model/PaddleOCR/ch_ppocr_mobile_v2.0_cls/._inference.pdmodel and /dev/null differ
diff --git a/BetterGenshinImpact/Assets/Model/PaddleOCR/ch_ppocr_mobile_v2.0_cls/inference.pdiparams b/BetterGenshinImpact/Assets/Model/PaddleOCR/ch_ppocr_mobile_v2.0_cls/inference.pdiparams
deleted file mode 100644
index 3449efb5..00000000
Binary files a/BetterGenshinImpact/Assets/Model/PaddleOCR/ch_ppocr_mobile_v2.0_cls/inference.pdiparams and /dev/null differ
diff --git a/BetterGenshinImpact/Assets/Model/PaddleOCR/ch_ppocr_mobile_v2.0_cls/inference.pdiparams.info b/BetterGenshinImpact/Assets/Model/PaddleOCR/ch_ppocr_mobile_v2.0_cls/inference.pdiparams.info
deleted file mode 100644
index f31a1575..00000000
Binary files a/BetterGenshinImpact/Assets/Model/PaddleOCR/ch_ppocr_mobile_v2.0_cls/inference.pdiparams.info and /dev/null differ
diff --git a/BetterGenshinImpact/Assets/Model/PaddleOCR/ch_ppocr_mobile_v2.0_cls/inference.pdmodel b/BetterGenshinImpact/Assets/Model/PaddleOCR/ch_ppocr_mobile_v2.0_cls/inference.pdmodel
deleted file mode 100644
index b90c1550..00000000
Binary files a/BetterGenshinImpact/Assets/Model/PaddleOCR/ch_ppocr_mobile_v2.0_cls/inference.pdmodel and /dev/null differ
diff --git a/BetterGenshinImpact/Assets/Model/PaddleOCR/chinese_cht_PP-OCRv3_rec_infer/inference.pdiparams b/BetterGenshinImpact/Assets/Model/PaddleOCR/chinese_cht_PP-OCRv3_rec_infer/inference.pdiparams
new file mode 100644
index 00000000..1b1ea1a9
Binary files /dev/null and b/BetterGenshinImpact/Assets/Model/PaddleOCR/chinese_cht_PP-OCRv3_rec_infer/inference.pdiparams differ
diff --git a/BetterGenshinImpact/Assets/Model/PaddleOCR/chinese_cht_PP-OCRv3_rec_infer/inference.pdiparams.info b/BetterGenshinImpact/Assets/Model/PaddleOCR/chinese_cht_PP-OCRv3_rec_infer/inference.pdiparams.info
new file mode 100644
index 00000000..1cdccfce
Binary files /dev/null and b/BetterGenshinImpact/Assets/Model/PaddleOCR/chinese_cht_PP-OCRv3_rec_infer/inference.pdiparams.info differ
diff --git a/BetterGenshinImpact/Assets/Model/PaddleOCR/chinese_cht_PP-OCRv3_rec_infer/inference.pdmodel b/BetterGenshinImpact/Assets/Model/PaddleOCR/chinese_cht_PP-OCRv3_rec_infer/inference.pdmodel
new file mode 100644
index 00000000..95acc925
Binary files /dev/null and b/BetterGenshinImpact/Assets/Model/PaddleOCR/chinese_cht_PP-OCRv3_rec_infer/inference.pdmodel differ
diff --git a/BetterGenshinImpact/Assets/Model/PaddleOCR/chinese_cht_dict.txt b/BetterGenshinImpact/Assets/Model/PaddleOCR/chinese_cht_dict.txt
new file mode 100644
index 00000000..cc1aa472
--- /dev/null
+++ b/BetterGenshinImpact/Assets/Model/PaddleOCR/chinese_cht_dict.txt
@@ -0,0 +1,8421 @@
+!
+"
+#
+$
+%
+&
+'
+(
+)
+*
++
+,
+-
+.
+/
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+:
+;
+<
+=
+>
+?
+@
+A
+B
+C
+D
+E
+F
+G
+H
+I
+J
+K
+L
+M
+N
+O
+P
+Q
+R
+S
+T
+U
+V
+W
+X
+Y
+Z
+[
+\
+]
+^
+_
+`
+a
+b
+c
+d
+e
+f
+g
+h
+i
+j
+k
+l
+m
+n
+o
+p
+q
+r
+s
+t
+u
+v
+w
+x
+y
+z
+{
+|
+}
+~
+¥
+®
+°
+±
+²
+´
+·
+»
+É
+Ë
+Ó
+×
+Ü
+à
+á
+ä
+è
+é
+ì
+í
+ò
+ó
+÷
+ú
+ü
+ā
+ē
+ī
+ō
+ū
+ǐ
+ǒ
+ɔ
+ɡ
+ʌ
+ˋ
+Λ
+Ο
+Φ
+Ω
+α
+β
+ε
+θ
+μ
+π
+З
+И
+Й
+П
+Я
+г
+—
+‖
+‘
+’
+“
+”
+•
+…
+‧
+′
+″
+※
+℃
+№
+™
+Ⅱ
+Ⅲ
+Ⅳ
+←
+↑
+→
+↓
+⇋
+∈
+∑
+√
+∞
+∣
+∧
+∩
+∫
+∶
+≈
+≠
+≤
+≥
+⊙
+⊥
+①
+②
+③
+④
+⑧
+⑴
+⑵
+⑶
+─
+│
+┅
+┌
+├
+█
+▎
+▏
+▕
+■
+□
+▪
+▲
+△
+▼
+◆
+◇
+○
+◎
+●
+◥
+★
+☆
+❋
+❤
+
+、
+。
+〇
+〉
+《
+》
+「
+」
+『
+』
+【
+】
+〔
+〕
+〖
+〗
+の
+サ
+シ
+ジ
+マ
+ㄱ
+ㆍ
+㎏
+㎡
+㐂
+㐱
+㙟
+㴪
+㸃
+䖝
+䝉
+䰾
+䲁
+一
+丁
+七
+丄
+丈
+三
+上
+下
+丌
+不
+与
+丏
+丐
+丑
+且
+丕
+世
+丘
+丙
+丞
+丟
+両
+並
+丨
+丫
+中
+丰
+串
+丶
+丸
+丹
+主
+丼
+丿
+乂
+乃
+久
+么
+之
+乍
+乎
+乏
+乒
+乓
+乖
+乗
+乘
+乙
+乚
+乜
+九
+乞
+也
+乩
+乭
+乳
+乸
+乹
+乾
+亀
+亂
+亅
+了
+予
+亊
+事
+二
+亍
+云
+互
+亓
+五
+井
+亘
+些
+亜
+亞
+亟
+亠
+亡
+亢
+交
+亥
+亦
+亨
+享
+京
+亭
+亮
+亰
+亳
+亶
+亹
+人
+亻
+什
+仁
+仂
+仃
+仄
+仇
+仉
+今
+介
+仍
+仏
+仔
+仕
+他
+仗
+付
+仙
+仛
+仝
+仞
+仟
+仡
+代
+令
+以
+仨
+仫
+仮
+仰
+仲
+仳
+仵
+件
+仺
+任
+仼
+份
+仿
+企
+伃
+伈
+伉
+伊
+伋
+伍
+伎
+伏
+伐
+休
+伕
+伙
+伝
+伢
+伯
+估
+伱
+伴
+伶
+伷
+伸
+伺
+似
+伽
+伾
+佀
+佁
+佃
+但
+佇
+佈
+佉
+佋
+位
+低
+住
+佐
+佑
+体
+佔
+何
+佗
+佘
+余
+佚
+佛
+作
+佝
+佞
+佟
+你
+佣
+佤
+佧
+佩
+佬
+佯
+佰
+佳
+併
+佶
+佹
+佺
+佼
+佾
+使
+侁
+侃
+侄
+侅
+來
+侈
+侊
+例
+侍
+侏
+侑
+侖
+侗
+侘
+侚
+供
+依
+侞
+価
+侮
+侯
+侵
+侶
+侷
+侹
+便
+俁
+係
+促
+俄
+俅
+俊
+俋
+俌
+俍
+俎
+俏
+俐
+俑
+俗
+俘
+俚
+俛
+保
+俞
+俟
+俠
+信
+俬
+修
+俯
+俱
+俳
+俴
+俵
+俶
+俸
+俺
+俽
+俾
+倆
+倈
+倉
+個
+倌
+倍
+們
+倒
+倓
+倔
+倖
+倗
+倘
+候
+倚
+倜
+倞
+借
+倡
+倢
+倣
+値
+倦
+倧
+倩
+倪
+倫
+倬
+倭
+倮
+倻
+值
+偁
+偃
+假
+偈
+偉
+偊
+偌
+偍
+偎
+偏
+偓
+偕
+做
+停
+健
+偪
+偲
+側
+偵
+偶
+偷
+偸
+偽
+傀
+傃
+傅
+傈
+傉
+傍
+傑
+傒
+傕
+傖
+傘
+備
+傜
+傢
+傣
+催
+傭
+傲
+傳
+債
+傷
+傻
+傾
+僅
+僉
+僊
+働
+像
+僑
+僔
+僕
+僖
+僙
+僚
+僜
+僡
+僧
+僩
+僭
+僮
+僰
+僱
+僳
+僴
+僵
+價
+僻
+儀
+儁
+儂
+億
+儆
+儇
+儈
+儉
+儋
+儐
+儒
+儔
+儕
+儘
+儚
+儞
+償
+儡
+儥
+儦
+優
+儫
+儱
+儲
+儷
+儺
+儻
+儼
+兀
+允
+元
+兄
+充
+兆
+先
+光
+克
+兌
+免
+児
+兒
+兔
+兕
+兗
+兜
+入
+內
+全
+兩
+兪
+八
+公
+六
+兮
+共
+兵
+其
+具
+典
+兼
+兿
+冀
+冂
+円
+冇
+冉
+冊
+再
+冏
+冑
+冒
+冕
+冖
+冗
+冚
+冠
+冢
+冤
+冥
+冧
+冨
+冪
+冫
+冬
+冮
+冰
+冴
+冶
+冷
+冼
+冽
+凃
+凄
+准
+凈
+凋
+凌
+凍
+凖
+凜
+凝
+凞
+几
+凡
+処
+凪
+凬
+凰
+凱
+凳
+凵
+凶
+凸
+凹
+出
+函
+刀
+刁
+刂
+刃
+刄
+分
+切
+刈
+刊
+刎
+刑
+划
+列
+初
+判
+別
+刦
+刧
+刨
+利
+刪
+刮
+到
+制
+刷
+券
+刺
+刻
+刼
+剁
+剃
+則
+削
+剋
+剌
+前
+剎
+剏
+剔
+剖
+剛
+剝
+剡
+剣
+剩
+剪
+剮
+副
+割
+創
+剿
+劃
+劄
+劇
+劈
+劉
+劊
+劌
+劍
+劑
+劔
+力
+功
+加
+劣
+助
+努
+劫
+劬
+劭
+劵
+効
+劼
+劾
+勁
+勃
+勅
+勇
+勉
+勐
+勑
+勒
+勔
+動
+勖
+勗
+勘
+務
+勛
+勝
+勞
+募
+勢
+勣
+勤
+勦
+勰
+勱
+勲
+勳
+勵
+勷
+勸
+勺
+勻
+勾
+勿
+匂
+匄
+包
+匆
+匈
+匋
+匍
+匏
+匐
+匕
+化
+北
+匙
+匚
+匝
+匠
+匡
+匣
+匪
+匯
+匱
+匸
+匹
+匾
+匿
+區
+十
+千
+卅
+升
+午
+卉
+半
+卋
+卍
+卐
+卑
+卒
+卓
+協
+南
+博
+卜
+卞
+卟
+占
+卡
+卣
+卦
+卧
+卩
+卬
+卮
+卯
+印
+危
+卲
+即
+卵
+卷
+卸
+卹
+卺
+卻
+卽
+卿
+厄
+厓
+厔
+厙
+厚
+厝
+原
+厥
+厭
+厰
+厲
+厴
+厶
+去
+參
+叄
+又
+叉
+及
+友
+反
+収
+叔
+叕
+取
+受
+叛
+叟
+叡
+叢
+口
+古
+句
+另
+叨
+叩
+只
+叫
+召
+叭
+叮
+可
+台
+叱
+史
+右
+叵
+司
+叻
+叼
+吁
+吃
+各
+吆
+合
+吉
+吊
+吋
+同
+名
+后
+吏
+吐
+向
+吒
+吔
+吖
+君
+吝
+吞
+吟
+吠
+吡
+吥
+否
+吧
+吩
+含
+吮
+吱
+吲
+吳
+吵
+吶
+吸
+吹
+吻
+吼
+吾
+呀
+呂
+呃
+呈
+呉
+告
+呋
+呎
+呢
+呤
+呦
+周
+呱
+味
+呵
+呷
+呸
+呼
+命
+呾
+咀
+咁
+咂
+咄
+咅
+咆
+咋
+和
+咎
+咑
+咒
+咔
+咕
+咖
+咗
+咘
+咚
+咟
+咤
+咥
+咧
+咨
+咩
+咪
+咫
+咬
+咭
+咯
+咱
+咲
+咳
+咸
+咻
+咼
+咽
+咾
+咿
+哀
+品
+哂
+哄
+哆
+哇
+哈
+哉
+哌
+哎
+哏
+哐
+哖
+哚
+哞
+員
+哥
+哦
+哨
+哩
+哪
+哭
+哮
+哱
+哲
+哺
+哼
+唃
+唄
+唆
+唇
+唉
+唏
+唐
+唑
+唔
+唘
+唧
+唫
+唬
+唭
+售
+唯
+唱
+唳
+唵
+唷
+唸
+唻
+唾
+啁
+啃
+啄
+商
+啉
+啊
+啍
+問
+啓
+啖
+啚
+啜
+啞
+啟
+啡
+啣
+啤
+啥
+啦
+啪
+啫
+啯
+啰
+啱
+啲
+啵
+啶
+啷
+啻
+啼
+啾
+喀
+喂
+喃
+善
+喆
+喇
+喈
+喉
+喊
+喋
+喏
+喔
+喘
+喙
+喚
+喜
+喝
+喢
+喦
+喧
+喪
+喫
+喬
+單
+喰
+喱
+喲
+喳
+喵
+喹
+喻
+喼
+嗄
+嗅
+嗆
+嗇
+嗊
+嗎
+嗑
+嗒
+嗓
+嗔
+嗖
+嗚
+嗜
+嗝
+嗞
+嗡
+嗢
+嗣
+嗦
+嗨
+嗩
+嗪
+嗮
+嗯
+嗲
+嗶
+嗹
+嗽
+嘀
+嘅
+嘆
+嘉
+嘌
+嘍
+嘎
+嘏
+嘔
+嘗
+嘚
+嘛
+嘜
+嘞
+嘟
+嘢
+嘣
+嘥
+嘧
+嘩
+嘬
+嘮
+嘯
+嘰
+嘲
+嘴
+嘶
+嘸
+嘹
+嘻
+嘿
+噁
+噌
+噍
+噏
+噓
+噗
+噝
+噠
+噢
+噤
+噥
+噦
+器
+噩
+噪
+噬
+噯
+噰
+噲
+噴
+噶
+噸
+噹
+噻
+嚇
+嚈
+嚎
+嚏
+嚐
+嚒
+嚓
+嚕
+嚗
+嚙
+嚞
+嚟
+嚤
+嚦
+嚧
+嚨
+嚩
+嚮
+嚳
+嚴
+嚶
+嚷
+嚼
+嚿
+囀
+囂
+囃
+囉
+囊
+囍
+囑
+囒
+囓
+囗
+囚
+四
+囝
+回
+因
+囡
+団
+囤
+囧
+囪
+囮
+囯
+困
+囲
+図
+囶
+囷
+囹
+固
+囿
+圂
+圃
+圄
+圈
+圉
+國
+圍
+圏
+園
+圓
+圖
+圗
+團
+圜
+土
+圧
+在
+圩
+圪
+圭
+圯
+地
+圳
+圻
+圾
+址
+均
+坊
+坋
+坌
+坍
+坎
+坐
+坑
+坖
+坡
+坣
+坤
+坦
+坨
+坩
+坪
+坫
+坬
+坭
+坮
+坯
+坳
+坵
+坶
+坷
+坻
+垂
+垃
+垈
+型
+垍
+垓
+垕
+垚
+垛
+垞
+垟
+垠
+垢
+垣
+垮
+垯
+垰
+垵
+垸
+垻
+垿
+埃
+埅
+埇
+埈
+埋
+埌
+城
+埏
+埒
+埔
+埕
+埗
+埜
+域
+埠
+埡
+埤
+埧
+埨
+埪
+埭
+埮
+埴
+埵
+執
+培
+基
+埻
+埼
+堀
+堂
+堃
+堅
+堆
+堇
+堈
+堉
+堊
+堍
+堖
+堝
+堡
+堤
+堦
+堪
+堮
+堯
+堰
+報
+場
+堵
+堷
+堺
+塀
+塅
+塆
+塊
+塋
+塌
+塍
+塏
+塑
+塔
+塗
+塘
+塙
+塜
+塞
+塡
+塢
+塤
+塨
+塩
+填
+塬
+塭
+塰
+塱
+塲
+塵
+塹
+塽
+塾
+墀
+境
+墅
+墉
+墊
+墎
+墓
+増
+墘
+墜
+增
+墟
+墡
+墣
+墨
+墩
+墫
+墬
+墮
+墱
+墳
+墺
+墼
+墾
+壁
+壄
+壆
+壇
+壋
+壌
+壎
+壐
+壑
+壓
+壔
+壕
+壘
+壙
+壞
+壟
+壠
+壢
+壤
+壩
+士
+壬
+壯
+壱
+壴
+壹
+壺
+壽
+夀
+夆
+変
+夊
+夋
+夌
+夏
+夔
+夕
+外
+夙
+多
+夜
+夠
+夢
+夤
+夥
+大
+天
+太
+夫
+夬
+夭
+央
+夯
+失
+夷
+夾
+奀
+奄
+奇
+奈
+奉
+奎
+奏
+奐
+契
+奓
+奔
+奕
+套
+奘
+奚
+奠
+奢
+奣
+奧
+奩
+奪
+奫
+奭
+奮
+女
+奴
+奶
+她
+好
+妀
+妁
+如
+妃
+妄
+妊
+妍
+妏
+妑
+妒
+妓
+妖
+妙
+妝
+妞
+妠
+妤
+妥
+妧
+妨
+妭
+妮
+妯
+妲
+妳
+妸
+妹
+妺
+妻
+妾
+姀
+姁
+姃
+姆
+姈
+姉
+姊
+始
+姌
+姍
+姐
+姑
+姒
+姓
+委
+姚
+姜
+姝
+姣
+姥
+姦
+姨
+姪
+姫
+姬
+姮
+姵
+姶
+姸
+姻
+姿
+威
+娃
+娉
+娋
+娌
+娍
+娎
+娑
+娖
+娘
+娛
+娜
+娟
+娠
+娣
+娥
+娩
+娫
+娳
+娶
+娸
+娼
+娽
+婀
+婁
+婆
+婉
+婊
+婑
+婕
+婚
+婢
+婦
+婧
+婪
+婭
+婯
+婷
+婺
+婻
+婼
+婿
+媃
+媄
+媊
+媐
+媒
+媓
+媖
+媗
+媚
+媛
+媜
+媞
+媧
+媭
+媯
+媲
+媳
+媺
+媼
+媽
+媾
+媿
+嫁
+嫂
+嫄
+嫈
+嫉
+嫌
+嫖
+嫘
+嫚
+嫡
+嫣
+嫦
+嫩
+嫪
+嫲
+嫳
+嫵
+嫺
+嫻
+嬅
+嬈
+嬉
+嬋
+嬌
+嬗
+嬛
+嬝
+嬡
+嬤
+嬨
+嬪
+嬬
+嬭
+嬰
+嬴
+嬸
+嬾
+嬿
+孀
+孃
+孆
+孋
+孌
+子
+孑
+孔
+孕
+孖
+字
+存
+孚
+孛
+孜
+孝
+孟
+孢
+季
+孤
+孩
+孫
+孬
+孮
+孰
+孳
+孵
+學
+孺
+孻
+孽
+孿
+宀
+它
+宅
+宇
+守
+安
+宋
+完
+宍
+宏
+宓
+宕
+宗
+官
+宙
+定
+宛
+宜
+実
+客
+宣
+室
+宥
+宦
+宧
+宮
+宰
+害
+宴
+宵
+家
+宸
+容
+宿
+寀
+寁
+寂
+寄
+寅
+密
+寇
+寈
+寊
+富
+寐
+寒
+寓
+寔
+寕
+寖
+寗
+寘
+寛
+寜
+寞
+察
+寡
+寢
+寤
+寥
+實
+寧
+寨
+審
+寫
+寬
+寮
+寯
+寰
+寳
+寵
+寶
+寸
+寺
+対
+封
+専
+尃
+射
+將
+專
+尉
+尊
+尋
+對
+導
+小
+尐
+少
+尓
+尕
+尖
+尗
+尙
+尚
+尢
+尤
+尨
+尪
+尬
+就
+尷
+尹
+尺
+尻
+尼
+尾
+尿
+局
+屁
+屄
+居
+屆
+屇
+屈
+屋
+屌
+屍
+屎
+屏
+屐
+屑
+屓
+展
+屚
+屜
+屠
+屢
+層
+履
+屬
+屭
+屯
+山
+屹
+屺
+屻
+岀
+岈
+岌
+岐
+岑
+岔
+岡
+岢
+岣
+岧
+岩
+岪
+岫
+岬
+岰
+岱
+岳
+岵
+岷
+岸
+岻
+峁
+峅
+峇
+峋
+峍
+峒
+峘
+峙
+峚
+峠
+峨
+峩
+峪
+峭
+峯
+峰
+峴
+島
+峻
+峼
+峽
+崁
+崆
+崇
+崈
+崋
+崍
+崎
+崐
+崑
+崒
+崔
+崖
+崗
+崘
+崙
+崚
+崛
+崞
+崟
+崠
+崢
+崤
+崧
+崩
+崬
+崮
+崱
+崴
+崵
+崶
+崽
+嵇
+嵊
+嵋
+嵌
+嵎
+嵐
+嵒
+嵕
+嵖
+嵗
+嵙
+嵛
+嵜
+嵨
+嵩
+嵬
+嵮
+嵯
+嵰
+嵴
+嵻
+嵿
+嶁
+嶂
+嶃
+嶄
+嶇
+嶋
+嶌
+嶍
+嶒
+嶔
+嶗
+嶝
+嶠
+嶢
+嶦
+嶧
+嶪
+嶬
+嶰
+嶲
+嶴
+嶷
+嶸
+嶺
+嶼
+嶽
+巂
+巄
+巆
+巋
+巌
+巍
+巎
+巑
+巒
+巔
+巖
+巘
+巛
+川
+州
+巡
+巢
+工
+左
+巧
+巨
+巫
+差
+巰
+己
+已
+巳
+巴
+巶
+巷
+巻
+巽
+巾
+巿
+市
+布
+帆
+希
+帑
+帔
+帕
+帖
+帘
+帙
+帚
+帛
+帝
+帡
+帢
+帥
+師
+席
+帯
+帰
+帳
+帶
+帷
+常
+帽
+幀
+幃
+幄
+幅
+幌
+幔
+幕
+幗
+幚
+幛
+幟
+幡
+幢
+幣
+幪
+幫
+干
+平
+年
+幵
+幷
+幸
+幹
+幺
+幻
+幼
+幽
+幾
+庀
+庁
+広
+庇
+床
+序
+底
+庖
+店
+庚
+府
+庠
+庢
+庥
+度
+座
+庫
+庭
+庲
+庵
+庶
+康
+庸
+庹
+庼
+庾
+廁
+廂
+廄
+廆
+廈
+廉
+廊
+廋
+廌
+廍
+廑
+廓
+廔
+廕
+廖
+廙
+廚
+廝
+廞
+廟
+廠
+廡
+廢
+廣
+廧
+廨
+廩
+廬
+廰
+廱
+廳
+延
+廷
+廸
+建
+廻
+廼
+廿
+弁
+弄
+弅
+弇
+弈
+弉
+弊
+弋
+弍
+式
+弐
+弒
+弓
+弔
+引
+弖
+弗
+弘
+弛
+弟
+弢
+弦
+弧
+弨
+弩
+弭
+弱
+張
+強
+弸
+弼
+弾
+彀
+彄
+彅
+彆
+彈
+彊
+彌
+彎
+彐
+彔
+彖
+彗
+彘
+彙
+彜
+彞
+彠
+彡
+形
+彣
+彤
+彥
+彧
+彩
+彪
+彫
+彬
+彭
+彰
+影
+彳
+彷
+役
+彼
+彿
+往
+征
+徂
+待
+徇
+很
+徉
+徊
+律
+後
+徐
+徑
+徒
+得
+徘
+徙
+徜
+從
+徠
+御
+徧
+徨
+復
+循
+徫
+徬
+徭
+微
+徳
+徴
+徵
+德
+徸
+徹
+徽
+心
+忄
+必
+忉
+忌
+忍
+忐
+忑
+忒
+志
+忘
+忙
+応
+忝
+忞
+忠
+快
+忬
+忯
+忱
+忳
+念
+忻
+忽
+忿
+怍
+怎
+怒
+怕
+怖
+怙
+怛
+思
+怠
+怡
+急
+怦
+性
+怨
+怪
+怯
+怵
+恁
+恂
+恃
+恆
+恊
+恍
+恐
+恕
+恙
+恢
+恣
+恤
+恥
+恨
+恩
+恪
+恬
+恭
+息
+恰
+恵
+恿
+悄
+悅
+悆
+悉
+悌
+悍
+悔
+悖
+悚
+悛
+悝
+悞
+悟
+悠
+患
+悧
+您
+悪
+悰
+悲
+悳
+悵
+悶
+悸
+悼
+情
+惆
+惇
+惑
+惔
+惕
+惘
+惚
+惜
+惟
+惠
+惡
+惣
+惦
+惰
+惱
+惲
+想
+惶
+惹
+惺
+愁
+愃
+愆
+愈
+愉
+愍
+意
+愐
+愒
+愔
+愕
+愚
+愛
+愜
+感
+愣
+愧
+愨
+愫
+愭
+愴
+愷
+愼
+愾
+愿
+慄
+慈
+態
+慌
+慎
+慕
+慘
+慚
+慜
+慟
+慢
+慣
+慥
+慧
+慨
+慮
+慰
+慳
+慵
+慶
+慷
+慾
+憂
+憊
+憋
+憍
+憎
+憐
+憑
+憓
+憕
+憙
+憚
+憤
+憧
+憨
+憩
+憫
+憬
+憲
+憶
+憺
+憻
+憾
+懂
+懃
+懇
+懈
+應
+懋
+懌
+懍
+懐
+懣
+懦
+懮
+懲
+懵
+懶
+懷
+懸
+懺
+懼
+懽
+懾
+懿
+戀
+戇
+戈
+戊
+戌
+戍
+戎
+成
+我
+戒
+戔
+戕
+或
+戙
+戚
+戛
+戟
+戡
+戢
+戥
+戦
+戩
+截
+戮
+戰
+戱
+戲
+戳
+戴
+戶
+戸
+戻
+戽
+戾
+房
+所
+扁
+扆
+扇
+扈
+扉
+手
+扌
+才
+扎
+扒
+打
+扔
+托
+扙
+扛
+扞
+扣
+扥
+扦
+扭
+扮
+扯
+扳
+扶
+批
+扼
+找
+承
+技
+抃
+抄
+抇
+抉
+把
+抑
+抒
+抓
+投
+抖
+抗
+折
+抦
+披
+抬
+抱
+抵
+抹
+抻
+押
+抽
+抿
+拂
+拆
+拇
+拈
+拉
+拋
+拌
+拍
+拎
+拏
+拐
+拒
+拓
+拔
+拖
+拗
+拘
+拙
+拚
+招
+拜
+拝
+拡
+括
+拭
+拮
+拯
+拱
+拳
+拴
+拷
+拺
+拼
+拽
+拾
+拿
+持
+指
+按
+挎
+挑
+挖
+挙
+挨
+挪
+挫
+振
+挲
+挵
+挹
+挺
+挻
+挾
+捂
+捆
+捉
+捌
+捍
+捎
+捏
+捐
+捒
+捕
+捜
+捦
+捧
+捨
+捩
+捫
+捭
+捱
+捲
+捶
+捷
+捺
+捻
+掀
+掂
+掃
+掄
+掇
+授
+掉
+掌
+掏
+掐
+排
+掖
+掘
+掙
+掛
+掞
+掟
+掠
+採
+探
+掣
+接
+控
+推
+掩
+措
+掬
+掰
+掾
+揀
+揄
+揆
+揉
+揍
+描
+提
+插
+揔
+揖
+揚
+換
+握
+揪
+揭
+揮
+援
+揸
+揺
+損
+搏
+搐
+搓
+搔
+搖
+搗
+搜
+搞
+搠
+搢
+搪
+搬
+搭
+搳
+搴
+搵
+搶
+搽
+搾
+摂
+摒
+摔
+摘
+摜
+摞
+摟
+摠
+摧
+摩
+摭
+摯
+摳
+摴
+摵
+摶
+摸
+摹
+摺
+摻
+摽
+撃
+撇
+撈
+撐
+撒
+撓
+撕
+撖
+撙
+撚
+撞
+撣
+撤
+撥
+撩
+撫
+撬
+播
+撮
+撰
+撲
+撳
+撻
+撼
+撾
+撿
+擀
+擁
+擂
+擅
+擇
+擊
+擋
+操
+擎
+擒
+擔
+擘
+據
+擠
+擢
+擥
+擦
+擬
+擯
+擰
+擱
+擲
+擴
+擷
+擺
+擼
+擾
+攀
+攏
+攔
+攖
+攘
+攜
+攝
+攞
+攢
+攣
+攤
+攪
+攫
+攬
+支
+攴
+攵
+收
+攷
+攸
+改
+攻
+攽
+放
+政
+故
+效
+敍
+敎
+敏
+救
+敔
+敕
+敖
+敗
+敘
+教
+敝
+敞
+敟
+敢
+散
+敦
+敫
+敬
+敭
+敲
+整
+敵
+敷
+數
+敻
+敾
+斂
+斃
+文
+斌
+斎
+斐
+斑
+斕
+斖
+斗
+料
+斛
+斜
+斝
+斟
+斡
+斤
+斥
+斧
+斬
+斯
+新
+斷
+方
+於
+施
+斿
+旁
+旂
+旃
+旄
+旅
+旉
+旋
+旌
+旎
+族
+旖
+旗
+旙
+旛
+旡
+既
+日
+旦
+旨
+早
+旬
+旭
+旱
+旲
+旳
+旺
+旻
+旼
+旽
+旾
+旿
+昀
+昂
+昃
+昆
+昇
+昉
+昊
+昌
+昍
+明
+昏
+昐
+易
+昔
+昕
+昚
+昛
+昜
+昝
+昞
+星
+映
+昡
+昣
+昤
+春
+昧
+昨
+昪
+昫
+昭
+是
+昰
+昱
+昴
+昵
+昶
+昺
+晁
+時
+晃
+晈
+晉
+晊
+晏
+晗
+晙
+晚
+晛
+晝
+晞
+晟
+晤
+晦
+晧
+晨
+晩
+晪
+晫
+晭
+普
+景
+晰
+晳
+晴
+晶
+晷
+晸
+智
+晾
+暃
+暄
+暅
+暇
+暈
+暉
+暊
+暌
+暎
+暏
+暐
+暑
+暕
+暖
+暗
+暘
+暝
+暟
+暠
+暢
+暦
+暨
+暫
+暮
+暱
+暲
+暴
+暸
+暹
+暻
+暾
+曄
+曅
+曆
+曇
+曉
+曌
+曔
+曖
+曙
+曜
+曝
+曠
+曦
+曧
+曨
+曩
+曬
+曮
+曰
+曲
+曳
+更
+曶
+曷
+書
+曹
+曺
+曼
+曽
+曾
+替
+最
+會
+月
+有
+朊
+朋
+服
+朏
+朐
+朓
+朔
+朕
+朖
+朗
+望
+朝
+期
+朦
+朧
+木
+未
+末
+本
+札
+朱
+朴
+朵
+朶
+朽
+朿
+杁
+杉
+杋
+杌
+李
+杏
+材
+村
+杓
+杖
+杙
+杜
+杞
+束
+杠
+杣
+杤
+杧
+杬
+杭
+杯
+東
+杲
+杳
+杴
+杵
+杷
+杻
+杼
+松
+板
+极
+枇
+枉
+枋
+枏
+析
+枕
+枖
+林
+枚
+枛
+果
+枝
+枠
+枡
+枯
+枰
+枱
+枲
+枳
+架
+枷
+枸
+枹
+枼
+柁
+柃
+柄
+柉
+柊
+柎
+柏
+某
+柑
+柒
+染
+柔
+柘
+柚
+柜
+柝
+柞
+柟
+查
+柩
+柬
+柯
+柰
+柱
+柳
+柴
+柵
+柶
+柷
+査
+柾
+柿
+栃
+栄
+栐
+栒
+栓
+栜
+栝
+栞
+校
+栢
+栨
+栩
+株
+栲
+栴
+核
+根
+栻
+格
+栽
+桀
+桁
+桂
+桃
+桄
+桅
+框
+案
+桉
+桌
+桎
+桐
+桑
+桓
+桔
+桕
+桖
+桙
+桜
+桝
+桫
+桱
+桲
+桴
+桶
+桷
+桼
+桿
+梀
+梁
+梂
+梃
+梅
+梆
+梉
+梏
+梓
+梔
+梗
+梘
+條
+梟
+梠
+梢
+梣
+梧
+梨
+梫
+梭
+梯
+械
+梱
+梳
+梵
+梶
+梽
+棄
+棆
+棉
+棋
+棍
+棐
+棒
+棓
+棕
+棖
+棗
+棘
+棚
+棛
+棟
+棠
+棡
+棣
+棧
+棨
+棩
+棪
+棫
+森
+棱
+棲
+棵
+棶
+棹
+棺
+棻
+棼
+棽
+椅
+椆
+椇
+椋
+植
+椎
+椏
+椒
+椙
+椥
+椪
+椰
+椲
+椴
+椵
+椹
+椽
+椿
+楂
+楊
+楓
+楔
+楗
+楙
+楚
+楝
+楞
+楠
+楡
+楢
+楣
+楤
+楦
+楧
+楨
+楫
+業
+楮
+楯
+楳
+極
+楷
+楸
+楹
+楽
+楿
+概
+榆
+榊
+榍
+榎
+榑
+榔
+榕
+榖
+榗
+榘
+榛
+榜
+榞
+榢
+榣
+榤
+榦
+榧
+榨
+榫
+榭
+榮
+榲
+榴
+榷
+榻
+榿
+槀
+槁
+槃
+槊
+構
+槌
+槍
+槎
+槐
+槓
+槔
+槗
+様
+槙
+槤
+槩
+槭
+槰
+槱
+槲
+槳
+槺
+槻
+槼
+槽
+槿
+樀
+樁
+樂
+樅
+樆
+樊
+樋
+樑
+樓
+樗
+樘
+標
+樞
+樟
+模
+樣
+樨
+権
+樫
+樵
+樸
+樹
+樺
+樻
+樽
+樾
+橄
+橇
+橈
+橋
+橐
+橒
+橓
+橘
+橙
+橚
+機
+橡
+橢
+橪
+橫
+橿
+檀
+檄
+檇
+檉
+檊
+檎
+檐
+檔
+檗
+檜
+檞
+檠
+檡
+檢
+檣
+檦
+檨
+檫
+檬
+檯
+檳
+檵
+檸
+檻
+檽
+櫂
+櫃
+櫆
+櫈
+櫓
+櫚
+櫛
+櫞
+櫟
+櫥
+櫨
+櫪
+櫱
+櫸
+櫻
+櫾
+櫿
+欄
+欉
+權
+欏
+欒
+欖
+欞
+欠
+次
+欣
+欥
+欲
+欸
+欹
+欺
+欽
+款
+歆
+歇
+歉
+歊
+歌
+歎
+歐
+歓
+歙
+歛
+歡
+止
+正
+此
+步
+武
+歧
+歩
+歪
+歲
+歳
+歴
+歷
+歸
+歹
+死
+歿
+殂
+殃
+殄
+殆
+殉
+殊
+殑
+殖
+殘
+殛
+殞
+殟
+殤
+殭
+殮
+殯
+殲
+殳
+段
+殷
+殺
+殻
+殼
+殿
+毀
+毅
+毆
+毉
+毋
+毌
+母
+毎
+每
+毐
+毒
+毓
+比
+毖
+毗
+毘
+毛
+毫
+毬
+毯
+毴
+毸
+毽
+毿
+氂
+氈
+氍
+氏
+氐
+民
+氓
+氖
+気
+氘
+氙
+氚
+氛
+氟
+氣
+氦
+氧
+氨
+氪
+氫
+氬
+氮
+氯
+氰
+水
+氵
+氷
+永
+氹
+氻
+氽
+氾
+汀
+汁
+求
+汊
+汎
+汐
+汕
+汗
+汛
+汜
+汝
+汞
+江
+池
+污
+汧
+汨
+汩
+汪
+汭
+汰
+汲
+汴
+汶
+決
+汽
+汾
+沁
+沂
+沃
+沄
+沅
+沆
+沇
+沈
+沉
+沌
+沍
+沏
+沐
+沒
+沓
+沔
+沖
+沘
+沙
+沚
+沛
+沜
+沢
+沨
+沫
+沭
+沮
+沯
+沱
+河
+沸
+油
+沺
+治
+沼
+沽
+沾
+沿
+況
+泂
+泄
+泆
+泇
+泉
+泊
+泌
+泐
+泓
+泔
+法
+泖
+泗
+泚
+泛
+泠
+泡
+波
+泣
+泥
+泩
+泫
+泮
+泯
+泰
+泱
+泳
+泵
+洄
+洋
+洌
+洎
+洗
+洙
+洛
+洞
+洢
+洣
+洤
+津
+洨
+洩
+洪
+洮
+洱
+洲
+洳
+洵
+洸
+洹
+洺
+活
+洽
+派
+流
+浄
+浙
+浚
+浛
+浜
+浞
+浟
+浠
+浡
+浣
+浤
+浥
+浦
+浩
+浪
+浮
+浯
+浴
+浵
+海
+浸
+浹
+涅
+涇
+消
+涉
+涌
+涎
+涑
+涓
+涔
+涕
+涙
+涪
+涫
+涮
+涯
+液
+涵
+涸
+涼
+涿
+淄
+淅
+淆
+淇
+淋
+淌
+淍
+淎
+淏
+淑
+淓
+淖
+淘
+淙
+淚
+淛
+淝
+淞
+淠
+淡
+淤
+淥
+淦
+淨
+淩
+淪
+淫
+淬
+淮
+淯
+淰
+深
+淳
+淵
+淶
+混
+淸
+淹
+淺
+添
+淼
+淽
+渃
+清
+済
+渉
+渋
+渕
+渙
+渚
+減
+渝
+渟
+渠
+渡
+渣
+渤
+渥
+渦
+渫
+測
+渭
+港
+渲
+渴
+游
+渺
+渼
+渽
+渾
+湃
+湄
+湉
+湊
+湍
+湓
+湔
+湖
+湘
+湛
+湜
+湞
+湟
+湣
+湥
+湧
+湫
+湮
+湯
+湳
+湴
+湼
+満
+溁
+溇
+溈
+溉
+溋
+溎
+溏
+源
+準
+溙
+溜
+溝
+溟
+溢
+溥
+溦
+溧
+溪
+溫
+溯
+溱
+溲
+溴
+溵
+溶
+溺
+溼
+滀
+滁
+滂
+滄
+滅
+滇
+滈
+滉
+滋
+滌
+滎
+滏
+滑
+滓
+滔
+滕
+滘
+滙
+滝
+滬
+滯
+滲
+滴
+滷
+滸
+滹
+滻
+滽
+滾
+滿
+漁
+漂
+漆
+漇
+漈
+漎
+漏
+漓
+演
+漕
+漚
+漠
+漢
+漣
+漩
+漪
+漫
+漬
+漯
+漱
+漲
+漳
+漴
+漵
+漷
+漸
+漼
+漾
+漿
+潁
+潑
+潔
+潘
+潛
+潞
+潟
+潢
+潤
+潭
+潮
+潯
+潰
+潲
+潺
+潼
+潽
+潾
+潿
+澀
+澁
+澂
+澄
+澆
+澇
+澈
+澉
+澋
+澌
+澍
+澎
+澔
+澗
+澠
+澡
+澣
+澤
+澥
+澧
+澪
+澮
+澯
+澱
+澳
+澶
+澹
+澻
+激
+濁
+濂
+濃
+濉
+濊
+濋
+濕
+濘
+濙
+濛
+濞
+濟
+濠
+濡
+濤
+濫
+濬
+濮
+濯
+濰
+濱
+濲
+濶
+濺
+濼
+濾
+瀁
+瀅
+瀆
+瀉
+瀍
+瀏
+瀑
+瀔
+瀕
+瀘
+瀚
+瀛
+瀝
+瀞
+瀟
+瀠
+瀣
+瀦
+瀧
+瀨
+瀬
+瀰
+瀲
+瀴
+瀶
+瀹
+瀾
+灃
+灊
+灌
+灑
+灘
+灝
+灞
+灡
+灣
+灤
+灧
+火
+灰
+灴
+灸
+灼
+災
+炁
+炅
+炆
+炊
+炎
+炒
+炔
+炕
+炘
+炙
+炟
+炣
+炤
+炫
+炬
+炭
+炮
+炯
+炱
+炲
+炳
+炷
+炸
+為
+炻
+烈
+烉
+烊
+烋
+烏
+烒
+烔
+烘
+烙
+烜
+烝
+烤
+烯
+烱
+烴
+烷
+烹
+烺
+烽
+焃
+焄
+焉
+焊
+焌
+焓
+焗
+焙
+焚
+焜
+焞
+無
+焦
+焯
+焰
+焱
+焴
+然
+焻
+焼
+焿
+煇
+煉
+煊
+煌
+煎
+煐
+煒
+煔
+煕
+煖
+煙
+煚
+煜
+煞
+煠
+煤
+煥
+煦
+照
+煨
+煩
+煬
+煮
+煲
+煳
+煵
+煶
+煸
+煽
+熄
+熅
+熇
+熈
+熊
+熏
+熒
+熔
+熖
+熗
+熘
+熙
+熜
+熟
+熠
+熤
+熥
+熨
+熬
+熯
+熱
+熲
+熳
+熵
+熹
+熺
+熼
+熾
+熿
+燁
+燃
+燄
+燈
+燉
+燊
+燎
+燏
+燐
+燒
+燔
+燕
+燘
+燙
+燚
+燜
+燝
+營
+燥
+燦
+燧
+燫
+燬
+燭
+燮
+燴
+燹
+燻
+燼
+燾
+燿
+爀
+爆
+爌
+爍
+爐
+爔
+爚
+爛
+爝
+爨
+爪
+爬
+爭
+爯
+爰
+爲
+爵
+父
+爸
+爹
+爺
+爻
+爽
+爾
+爿
+牁
+牂
+牆
+片
+版
+牌
+牒
+牕
+牖
+牘
+牙
+牛
+牝
+牟
+牠
+牡
+牢
+牧
+物
+牯
+牲
+特
+牻
+牼
+牽
+犀
+犁
+犂
+犇
+犍
+犎
+犖
+犛
+犢
+犧
+犨
+犬
+犯
+犰
+犴
+犽
+狀
+狂
+狄
+狍
+狎
+狐
+狒
+狓
+狗
+狙
+狛
+狟
+狠
+狡
+狦
+狨
+狩
+狳
+狶
+狷
+狸
+狹
+狻
+狼
+猁
+猄
+猇
+猊
+猗
+猙
+猛
+猜
+猝
+猞
+猢
+猥
+猨
+猩
+猳
+猴
+猶
+猷
+猺
+猻
+猾
+猿
+獁
+獃
+獄
+獅
+獇
+獎
+獏
+獐
+獒
+獠
+獢
+獣
+獨
+獬
+獮
+獯
+獰
+獲
+獴
+獵
+獷
+獸
+獺
+獻
+獼
+獾
+玀
+玄
+玆
+率
+玉
+王
+玎
+玏
+玓
+玕
+玖
+玗
+玘
+玙
+玟
+玠
+玡
+玢
+玥
+玧
+玨
+玩
+玫
+玭
+玲
+玳
+玶
+玷
+玹
+玻
+玾
+珀
+珂
+珅
+珈
+珉
+珊
+珌
+珍
+珎
+珏
+珖
+珙
+珝
+珞
+珠
+珡
+珣
+珤
+珥
+珦
+珧
+珩
+珪
+班
+珮
+珵
+珹
+珺
+珽
+現
+琁
+球
+琄
+琅
+理
+琇
+琉
+琊
+琍
+琎
+琚
+琛
+琡
+琢
+琤
+琥
+琦
+琨
+琪
+琬
+琮
+琯
+琰
+琱
+琳
+琴
+琵
+琶
+琹
+琺
+琿
+瑀
+瑁
+瑂
+瑄
+瑅
+瑆
+瑈
+瑊
+瑋
+瑑
+瑒
+瑕
+瑗
+瑙
+瑚
+瑛
+瑜
+瑝
+瑞
+瑟
+瑠
+瑢
+瑣
+瑤
+瑥
+瑧
+瑨
+瑩
+瑪
+瑭
+瑯
+瑰
+瑱
+瑳
+瑴
+瑺
+瑾
+璀
+璁
+璃
+璄
+璆
+璇
+璈
+璉
+璋
+璌
+璐
+璕
+璘
+璙
+璚
+璜
+璞
+璟
+璠
+璡
+璣
+璥
+璦
+璧
+璨
+璩
+璪
+璫
+璬
+璮
+環
+璱
+璵
+璸
+璹
+璽
+璿
+瓈
+瓊
+瓌
+瓏
+瓑
+瓔
+瓖
+瓘
+瓚
+瓛
+瓜
+瓞
+瓠
+瓢
+瓣
+瓤
+瓦
+瓮
+瓴
+瓶
+瓷
+瓿
+甂
+甄
+甌
+甍
+甑
+甕
+甘
+甙
+甚
+甜
+生
+甡
+產
+産
+甥
+甦
+用
+甩
+甪
+甫
+甬
+甯
+田
+由
+甲
+申
+男
+甸
+甹
+町
+甾
+畀
+畇
+畈
+畊
+畋
+界
+畎
+畏
+畐
+畑
+畔
+留
+畜
+畝
+畠
+畢
+略
+畦
+畧
+番
+畫
+畬
+畯
+異
+畲
+畳
+畵
+當
+畷
+畸
+畹
+畿
+疃
+疆
+疇
+疊
+疋
+疌
+疍
+疏
+疑
+疒
+疕
+疙
+疚
+疝
+疣
+疤
+疥
+疫
+疲
+疳
+疵
+疸
+疹
+疼
+疽
+疾
+痂
+病
+症
+痊
+痍
+痔
+痕
+痘
+痙
+痛
+痞
+痟
+痠
+痢
+痣
+痤
+痧
+痩
+痰
+痱
+痲
+痴
+痹
+痺
+痿
+瘀
+瘁
+瘊
+瘋
+瘍
+瘓
+瘙
+瘜
+瘞
+瘟
+瘠
+瘡
+瘢
+瘤
+瘦
+瘧
+瘩
+瘰
+瘴
+瘺
+癀
+療
+癆
+癇
+癌
+癒
+癖
+癘
+癜
+癟
+癡
+癢
+癤
+癥
+癩
+癬
+癭
+癮
+癯
+癰
+癱
+癲
+癸
+発
+登
+發
+白
+百
+皂
+的
+皆
+皇
+皈
+皋
+皎
+皐
+皓
+皖
+皙
+皚
+皛
+皝
+皞
+皮
+皰
+皴
+皷
+皸
+皺
+皿
+盂
+盃
+盅
+盆
+盈
+益
+盋
+盌
+盎
+盒
+盔
+盛
+盜
+盞
+盟
+盡
+監
+盤
+盥
+盦
+盧
+盨
+盩
+盪
+盫
+目
+盯
+盱
+盲
+直
+盷
+相
+盹
+盺
+盼
+盾
+眀
+省
+眉
+看
+県
+眙
+眛
+眜
+眞
+真
+眠
+眥
+眨
+眩
+眭
+眯
+眵
+眶
+眷
+眸
+眺
+眼
+眾
+着
+睇
+睛
+睜
+睞
+睡
+睢
+督
+睥
+睦
+睨
+睪
+睫
+睭
+睹
+睺
+睽
+睾
+睿
+瞄
+瞅
+瞋
+瞌
+瞎
+瞑
+瞓
+瞞
+瞢
+瞥
+瞧
+瞪
+瞫
+瞬
+瞭
+瞰
+瞳
+瞻
+瞼
+瞽
+瞿
+矇
+矍
+矗
+矚
+矛
+矜
+矞
+矢
+矣
+知
+矧
+矩
+短
+矮
+矯
+石
+矸
+矽
+砂
+砋
+砌
+砍
+砒
+研
+砝
+砢
+砥
+砦
+砧
+砩
+砫
+砭
+砮
+砯
+砰
+砲
+砳
+破
+砵
+砷
+砸
+砼
+硂
+硃
+硅
+硇
+硏
+硐
+硒
+硓
+硚
+硜
+硝
+硤
+硨
+硫
+硬
+硭
+硯
+硼
+碁
+碇
+碉
+碌
+碎
+碑
+碓
+碕
+碗
+碘
+碚
+碟
+碡
+碣
+碧
+碩
+碪
+碭
+碰
+碲
+碳
+碴
+碶
+碸
+確
+碻
+碼
+碽
+碾
+磁
+磅
+磊
+磋
+磐
+磔
+磕
+磘
+磙
+磚
+磜
+磡
+磨
+磪
+磬
+磯
+磱
+磲
+磵
+磷
+磺
+磻
+磾
+礁
+礄
+礎
+礐
+礑
+礒
+礙
+礠
+礦
+礪
+礫
+礬
+礮
+礱
+礴
+示
+礻
+礽
+社
+祀
+祁
+祂
+祆
+祇
+祈
+祉
+祋
+祏
+祐
+祓
+祕
+祖
+祗
+祙
+祚
+祛
+祜
+祝
+神
+祟
+祠
+祥
+祧
+票
+祭
+祹
+祺
+祼
+祿
+禁
+禃
+禇
+禍
+禎
+福
+禑
+禓
+禔
+禕
+禘
+禛
+禟
+禠
+禤
+禦
+禧
+禨
+禩
+禪
+禮
+禰
+禱
+禵
+禹
+禺
+禼
+禽
+禾
+禿
+秀
+私
+秈
+秉
+秋
+科
+秒
+秕
+秘
+租
+秠
+秣
+秤
+秦
+秧
+秩
+秭
+秳
+秸
+移
+稀
+稅
+稈
+稉
+程
+稍
+稑
+稔
+稗
+稘
+稙
+稚
+稜
+稞
+稟
+稠
+種
+稱
+稲
+稷
+稹
+稺
+稻
+稼
+稽
+稾
+稿
+穀
+穂
+穆
+穈
+穉
+穌
+積
+穎
+穗
+穟
+穠
+穡
+穢
+穣
+穩
+穫
+穰
+穴
+穵
+究
+穹
+空
+穿
+突
+窄
+窅
+窈
+窋
+窒
+窕
+窖
+窗
+窘
+窟
+窠
+窣
+窨
+窩
+窪
+窮
+窯
+窰
+窶
+窺
+窿
+竄
+竅
+竇
+竈
+竊
+立
+竑
+站
+竜
+竟
+章
+竣
+童
+竦
+竩
+竭
+端
+競
+竹
+竺
+竻
+竿
+笄
+笆
+笈
+笏
+笑
+笘
+笙
+笛
+笞
+笠
+笥
+符
+笨
+笩
+笪
+第
+笭
+笮
+笯
+笱
+笳
+笹
+筅
+筆
+等
+筊
+筋
+筌
+筍
+筏
+筐
+筒
+答
+策
+筘
+筠
+筥
+筦
+筧
+筬
+筭
+筱
+筲
+筳
+筵
+筶
+筷
+筻
+箆
+箇
+箋
+箍
+箏
+箐
+箑
+箒
+箔
+箕
+算
+箜
+管
+箬
+箭
+箱
+箴
+箸
+節
+篁
+範
+篆
+篇
+築
+篊
+篋
+篌
+篔
+篙
+篝
+篠
+篡
+篤
+篥
+篦
+篩
+篪
+篭
+篯
+篳
+篷
+簀
+簃
+簇
+簉
+簋
+簍
+簑
+簕
+簗
+簞
+簠
+簡
+簧
+簪
+簫
+簷
+簸
+簹
+簺
+簽
+簾
+簿
+籀
+籃
+籌
+籍
+籐
+籙
+籛
+籜
+籝
+籟
+籠
+籣
+籤
+籥
+籪
+籬
+籮
+籲
+米
+籽
+籾
+粄
+粉
+粍
+粑
+粒
+粕
+粗
+粘
+粟
+粢
+粥
+粦
+粧
+粩
+粱
+粲
+粳
+粵
+粹
+粼
+粽
+精
+粿
+糀
+糅
+糊
+糌
+糍
+糎
+糕
+糖
+糙
+糜
+糝
+糞
+糟
+糠
+糢
+糧
+糬
+糯
+糰
+糴
+糶
+糸
+糹
+糺
+系
+糾
+紀
+紂
+約
+紅
+紆
+紇
+紈
+紉
+紊
+紋
+納
+紐
+紑
+紓
+純
+紕
+紗
+紘
+紙
+級
+紛
+紜
+紝
+紞
+素
+紡
+索
+紫
+紮
+累
+細
+紱
+紲
+紳
+紵
+紹
+紺
+紿
+終
+絃
+組
+絆
+経
+絎
+結
+絕
+絛
+絜
+絞
+絡
+絢
+給
+絨
+絪
+絮
+統
+絲
+絳
+絵
+絶
+絹
+絺
+綁
+綃
+綈
+綉
+綎
+綏
+經
+綖
+継
+続
+綜
+綝
+綞
+綠
+綢
+綣
+綦
+綧
+綫
+綬
+維
+綮
+綰
+綱
+網
+綳
+綴
+綸
+綺
+綻
+綽
+綾
+綿
+緁
+緃
+緄
+緈
+緊
+緋
+総
+緑
+緒
+緖
+緘
+線
+緜
+緝
+緞
+締
+緡
+緣
+緤
+編
+緩
+緬
+緯
+緱
+緲
+練
+緹
+緻
+縂
+縄
+縈
+縉
+縊
+縕
+縛
+縝
+縞
+縠
+縡
+縣
+縤
+縫
+縮
+縯
+縱
+縴
+縵
+縷
+縹
+縻
+總
+績
+繁
+繃
+繆
+繇
+繒
+織
+繕
+繖
+繙
+繚
+繞
+繡
+繩
+繪
+繫
+繭
+繰
+繳
+繹
+繻
+繼
+繽
+繾
+纁
+纂
+纈
+續
+纍
+纏
+纓
+纔
+纕
+纖
+纘
+纛
+纜
+缐
+缶
+缸
+缺
+缽
+罃
+罄
+罅
+罈
+罉
+罌
+罍
+罐
+罔
+罕
+罘
+罟
+罡
+罨
+罩
+罪
+置
+罰
+罱
+署
+罳
+罵
+罶
+罷
+罹
+罽
+羂
+羅
+羆
+羈
+羊
+羋
+羌
+美
+羔
+羕
+羗
+羙
+羚
+羞
+羡
+羣
+群
+羥
+羧
+羨
+義
+羯
+羰
+羱
+羲
+羸
+羹
+羽
+羿
+翀
+翁
+翂
+翃
+翅
+翊
+翌
+翎
+翏
+習
+翔
+翕
+翙
+翜
+翟
+翠
+翡
+翥
+翦
+翩
+翬
+翮
+翰
+翱
+翳
+翹
+翻
+翼
+耀
+老
+考
+耄
+者
+耆
+而
+耍
+耎
+耐
+耑
+耒
+耔
+耕
+耗
+耘
+耙
+耜
+耦
+耨
+耬
+耳
+耵
+耶
+耷
+耽
+耿
+聃
+聆
+聊
+聒
+聖
+聘
+聚
+聞
+聟
+聨
+聯
+聰
+聱
+聲
+聳
+聴
+聶
+職
+聽
+聾
+聿
+肄
+肅
+肆
+肇
+肉
+肋
+肌
+肏
+肖
+肘
+肚
+肛
+肜
+肝
+肟
+股
+肢
+肥
+肩
+肪
+肫
+肯
+肱
+育
+肸
+肹
+肺
+肼
+肽
+胂
+胃
+胄
+胅
+胇
+胊
+背
+胍
+胎
+胖
+胗
+胙
+胚
+胛
+胝
+胞
+胡
+胤
+胥
+胬
+胭
+胰
+胱
+胳
+胴
+胸
+胺
+胼
+能
+脂
+脅
+脆
+脇
+脈
+脊
+脒
+脖
+脘
+脛
+脣
+脩
+脫
+脬
+脭
+脯
+脲
+脳
+脷
+脹
+脾
+腆
+腈
+腊
+腋
+腌
+腎
+腐
+腑
+腓
+腔
+腕
+腥
+腦
+腧
+腩
+腫
+腮
+腰
+腱
+腳
+腴
+腸
+腹
+腺
+腿
+膀
+膂
+膈
+膊
+膏
+膚
+膛
+膜
+膝
+膠
+膣
+膥
+膦
+膨
+膩
+膮
+膳
+膺
+膽
+膾
+膿
+臀
+臂
+臃
+臆
+臉
+臊
+臍
+臏
+臘
+臚
+臞
+臟
+臠
+臣
+臧
+臨
+自
+臭
+臯
+至
+致
+臺
+臻
+臼
+臾
+舂
+舅
+與
+興
+舉
+舊
+舌
+舍
+舎
+舒
+舔
+舖
+舘
+舛
+舜
+舞
+舟
+舢
+舥
+舨
+舩
+航
+舫
+般
+舲
+舵
+舶
+舷
+舸
+船
+舺
+艅
+艇
+艉
+艋
+艎
+艏
+艔
+艘
+艙
+艚
+艦
+艮
+良
+艱
+色
+艶
+艷
+艸
+艽
+艾
+艿
+芃
+芊
+芋
+芍
+芎
+芑
+芒
+芘
+芙
+芛
+芝
+芡
+芥
+芨
+芩
+芪
+芫
+芬
+芭
+芮
+芯
+花
+芳
+芴
+芷
+芸
+芹
+芻
+芽
+芾
+苄
+苅
+苑
+苒
+苓
+苔
+苕
+苗
+苛
+苜
+苝
+苞
+苟
+苡
+苣
+苤
+若
+苦
+苧
+苪
+苫
+苯
+英
+苳
+苴
+苷
+苺
+苻
+苼
+苾
+茀
+茁
+茂
+范
+茄
+茅
+茆
+茇
+茈
+茉
+茌
+茗
+茘
+茚
+茛
+茜
+茝
+茨
+茫
+茬
+茭
+茮
+茯
+茱
+茲
+茴
+茵
+茶
+茷
+茸
+茹
+茺
+茼
+荀
+荃
+荅
+荇
+草
+荊
+荎
+荏
+荒
+荔
+荖
+荘
+荳
+荷
+荸
+荻
+荼
+荽
+莆
+莉
+莊
+莎
+莒
+莓
+莕
+莖
+莘
+莙
+莛
+莜
+莞
+莠
+莢
+莧
+莨
+莩
+莪
+莫
+莽
+莿
+菀
+菁
+菅
+菇
+菈
+菉
+菊
+菌
+菍
+菏
+菑
+菓
+菔
+菖
+菘
+菜
+菝
+菟
+菠
+菡
+菥
+菩
+菪
+菫
+華
+菰
+菱
+菲
+菴
+菶
+菸
+菹
+菺
+菼
+菽
+菾
+萁
+萃
+萄
+萇
+萊
+萌
+萍
+萎
+萐
+萘
+萜
+萠
+萡
+萣
+萩
+萬
+萭
+萱
+萵
+萸
+萹
+萼
+落
+葃
+葆
+葉
+葊
+葎
+葑
+葒
+著
+葙
+葚
+葛
+葜
+葝
+葡
+董
+葦
+葩
+葫
+葬
+葭
+葯
+葰
+葳
+葵
+葶
+葷
+葺
+蒂
+蒄
+蒍
+蒎
+蒐
+蒓
+蒔
+蒗
+蒙
+蒜
+蒞
+蒟
+蒡
+蒢
+蒤
+蒧
+蒨
+蒭
+蒯
+蒲
+蒴
+蒸
+蒹
+蒺
+蒻
+蒼
+蒽
+蒾
+蒿
+蓀
+蓁
+蓂
+蓄
+蓆
+蓉
+蓋
+蓍
+蓑
+蓓
+蓖
+蓘
+蓚
+蓧
+蓨
+蓪
+蓬
+蓭
+蓮
+蓯
+蓳
+蓼
+蓽
+蓿
+蔆
+蔎
+蔑
+蔓
+蔔
+蔕
+蔗
+蔘
+蔚
+蔝
+蔞
+蔡
+蔣
+蔥
+蔦
+蔬
+蔭
+蔴
+蔵
+蔻
+蔽
+蕁
+蕃
+蕅
+蕈
+蕉
+蕊
+蕎
+蕑
+蕒
+蕖
+蕘
+蕙
+蕚
+蕟
+蕡
+蕢
+蕤
+蕨
+蕩
+蕪
+蕭
+蕷
+蕹
+蕺
+蕻
+蕾
+薀
+薄
+薆
+薇
+薈
+薊
+薌
+薏
+薐
+薑
+薔
+薗
+薘
+薙
+薛
+薜
+薞
+薟
+薡
+薦
+薨
+薩
+薪
+薫
+薬
+薯
+薰
+薲
+薷
+薸
+薹
+薺
+薾
+薿
+藁
+藉
+藍
+藎
+藏
+藐
+藔
+藕
+藜
+藝
+藟
+藤
+藥
+藦
+藨
+藩
+藪
+藶
+藸
+藹
+藺
+藻
+藿
+蘂
+蘄
+蘅
+蘆
+蘇
+蘊
+蘋
+蘐
+蘑
+蘓
+蘗
+蘘
+蘚
+蘞
+蘢
+蘧
+蘩
+蘭
+蘵
+蘶
+蘸
+蘼
+蘿
+虉
+虎
+虐
+虓
+虔
+處
+虖
+虛
+虜
+虞
+號
+虢
+虧
+虨
+虯
+虱
+虵
+虹
+虺
+虻
+蚆
+蚊
+蚋
+蚌
+蚍
+蚓
+蚖
+蚜
+蚝
+蚡
+蚢
+蚣
+蚤
+蚧
+蚨
+蚩
+蚪
+蚯
+蚱
+蚴
+蚵
+蚶
+蚺
+蚼
+蛀
+蛄
+蛇
+蛉
+蛋
+蛍
+蛐
+蛑
+蛔
+蛙
+蛛
+蛞
+蛟
+蛤
+蛭
+蛯
+蛸
+蛹
+蛺
+蛻
+蛾
+蜀
+蜂
+蜃
+蜆
+蜇
+蜈
+蜉
+蜊
+蜍
+蜑
+蜒
+蜓
+蜘
+蜚
+蜛
+蜜
+蜞
+蜢
+蜣
+蜥
+蜨
+蜮
+蜯
+蜱
+蜴
+蜷
+蜻
+蜾
+蜿
+蝀
+蝌
+蝍
+蝎
+蝓
+蝕
+蝗
+蝘
+蝙
+蝚
+蝟
+蝠
+蝣
+蝤
+蝦
+蝨
+蝮
+蝯
+蝰
+蝲
+蝴
+蝶
+蝸
+蝽
+螂
+螃
+螄
+螅
+螈
+螋
+融
+螐
+螔
+螞
+螟
+螠
+螢
+螣
+螥
+螫
+螭
+螯
+螳
+螶
+螺
+螻
+螽
+螾
+蟀
+蟄
+蟅
+蟆
+蟊
+蟋
+蟌
+蟎
+蟑
+蟒
+蟜
+蟠
+蟥
+蟪
+蟫
+蟬
+蟯
+蟲
+蟳
+蟴
+蟶
+蟹
+蟻
+蟾
+蠂
+蠃
+蠄
+蠅
+蠆
+蠊
+蠋
+蠍
+蠐
+蠑
+蠓
+蠔
+蠕
+蠖
+蠘
+蠙
+蠟
+蠡
+蠢
+蠣
+蠱
+蠲
+蠵
+蠶
+蠷
+蠹
+蠻
+血
+衂
+衆
+行
+衍
+衎
+術
+衕
+衖
+街
+衙
+衚
+衛
+衜
+衝
+衞
+衡
+衢
+衣
+表
+衩
+衫
+衰
+衲
+衷
+衽
+衾
+衿
+袁
+袂
+袈
+袋
+袍
+袓
+袖
+袛
+袞
+袤
+袪
+被
+袱
+袴
+袾
+裁
+裂
+裊
+裎
+裒
+裔
+裕
+裖
+裘
+裙
+補
+裝
+裟
+裡
+裨
+裬
+裱
+裳
+裴
+裵
+裸
+裹
+製
+裾
+裿
+褀
+褂
+複
+褌
+褍
+褎
+褐
+褒
+褓
+褔
+褘
+褙
+褚
+褞
+褥
+褧
+褪
+褫
+褭
+褲
+褶
+褸
+褻
+襄
+襌
+襖
+襞
+襟
+襠
+襤
+襦
+襪
+襯
+襲
+襴
+襶
+襻
+襾
+西
+要
+覃
+覆
+覇
+覈
+見
+覌
+規
+覓
+視
+覚
+覡
+覦
+覧
+親
+覬
+覲
+観
+覺
+覽
+覿
+觀
+角
+觔
+觙
+觚
+觜
+解
+觭
+觱
+觴
+觶
+觸
+觿
+言
+訁
+訂
+訃
+訇
+計
+訊
+訌
+討
+訏
+訐
+訒
+訓
+訔
+訕
+訖
+託
+記
+訛
+訝
+訟
+訣
+訥
+訪
+設
+許
+訴
+訶
+診
+註
+証
+訾
+詁
+詆
+詈
+詐
+詒
+詔
+評
+詛
+詞
+詠
+詡
+詢
+詣
+詥
+試
+詧
+詩
+詫
+詭
+詮
+詰
+話
+該
+詳
+詵
+詹
+詼
+誄
+誅
+誇
+誌
+認
+誒
+誓
+誕
+誘
+語
+誠
+誡
+誣
+誤
+誥
+誦
+誨
+說
+説
+読
+誰
+課
+誴
+誹
+誼
+誾
+調
+談
+請
+諍
+諏
+諒
+論
+諗
+諜
+諟
+諠
+諡
+諤
+諦
+諧
+諪
+諫
+諭
+諮
+諱
+諲
+諳
+諴
+諶
+諷
+諸
+諺
+諼
+諾
+謀
+謁
+謂
+謄
+謇
+謊
+謌
+謎
+謏
+謐
+謔
+謖
+謗
+謙
+謚
+講
+謜
+謝
+謠
+謢
+謤
+謨
+謩
+謫
+謬
+謳
+謹
+謾
+證
+譏
+譓
+譔
+識
+譙
+譚
+譜
+譞
+警
+譫
+譬
+譭
+譯
+議
+譲
+譳
+譴
+護
+譽
+譿
+讀
+讃
+變
+讌
+讎
+讓
+讖
+讙
+讚
+讜
+讞
+谷
+谿
+豁
+豆
+豇
+豈
+豉
+豊
+豌
+豎
+豐
+豔
+豕
+豚
+象
+豢
+豨
+豪
+豫
+豬
+豳
+豸
+豹
+豺
+豿
+貂
+貅
+貉
+貊
+貌
+貐
+貒
+貓
+貔
+貘
+貝
+貞
+負
+財
+貢
+貤
+貧
+貨
+販
+貪
+貫
+責
+貭
+貮
+貯
+貲
+貳
+貴
+貶
+買
+貸
+貺
+費
+貼
+貽
+貿
+賀
+賁
+賂
+賃
+賄
+資
+賈
+賊
+賑
+賒
+賓
+賔
+賕
+賚
+賜
+賞
+賠
+賡
+賢
+賣
+賤
+賦
+賨
+質
+賬
+賭
+賴
+賹
+賺
+賻
+購
+賽
+賾
+贄
+贅
+贇
+贈
+贊
+贌
+贍
+贏
+贓
+贔
+贖
+贛
+赤
+赦
+赧
+赫
+赬
+赭
+走
+赳
+赴
+起
+趁
+超
+越
+趐
+趕
+趖
+趙
+趟
+趣
+趨
+足
+趴
+趵
+趺
+趼
+趾
+跅
+跆
+跋
+跌
+跏
+跑
+跖
+跗
+跛
+距
+跟
+跡
+跣
+跤
+跨
+跩
+跪
+路
+跳
+踎
+踏
+踐
+踝
+踞
+踢
+踩
+踰
+踴
+踹
+踺
+蹂
+蹄
+蹇
+蹈
+蹉
+蹊
+蹋
+蹕
+蹙
+蹟
+蹠
+蹤
+蹦
+蹬
+蹭
+蹯
+蹲
+蹴
+蹶
+蹺
+蹻
+蹼
+躁
+躂
+躄
+躉
+躋
+躍
+躑
+躒
+躔
+躝
+躪
+身
+躬
+躰
+躲
+躺
+軀
+車
+軋
+軌
+軍
+軎
+軒
+軔
+軛
+軟
+転
+軫
+軲
+軸
+軹
+軺
+軻
+軼
+軽
+軾
+較
+輄
+輅
+載
+輋
+輒
+輓
+輔
+輕
+輛
+輝
+輞
+輟
+輥
+輦
+輩
+輪
+輬
+輭
+輯
+輶
+輸
+輻
+輾
+輿
+轀
+轂
+轄
+轅
+轆
+轉
+轍
+轎
+轘
+轝
+轟
+轤
+辛
+辜
+辟
+辣
+辦
+辧
+辨
+辭
+辮
+辯
+辰
+辱
+農
+辵
+辺
+辻
+込
+迂
+迄
+迅
+迎
+近
+返
+迢
+迤
+迥
+迦
+迪
+迫
+迭
+迮
+述
+迴
+迵
+迷
+迸
+迺
+追
+退
+送
+逃
+逄
+逅
+逆
+逈
+逋
+逌
+逍
+逎
+透
+逐
+逑
+途
+逕
+逖
+逗
+這
+通
+逛
+逝
+逞
+速
+造
+逢
+連
+逤
+逨
+逮
+逯
+進
+逴
+逵
+逸
+逹
+逺
+逼
+逾
+遁
+遂
+遄
+遇
+遊
+運
+遍
+過
+遏
+遐
+遒
+道
+達
+違
+遘
+遙
+遛
+遜
+遞
+遠
+遢
+遣
+遨
+適
+遭
+遮
+遯
+遲
+遴
+遵
+遶
+遷
+選
+遹
+遺
+遼
+避
+邀
+邁
+邂
+邃
+還
+邇
+邈
+邉
+邊
+邋
+邏
+邑
+邕
+邗
+邙
+邛
+邠
+邡
+邢
+那
+邦
+邨
+邪
+邯
+邰
+邱
+邲
+邳
+邴
+邵
+邸
+邽
+邾
+郁
+郃
+郄
+郅
+郇
+郊
+郋
+郎
+郗
+郛
+郜
+郝
+郞
+郟
+郡
+郢
+郤
+部
+郪
+郫
+郭
+郯
+郳
+郴
+郵
+郷
+都
+郾
+郿
+鄂
+鄃
+鄄
+鄆
+鄉
+鄋
+鄑
+鄒
+鄔
+鄖
+鄗
+鄘
+鄙
+鄚
+鄜
+鄞
+鄠
+鄢
+鄣
+鄤
+鄧
+鄩
+鄫
+鄭
+鄯
+鄰
+鄱
+鄲
+鄳
+鄴
+鄺
+酃
+酆
+酈
+酉
+酊
+酋
+酌
+配
+酎
+酏
+酐
+酒
+酔
+酗
+酚
+酞
+酡
+酢
+酣
+酥
+酩
+酪
+酬
+酮
+酯
+酰
+酴
+酵
+酶
+酷
+酸
+酺
+酼
+醁
+醂
+醃
+醅
+醇
+醉
+醋
+醌
+醍
+醐
+醒
+醚
+醛
+醜
+醞
+醢
+醣
+醪
+醫
+醬
+醮
+醯
+醴
+醺
+醾
+醿
+釀
+釁
+釆
+采
+釉
+釋
+里
+重
+野
+量
+釐
+金
+釒
+釓
+釔
+釕
+釗
+釘
+釙
+釚
+釜
+針
+釣
+釤
+釦
+釧
+釩
+釪
+釭
+釴
+釵
+釷
+釹
+釺
+鈀
+鈁
+鈄
+鈇
+鈈
+鈉
+鈊
+鈍
+鈏
+鈐
+鈑
+鈔
+鈕
+鈖
+鈞
+鈢
+鈣
+鈥
+鈦
+鈫
+鈮
+鈰
+鈳
+鈴
+鈷
+鈸
+鈹
+鈺
+鈾
+鈿
+鉀
+鉄
+鉅
+鉆
+鉈
+鉉
+鉋
+鉌
+鉍
+鉏
+鉑
+鉓
+鉗
+鉚
+鉛
+鉞
+鉟
+鉤
+鉦
+鉬
+鉭
+鉲
+鉶
+鉷
+鉸
+鉻
+鉾
+鉿
+銀
+銂
+銃
+銅
+銋
+銍
+銑
+銓
+銕
+銖
+銘
+銚
+銜
+銠
+銣
+銥
+銦
+銨
+銩
+銪
+銫
+銬
+銭
+銱
+銲
+銳
+銶
+銷
+銹
+銻
+銼
+銾
+鋁
+鋅
+鋆
+鋇
+鋌
+鋏
+鋐
+鋒
+鋕
+鋗
+鋙
+鋡
+鋤
+鋥
+鋦
+鋨
+鋪
+鋮
+鋯
+鋰
+鋱
+鋳
+鋶
+鋸
+鋹
+鋼
+錀
+錄
+錏
+錐
+錒
+錕
+錘
+錚
+錞
+錟
+錠
+錡
+錢
+錦
+錨
+錫
+錬
+錮
+錯
+錳
+錶
+錸
+錻
+鍀
+鍇
+鍈
+鍉
+鍊
+鍋
+鍍
+鍏
+鍔
+鍘
+鍛
+鍝
+鍟
+鍠
+鍥
+鍩
+鍬
+鍱
+鍳
+鍵
+鍶
+鍷
+鍺
+鍼
+鍾
+鎂
+鎅
+鎊
+鎌
+鎏
+鎓
+鎔
+鎖
+鎗
+鎘
+鎚
+鎛
+鎢
+鎣
+鎦
+鎧
+鎪
+鎬
+鎭
+鎮
+鎰
+鎳
+鎵
+鎻
+鏃
+鏇
+鏈
+鏊
+鏌
+鏐
+鏑
+鏓
+鏖
+鏗
+鏘
+鏜
+鏝
+鏞
+鏟
+鏡
+鏢
+鏤
+鏦
+鏳
+鏴
+鏵
+鏷
+鏻
+鏽
+鐃
+鐇
+鐈
+鐓
+鐔
+鐘
+鐙
+鐠
+鐡
+鐤
+鐦
+鐧
+鐫
+鐬
+鐭
+鐮
+鐲
+鐳
+鐵
+鐸
+鐺
+鐽
+鐿
+鑀
+鑁
+鑂
+鑄
+鑅
+鑊
+鑌
+鑑
+鑒
+鑛
+鑠
+鑣
+鑨
+鑪
+鑫
+鑭
+鑰
+鑲
+鑴
+鑷
+鑼
+鑽
+鑾
+鑿
+長
+門
+閂
+閃
+閆
+閉
+開
+閎
+閏
+閑
+閒
+間
+閔
+閘
+閜
+閞
+閟
+関
+閣
+閥
+閦
+閨
+閩
+閬
+閭
+閰
+閱
+閶
+閹
+閻
+閼
+閾
+閿
+闆
+闇
+闈
+闊
+闋
+闌
+闍
+闐
+闓
+闔
+闕
+闖
+闘
+關
+闞
+闡
+闢
+闥
+阜
+阝
+阡
+阪
+阭
+阮
+阯
+阱
+防
+阻
+阿
+陀
+陁
+陂
+附
+陋
+陌
+降
+限
+陔
+陘
+陛
+陜
+陝
+陞
+陟
+陡
+院
+陣
+除
+陪
+陬
+陰
+陲
+陳
+陵
+陶
+陷
+陸
+険
+陽
+隄
+隅
+隆
+隈
+隊
+隋
+隍
+階
+隔
+隕
+隗
+隘
+隙
+際
+障
+隣
+隧
+隨
+險
+隰
+隱
+隲
+隳
+隴
+隷
+隸
+隹
+隻
+隼
+雀
+雁
+雄
+雅
+集
+雇
+雉
+雋
+雌
+雍
+雎
+雑
+雒
+雕
+雖
+雙
+雛
+雜
+雝
+雞
+離
+難
+雨
+雩
+雪
+雫
+雯
+雱
+雲
+零
+雷
+雹
+電
+需
+霄
+霅
+霆
+震
+霈
+霉
+霊
+霍
+霎
+霏
+霑
+霓
+霖
+霙
+霜
+霞
+霤
+霧
+霨
+霰
+露
+霶
+霸
+霹
+霽
+霾
+靁
+靂
+靄
+靈
+靉
+靑
+青
+靖
+靚
+靛
+靜
+非
+靠
+靡
+面
+革
+靫
+靬
+靭
+靳
+靴
+靶
+靺
+靼
+鞅
+鞆
+鞋
+鞍
+鞏
+鞘
+鞞
+鞠
+鞣
+鞥
+鞦
+鞨
+鞭
+鞮
+鞴
+韁
+韃
+韆
+韋
+韌
+韑
+韓
+韙
+韜
+韞
+韠
+韡
+韭
+韮
+音
+韶
+韺
+韻
+韾
+響
+頁
+頂
+頃
+項
+順
+須
+頊
+頌
+頍
+頎
+頏
+預
+頑
+頒
+頓
+頔
+頗
+領
+頜
+頠
+頡
+頤
+頦
+頫
+頭
+頰
+頴
+頵
+頷
+頸
+頹
+頻
+頼
+顆
+題
+額
+顎
+顏
+顒
+顓
+顔
+顕
+顗
+願
+顙
+顛
+類
+顥
+顧
+顫
+顯
+顰
+顱
+顳
+顴
+風
+颮
+颯
+颱
+颶
+颺
+颼
+飄
+飆
+飈
+飛
+食
+飠
+飡
+飢
+飥
+飩
+飪
+飫
+飬
+飭
+飮
+飯
+飲
+飴
+飼
+飽
+飾
+餃
+餄
+餅
+餉
+養
+餌
+餎
+餐
+餒
+餓
+餗
+餘
+餚
+餛
+餞
+餠
+餡
+館
+餮
+餵
+餺
+餾
+餿
+饃
+饅
+饋
+饌
+饑
+饒
+饕
+饗
+饞
+饟
+饢
+首
+馗
+馘
+香
+馛
+馥
+馦
+馨
+馬
+馭
+馮
+馯
+馱
+馳
+馴
+馼
+駁
+駄
+駅
+駆
+駐
+駑
+駒
+駔
+駕
+駘
+駙
+駛
+駝
+駟
+駢
+駭
+駰
+駱
+駿
+騁
+騂
+騄
+騅
+騋
+騎
+騏
+験
+騖
+騙
+騤
+騨
+騫
+騭
+騮
+騰
+騶
+騷
+騾
+驁
+驃
+驄
+驅
+驊
+驌
+驍
+驎
+驒
+驕
+驗
+驚
+驛
+驟
+驢
+驤
+驥
+驩
+驪
+骨
+骯
+骰
+骶
+骷
+骸
+骼
+髀
+髂
+髎
+髏
+髑
+髒
+髓
+體
+高
+髙
+髡
+髦
+髪
+髭
+髮
+髯
+髲
+髷
+髹
+髻
+鬃
+鬄
+鬅
+鬆
+鬍
+鬚
+鬟
+鬢
+鬣
+鬥
+鬧
+鬨
+鬩
+鬪
+鬬
+鬮
+鬯
+鬱
+鬲
+鬹
+鬻
+鬼
+魁
+魂
+魃
+魄
+魅
+魈
+魋
+魍
+魎
+魏
+魔
+魕
+魘
+魚
+魛
+魞
+魟
+魣
+魨
+魩
+魮
+魯
+魴
+魷
+鮀
+鮁
+鮃
+鮄
+鮊
+鮋
+鮍
+鮐
+鮑
+鮒
+鮓
+鮗
+鮜
+鮟
+鮠
+鮡
+鮣
+鮨
+鮪
+鮫
+鮭
+鮮
+鮰
+鮸
+鮹
+鮻
+鯀
+鯁
+鯃
+鯇
+鯉
+鯊
+鯏
+鯒
+鯓
+鯔
+鯕
+鯖
+鯗
+鯙
+鯛
+鯡
+鯢
+鯤
+鯧
+鯨
+鯪
+鯭
+鯮
+鯰
+鯶
+鯷
+鯻
+鯽
+鯿
+鰂
+鰃
+鰆
+鰈
+鰉
+鰍
+鰏
+鰒
+鰓
+鰕
+鰗
+鰛
+鰜
+鰟
+鰣
+鰤
+鰧
+鰨
+鰩
+鰭
+鰮
+鰱
+鰲
+鰳
+鰶
+鰷
+鰹
+鰺
+鰻
+鰼
+鰾
+鱀
+鱂
+鱅
+鱇
+鱈
+鱉
+鱊
+鱒
+鱓
+鱔
+鱖
+鱗
+鱘
+鱚
+鱝
+鱟
+鱠
+鱣
+鱥
+鱧
+鱨
+鱬
+鱮
+鱰
+鱲
+鱵
+鱷
+鱸
+鱺
+鱻
+鳥
+鳧
+鳩
+鳯
+鳰
+鳳
+鳴
+鳶
+鳽
+鴆
+鴇
+鴉
+鴒
+鴓
+鴕
+鴗
+鴛
+鴝
+鴞
+鴟
+鴡
+鴣
+鴦
+鴨
+鴫
+鴯
+鴰
+鴴
+鴻
+鴿
+鵂
+鵄
+鵎
+鵐
+鵑
+鵒
+鵓
+鵙
+鵜
+鵝
+鵞
+鵟
+鵠
+鵡
+鵪
+鵬
+鵯
+鵰
+鵲
+鵵
+鵼
+鵾
+鶆
+鶇
+鶉
+鶏
+鶒
+鶓
+鶘
+鶚
+鶡
+鶥
+鶩
+鶬
+鶯
+鶲
+鶴
+鶹
+鶺
+鶻
+鶼
+鶿
+鷂
+鷄
+鷉
+鷎
+鷓
+鷗
+鷙
+鷚
+鷟
+鷥
+鷦
+鷫
+鷯
+鷲
+鷳
+鷸
+鷹
+鷺
+鸊
+鸌
+鸐
+鸑
+鸕
+鸘
+鸚
+鸛
+鸜
+鸝
+鸞
+鹮
+鹵
+鹹
+鹼
+鹽
+鹿
+麂
+麅
+麇
+麈
+麊
+麋
+麐
+麒
+麓
+麗
+麝
+麞
+麟
+麥
+麩
+麪
+麯
+麴
+麵
+麹
+麺
+麻
+麼
+麽
+麾
+麿
+黁
+黃
+黇
+黌
+黍
+黎
+黏
+黐
+黑
+黒
+黔
+默
+黙
+黛
+黜
+黝
+點
+黟
+黥
+黧
+黨
+黯
+黴
+黶
+黻
+黼
+黽
+黿
+鼂
+鼇
+鼈
+鼉
+鼎
+鼐
+鼒
+鼓
+鼕
+鼙
+鼠
+鼢
+鼩
+鼬
+鼯
+鼱
+鼴
+鼷
+鼻
+鼽
+鼾
+齊
+齋
+齒
+齕
+齡
+齣
+齦
+齧
+齲
+齶
+龍
+龎
+龐
+龑
+龔
+龕
+龜
+龝
+龠
+龢
+郎
+凉
+﹑
+﹗
+﹝
+﹞
+﹢
+!
+"
+#
+$
+%
+&
+'
+(
+)
+*
++
+,
+-
+.
+/
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+:
+;
+<
+=
+>
+?
+A
+B
+C
+D
+E
+F
+G
+H
+I
+K
+L
+M
+N
+O
+P
+R
+S
+T
+U
+V
+W
+Y
+Z
+[
+]
+`
+a
+b
+c
+d
+e
+f
+g
+h
+i
+j
+k
+l
+m
+n
+o
+p
+r
+s
+t
+u
+z
+{
+|
+}
+~
+¥
+𣇉
+
diff --git a/BetterGenshinImpact/Assets/Model/PaddleOCR/en_PP-OCRv3_det_infer/inference.pdiparams b/BetterGenshinImpact/Assets/Model/PaddleOCR/en_PP-OCRv3_det_infer/inference.pdiparams
new file mode 100644
index 00000000..2efedca1
Binary files /dev/null and b/BetterGenshinImpact/Assets/Model/PaddleOCR/en_PP-OCRv3_det_infer/inference.pdiparams differ
diff --git a/BetterGenshinImpact/Assets/Model/PaddleOCR/en_PP-OCRv3_det_infer/inference.pdiparams.info b/BetterGenshinImpact/Assets/Model/PaddleOCR/en_PP-OCRv3_det_infer/inference.pdiparams.info
new file mode 100644
index 00000000..622d87ba
Binary files /dev/null and b/BetterGenshinImpact/Assets/Model/PaddleOCR/en_PP-OCRv3_det_infer/inference.pdiparams.info differ
diff --git a/BetterGenshinImpact/Assets/Model/PaddleOCR/en_PP-OCRv3_det_infer/inference.pdmodel b/BetterGenshinImpact/Assets/Model/PaddleOCR/en_PP-OCRv3_det_infer/inference.pdmodel
new file mode 100644
index 00000000..0a6bf1e4
Binary files /dev/null and b/BetterGenshinImpact/Assets/Model/PaddleOCR/en_PP-OCRv3_det_infer/inference.pdmodel differ
diff --git a/BetterGenshinImpact/Assets/Model/PaddleOCR/latin_PP-OCRv3_rec_infer/inference.pdiparams b/BetterGenshinImpact/Assets/Model/PaddleOCR/latin_PP-OCRv3_rec_infer/inference.pdiparams
new file mode 100644
index 00000000..6a7305b7
Binary files /dev/null and b/BetterGenshinImpact/Assets/Model/PaddleOCR/latin_PP-OCRv3_rec_infer/inference.pdiparams differ
diff --git a/BetterGenshinImpact/Assets/Model/PaddleOCR/latin_PP-OCRv3_rec_infer/inference.pdiparams.info b/BetterGenshinImpact/Assets/Model/PaddleOCR/latin_PP-OCRv3_rec_infer/inference.pdiparams.info
new file mode 100644
index 00000000..1cdccfce
Binary files /dev/null and b/BetterGenshinImpact/Assets/Model/PaddleOCR/latin_PP-OCRv3_rec_infer/inference.pdiparams.info differ
diff --git a/BetterGenshinImpact/Assets/Model/PaddleOCR/latin_PP-OCRv3_rec_infer/inference.pdmodel b/BetterGenshinImpact/Assets/Model/PaddleOCR/latin_PP-OCRv3_rec_infer/inference.pdmodel
new file mode 100644
index 00000000..144978c1
Binary files /dev/null and b/BetterGenshinImpact/Assets/Model/PaddleOCR/latin_PP-OCRv3_rec_infer/inference.pdmodel differ
diff --git a/BetterGenshinImpact/Assets/Model/PaddleOCR/latin_dict.txt b/BetterGenshinImpact/Assets/Model/PaddleOCR/latin_dict.txt
new file mode 100644
index 00000000..e166bf33
--- /dev/null
+++ b/BetterGenshinImpact/Assets/Model/PaddleOCR/latin_dict.txt
@@ -0,0 +1,185 @@
+
+!
+"
+#
+$
+%
+&
+'
+(
+)
+*
++
+,
+-
+.
+/
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+:
+;
+<
+=
+>
+?
+@
+A
+B
+C
+D
+E
+F
+G
+H
+I
+J
+K
+L
+M
+N
+O
+P
+Q
+R
+S
+T
+U
+V
+W
+X
+Y
+Z
+[
+]
+_
+`
+a
+b
+c
+d
+e
+f
+g
+h
+i
+j
+k
+l
+m
+n
+o
+p
+q
+r
+s
+t
+u
+v
+w
+x
+y
+z
+{
+}
+¡
+£
+§
+ª
+«
+
+°
+²
+³
+´
+µ
+·
+º
+»
+¿
+À
+Á
+Â
+Ä
+Å
+Ç
+È
+É
+Ê
+Ë
+Ì
+Í
+Î
+Ï
+Ò
+Ó
+Ô
+Õ
+Ö
+Ú
+Ü
+Ý
+ß
+à
+á
+â
+ã
+ä
+å
+æ
+ç
+è
+é
+ê
+ë
+ì
+í
+î
+ï
+ñ
+ò
+ó
+ô
+õ
+ö
+ø
+ù
+ú
+û
+ü
+ý
+ą
+Ć
+ć
+Č
+č
+Đ
+đ
+ę
+ı
+Ł
+ł
+ō
+Œ
+œ
+Š
+š
+Ÿ
+Ž
+ž
+ʒ
+β
+δ
+ε
+з
+Ṡ
+‘
+€
+™
diff --git a/BetterGenshinImpact/BetterGenshinImpact.csproj b/BetterGenshinImpact/BetterGenshinImpact.csproj
index a7ad8e12..f5d6c7a2 100644
--- a/BetterGenshinImpact/BetterGenshinImpact.csproj
+++ b/BetterGenshinImpact/BetterGenshinImpact.csproj
@@ -49,6 +49,7 @@
+
@@ -63,10 +64,8 @@
-
-
@@ -172,5 +171,5 @@
WelcomeDialog.xaml
-
+
\ No newline at end of file
diff --git a/BetterGenshinImpact/Core/Config/OtherConfig.cs b/BetterGenshinImpact/Core/Config/OtherConfig.cs
index 4255e03e..803afe97 100644
--- a/BetterGenshinImpact/Core/Config/OtherConfig.cs
+++ b/BetterGenshinImpact/Core/Config/OtherConfig.cs
@@ -10,5 +10,16 @@ public partial class OtherConfig : ObservableObject
//调度器任务和部分独立任务,失去焦点,自动激活游戏窗口
[ObservableProperty]
private bool _restoreFocusOnLostEnabled = false;
-
+
+ ///
+ /// 游戏语言名称
+ ///
+ [ObservableProperty]
+ private string _gameCultureInfoName = "zh-Hans";
+
+ ///
+ /// BGI界面语言名称
+ ///
+ [ObservableProperty]
+ private string _uiCultureInfoName = "zh-Hans";
}
\ No newline at end of file
diff --git a/BetterGenshinImpact/Core/Recognition/OCR/OcrFactory.cs b/BetterGenshinImpact/Core/Recognition/OCR/OcrFactory.cs
index 14ca362b..0338a2bc 100644
--- a/BetterGenshinImpact/Core/Recognition/OCR/OcrFactory.cs
+++ b/BetterGenshinImpact/Core/Recognition/OCR/OcrFactory.cs
@@ -1,18 +1,33 @@
using System;
+using System.Diagnostics;
+using System.Threading;
+using System.Threading.Tasks;
namespace BetterGenshinImpact.Core.Recognition.OCR;
public class OcrFactory
{
// public static IOcrService Media = Create(OcrEngineTypes.Media);
- public static IOcrService Paddle { get; } = Create(OcrEngineTypes.Paddle);
+ public static IOcrService Paddle { get; private set; } = Create(OcrEngineTypes.Paddle);
- public static IOcrService Create(OcrEngineTypes type)
+ public static IOcrService Create(OcrEngineTypes type, string? cultureInfoName = null)
{
return type switch
{
- OcrEngineTypes.Paddle => new PaddleOcrService(),
+ OcrEngineTypes.Paddle => new PaddleOcrService(cultureInfoName),
_ => throw new ArgumentOutOfRangeException(nameof(type), type, null),
};
}
+
+ public static async Task ChangeCulture(string cultrueInfoName)
+ {
+ await Task.Run(() =>
+ {
+ lock (Paddle)
+ {
+ Paddle = Create(OcrEngineTypes.Paddle, cultrueInfoName);
+ GC.Collect();
+ }
+ });
+ }
}
diff --git a/BetterGenshinImpact/Core/Recognition/OCR/PaddleOcrService.cs b/BetterGenshinImpact/Core/Recognition/OCR/PaddleOcrService.cs
index 5d6c9b1c..1d084d3c 100644
--- a/BetterGenshinImpact/Core/Recognition/OCR/PaddleOcrService.cs
+++ b/BetterGenshinImpact/Core/Recognition/OCR/PaddleOcrService.cs
@@ -21,13 +21,30 @@ public class PaddleOcrService : IOcrService
///
private readonly PaddleOcrAll _paddleOcrAll;
- public PaddleOcrService()
+ public PaddleOcrService(string? cultureInfoName = null)
{
var path = Global.Absolute(@"Assets\Model\PaddleOcr");
- var localDetModel = DetectionModel.FromDirectory(Path.Combine(path, "ch_PP-OCRv4_det"), ModelVersion.V4);
- var localClsModel = ClassificationModel.FromDirectory(Path.Combine(path, "ch_ppocr_mobile_v2.0_cls"));
- var localRecModel = RecognizationModel.FromDirectory(Path.Combine(path, "ch_PP-OCRv4_rec"), Path.Combine(path, "ppocr_keys_v1.txt"), ModelVersion.V4);
- var model = new FullOcrModel(localDetModel, localClsModel, localRecModel);
+ DetectionModel localDetModel;
+ RecognizationModel localRecModel;
+ FullOcrModel model;
+ switch (cultureInfoName)
+ {
+ case "zh-Hant":
+ localDetModel = DetectionModel.FromDirectory(Path.Combine(path, "ch_PP-OCRv4_det"), ModelVersion.V4); // 和简中共用一下det
+ localRecModel = RecognizationModel.FromDirectory(Path.Combine(path, "chinese_cht_PP-OCRv3_rec_infer"), Path.Combine(path, "chinese_cht_dict.txt"), ModelVersion.V3);
+ //model = OnlineFullModels.TraditionalChineseV3.DownloadAsync().Result;
+ break;
+ case "fr":
+ localDetModel = DetectionModel.FromDirectory(Path.Combine(path, "en_PP-OCRv3_det_infer"), ModelVersion.V3);
+ localRecModel = RecognizationModel.FromDirectory(Path.Combine(path, "latin_PP-OCRv3_rec_infer"), Path.Combine(path, "latin_dict.txt"), ModelVersion.V3);
+ break;
+ default:
+ localDetModel = DetectionModel.FromDirectory(Path.Combine(path, "ch_PP-OCRv4_det"), ModelVersion.V4);
+ localRecModel = RecognizationModel.FromDirectory(Path.Combine(path, "ch_PP-OCRv4_rec"), Path.Combine(path, "ppocr_keys_v1.txt"), ModelVersion.V4);
+
+ break;
+ }
+ model = new FullOcrModel(localDetModel, localRecModel);
// Action device = TaskContext.Instance().Config.InferenceDevice switch
// {
// "CPU" => PaddleDevice.Onnx(),
diff --git a/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.cs b/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.cs
index 1c808d93..d6dcf46f 100644
--- a/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.cs
+++ b/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.cs
@@ -36,6 +36,9 @@ using Vanara.PInvoke;
using static BetterGenshinImpact.GameTask.Common.TaskControl;
using static Vanara.PInvoke.Kernel32;
using static Vanara.PInvoke.User32;
+using Microsoft.Extensions.Localization;
+using System.Globalization;
+using System.Text.RegularExpressions;
namespace BetterGenshinImpact.GameTask.AutoDomain;
@@ -53,6 +56,10 @@ public class AutoDomainTask : ISoloTask
private CancellationToken _ct;
+ private readonly string challengeCompletedLocalizedString;
+ private readonly string autoLeavingLocalizedString;
+ private readonly string skipLocalizedString;
+
public AutoDomainTask(AutoDomainParam taskParam)
{
AutoFightAssets.DestroyInstance();
@@ -65,6 +72,12 @@ public class AutoDomainTask : ISoloTask
_config = TaskContext.Instance().Config.AutoDomainConfig;
_combatScriptBag = CombatScriptParser.ReadAndParse(_taskParam.CombatStrategyPath);
+
+ IStringLocalizer stringLocalizer = App.GetService>() ?? throw new NullReferenceException();
+ CultureInfo cultureInfo = new CultureInfo(TaskContext.Instance().Config.OtherConfig.GameCultureInfoName);
+ this.challengeCompletedLocalizedString = stringLocalizer.WithCultureGet(cultureInfo, "挑战达成");
+ this.autoLeavingLocalizedString = stringLocalizer.WithCultureGet(cultureInfo, "自动退出");
+ this.skipLocalizedString = stringLocalizer.WithCultureGet(cultureInfo, "跳过");
}
public async Task Start(CancellationToken ct)
@@ -541,7 +554,7 @@ public class AutoDomainTask : ISoloTask
var endTipsRect = ra.DeriveCrop(AutoFightAssets.Instance.EndTipsUpperRect);
var text = OcrFactory.Paddle.Ocr(endTipsRect.SrcGreyMat);
- if (text.Contains("挑战") || text.Contains("达成"))
+ if (Regex.IsMatch(text, this.challengeCompletedLocalizedString))
{
Logger.LogInformation("检测到秘境结束提示(挑战达成),结束秘境");
return true;
@@ -549,7 +562,7 @@ public class AutoDomainTask : ISoloTask
endTipsRect = ra.DeriveCrop(AutoFightAssets.Instance.EndTipsRect);
text = OcrFactory.Paddle.Ocr(endTipsRect.SrcGreyMat);
- if (text.Contains("自动") || text.Contains("退出"))
+ if (Regex.IsMatch(text, this.autoLeavingLocalizedString))
{
Logger.LogInformation("检测到秘境结束提示(xxx秒后自动退出),结束秘境");
return true;
@@ -926,7 +939,7 @@ public class AutoDomainTask : ISoloTask
// OCR识别是否有跳过
var ocrList = ra.FindMulti(RecognitionObject.Ocr(captureArea.Width - 230 * assetScale, 0, 230 * assetScale - 5, 80 * assetScale));
- var skipTextRa = ocrList.FirstOrDefault(t => t.Text.Contains("跳过"));
+ var skipTextRa = ocrList.FirstOrDefault(t => Regex.IsMatch(t.Text, this.skipLocalizedString));
if (skipTextRa != null)
{
hasSkip = true;
diff --git a/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.en.resx b/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.en.resx
new file mode 100644
index 00000000..64720193
--- /dev/null
+++ b/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.en.resx
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ [Challenge,Completed]
+
+
+ Leaving
+
+
+ Skip
+
+
\ No newline at end of file
diff --git a/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.fr.resx b/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.fr.resx
new file mode 100644
index 00000000..2b0b6840
--- /dev/null
+++ b/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.fr.resx
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ [Défi,terminé]
+
+
+ Sortie
+
+
+ Passer
+
+
\ No newline at end of file
diff --git a/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.zh-Hans.resx b/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.zh-Hans.resx
new file mode 100644
index 00000000..4b01df9c
--- /dev/null
+++ b/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.zh-Hans.resx
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ [挑战,达成]
+
+
+ [自动,退出]
+
+
+ 跳过
+
+
\ No newline at end of file
diff --git a/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.zh-Hant.resx b/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.zh-Hant.resx
new file mode 100644
index 00000000..e2b4f460
--- /dev/null
+++ b/BetterGenshinImpact/GameTask/AutoDomain/AutoDomainTask.zh-Hant.resx
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ [挑戰,達成]
+
+
+ [自動,退出]
+
+
+ 跳過
+
+
\ No newline at end of file
diff --git a/BetterGenshinImpact/GameTask/AutoFight/Assets/AutoFightAssets.cs b/BetterGenshinImpact/GameTask/AutoFight/Assets/AutoFightAssets.cs
index e48bcb4f..4690cafa 100644
--- a/BetterGenshinImpact/GameTask/AutoFight/Assets/AutoFightAssets.cs
+++ b/BetterGenshinImpact/GameTask/AutoFight/Assets/AutoFightAssets.cs
@@ -163,7 +163,7 @@ public class AutoFightAssets : BaseAssets
Name = "P",
RecognitionType = RecognitionTypes.TemplateMatch,
TemplateImageMat = GameTaskManager.LoadAssetImage("AutoFight", "p.png"),
- RegionOfInterest = new Rect(CaptureRect.Width - CaptureRect.Width / 7, CaptureRect.Height / 5, CaptureRect.Width / 7, CaptureRect.Height / 2 - CaptureRect.Width / 7),
+ RegionOfInterest = new Rect(CaptureRect.Width - (int)(CaptureRect.Width / 12.5), CaptureRect.Height / 5, (int)(CaptureRect.Width / 12.5), CaptureRect.Height / 2 - CaptureRect.Width / 7),
DrawOnWindow = false
}.InitTemplate();
diff --git a/BetterGenshinImpact/GameTask/AutoFight/Assets/combat_avatar.json b/BetterGenshinImpact/GameTask/AutoFight/Assets/combat_avatar.json
index 1e2a05dc..bf10ff6a 100644
--- a/BetterGenshinImpact/GameTask/AutoFight/Assets/combat_avatar.json
+++ b/BetterGenshinImpact/GameTask/AutoFight/Assets/combat_avatar.json
@@ -1804,7 +1804,6 @@
"瓦雷沙",
"牛头人",
"牛战士",
- "牛牛",
"奶牛",
"奶牛妹"
],
diff --git a/BetterGenshinImpact/GameTask/AutoFight/Config/DefaultAutoFightConfig.cs b/BetterGenshinImpact/GameTask/AutoFight/Config/DefaultAutoFightConfig.cs
index 7f8d6f21..928f0c5e 100644
--- a/BetterGenshinImpact/GameTask/AutoFight/Config/DefaultAutoFightConfig.cs
+++ b/BetterGenshinImpact/GameTask/AutoFight/Config/DefaultAutoFightConfig.cs
@@ -1,6 +1,6 @@
using BetterGenshinImpact.Core.Config;
-using BetterGenshinImpact.Service;
using System;
+using System.Collections.Frozen;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -10,24 +10,31 @@ namespace BetterGenshinImpact.GameTask.AutoFight.Config;
public class DefaultAutoFightConfig
{
- public static List CombatAvatars { get; set; }
+ //public static List CombatAvatars { get; set; }
public static List CombatAvatarNames { get; set; }
public static Dictionary CombatAvatarMap { get; set; }
public static Dictionary CombatAvatarNameEnMap { get; set; }
+ public static FrozenDictionary CombatAvatarAliasToNameMap { get; set; }
static DefaultAutoFightConfig()
{
var json = File.ReadAllText(Global.Absolute(@"GameTask\AutoFight\Assets\combat_avatar.json"));
- var config = Newtonsoft.Json.JsonConvert.DeserializeObject>(json);
- CombatAvatars = config ?? throw new Exception("combat_avatar.json deserialize failed");
+ var config = Newtonsoft.Json.JsonConvert.DeserializeObject>(json) ?? throw new Exception("combat_avatar.json deserialize failed");
+ //CombatAvatars = config;
CombatAvatarNames = config.Select(x => x.Name).ToList();
CombatAvatarMap = config.ToDictionary(x => x.Name);
CombatAvatarNameEnMap = config.ToDictionary(x => x.NameEn);
+ CombatAvatarAliasToNameMap = config.SelectMany(c => c.Alias.Select(a => new KeyValuePair(a, c.Name))).ToFrozenDictionary();
}
public static string AvatarAliasToStandardName(string alias)
{
- var avatar = CombatAvatars.Find(x => x.Alias.Contains(alias)) ?? throw new Exception($"角色名称校验失败:{alias}");
- return avatar.Name;
+ if (CombatAvatarAliasToNameMap.TryGetValue(alias, out string? name) && name != null)
+ {
+ return name;
+ }
+ throw new Exception($"角色名称校验失败:{alias}");
+
+ // return CombatAvatars.Find(x => x.Alias.Contains(alias))?.Name ?? throw new Exception($"角色名称校验失败:{alias}");
}
}
diff --git a/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingImageRecognition.en.resx b/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingImageRecognition.en.resx
new file mode 100644
index 00000000..627959b6
--- /dev/null
+++ b/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingImageRecognition.en.resx
@@ -0,0 +1,126 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ bite
+
+
+ Fishing
+
+
\ No newline at end of file
diff --git a/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingImageRecognition.fr.resx b/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingImageRecognition.fr.resx
new file mode 100644
index 00000000..e81752ca
--- /dev/null
+++ b/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingImageRecognition.fr.resx
@@ -0,0 +1,126 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ mordu
+
+
+ P[ê|é]cher
+
+
\ No newline at end of file
diff --git a/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingImageRecognition.zh-Hans.resx b/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingImageRecognition.zh-Hans.resx
new file mode 100644
index 00000000..80880314
--- /dev/null
+++ b/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingImageRecognition.zh-Hans.resx
@@ -0,0 +1,126 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 上钩
+
+
+ 钓鱼
+
+
\ No newline at end of file
diff --git a/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingImageRecognition.zh-Hant.resx b/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingImageRecognition.zh-Hant.resx
new file mode 100644
index 00000000..30a47577
--- /dev/null
+++ b/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingImageRecognition.zh-Hant.resx
@@ -0,0 +1,126 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 上鉤
+
+
+ 釣魚
+
+
\ No newline at end of file
diff --git a/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingTask.cs b/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingTask.cs
index 86c38fc7..6ca5b765 100644
--- a/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingTask.cs
+++ b/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingTask.cs
@@ -25,6 +25,10 @@ using BetterGenshinImpact.Core.Config;
using BetterGenshinImpact.Core.Recognition.ONNX;
using static Vanara.PInvoke.User32;
using BetterGenshinImpact.GameTask.AutoFight.Assets;
+using System.Globalization;
+using Microsoft.Extensions.Localization;
+using BetterGenshinImpact.Helpers;
+using BetterGenshinImpact.Core.Recognition.OCR;
namespace BetterGenshinImpact.GameTask.AutoFishing
{
@@ -47,6 +51,10 @@ namespace BetterGenshinImpact.GameTask.AutoFishing
{
this._ct = ct;
+ IOcrService ocrService = OcrFactory.Paddle;
+
+ IStringLocalizer stringLocalizer = App.GetService>() ?? throw new NullReferenceException(nameof(stringLocalizer));
+
var predictor = YoloV8Builder.CreateDefaultBuilder().UseOnnxModel(Global.Absolute(@"Assets\Model\Fish\bgi_fish.onnx")).WithSessionOptions(BgiSessionOption.Instance.Options).Build();
Blackboard blackboard = new Blackboard(predictor, this.Sleep, AutoFishingAssets.Instance);
@@ -60,7 +68,7 @@ namespace BetterGenshinImpact.GameTask.AutoFishing
.PushLeaf(() => new TurnAround("转圈圈调整视角", blackboard, _logger, param.SaveScreenshotOnKeyTick, input))
.PushLeaf(() => new FindFishTimeout("找到鱼", 20, blackboard, _logger, param.SaveScreenshotOnKeyTick))
.End()
- .PushLeaf(() => new EnterFishingMode("进入钓鱼模式", blackboard, _logger, param.SaveScreenshotOnKeyTick, input))
+ .PushLeaf(() => new EnterFishingMode("进入钓鱼模式", blackboard, _logger, param.SaveScreenshotOnKeyTick, input, cultureInfo: param.GameCultureInfo))
.UntilFailed(@"\")
.Sequence("一直钓鱼直到没鱼")
.AlwaysSucceed(@"\")
@@ -80,17 +88,17 @@ namespace BetterGenshinImpact.GameTask.AutoFishing
.UntilSuccess("重复抛竿")
.Sequence("-")
.PushLeaf(() => new MoveViewpointDown("调整视角至俯视", blackboard, _logger, param.SaveScreenshotOnKeyTick, input))
- //.MySimpleParallel("举起鱼竿并抛竿", policy: SimpleParallelPolicy.OnlyOneMustSucceed)
- // .PushLeaf(() => new LiftAndHold("举起鱼竿", blackboard, _logger, param.SaveScreenshotOnKeyTick, input))
+ //.MySimpleParallel("举起鱼竿并抛竿", policy: SimpleParallelPolicy.OnlyOneMustSucceed)
+ // .PushLeaf(() => new LiftAndHold("举起鱼竿", blackboard, _logger, param.SaveScreenshotOnKeyTick, input))
.PushLeaf(() => new ThrowRod("抛竿", blackboard, _logger, param.SaveScreenshotOnKeyTick, input))
- //.End()
+ //.End()
.End()
.End()
.Do("抛竿检查", _ => (blackboard.abort || blackboard.throwRodNoTarget || blackboard.throwRodNoBaitFish) ? BehaviourStatus.Failed : BehaviourStatus.Running)
.End()
.MySimpleParallel("下杆中", SimpleParallelPolicy.OnlyOneMustSucceed)
.PushLeaf(() => new CheckThrowRod("检查抛竿结果", blackboard, _logger, param.SaveScreenshotOnKeyTick)) // todo 后面串联一个召回率高的下杆中检测方法
- .PushLeaf(() => new FishBite("自动提竿", blackboard, _logger, param.SaveScreenshotOnKeyTick, input))
+ .PushLeaf(() => new FishBite("自动提竿", blackboard, _logger, param.SaveScreenshotOnKeyTick, input, ocrService, cultureInfo: param.GameCultureInfo, stringLocalizer: stringLocalizer))
.PushLeaf(() => new FishBiteTimeout("下杆超时检查", param.ThrowRodTimeOutTimeoutSeconds, _logger, param.SaveScreenshotOnKeyTick, input))
.End()
.MySimpleParallel("拉条中", policy: SimpleParallelPolicy.OnlyOneMustSucceed)
@@ -108,13 +116,13 @@ namespace BetterGenshinImpact.GameTask.AutoFishing
.End()
.PushLeaf(() => new WholeProcessTimeout("检查整体超时", param.WholeProcessTimeoutSeconds, _logger, param.SaveScreenshotOnKeyTick))
.End()
- .PushLeaf(() => new QuitFishingMode("退出钓鱼模式", blackboard, _logger, param.SaveScreenshotOnKeyTick, input))
+ .PushLeaf(() => new QuitFishingMode("退出钓鱼模式", blackboard, _logger, param.SaveScreenshotOnKeyTick, input, param.GameCultureInfo))
.End()
.Build();
// @formatter:on
_logger.LogInformation("→ {Text}", "自动钓鱼,启动!");
_logger.LogWarning("请不要携带任何{Msg},极有可能会误识别导致无法结束自动钓鱼!", "跟宠");
- _logger.LogInformation($"当前参数:{param.WholeProcessTimeoutSeconds},{param.ThrowRodTimeOutTimeoutSeconds},{param.FishingTimePolicy}, {param.SaveScreenshotOnKeyTick}");
+ _logger.LogInformation($"当前参数:{param.WholeProcessTimeoutSeconds},{param.ThrowRodTimeOutTimeoutSeconds},{param.FishingTimePolicy}, {param.SaveScreenshotOnKeyTick}, {param.GameCultureInfo}");
TaskContext.Instance().Config.AutoFishingConfig.Enabled = false;
_logger.LogInformation("全自动运行时,自动切换实时任务中的半自动钓鱼功能为关闭状态");
@@ -340,12 +348,15 @@ namespace BetterGenshinImpact.GameTask.AutoFishing
private DateTimeOffset? pressFWaitEndTime;
private DateTimeOffset? clickWhiteConfirmButtonWaitEndTime;
private DateTimeOffset? overallWaitEndTime;
+ private readonly string fishingLocalizedString;
- public EnterFishingMode(string name, Blackboard blackboard, ILogger logger, bool saveScreenshotOnTerminate, IInputSimulator input, TimeProvider? timeProvider = null) : base(name, logger, saveScreenshotOnTerminate)
+ public EnterFishingMode(string name, Blackboard blackboard, ILogger logger, bool saveScreenshotOnTerminate, IInputSimulator input, TimeProvider? timeProvider = null, CultureInfo? cultureInfo = null) : base(name, logger, saveScreenshotOnTerminate)
{
this.blackboard = blackboard;
this.input = input;
this.timeProvider = timeProvider ?? TimeProvider.System;
+ IStringLocalizer stringLocalizer = App.GetService>() ?? throw new NullReferenceException(nameof(stringLocalizer));
+ this.fishingLocalizedString = stringLocalizer.WithCultureGet(cultureInfo, "钓鱼");
}
protected override BehaviourStatus Update(ImageRegion imageRegion)
@@ -356,7 +367,7 @@ namespace BetterGenshinImpact.GameTask.AutoFishing
return BehaviourStatus.Running;
}
- if ((pressFWaitEndTime == null || pressFWaitEndTime < timeProvider.GetLocalNow()) && Bv.FindFAndPress(imageRegion, input.Keyboard, "钓鱼"))
+ if ((pressFWaitEndTime == null || pressFWaitEndTime < timeProvider.GetLocalNow()) && Bv.FindFAndPress(imageRegion, input.Keyboard, this.fishingLocalizedString))
{
logger.LogInformation("按下钓鱼键");
pressFWaitEndTime = timeProvider.GetLocalNow().AddSeconds(3);
@@ -397,11 +408,14 @@ namespace BetterGenshinImpact.GameTask.AutoFishing
{
private readonly IInputSimulator input;
private readonly Blackboard blackboard;
+ private readonly string fishingLocalizedString;
- public QuitFishingMode(string name, Blackboard blackboard, ILogger logger, bool saveScreenshotOnTerminate, IInputSimulator input) : base(name, logger, saveScreenshotOnTerminate)
+ public QuitFishingMode(string name, Blackboard blackboard, ILogger logger, bool saveScreenshotOnTerminate, IInputSimulator input, CultureInfo? cultureInfo = null) : base(name, logger, saveScreenshotOnTerminate)
{
this.blackboard = blackboard;
this.input = input;
+ IStringLocalizer stringLocalizer = App.GetService>() ?? throw new NullReferenceException(nameof(stringLocalizer));
+ this.fishingLocalizedString = stringLocalizer.WithCultureGet(cultureInfo, "钓鱼");
}
protected override BehaviourStatus Update(ImageRegion imageRegion)
@@ -411,7 +425,7 @@ namespace BetterGenshinImpact.GameTask.AutoFishing
return BehaviourStatus.Running;
}
- if (Bv.FindF(imageRegion, "钓鱼"))
+ if (Bv.FindF(imageRegion, this.fishingLocalizedString))
{
logger.LogInformation("退出完成");
return BehaviourStatus.Succeeded;
diff --git a/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingTaskParam.cs b/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingTaskParam.cs
index 6b3567fa..44252a3d 100644
--- a/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingTaskParam.cs
+++ b/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingTaskParam.cs
@@ -4,12 +4,13 @@ using System.Collections.Generic;
using System.Text;
using BetterGenshinImpact.Helpers;
using Microsoft.ClearScript;
+using System.Globalization;
namespace BetterGenshinImpact.GameTask.AutoFishing
{
public class AutoFishingTaskParam : BaseTaskParam
{
- public AutoFishingTaskParam(int wholeProcessTimeoutSeconds, int throwRodTimeOutTimeoutSeconds, FishingTimePolicy fishingTimePolicy, bool saveScreenshotOnKeyTick)
+ public AutoFishingTaskParam(int wholeProcessTimeoutSeconds, int throwRodTimeOutTimeoutSeconds, FishingTimePolicy fishingTimePolicy, bool saveScreenshotOnKeyTick, CultureInfo? cultureInfo) : base(cultureInfo)
{
WholeProcessTimeoutSeconds = wholeProcessTimeoutSeconds;
ThrowRodTimeOutTimeoutSeconds = throwRodTimeOutTimeoutSeconds;
@@ -43,7 +44,7 @@ namespace BetterGenshinImpact.GameTask.AutoFishing
var fishingTimePolicy = (FishingTimePolicy)ScriptObjectConverter.GetValue(jsObject, "fishingTimePolicy", (int)autoFishingConfig.FishingTimePolicy);
var saveScreenshotOnKeyTick = ScriptObjectConverter.GetValue(jsObject, "saveScreenshotOnKeyTick", false);
- return new AutoFishingTaskParam(wholeProcessTimeoutSeconds, throwRodTimeOutTimeoutSeconds, fishingTimePolicy, saveScreenshotOnKeyTick);
+ return new AutoFishingTaskParam(wholeProcessTimeoutSeconds, throwRodTimeOutTimeoutSeconds, fishingTimePolicy, saveScreenshotOnKeyTick, null);
}
///
@@ -54,7 +55,8 @@ namespace BetterGenshinImpact.GameTask.AutoFishing
///
public static AutoFishingTaskParam BuildFromConfig(AutoFishingConfig config, bool saveScreenshotOnKeyTick = false)
{
- return new AutoFishingTaskParam(config.WholeProcessTimeoutSeconds, config.AutoThrowRodTimeOut, config.FishingTimePolicy, saveScreenshotOnKeyTick);
+ CultureInfo cultureInfo = new CultureInfo(TaskContext.Instance().Config.OtherConfig.GameCultureInfoName);
+ return new AutoFishingTaskParam(config.WholeProcessTimeoutSeconds, config.AutoThrowRodTimeOut, config.FishingTimePolicy, saveScreenshotOnKeyTick, cultureInfo);
}
}
}
\ No newline at end of file
diff --git a/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingTrigger.cs b/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingTrigger.cs
index 8d6c8999..a6621459 100644
--- a/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingTrigger.cs
+++ b/BetterGenshinImpact/GameTask/AutoFishing/AutoFishingTrigger.cs
@@ -17,6 +17,8 @@ using BetterGenshinImpact.GameTask.Model.Area;
using BetterGenshinImpact.Core.Config;
using BetterGenshinImpact.Core.Recognition.ONNX;
using Compunet.YoloV8;
+using Microsoft.Extensions.Localization;
+using BetterGenshinImpact.Core.Recognition.OCR;
namespace BetterGenshinImpact.GameTask.AutoFishing
{
@@ -45,6 +47,10 @@ namespace BetterGenshinImpact.GameTask.AutoFishing
public AutoFishingTrigger()
{
+ AutoFishingTaskParam autoFishingTaskParam = AutoFishingTaskParam.BuildFromConfig(TaskContext.Instance().Config.AutoFishingConfig);
+ IOcrService ocrService = OcrFactory.Paddle;
+ IStringLocalizer stringLocalizer = App.GetService>() ?? throw new NullReferenceException(nameof(stringLocalizer));
+
var predictor = YoloV8Builder.CreateDefaultBuilder().UseOnnxModel(Global.Absolute(@"Assets\Model\Fish\bgi_fish.onnx")).WithSessionOptions(BgiSessionOption.Instance.Options).Build();
this.blackboard = new Blackboard(predictor, this.Sleep, AutoFishingAssets.Instance);
@@ -53,7 +59,7 @@ namespace BetterGenshinImpact.GameTask.AutoFishing
.Do("检查是否在钓鱼界面", CheckFishingUserInterface)
.UntilSuccess("拉条循环")
.Sequence("拉条")
- .PushLeaf(() => new FishBite("自动提竿", blackboard, _logger, false, input))
+ .PushLeaf(() => new FishBite("自动提竿", blackboard, _logger, false, input, ocrService, cultureInfo: autoFishingTaskParam.GameCultureInfo, stringLocalizer: stringLocalizer))
.PushLeaf(() => new GetFishBoxArea("等待拉条出现", blackboard, _logger, false))
.PushLeaf(() => new Fishing("钓鱼拉条", blackboard, _logger, false, input))
.End()
diff --git a/BetterGenshinImpact/GameTask/AutoFishing/Behaviours.cs b/BetterGenshinImpact/GameTask/AutoFishing/Behaviours.cs
index dfe461a9..42f703b2 100644
--- a/BetterGenshinImpact/GameTask/AutoFishing/Behaviours.cs
+++ b/BetterGenshinImpact/GameTask/AutoFishing/Behaviours.cs
@@ -21,6 +21,8 @@ using Fischless.WindowsInput;
using BetterGenshinImpact.Core.Recognition.OpenCv;
using BetterGenshinImpact.Core.Simulator;
using BetterGenshinImpact.GameTask.Model;
+using System.Globalization;
+using Microsoft.Extensions.Localization;
namespace BetterGenshinImpact.GameTask.AutoFishing
{
@@ -684,12 +686,15 @@ namespace BetterGenshinImpact.GameTask.AutoFishing
private readonly Blackboard blackboard;
private readonly IInputSimulator input;
private readonly DrawContent drawContent;
- private readonly IOcrService ocrService = OcrFactory.Paddle;
- public FishBite(string name, Blackboard blackboard, ILogger logger, bool saveScreenshotOnTerminat, IInputSimulator input, DrawContent? drawContent = null) : base(name, logger, saveScreenshotOnTerminat)
+ private readonly IOcrService ocrService;
+ private readonly string getABiteLocalizedString;
+ public FishBite(string name, Blackboard blackboard, ILogger logger, bool saveScreenshotOnTerminat, IInputSimulator input, IOcrService ocrService, DrawContent? drawContent = null, CultureInfo? cultureInfo = null, IStringLocalizer? stringLocalizer = null) : base(name, logger, saveScreenshotOnTerminat)
{
this.blackboard = blackboard;
this.input = input;
+ this.ocrService = ocrService;
this.drawContent = drawContent ?? VisionContext.Instance().DrawContent;
+ this.getABiteLocalizedString = stringLocalizer == null ? "上钩" : stringLocalizer.WithCultureGet(cultureInfo, "上钩");
}
protected override void OnInitialize()
@@ -702,11 +707,11 @@ namespace BetterGenshinImpact.GameTask.AutoFishing
// 自动识别的钓鱼框向下延伸到屏幕中间
//var liftingWordsAreaRect = new Rect(fishBoxRect.X, fishBoxRect.Y + fishBoxRect.Height * 2,
// fishBoxRect.Width, imageRegion.CaptureRectArea.SrcMat.Height / 2 - fishBoxRect.Y - fishBoxRect.Height * 5);
- // 上半屏幕和中间1/3的区域
+ // 上半屏幕和中间1/2的区域
var liftingWordsAreaRect = new Rect(imageRegion.SrcMat.Width / 3, 0, imageRegion.SrcMat.Width / 3,
imageRegion.SrcMat.Height / 2);
//VisionContext.Instance().DrawContent.PutRect("liftingWordsAreaRect", liftingWordsAreaRect.ToRectDrawable(new Pen(Color.Cyan, 2)));
- var wordCaptureMat = new Mat(imageRegion.SrcMat, liftingWordsAreaRect);
+ using var wordCaptureMat = new Mat(imageRegion.SrcMat, liftingWordsAreaRect);
var currentBiteWordsTips = AutoFishingImageRecognition.MatchFishBiteWords(wordCaptureMat, liftingWordsAreaRect);
if (currentBiteWordsTips != Rect.Empty)
{
@@ -717,40 +722,36 @@ namespace BetterGenshinImpact.GameTask.AutoFishing
using var tipsRa = imageRegion.Derive(currentBiteWordsTips + liftingWordsAreaRect.Location);
tipsRa.DrawSelf("FishBiteTips");
- // 图像提竿判断
- using var liftRodButtonRa = imageRegion.Find(blackboard.AutoFishingAssets.LiftRodButtonRo);
- if (!liftRodButtonRa.IsEmpty())
- {
- input.Mouse.LeftButtonClick();
- logger.LogInformation(@"┌------------------------┐");
- logger.LogInformation(" 自动提竿(图像识别)");
- drawContent.RemoveRect("FishBiteTips");
- return BehaviourStatus.Succeeded;
- }
+ return RaiseRod("文字块");
+ }
- // OCR 提竿判断
- var text = ocrService.Ocr(new Mat(imageRegion.SrcGreyMat,
- new Rect(currentBiteWordsTips.X + liftingWordsAreaRect.X,
- currentBiteWordsTips.Y + liftingWordsAreaRect.Y,
- currentBiteWordsTips.Width, currentBiteWordsTips.Height)));
- if (!string.IsNullOrEmpty(text) && StringUtils.RemoveAllSpace(text).Contains("上钩"))
- {
- input.Mouse.LeftButtonClick();
- logger.LogInformation(@"┌------------------------┐");
- logger.LogInformation(" 自动提竿(OCR)");
- drawContent.RemoveRect("FishBiteTips");
- return BehaviourStatus.Succeeded;
- }
+ // 图像提竿判断
+ using var liftRodButtonRa = imageRegion.Find(blackboard.AutoFishingAssets.LiftRodButtonRo);
+ if (!liftRodButtonRa.IsEmpty())
+ {
+ return RaiseRod("图像识别");
+ }
- input.Mouse.LeftButtonClick();
- logger.LogInformation(@"┌------------------------┐");
- logger.LogInformation(" 自动提竿(文字块)");
- drawContent.RemoveRect("FishBiteTips");
- return BehaviourStatus.Succeeded;
+ // OCR 提竿判断
+ using Mat wordCaptureGreyMat = new Mat(imageRegion.SrcGreyMat, liftingWordsAreaRect);
+ var text = ocrService.Ocr(wordCaptureGreyMat);
+
+ if (!string.IsNullOrEmpty(text) && StringUtils.RemoveAllSpace(text).Contains(this.getABiteLocalizedString))
+ {
+ return RaiseRod("OCR");
}
return BehaviourStatus.Running;
}
+
+ private BehaviourStatus RaiseRod(string method)
+ {
+ input.Mouse.LeftButtonClick();
+ logger.LogInformation(@"┌------------------------┐");
+ logger.LogInformation(" 自动提竿({m})", method);
+ drawContent.RemoveRect("FishBiteTips");
+ return BehaviourStatus.Succeeded;
+ }
}
///
diff --git a/BetterGenshinImpact/GameTask/AutoFishing/RodNet.cs b/BetterGenshinImpact/GameTask/AutoFishing/RodNet.cs
index c4a09342..a923b2a0 100644
--- a/BetterGenshinImpact/GameTask/AutoFishing/RodNet.cs
+++ b/BetterGenshinImpact/GameTask/AutoFishing/RodNet.cs
@@ -6,6 +6,33 @@ namespace BetterGenshinImpact.GameTask.AutoFishing;
///
/// copy from https://github.com/myHuTao-qwq/HutaoFisher/blob/master/src/rodnet.cpp
+///
+/// 以下是hutaofisher的访谈:
+///
+/// 修改我的qq昵称: 03-20 00:22:48
+/// 有任何问题可以问我 只要我在工位而不是在实验室里跟XXXX斗智斗勇就回答你
+///
+/// 额 我的算法有几个感觉挺符合直觉的假设
+///
+/// 就是 你抛竿的时候鱼是否会咬钩取决于鱼饵落点到鱼的距离
+///
+/// 这里的距离是鱼饵落点的(x, y, z)坐标与鱼的(x, y, z)坐标之差在xy平面(水平面)上的投影
+///
+/// 现在问题转化成了如何估计这两个坐标
+///
+/// 这里我们先约定x轴就是水平面上与屏幕长边平行的线 y轴就是屏幕短边的对于 剩下一个z就是游戏里面往天上的方向
+///
+/// 然后经验告诉我鱼饵落点环的x几乎为0
+///
+/// 剩下我们可以用鱼饵落点环的长和宽算出y和z
+///
+/// 再近似鱼的bouding box的中心就是鱼计算咬钩的那个点 同时近似一个大类里面的所有鱼的z是相同的(这个参数可学习) 于是我们也可以计算出鱼的xyz
+///
+/// 最后一步就是把对应的投影距离算出来 然后线性回归一下得到太近 刚好 太远三个类
+///
+/// tmd 今天我意识到 XXXX可不就是XXXX
+///
+/// 哦 到这一步以后剩下的就很弱智了 远了挪近一点 近了挪远一点 调调参差不多得了
///
public class RodNet
{
diff --git a/BetterGenshinImpact/GameTask/AutoTrackPath/TpTask.cs b/BetterGenshinImpact/GameTask/AutoTrackPath/TpTask.cs
index 145961e7..44572a35 100644
--- a/BetterGenshinImpact/GameTask/AutoTrackPath/TpTask.cs
+++ b/BetterGenshinImpact/GameTask/AutoTrackPath/TpTask.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
+using System.Globalization;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -22,7 +23,9 @@ using BetterGenshinImpact.GameTask.Common.Job;
using BetterGenshinImpact.GameTask.Common.Map;
using BetterGenshinImpact.GameTask.Model.Area;
using BetterGenshinImpact.GameTask.QuickTeleport.Assets;
+using BetterGenshinImpact.Helpers;
using BetterGenshinImpact.Helpers.Extensions;
+using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using OpenCvSharp;
using Vanara.PInvoke;
@@ -48,7 +51,7 @@ public class TpTask(CancellationToken ct)
/// 直接通过缩放比例按钮计算缩小按钮的Y坐标
///
private readonly int _zoomOutButtonY = TaskContext.Instance().Config.TpConfig.ZoomEndY + 24; // y-coordinate for zoom-out button = _zoomEndY + 24
-
+
private const double DisplayTpPointZoomLevel = 4.4; // 传送点显示的时候的地图比例
///
@@ -57,7 +60,7 @@ public class TpTask(CancellationToken ct)
public async Task TpToStatueOfTheSeven()
{
await CheckInBigMapUi();
-
+
// 提前调整至恰当的缩放以更快的传送
if (_tpConfig.MapZoomEnabled)
{
@@ -103,7 +106,7 @@ public class TpTask(CancellationToken ct)
await new PathExecutor(ct).MoveTo(waypointForTrack);
Simulation.SendInput.SimulateAction(GIActions.Drop);
}
-
+
await Delay((int)(_tpConfig.HpRestoreDuration * 1000), ct);
}
@@ -153,9 +156,9 @@ public class TpTask(CancellationToken ct)
}
}
// 获取最近的神像位置
- return nearestGiTpPosition ?? throw new InvalidOperationException("没找到最近的七天神像");;
+ return nearestGiTpPosition ?? throw new InvalidOperationException("没找到最近的七天神像");
}
-
+
///
/// 通过大地图传送到指定坐标最近的传送点,然后移动到指定坐标
///
@@ -275,7 +278,7 @@ public class TpTask(CancellationToken ct)
Logger.LogWarning("传送等待超时,换台电脑吧");
}
-
+
///
/// 传送点是否在大地图窗口内
///
@@ -423,13 +426,13 @@ public class TpTask(CancellationToken ct)
++exceptionTimes;
mapCenterPoint = new Point2f(0f, 0f); // 其他恰当的初始值?
}
-
+
var (xOffset, yOffset) = (x - mapCenterPoint.X, y - mapCenterPoint.Y);
double totalMoveMouseX = _tpConfig.MapScaleFactor * Math.Abs(xOffset) / currentZoomLevel;
double totalMoveMouseY = _tpConfig.MapScaleFactor * Math.Abs(yOffset) / currentZoomLevel;
double mouseDistance = Math.Sqrt(totalMoveMouseX * totalMoveMouseX + totalMoveMouseY * totalMoveMouseY);
// 缩小地图到恰当的缩放
- if (_tpConfig.MapZoomEnabled)
+ if (_tpConfig.MapZoomEnabled)
{
if (mouseDistance > _tpConfig.MapZoomOutDistance)
{
@@ -443,7 +446,7 @@ public class TpTask(CancellationToken ct)
currentZoomLevel = nextZoomLevel;
}
}
-
+
// 开始移动并放大地图
for (var iteration = 0; iteration < _tpConfig.MaxIterations; iteration++)
{
@@ -476,7 +479,7 @@ public class TpTask(CancellationToken ct)
int moveMouseY = (int)Math.Min(totalMoveMouseY, _tpConfig.MaxMouseMove * totalMoveMouseY / mouseDistance) * Math.Sign(yOffset);
double moveMouseLength = Math.Sqrt(moveMouseX * moveMouseX + moveMouseY * moveMouseY);
int moveSteps = Math.Max((int)moveMouseLength / 10, 3); // 每次移动的步数最小为 3,避免除 0 错误
-
+
await MouseMoveMap(moveMouseX, moveMouseY, moveSteps);
try
{
@@ -526,7 +529,7 @@ public class TpTask(CancellationToken ct)
/// 调整地图缩放级别以加速移动
///
/// 是否放大地图
- [Obsolete]
+ [Obsolete]
private async Task AdjustMapZoomLevel(bool zoomIn)
{
if (zoomIn)
@@ -598,33 +601,37 @@ public class TpTask(CancellationToken ct)
Simulation.SendInput.Mouse.LeftButtonUp();
}
- private int[] GenerateSteps(int delta, int steps) {
+ private int[] GenerateSteps(int delta, int steps)
+ {
double[] factors = new double[steps];
double sum = 0;
- for (int i = 0; i < steps; i++) {
+ for (int i = 0; i < steps; i++)
+ {
factors[i] = Math.Cos(i * Math.PI / (2 * steps));
sum += factors[i];
}
int[] stepsArr = new int[steps];
int remaining = delta;
-
+
// 两阶段分配:基础值 + 余数补偿
- for (int i = 0; i < steps; i++) {
+ for (int i = 0; i < steps; i++)
+ {
double ratio = factors[i] / sum;
stepsArr[i] = (int)(delta * ratio); // 基础值
remaining -= stepsArr[i];
}
int center = steps / 2;
- for (int r = 0; r < Math.Abs(remaining); r++) {
+ for (int r = 0; r < Math.Abs(remaining); r++)
+ {
int target = (center + r) % steps; // 从中点开始螺旋分配
stepsArr[target] += remaining > 0 ? 1 : -1;
}
return stepsArr;
}
-
+
public Point2f GetPositionFromBigMap()
{
return GetBigMapCenterPoint();
@@ -796,14 +803,26 @@ public class TpTask(CancellationToken ct)
GameCaptureRegion.GameRegionClick((rect, scale) => (rect.Width - 160 * scale, rect.Height - 60 * scale));
await Delay(300, ct);
- var ra = CaptureToRectArea();
+ using var ra = CaptureToRectArea();
var list = ra.FindMulti(new RecognitionObject
{
RecognitionType = RecognitionTypes.Ocr,
RegionOfInterest = new Rect(ra.Width / 2, 0, ra.Width / 2, ra.Height)
});
- list.FirstOrDefault(r => r.Text.Length == minCountry.Length && !r.Text.Contains("委托") && r.Text.Contains(minCountry))?.Click();
- Logger.LogInformation("切换到区域:{Country}", minCountry);
+ IStringLocalizer stringLocalizer = App.GetService>() ?? throw new NullReferenceException(nameof(stringLocalizer));
+ CultureInfo cultureInfo = new CultureInfo(TaskContext.Instance().Config.OtherConfig.GameCultureInfoName);
+ string minCountryLocalized = stringLocalizer.WithCultureGet(cultureInfo, minCountry);
+ string commissionLocalized = stringLocalizer.WithCultureGet(cultureInfo, "委托");
+ Region? matchRect = list.FirstOrDefault(r => r.Text.Length == minCountryLocalized.Length && !r.Text.Contains(commissionLocalized) && r.Text.Contains(minCountryLocalized));
+ if (matchRect == null)
+ {
+ Logger.LogWarning("切换区域失败:{Country}", minCountry);
+ }
+ else
+ {
+ matchRect.Click();
+ Logger.LogInformation("切换到区域:{Country}", minCountry);
+ }
await Delay(500, ct);
return true;
}
diff --git a/BetterGenshinImpact/GameTask/Common/BgiVision/BvSimpleOperation.cs b/BetterGenshinImpact/GameTask/Common/BgiVision/BvSimpleOperation.cs
index 419fe8fa..1907cf9a 100644
--- a/BetterGenshinImpact/GameTask/Common/BgiVision/BvSimpleOperation.cs
+++ b/BetterGenshinImpact/GameTask/Common/BgiVision/BvSimpleOperation.cs
@@ -1,12 +1,11 @@
-using System.Windows.Documents;
-using BetterGenshinImpact.Core.Recognition;
+using BetterGenshinImpact.Core.Recognition;
using BetterGenshinImpact.Core.Simulator;
using BetterGenshinImpact.GameTask.AutoPick.Assets;
-using BetterGenshinImpact.GameTask.AutoSkip.Assets;
using BetterGenshinImpact.GameTask.Common.Element.Assets;
using BetterGenshinImpact.GameTask.Model.Area;
using Fischless.WindowsInput;
using OpenCvSharp;
+using System.Text.RegularExpressions;
namespace BetterGenshinImpact.GameTask.Common.BgiVision;
@@ -170,7 +169,7 @@ public static partial class Bv
var success = true;
foreach (var t in text)
{
- if (!item.Text.Contains(t))
+ if (!Regex.IsMatch(item.Text, t))
{
success = false;
}
diff --git a/BetterGenshinImpact/GameTask/Common/BgiVision/BvStatus.cs b/BetterGenshinImpact/GameTask/Common/BgiVision/BvStatus.cs
index 8c4570a8..16d879e4 100644
--- a/BetterGenshinImpact/GameTask/Common/BgiVision/BvStatus.cs
+++ b/BetterGenshinImpact/GameTask/Common/BgiVision/BvStatus.cs
@@ -6,9 +6,6 @@ using System;
using System.Linq;
using System.Threading.Tasks;
using BetterGenshinImpact.Core.Recognition;
-using BetterGenshinImpact.Core.Simulator;
-using BetterGenshinImpact.GameTask.AutoFight;
-using Vanara.PInvoke;
using System.Threading;
using BetterGenshinImpact.GameTask.AutoFight.Assets;
using BetterGenshinImpact.GameTask.AutoSkip.Assets;
diff --git a/BetterGenshinImpact/GameTask/Common/Element/Assets/MapLazyAssets.en.resx b/BetterGenshinImpact/GameTask/Common/Element/Assets/MapLazyAssets.en.resx
new file mode 100644
index 00000000..da0f2d6b
--- /dev/null
+++ b/BetterGenshinImpact/GameTask/Common/Element/Assets/MapLazyAssets.en.resx
@@ -0,0 +1,141 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Commission
+
+
+ Fontaine
+
+
+ Liyue
+
+
+ Inazuma
+
+
+ Natlan
+
+
+ Mondstadt
+
+
+ Sumeru
+
+
\ No newline at end of file
diff --git a/BetterGenshinImpact/GameTask/Common/Element/Assets/MapLazyAssets.fr.resx b/BetterGenshinImpact/GameTask/Common/Element/Assets/MapLazyAssets.fr.resx
new file mode 100644
index 00000000..3b4d5fc7
--- /dev/null
+++ b/BetterGenshinImpact/GameTask/Common/Element/Assets/MapLazyAssets.fr.resx
@@ -0,0 +1,141 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Mission
+
+
+ Fontaine
+
+
+ Liyue
+
+
+ Inazuma
+
+
+ Natlan
+
+
+ Mondstadt
+
+
+ Sumeru
+
+
\ No newline at end of file
diff --git a/BetterGenshinImpact/GameTask/Common/Element/Assets/MapLazyAssets.zh-Hans.resx b/BetterGenshinImpact/GameTask/Common/Element/Assets/MapLazyAssets.zh-Hans.resx
new file mode 100644
index 00000000..36052e90
--- /dev/null
+++ b/BetterGenshinImpact/GameTask/Common/Element/Assets/MapLazyAssets.zh-Hans.resx
@@ -0,0 +1,141 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 委托
+
+
+ 枫丹
+
+
+ 璃月
+
+
+ 稻妻
+
+
+ 纳塔
+
+
+ 蒙德
+
+
+ 须弥
+
+
\ No newline at end of file
diff --git a/BetterGenshinImpact/GameTask/Common/Element/Assets/MapLazyAssets.zh-Hant.resx b/BetterGenshinImpact/GameTask/Common/Element/Assets/MapLazyAssets.zh-Hant.resx
new file mode 100644
index 00000000..e49b43e1
--- /dev/null
+++ b/BetterGenshinImpact/GameTask/Common/Element/Assets/MapLazyAssets.zh-Hant.resx
@@ -0,0 +1,141 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 委[託,話]
+
+
+ 楓丹
+
+
+ 璃月
+
+
+ 稻妻
+
+
+ 納塔
+
+
+ 蒙德
+
+
+ 須彌
+
+
\ No newline at end of file
diff --git a/BetterGenshinImpact/GameTask/Common/Job/CheckRewardsTask.cs b/BetterGenshinImpact/GameTask/Common/Job/CheckRewardsTask.cs
index 33b33b78..7de64c5f 100644
--- a/BetterGenshinImpact/GameTask/Common/Job/CheckRewardsTask.cs
+++ b/BetterGenshinImpact/GameTask/Common/Job/CheckRewardsTask.cs
@@ -1,12 +1,16 @@
using System;
+using System.Globalization;
using System.Linq;
+using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using BetterGenshinImpact.Core.Recognition;
using BetterGenshinImpact.Core.Simulator;
using BetterGenshinImpact.Core.Simulator.Extensions;
+using BetterGenshinImpact.Helpers;
using BetterGenshinImpact.Service.Notification;
using BetterGenshinImpact.Service.Notification.Model.Enum;
+using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using static BetterGenshinImpact.GameTask.Common.TaskControl;
@@ -20,6 +24,15 @@ public class CheckRewardsTask
{
private readonly ILogger _logger = App.GetLogger();
+ private readonly string dailyRewardsClaimedLocalizedString;
+
+ public CheckRewardsTask()
+ {
+ IStringLocalizer stringLocalizer = App.GetService>() ?? throw new NullReferenceException();
+ CultureInfo cultureInfo = new CultureInfo(TaskContext.Instance().Config.OtherConfig.GameCultureInfoName);
+ this.dailyRewardsClaimedLocalizedString = stringLocalizer.WithCultureGet(cultureInfo, "今日奖励已领取");
+ }
+
public string Name => "检查奖励并通知的任务";
public async Task Start(CancellationToken ct)
@@ -33,7 +46,7 @@ public class CheckRewardsTask
var assetScale = TaskContext.Instance().SystemInfo.AssetScale;
using var ra = CaptureToRectArea();
var ocrList = ra.FindMulti(RecognitionObject.Ocr(0, ra.Height - ra.Height / 3.0, 730 * assetScale, ra.Height / 3.0));
- var done = ocrList.FirstOrDefault(txt => txt.Text.Contains("今日奖励已领取"));
+ var done = ocrList.FirstOrDefault(txt => Regex.IsMatch(txt.Text, this.dailyRewardsClaimedLocalizedString));
if (done != null)
{
Logger.LogInformation("检查每日奖励结果:{Msg}", "今日奖励已领取");
diff --git a/BetterGenshinImpact/GameTask/Common/Job/CheckRewardsTask.en.resx b/BetterGenshinImpact/GameTask/Common/Job/CheckRewardsTask.en.resx
new file mode 100644
index 00000000..63cf9bf9
--- /dev/null
+++ b/BetterGenshinImpact/GameTask/Common/Job/CheckRewardsTask.en.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ claimed
+
+
\ No newline at end of file
diff --git a/BetterGenshinImpact/GameTask/Common/Job/CheckRewardsTask.fr.resx b/BetterGenshinImpact/GameTask/Common/Job/CheckRewardsTask.fr.resx
new file mode 100644
index 00000000..d32af2bf
--- /dev/null
+++ b/BetterGenshinImpact/GameTask/Common/Job/CheckRewardsTask.fr.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ récupérées
+
+
\ No newline at end of file
diff --git a/BetterGenshinImpact/GameTask/Common/Job/CheckRewardsTask.zh-Hans.resx b/BetterGenshinImpact/GameTask/Common/Job/CheckRewardsTask.zh-Hans.resx
new file mode 100644
index 00000000..8a900032
--- /dev/null
+++ b/BetterGenshinImpact/GameTask/Common/Job/CheckRewardsTask.zh-Hans.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 今日奖励已领取
+
+
\ No newline at end of file
diff --git a/BetterGenshinImpact/GameTask/Common/Job/CheckRewardsTask.zh-Hant.resx b/BetterGenshinImpact/GameTask/Common/Job/CheckRewardsTask.zh-Hant.resx
new file mode 100644
index 00000000..fd780202
--- /dev/null
+++ b/BetterGenshinImpact/GameTask/Common/Job/CheckRewardsTask.zh-Hant.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 今日獎勵已領取
+
+
\ No newline at end of file
diff --git a/BetterGenshinImpact/GameTask/Common/Job/ClaimBattlePassRewardsTask.cs b/BetterGenshinImpact/GameTask/Common/Job/ClaimBattlePassRewardsTask.cs
index e06df9a7..2aac397b 100644
--- a/BetterGenshinImpact/GameTask/Common/Job/ClaimBattlePassRewardsTask.cs
+++ b/BetterGenshinImpact/GameTask/Common/Job/ClaimBattlePassRewardsTask.cs
@@ -1,12 +1,16 @@
using System;
+using System.Globalization;
using System.Linq;
+using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using BetterGenshinImpact.Core.Recognition;
using BetterGenshinImpact.Core.Simulator.Extensions;
using BetterGenshinImpact.GameTask.Common.Element.Assets;
using BetterGenshinImpact.GameTask.Model.Area;
+using BetterGenshinImpact.Helpers;
using BetterGenshinImpact.Helpers.Extensions;
+using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using Vanara.PInvoke;
using static BetterGenshinImpact.GameTask.Common.TaskControl;
@@ -20,6 +24,15 @@ public class ClaimBattlePassRewardsTask
{
private readonly ReturnMainUiTask _returnMainUiTask = new();
+ private readonly string claimAllLocalizedString;
+
+ public ClaimBattlePassRewardsTask()
+ {
+ IStringLocalizer stringLocalizer = App.GetService>() ?? throw new NullReferenceException();
+ CultureInfo cultureInfo = new CultureInfo(TaskContext.Instance().Config.OtherConfig.GameCultureInfoName);
+ this.claimAllLocalizedString = stringLocalizer.WithCultureGet(cultureInfo, "一键");
+ }
+
public async Task Start(CancellationToken ct)
{
try
@@ -74,7 +87,7 @@ public class ClaimBattlePassRewardsTask
{
using var ra = CaptureToRectArea();
var ocrList = ra.FindMulti(RecognitionObject.Ocr(ra.ToRect().CutRightBottom(0.3, 0.18)));
- var wt = ocrList.FirstOrDefault(txt => txt.Text.Contains("一键"));
+ var wt = ocrList.FirstOrDefault(txt => Regex.IsMatch(txt.Text, this.claimAllLocalizedString));
if (wt != null)
{
wt.Click();
diff --git a/BetterGenshinImpact/GameTask/Common/Job/ClaimBattlePassRewardsTask.en.resx b/BetterGenshinImpact/GameTask/Common/Job/ClaimBattlePassRewardsTask.en.resx
new file mode 100644
index 00000000..fb941363
--- /dev/null
+++ b/BetterGenshinImpact/GameTask/Common/Job/ClaimBattlePassRewardsTask.en.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ All
+
+
\ No newline at end of file
diff --git a/BetterGenshinImpact/GameTask/Common/Job/ClaimBattlePassRewardsTask.fr.resx b/BetterGenshinImpact/GameTask/Common/Job/ClaimBattlePassRewardsTask.fr.resx
new file mode 100644
index 00000000..d57ecdfa
--- /dev/null
+++ b/BetterGenshinImpact/GameTask/Common/Job/ClaimBattlePassRewardsTask.fr.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Tout
+
+
\ No newline at end of file
diff --git a/BetterGenshinImpact/GameTask/Common/Job/ClaimBattlePassRewardsTask.zh-Hans.resx b/BetterGenshinImpact/GameTask/Common/Job/ClaimBattlePassRewardsTask.zh-Hans.resx
new file mode 100644
index 00000000..4c89b85f
--- /dev/null
+++ b/BetterGenshinImpact/GameTask/Common/Job/ClaimBattlePassRewardsTask.zh-Hans.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 一键
+
+
\ No newline at end of file
diff --git a/BetterGenshinImpact/GameTask/Common/Job/ClaimBattlePassRewardsTask.zh-Hant.resx b/BetterGenshinImpact/GameTask/Common/Job/ClaimBattlePassRewardsTask.zh-Hant.resx
new file mode 100644
index 00000000..ce0c0e49
--- /dev/null
+++ b/BetterGenshinImpact/GameTask/Common/Job/ClaimBattlePassRewardsTask.zh-Hant.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 一鍵
+
+
\ No newline at end of file
diff --git a/BetterGenshinImpact/GameTask/Common/Job/ClaimEncounterPointsRewardsTask.cs b/BetterGenshinImpact/GameTask/Common/Job/ClaimEncounterPointsRewardsTask.cs
index 94df7cd7..5387ba45 100644
--- a/BetterGenshinImpact/GameTask/Common/Job/ClaimEncounterPointsRewardsTask.cs
+++ b/BetterGenshinImpact/GameTask/Common/Job/ClaimEncounterPointsRewardsTask.cs
@@ -1,5 +1,7 @@
using System;
+using System.Globalization;
using System.Linq;
+using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using BetterGenshinImpact.Core.Recognition;
@@ -7,6 +9,8 @@ using BetterGenshinImpact.Core.Simulator;
using BetterGenshinImpact.Core.Simulator.Extensions;
using BetterGenshinImpact.GameTask.Common.Element.Assets;
using BetterGenshinImpact.GameTask.Model.Area;
+using BetterGenshinImpact.Helpers;
+using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using Vanara.PInvoke;
using static BetterGenshinImpact.GameTask.Common.TaskControl;
@@ -20,6 +24,15 @@ public class ClaimEncounterPointsRewardsTask
{
private readonly ReturnMainUiTask _returnMainUiTask = new();
+ private readonly string commissionsLocalizedString;
+
+ public ClaimEncounterPointsRewardsTask()
+ {
+ IStringLocalizer stringLocalizer = App.GetService>() ?? throw new NullReferenceException();
+ CultureInfo cultureInfo = new CultureInfo(TaskContext.Instance().Config.OtherConfig.GameCultureInfoName);
+ this.commissionsLocalizedString = stringLocalizer.WithCultureGet(cultureInfo, "委托");
+ }
+
public async Task Start(CancellationToken ct)
{
try
@@ -51,9 +64,9 @@ public class ClaimEncounterPointsRewardsTask
{
using var ra = CaptureToRectArea();
- var ocrList = ra.FindMulti(RecognitionObject.Ocr(0, 0, 360 * assetScale, ra.Height));
+ var ocrList = ra.FindMulti(RecognitionObject.Ocr(0, 0, 380 * assetScale, ra.Height));
- var wt = ocrList.FirstOrDefault(txt => txt.Text.Contains("委托"));
+ var wt = ocrList.FirstOrDefault(txt => Regex.IsMatch(txt.Text, this.commissionsLocalizedString));
if (wt != null)
{
diff --git a/BetterGenshinImpact/GameTask/Common/Job/ClaimEncounterPointsRewardsTask.en.resx b/BetterGenshinImpact/GameTask/Common/Job/ClaimEncounterPointsRewardsTask.en.resx
new file mode 100644
index 00000000..6a96b443
--- /dev/null
+++ b/BetterGenshinImpact/GameTask/Common/Job/ClaimEncounterPointsRewardsTask.en.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Commissions
+
+
\ No newline at end of file
diff --git a/BetterGenshinImpact/GameTask/Common/Job/ClaimEncounterPointsRewardsTask.fr.resx b/BetterGenshinImpact/GameTask/Common/Job/ClaimEncounterPointsRewardsTask.fr.resx
new file mode 100644
index 00000000..f6f62ef4
--- /dev/null
+++ b/BetterGenshinImpact/GameTask/Common/Job/ClaimEncounterPointsRewardsTask.fr.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Missions
+
+
\ No newline at end of file
diff --git a/BetterGenshinImpact/GameTask/Common/Job/ClaimEncounterPointsRewardsTask.zh-Hans.resx b/BetterGenshinImpact/GameTask/Common/Job/ClaimEncounterPointsRewardsTask.zh-Hans.resx
new file mode 100644
index 00000000..6a6efcc2
--- /dev/null
+++ b/BetterGenshinImpact/GameTask/Common/Job/ClaimEncounterPointsRewardsTask.zh-Hans.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 委托
+
+
\ No newline at end of file
diff --git a/BetterGenshinImpact/GameTask/Common/Job/ClaimEncounterPointsRewardsTask.zh-Hant.resx b/BetterGenshinImpact/GameTask/Common/Job/ClaimEncounterPointsRewardsTask.zh-Hant.resx
new file mode 100644
index 00000000..a97a24e7
--- /dev/null
+++ b/BetterGenshinImpact/GameTask/Common/Job/ClaimEncounterPointsRewardsTask.zh-Hant.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 委[託,話]
+
+
\ No newline at end of file
diff --git a/BetterGenshinImpact/GameTask/Common/Job/GoToAdventurersGuildTask.cs b/BetterGenshinImpact/GameTask/Common/Job/GoToAdventurersGuildTask.cs
index 3def90d1..d1825583 100644
--- a/BetterGenshinImpact/GameTask/Common/Job/GoToAdventurersGuildTask.cs
+++ b/BetterGenshinImpact/GameTask/Common/Job/GoToAdventurersGuildTask.cs
@@ -13,6 +13,9 @@ using BetterGenshinImpact.GameTask.AutoPick.Assets;
using BetterGenshinImpact.GameTask.Common.Element.Assets;
using Vanara.PInvoke;
using static BetterGenshinImpact.GameTask.Common.TaskControl;
+using Microsoft.Extensions.Localization;
+using BetterGenshinImpact.Helpers;
+using System.Globalization;
namespace BetterGenshinImpact.GameTask.Common.Job;
@@ -24,6 +27,19 @@ public class GoToAdventurersGuildTask
private readonly ChooseTalkOptionTask _chooseTalkOptionTask = new();
+ private readonly string dailyLocalizedString;
+ private readonly string catherineLocalizedString;
+ private readonly string expeditionLocalizedString;
+
+ public GoToAdventurersGuildTask()
+ {
+ IStringLocalizer stringLocalizer = App.GetService>() ?? throw new NullReferenceException();
+ CultureInfo cultureInfo = new CultureInfo(TaskContext.Instance().Config.OtherConfig.GameCultureInfoName);
+ this.dailyLocalizedString = stringLocalizer.WithCultureGet(cultureInfo, "每日");
+ this.catherineLocalizedString = stringLocalizer.WithCultureGet(cultureInfo, "凯瑟琳");
+ this.expeditionLocalizedString = stringLocalizer.WithCultureGet(cultureInfo, "探索");
+ }
+
public async Task Start(string country, CancellationToken ct, string? dailyRewardPartyName = null)
{
Logger.LogInformation("→ {Name} 开始", Name);
@@ -36,7 +52,7 @@ public class GoToAdventurersGuildTask
{
await new SwitchPartyTask().Start(dailyRewardPartyName, ct);
}
-
+
// F1领取奖励
await new ClaimEncounterPointsRewardsTask().Start(ct);
@@ -68,7 +84,7 @@ public class GoToAdventurersGuildTask
await GoToAdventurersGuild(country, ct);
// 每日
- var res = await _chooseTalkOptionTask.SingleSelectText("每日", ct, 10, true);
+ var res = await _chooseTalkOptionTask.SingleSelectText(this.dailyLocalizedString, ct, 10, true);
if (res == TalkOptionRes.FoundAndClick)
{
Logger.LogInformation("▶ {Text}", "领取『每日委托』奖励!");
@@ -82,7 +98,7 @@ public class GoToAdventurersGuildTask
// 结束后重新打开
await Delay(1200, ct);
var ra = CaptureToRectArea();
- if (!Bv.FindFAndPress(ra, "凯瑟琳"))
+ if (!Bv.FindFAndPress(ra, text: this.catherineLocalizedString))
{
throw new Exception("未找与凯瑟琳对话交互按钮");
}
@@ -97,7 +113,7 @@ public class GoToAdventurersGuildTask
}
// 探索
- res = await _chooseTalkOptionTask.SingleSelectText("探索", ct, 10, true);
+ res = await _chooseTalkOptionTask.SingleSelectText(this.expeditionLocalizedString, ct, 10, true);
if (res == TalkOptionRes.FoundAndClick)
{
await Delay(500, ct);
@@ -136,7 +152,7 @@ public class GoToAdventurersGuildTask
Enabled = true,
AutoSkipEnabled = true
},
- EndAction = region => Bv.FindFAndPress(region, "凯瑟琳")
+ EndAction = region => Bv.FindFAndPress(region, text: this.catherineLocalizedString)
};
await pathingTask.Pathing(task);
diff --git a/BetterGenshinImpact/GameTask/Common/Job/GoToAdventurersGuildTask.en.resx b/BetterGenshinImpact/GameTask/Common/Job/GoToAdventurersGuildTask.en.resx
new file mode 100644
index 00000000..dbf7b3c3
--- /dev/null
+++ b/BetterGenshinImpact/GameTask/Common/Job/GoToAdventurersGuildTask.en.resx
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Katheryne
+
+
+ Expedition
+
+
+ Daily
+
+
\ No newline at end of file
diff --git a/BetterGenshinImpact/GameTask/Common/Job/GoToAdventurersGuildTask.fr.resx b/BetterGenshinImpact/GameTask/Common/Job/GoToAdventurersGuildTask.fr.resx
new file mode 100644
index 00000000..a98e8632
--- /dev/null
+++ b/BetterGenshinImpact/GameTask/Common/Job/GoToAdventurersGuildTask.fr.resx
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Catherine
+
+
+ Expédition
+
+
+ quotidien
+
+
\ No newline at end of file
diff --git a/BetterGenshinImpact/GameTask/Common/Job/GoToAdventurersGuildTask.zh-Hans.resx b/BetterGenshinImpact/GameTask/Common/Job/GoToAdventurersGuildTask.zh-Hans.resx
new file mode 100644
index 00000000..08228755
--- /dev/null
+++ b/BetterGenshinImpact/GameTask/Common/Job/GoToAdventurersGuildTask.zh-Hans.resx
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 凯瑟琳
+
+
+ 探索
+
+
+ 每日
+
+
\ No newline at end of file
diff --git a/BetterGenshinImpact/GameTask/Common/Job/GoToAdventurersGuildTask.zh-Hant.resx b/BetterGenshinImpact/GameTask/Common/Job/GoToAdventurersGuildTask.zh-Hant.resx
new file mode 100644
index 00000000..6c36454a
--- /dev/null
+++ b/BetterGenshinImpact/GameTask/Common/Job/GoToAdventurersGuildTask.zh-Hant.resx
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 凱瑟琳
+
+
+ 探索
+
+
+ 每日
+
+
\ No newline at end of file
diff --git a/BetterGenshinImpact/GameTask/Common/Job/GoToCraftingBenchTask.cs b/BetterGenshinImpact/GameTask/Common/Job/GoToCraftingBenchTask.cs
index d590c4f9..805cc4ec 100644
--- a/BetterGenshinImpact/GameTask/Common/Job/GoToCraftingBenchTask.cs
+++ b/BetterGenshinImpact/GameTask/Common/Job/GoToCraftingBenchTask.cs
@@ -11,6 +11,9 @@ using System.Threading.Tasks;
using BetterGenshinImpact.Core.Simulator.Extensions;
using Vanara.PInvoke;
using static BetterGenshinImpact.GameTask.Common.TaskControl;
+using Microsoft.Extensions.Localization;
+using System.Globalization;
+using BetterGenshinImpact.Helpers;
namespace BetterGenshinImpact.GameTask.Common.Job;
@@ -22,6 +25,15 @@ public class GoToCraftingBenchTask
private readonly ChooseTalkOptionTask _chooseTalkOptionTask = new();
+ private readonly string craftLocalizedString;
+
+ public GoToCraftingBenchTask()
+ {
+ IStringLocalizer stringLocalizer = App.GetService>() ?? throw new NullReferenceException();
+ CultureInfo cultureInfo = new CultureInfo(TaskContext.Instance().Config.OtherConfig.GameCultureInfoName);
+ this.craftLocalizedString = stringLocalizer.WithCultureGet(cultureInfo, "合成");
+ }
+
public async Task Start(string country, CancellationToken ct)
{
Logger.LogInformation("→ {Name} 开始", Name);
@@ -102,7 +114,7 @@ public class GoToCraftingBenchTask
AutoSkipEnabled = true,
AutoRunEnabled = country != "枫丹",
},
- EndAction = region => Bv.FindFAndPress(region, "合成")
+ EndAction = region => Bv.FindFAndPress(region, text: this.craftLocalizedString)
};
await pathingTask.Pathing(task);
@@ -144,7 +156,7 @@ public class GoToCraftingBenchTask
private async Task TryPressCrafting( CancellationToken ct)
{
using var ra1 = CaptureToRectArea();
- var res = Bv.FindFAndPress(ra1, "合成");
+ var res = Bv.FindFAndPress(ra1, text: this.craftLocalizedString);
if (res)
{
await Delay(1000, ct);
diff --git a/BetterGenshinImpact/GameTask/Common/Job/GoToCraftingBenchTask.en.resx b/BetterGenshinImpact/GameTask/Common/Job/GoToCraftingBenchTask.en.resx
new file mode 100644
index 00000000..a1606c56
--- /dev/null
+++ b/BetterGenshinImpact/GameTask/Common/Job/GoToCraftingBenchTask.en.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Craft
+
+
\ No newline at end of file
diff --git a/BetterGenshinImpact/GameTask/Common/Job/GoToCraftingBenchTask.fr.resx b/BetterGenshinImpact/GameTask/Common/Job/GoToCraftingBenchTask.fr.resx
new file mode 100644
index 00000000..164dd0e9
--- /dev/null
+++ b/BetterGenshinImpact/GameTask/Common/Job/GoToCraftingBenchTask.fr.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Synth[è|é]se
+
+
\ No newline at end of file
diff --git a/BetterGenshinImpact/GameTask/Common/Job/GoToCraftingBenchTask.zh-Hans.resx b/BetterGenshinImpact/GameTask/Common/Job/GoToCraftingBenchTask.zh-Hans.resx
new file mode 100644
index 00000000..b2fd29a9
--- /dev/null
+++ b/BetterGenshinImpact/GameTask/Common/Job/GoToCraftingBenchTask.zh-Hans.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 合成
+
+
\ No newline at end of file
diff --git a/BetterGenshinImpact/GameTask/Common/Job/GoToCraftingBenchTask.zh-Hant.resx b/BetterGenshinImpact/GameTask/Common/Job/GoToCraftingBenchTask.zh-Hant.resx
new file mode 100644
index 00000000..b2fd29a9
--- /dev/null
+++ b/BetterGenshinImpact/GameTask/Common/Job/GoToCraftingBenchTask.zh-Hant.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 合成
+
+
\ No newline at end of file
diff --git a/BetterGenshinImpact/GameTask/Model/BaseTaskParam.cs b/BetterGenshinImpact/GameTask/Model/BaseTaskParam.cs
index 527f1a96..40b53621 100644
--- a/BetterGenshinImpact/GameTask/Model/BaseTaskParam.cs
+++ b/BetterGenshinImpact/GameTask/Model/BaseTaskParam.cs
@@ -1,4 +1,6 @@
+using BetterGenshinImpact.GameTask.AutoFishing;
+using System.Globalization;
using System.Threading;
namespace BetterGenshinImpact.GameTask.Model;
@@ -8,4 +10,12 @@ namespace BetterGenshinImpact.GameTask.Model;
///
public class BaseTaskParam
{
+ public CultureInfo? GameCultureInfo { get; set; }
+ public BaseTaskParam()
+ {
+ }
+ public BaseTaskParam(CultureInfo? gameCultureInfo)
+ {
+ GameCultureInfo = gameCultureInfo;
+ }
}
diff --git a/BetterGenshinImpact/Helpers/CultureHelper.cs b/BetterGenshinImpact/Helpers/CultureHelper.cs
new file mode 100644
index 00000000..a0b24f59
--- /dev/null
+++ b/BetterGenshinImpact/Helpers/CultureHelper.cs
@@ -0,0 +1,84 @@
+using BetterGenshinImpact.GameTask.Common.BgiVision;
+using Microsoft.Extensions.Localization;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace BetterGenshinImpact.Helpers;
+public static class CultureHelper
+{
+ public static string WithCultureGet(this IStringLocalizer stringLocalizer, CultureInfo? culture, string text)
+ {
+ if (culture == null)
+ {
+ return text;
+ }
+ else
+ {
+ using var _ = Use(culture);
+ return stringLocalizer[text];
+ }
+ }
+
+ public static IDisposable Use([NotNull] string culture, string? uiCulture = null)
+ {
+ ArgumentNullException.ThrowIfNull(culture, nameof(culture));
+
+ return Use(
+ new CultureInfo(culture),
+ uiCulture == null
+ ? null
+ : new CultureInfo(uiCulture)
+ );
+ }
+
+ ///
+ /// WithCulture被微软移除了,这是个替代方法,用于临时切换到某个CurrentCulture、CurrentUICulture
+ ///
+ ///
+ ///
+ ///
+ public static IDisposable Use([NotNull] CultureInfo culture, CultureInfo? uiCulture = null)
+ {
+ ArgumentNullException.ThrowIfNull(culture, nameof(culture));
+
+ var currentCulture = CultureInfo.CurrentCulture;
+ var currentUiCulture = CultureInfo.CurrentUICulture;
+
+ CultureInfo.CurrentCulture = culture;
+ CultureInfo.CurrentUICulture = uiCulture ?? culture;
+
+ return new DisposeAction>(static (state) =>
+ {
+ var (currentCulture, currentUiCulture) = state;
+ CultureInfo.CurrentCulture = currentCulture;
+ CultureInfo.CurrentUICulture = currentUiCulture;
+ }, (currentCulture, currentUiCulture));
+ }
+
+ public class DisposeAction : IDisposable
+ {
+ private readonly Action _action;
+
+ private readonly T? _parameter;
+
+ public DisposeAction(Action action, T parameter)
+ {
+ ArgumentNullException.ThrowIfNull(action, nameof(action));
+
+ _action = action;
+ _parameter = parameter;
+ }
+
+ public void Dispose()
+ {
+ if (_parameter != null)
+ {
+ _action(_parameter);
+ }
+ }
+ }
+}
diff --git a/BetterGenshinImpact/Model/ConditionDefinition.cs b/BetterGenshinImpact/Model/ConditionDefinition.cs
index f2c8dcdc..67d0feb1 100644
--- a/BetterGenshinImpact/Model/ConditionDefinition.cs
+++ b/BetterGenshinImpact/Model/ConditionDefinition.cs
@@ -13,7 +13,7 @@ public class ConditionDefinition
// 谓语选项
public List PredicateOptions { get; set; } = ["包含"];
- public List? ObjectOptions { get; set; } // 宾语选项
+ public IEnumerable? ObjectOptions { get; set; } // 宾语选项
public List? ResultOptions { get; set; } // 结果选项 为空使用文本框
}
diff --git a/BetterGenshinImpact/View/Converters/CultureInfoNameToKVPConverter.cs b/BetterGenshinImpact/View/Converters/CultureInfoNameToKVPConverter.cs
new file mode 100644
index 00000000..31403d09
--- /dev/null
+++ b/BetterGenshinImpact/View/Converters/CultureInfoNameToKVPConverter.cs
@@ -0,0 +1,43 @@
+using BetterGenshinImpact.Helpers;
+using Microsoft.Extensions.Localization;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Text;
+using System.Windows.Data;
+
+namespace BetterGenshinImpact.View.Converters;
+
+[ValueConversion(typeof(KeyValuePair), typeof(string))]
+class CultureInfoNameToKVPConverter : IValueConverter
+{
+ public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
+ {
+ if (value == null)
+ {
+ return null;
+ }
+
+ string? cultureInfoName = value as string;
+ if (cultureInfoName is null)
+ {
+ throw new ArgumentException("Value must be a CultureInfoName");
+ }
+
+ var stringLocalizer = App.GetService>() ?? throw new NullReferenceException();
+ var description = stringLocalizer.WithCultureGet(new CultureInfo(cultureInfoName), "简体中文");
+
+ return new KeyValuePair(cultureInfoName, description);
+ }
+
+ public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
+ {
+ if (value == null)
+ {
+ return null;
+ }
+
+ var kvp = (KeyValuePair)value;
+ return kvp.Key;
+ }
+}
diff --git a/BetterGenshinImpact/View/Converters/CultureInfoNameToKVPConverter.en.resx b/BetterGenshinImpact/View/Converters/CultureInfoNameToKVPConverter.en.resx
new file mode 100644
index 00000000..4332c376
--- /dev/null
+++ b/BetterGenshinImpact/View/Converters/CultureInfoNameToKVPConverter.en.resx
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ English
+
+
\ No newline at end of file
diff --git a/BetterGenshinImpact/View/Converters/CultureInfoNameToKVPConverter.fr.resx b/BetterGenshinImpact/View/Converters/CultureInfoNameToKVPConverter.fr.resx
new file mode 100644
index 00000000..170ffb37
--- /dev/null
+++ b/BetterGenshinImpact/View/Converters/CultureInfoNameToKVPConverter.fr.resx
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Français
+
+
\ No newline at end of file
diff --git a/BetterGenshinImpact/View/Converters/CultureInfoNameToKVPConverter.zh-Hans.resx b/BetterGenshinImpact/View/Converters/CultureInfoNameToKVPConverter.zh-Hans.resx
new file mode 100644
index 00000000..7451e481
--- /dev/null
+++ b/BetterGenshinImpact/View/Converters/CultureInfoNameToKVPConverter.zh-Hans.resx
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 简体中文
+
+
\ No newline at end of file
diff --git a/BetterGenshinImpact/View/Converters/CultureInfoNameToKVPConverter.zh-Hant.resx b/BetterGenshinImpact/View/Converters/CultureInfoNameToKVPConverter.zh-Hant.resx
new file mode 100644
index 00000000..d35382fa
--- /dev/null
+++ b/BetterGenshinImpact/View/Converters/CultureInfoNameToKVPConverter.zh-Hant.resx
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 繁體中文
+
+
\ No newline at end of file
diff --git a/BetterGenshinImpact/View/Converters/EnumToKVPConverter.cs b/BetterGenshinImpact/View/Converters/EnumToKVPConverter.cs
index b71110a9..977671c2 100644
--- a/BetterGenshinImpact/View/Converters/EnumToKVPConverter.cs
+++ b/BetterGenshinImpact/View/Converters/EnumToKVPConverter.cs
@@ -5,10 +5,7 @@ using System.Windows.Data;
using System.Windows;
using System.ComponentModel;
using System.Globalization;
-using BetterGenshinImpact.GameTask.AutoFishing;
-using BetterGenshinImpact.GameTask.AutoFight.Script;
using System.Reflection;
-using Vanara.Extensions.Reflection;
namespace BetterGenshinImpact.View.Converters;
@@ -28,7 +25,7 @@ public class EnumToKVPConverter : IValueConverter
throw new ArgumentException("Value must be an enum");
}
- var name = Enum.GetName(enumType, value);
+ var name = Enum.GetName(enumType, value) ?? throw new NullReferenceException();
var field = enumType.GetField(name);
var descriptionAttribute = field?.GetCustomAttribute();
diff --git a/BetterGenshinImpact/View/Pages/TaskSettingsPage.xaml b/BetterGenshinImpact/View/Pages/TaskSettingsPage.xaml
index 81010529..1ccf786d 100644
--- a/BetterGenshinImpact/View/Pages/TaskSettingsPage.xaml
+++ b/BetterGenshinImpact/View/Pages/TaskSettingsPage.xaml
@@ -1569,13 +1569,79 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/BetterGenshinImpact/ViewModel/MainWindowViewModel.cs b/BetterGenshinImpact/ViewModel/MainWindowViewModel.cs
index 7b4fbc4a..60c4a016 100644
--- a/BetterGenshinImpact/ViewModel/MainWindowViewModel.cs
+++ b/BetterGenshinImpact/ViewModel/MainWindowViewModel.cs
@@ -132,7 +132,7 @@ public partial class MainWindowViewModel : ObservableObject, IViewModel
ModifyFolderSecurity();
Config.CommonConfig.RunForVersion = Global.Version;
}
-
+
OnceRun();
// 检查更新
@@ -218,10 +218,12 @@ public partial class MainWindowViewModel : ObservableObject, IViewModel
{
try
{
- await Task.Run(() =>
+ await Task.Run(async () =>
{
try
{
+ string gameCultureInfoName = TaskContext.Instance().Config.OtherConfig.GameCultureInfoName;
+ await OcrFactory.ChangeCulture(gameCultureInfoName);
var s = OcrFactory.Paddle.Ocr(new Mat(Global.Absolute(@"Assets\Model\PaddleOCR\test_ocr.png"), ImreadModes.Grayscale));
Debug.WriteLine("PaddleOcr预热结果:" + s);
}
@@ -265,7 +267,7 @@ public partial class MainWindowViewModel : ObservableObject, IViewModel
{
_logger.LogDebug("获取设备ID异常:" + e.Source + "\r\n--" + Environment.NewLine + e.StackTrace + "\r\n---" + Environment.NewLine + e.Message);
}
-
+
// 每个设备只运行一次
if (!Config.CommonConfig.OnceHadRunDeviceIdList.Contains(deviceId))
{
@@ -275,7 +277,7 @@ public partial class MainWindowViewModel : ObservableObject, IViewModel
};
prompt.ShowDialog();
prompt.Focus();
-
+
Config.CommonConfig.OnceHadRunDeviceIdList.Add(deviceId);
_configService.Save();
}
diff --git a/BetterGenshinImpact/ViewModel/Pages/ScriptControlViewModel.cs b/BetterGenshinImpact/ViewModel/Pages/ScriptControlViewModel.cs
index 1b6aed2c..312e80cb 100644
--- a/BetterGenshinImpact/ViewModel/Pages/ScriptControlViewModel.cs
+++ b/BetterGenshinImpact/ViewModel/Pages/ScriptControlViewModel.cs
@@ -29,7 +29,6 @@ using BetterGenshinImpact.ViewModel.Pages.View;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Microsoft.Extensions.Logging;
-using SharpCompress;
using Wpf.Ui;
using Wpf.Ui.Controls;
using Wpf.Ui.Violeta.Controls;
@@ -997,7 +996,14 @@ public partial class ScriptControlViewModel : ViewModel
return;
}
- SelectedScriptGroup?.Projects.ToList().Where(item2 => item2.FolderName == item.FolderName).ForEach(OnDeleteScript);
+ var toBeDeletedProjects = SelectedScriptGroup?.Projects.ToList().Where(item2 => item2.FolderName == item.FolderName);
+ if (toBeDeletedProjects != null)
+ {
+ foreach (var project in toBeDeletedProjects)
+ {
+ OnDeleteScript(project);
+ }
+ }
}
[RelayCommand]
diff --git a/BetterGenshinImpact/ViewModel/Pages/TaskSettingsPageViewModel.cs b/BetterGenshinImpact/ViewModel/Pages/TaskSettingsPageViewModel.cs
index f91db6a4..2b4336f3 100644
--- a/BetterGenshinImpact/ViewModel/Pages/TaskSettingsPageViewModel.cs
+++ b/BetterGenshinImpact/ViewModel/Pages/TaskSettingsPageViewModel.cs
@@ -32,6 +32,11 @@ using BetterGenshinImpact.ViewModel.Pages.View;
using System.Linq;
using System.Reflection;
using Vanara.Extensions;
+using System.Collections.Frozen;
+using System.Globalization;
+using Microsoft.Extensions.Localization;
+using BetterGenshinImpact.View.Converters;
+using BetterGenshinImpact.Core.Recognition.OCR;
namespace BetterGenshinImpact.ViewModel.Pages;
@@ -120,15 +125,27 @@ public partial class TaskSettingsPageViewModel : ViewModel
private string _switchAutoFishingButtonText = "启动";
[ObservableProperty]
- private Dictionary _fishingTimePolicyDict = Enum.GetValues(typeof(FishingTimePolicy))
+ private FrozenDictionary _fishingTimePolicyDict = Enum.GetValues(typeof(FishingTimePolicy))
.Cast()
- .ToDictionary(
+ .ToFrozenDictionary(
e => (Enum)e,
e => e.GetType()
.GetField(e.ToString())?
.GetCustomAttribute()?
.Description ?? e.ToString());
-
+
+ [ObservableProperty]
+ private FrozenDictionary _languageDict = new string[] { "zh-Hans", "zh-Hant", "en", "fr" }
+ .ToFrozenDictionary(
+ c => c,
+ c =>
+ {
+ CultureInfo.CurrentUICulture = new CultureInfo(c);
+ var stringLocalizer = App.GetService>() ?? throw new NullReferenceException();
+ return stringLocalizer["简体中文"].ToString();
+ }
+ );
+
private bool saveScreenshotOnKeyTick;
public bool SaveScreenshotOnKeyTick
{
@@ -417,4 +434,10 @@ public partial class TaskSettingsPageViewModel : ViewModel
{
_autoFightViewModel.OnOpenLocalScriptRepo();
}
+
+ [RelayCommand]
+ private async Task OnGameLangSelectionChanged(KeyValuePair type)
+ {
+ await OcrFactory.ChangeCulture(type.Key);
+ }
}
\ No newline at end of file
diff --git a/Test/BetterGenshinImpact.UnitTest/CoreTests/RecognitionTests/OCRTests/PaddleOcrServiceTests.cs b/Test/BetterGenshinImpact.UnitTest/CoreTests/RecognitionTests/OCRTests/PaddleOcrServiceTests.cs
new file mode 100644
index 00000000..e68f0a97
--- /dev/null
+++ b/Test/BetterGenshinImpact.UnitTest/CoreTests/RecognitionTests/OCRTests/PaddleOcrServiceTests.cs
@@ -0,0 +1,67 @@
+using OpenCvSharp;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using BetterGenshinImpact.Core.Recognition.OCR;
+using System.Drawing;
+using OpenCvSharp.Extensions;
+using System.Text.RegularExpressions;
+using System.Collections.Concurrent;
+
+namespace BetterGenshinImpact.UnitTest.CoreTests.RecognitionTests.OCRTests
+{
+ public partial class PaddleOcrServiceTests
+ {
+ private static readonly ConcurrentDictionary paddleOcrServices = new ConcurrentDictionary();
+
+ [Theory]
+ [InlineData("zh-Hans", "挑战,达成", "[挑战,达成]")]
+ [InlineData("zh-Hans", "凯瑟琳")]
+ [InlineData("en", "Daily")]
+ [InlineData("en", "Katheryne")]
+ [InlineData("zh-Hant", "凱瑟琳")]
+ [InlineData("zh-Hant", "委託", "委[託,話]")]
+ [InlineData("zh-Hant", "挑戰,達成", "[挑戰,達成]")]
+ [InlineData("zh-Hant", "自動,退出", "[自動,退出]")]
+ [InlineData("zh-Hant", "跳過")]
+ [InlineData("fr", "quotidien")]
+ [InlineData("fr", "Expédition")]
+ [InlineData("fr", "Pêcher", "P[ê|é]cher")]
+ [InlineData("fr", "Synthèse", "Synth[è|é]se")]
+ [InlineData("fr", "Défi, terminé", "[Défi,terminé]")]
+ [InlineData("fr", "Sortie")]
+ [InlineData("fr", "Passer")]
+ ///
+ /// 测试识别各种文字,结果为成功
+ ///
+ public void PaddleOcrService_VariousLangWords_ShouldEqualOrMatch(string cultureInfoName, string word, string? pattern = null)
+ {
+ //
+ using Bitmap bitmap = new Bitmap(word.Length * 50, 100);
+
+ using Graphics g = Graphics.FromImage(bitmap);
+ g.Clear(Color.White);
+ using Font font = new Font("Arial", 12);
+ using Brush brush = new SolidBrush(Color.Black);
+ g.DrawString(word, font, brush, 0, 50);
+ using Mat mat4 = bitmap.ToMat();
+ using Mat mat = mat4.CvtColor(ColorConversionCodes.RGBA2RGB);
+
+ //
+ PaddleOcrService sut = paddleOcrServices.GetOrAdd(cultureInfoName, name => { lock (paddleOcrServices) { return new PaddleOcrService(name); } });
+ string actual = sut.Ocr(mat).Replace(" ", "");
+
+ //
+ if (pattern == null)
+ {
+ Assert.Equal(word, actual);
+ }
+ else
+ {
+ Assert.Matches(pattern, actual);
+ }
+ }
+ }
+}
diff --git a/Test/BetterGenshinImpact.UnitTest/GameTaskTests/AutoFightTests/DefaultAutoFightConfigTests.cs b/Test/BetterGenshinImpact.UnitTest/GameTaskTests/AutoFightTests/DefaultAutoFightConfigTests.cs
new file mode 100644
index 00000000..b69f6626
--- /dev/null
+++ b/Test/BetterGenshinImpact.UnitTest/GameTaskTests/AutoFightTests/DefaultAutoFightConfigTests.cs
@@ -0,0 +1,28 @@
+using BetterGenshinImpact.GameTask.AutoFight.Config;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BetterGenshinImpact.UnitTest.GameTaskTests.AutoFightTests
+{
+ public partial class DefaultAutoFightConfigTests
+ {
+ ///
+ /// 测试默认战斗配置初始化,获取所有别名,结果应成功
+ ///
+ [Fact]
+ public void DefaultAutoFightConfig_Init_AllAliasShouldSuccess()
+ {
+ //
+ // Do nothing
+
+ //
+ var sut = DefaultAutoFightConfig.CombatAvatarAliasToNameMap;
+
+ //
+ Assert.All(sut.Keys, alias => DefaultAutoFightConfig.AvatarAliasToStandardName(alias)); // 顺便测试一下查询别名方法的速度
+ }
+ }
+}
diff --git a/Test/BetterGenshinImpact.UnitTest/GameTaskTests/AutoFishingTests/BehavioursTests.CheckRaiseHook.cs b/Test/BetterGenshinImpact.UnitTest/GameTaskTests/AutoFishingTests/BehavioursTests.CheckRaiseHook.cs
index 63120538..a23f9e5f 100644
--- a/Test/BetterGenshinImpact.UnitTest/GameTaskTests/AutoFishingTests/BehavioursTests.CheckRaiseHook.cs
+++ b/Test/BetterGenshinImpact.UnitTest/GameTaskTests/AutoFishingTests/BehavioursTests.CheckRaiseHook.cs
@@ -45,7 +45,7 @@ namespace BetterGenshinImpact.UnitTest.GameTaskTests.AutoFishingTests
var sut = FluentBuilder.Create()
.MySimpleParallel("下杆中", SimpleParallelPolicy.OnlyOneMustSucceed)
.PushLeaf(() => new CheckThrowRod("检查抛竿结果", blackboard, logger, false, timeProvider)) // todo 后面串联一个召回率高的下杆中检测方法
- .PushLeaf(() => new FishBite("自动提竿", blackboard, logger, false, input, drawContent))
+ .PushLeaf(() => new FishBite("自动提竿", blackboard, logger, false, input, ocrService, drawContent))
.PushLeaf(() => new FishBiteTimeout("下杆超时检查", 15, logger, false, input, timeProvider))
.End()
.Build();
diff --git a/Test/BetterGenshinImpact.UnitTest/GameTaskTests/AutoFishingTests/BehavioursTests.FishBite.cs b/Test/BetterGenshinImpact.UnitTest/GameTaskTests/AutoFishingTests/BehavioursTests.FishBite.cs
index 64fe24ec..d6296348 100644
--- a/Test/BetterGenshinImpact.UnitTest/GameTaskTests/AutoFishingTests/BehavioursTests.FishBite.cs
+++ b/Test/BetterGenshinImpact.UnitTest/GameTaskTests/AutoFishingTests/BehavioursTests.FishBite.cs
@@ -29,7 +29,7 @@ namespace BetterGenshinImpact.UnitTest.GameTaskTests.AutoFishingTests
Blackboard blackboard = new Blackboard(autoFishingAssets: autoFishingAssets);
//
- FishBite sut = new FishBite("-", blackboard, new FakeLogger(), false, new FakeInputSimulator(), drawContent: new FakeDrawContent());
+ FishBite sut = new FishBite("-", blackboard, new FakeLogger(), false, new FakeInputSimulator(), ocrService, drawContent: new FakeDrawContent());
BehaviourStatus actual = sut.Tick(imageRegion);
//
@@ -60,7 +60,7 @@ namespace BetterGenshinImpact.UnitTest.GameTaskTests.AutoFishingTests
var sut = FluentBuilder.Create()
.MySimpleParallel("-", SimpleParallelPolicy.OnlyOneMustSucceed)
//.PushLeaf(() => new CheckThrowRod("-", logger, false, fakeTimeProvider)) // todo
- .PushLeaf(() => new FishBite("-", blackboard, logger, false, input, drawContent: new FakeDrawContent()))
+ .PushLeaf(() => new FishBite("-", blackboard, logger, false, input, ocrService, drawContent: new FakeDrawContent()))
.PushLeaf(() => fishBiteTimeoutBehaviour)
.End()
.Build();
@@ -92,5 +92,28 @@ namespace BetterGenshinImpact.UnitTest.GameTaskTests.AutoFishingTests
Assert.Equal(BehaviourStatus.Succeeded, actual);
Assert.True(fishBiteTimeoutBehaviour.leftButtonClicked);
}
+
+ [Theory]
+ [InlineData(@"202503230049406101_en.png", "en")] // 一张移除了右下角按钮的咬钩截图
+ ///
+ /// 测试外语鱼咬钩,结果为成功
+ ///
+ public void FishBite_English_ShouldSuccess(string screenshot1080p, string cultureName)
+ {
+ //
+ Mat mat = new Mat(@$"..\..\..\Assets\AutoFishing\{screenshot1080p}");
+ var imageRegion = new GameCaptureRegion(mat, 0, 0, new DesktopRegion(new FakeMouseSimulator()), converter: new ScaleConverter(1d), drawContent: new FakeDrawContent());
+
+ FakeSystemInfo systemInfo = new FakeSystemInfo(new Vanara.PInvoke.RECT(0, 0, mat.Width, mat.Height), 1);
+ AutoFishingAssets autoFishingAssets = new AutoFishingAssets(systemInfo);
+ Blackboard blackboard = new Blackboard(autoFishingAssets: autoFishingAssets);
+
+ //
+ FishBite sut = new FishBite("-", blackboard, new FakeLogger(), false, new FakeInputSimulator(), ocrService, drawContent: new FakeDrawContent(), new System.Globalization.CultureInfo(cultureName), this.autoFishingImageRecognitionStringLocalizer);
+ BehaviourStatus actual = sut.Tick(imageRegion);
+
+ //
+ Assert.Equal(BehaviourStatus.Succeeded, actual);
+ }
}
}
diff --git a/Test/BetterGenshinImpact.UnitTest/GameTaskTests/AutoFishingTests/BehavioursTests.cs b/Test/BetterGenshinImpact.UnitTest/GameTaskTests/AutoFishingTests/BehavioursTests.cs
new file mode 100644
index 00000000..b57989e0
--- /dev/null
+++ b/Test/BetterGenshinImpact.UnitTest/GameTaskTests/AutoFishingTests/BehavioursTests.cs
@@ -0,0 +1,29 @@
+using BetterGenshinImpact.Core.Recognition.OCR;
+using BetterGenshinImpact.GameTask.AutoFishing;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Localization;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BetterGenshinImpact.UnitTest.GameTaskTests.AutoFishingTests
+{
+ public partial class BehavioursTests
+ {
+ private readonly IStringLocalizer? autoFishingImageRecognitionStringLocalizer;
+#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑添加 "required" 修饰符或声明为可为 null。
+ private static IOcrService ocrService;
+#pragma warning restore CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑添加 "required" 修饰符或声明为可为 null。
+ public BehavioursTests()
+ {
+ ServiceCollection services = new ServiceCollection();
+ services.AddLogging().AddLocalization();
+ using ServiceProvider sp = services.BuildServiceProvider();
+ this.autoFishingImageRecognitionStringLocalizer = sp.GetRequiredService>();
+
+ LazyInitializer.EnsureInitialized(ref ocrService, () => new PaddleOcrService());
+ }
+ }
+}