Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
N
Neos
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
love_飞影
Neos
Commits
fef43d79
Commit
fef43d79
authored
Apr 21, 2023
by
timel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: valtio store logic 55%
parent
1802f14a
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
510 additions
and
315 deletions
+510
-315
src/service/duel/selectCard.ts
src/service/duel/selectCard.ts
+12
-1
src/service/duel/selectChain.ts
src/service/duel/selectChain.ts
+23
-1
src/valtioStores/matStore/index.ts
src/valtioStores/matStore/index.ts
+2
-298
src/valtioStores/matStore/methods/fetchCheckCardMeta.ts
src/valtioStores/matStore/methods/fetchCheckCardMeta.ts
+142
-0
src/valtioStores/matStore/methods/fetchHint.ts
src/valtioStores/matStore/methods/fetchHint.ts
+75
-0
src/valtioStores/matStore/methods/index.ts
src/valtioStores/matStore/methods/index.ts
+2
-0
src/valtioStores/matStore/store.ts
src/valtioStores/matStore/store.ts
+248
-0
src/valtioStores/matStore/types.ts
src/valtioStores/matStore/types.ts
+6
-15
No files found.
src/service/duel/selectCard.ts
View file @
fef43d79
...
@@ -7,7 +7,10 @@ import {
...
@@ -7,7 +7,10 @@ import {
import
{
fetchCheckCardMeta
}
from
"
@/reducers/duel/modal/mod
"
;
import
{
fetchCheckCardMeta
}
from
"
@/reducers/duel/modal/mod
"
;
import
{
AppDispatch
}
from
"
@/store
"
;
import
{
AppDispatch
}
from
"
@/store
"
;
import
MsgSelectCard
=
ygopro
.
StocGameMessage
.
MsgSelectCard
;
import
MsgSelectCard
=
ygopro
.
StocGameMessage
.
MsgSelectCard
;
import
{
messageStore
}
from
"
@/valtioStores
"
;
import
{
messageStore
,
fetchCheckCardMeta
as
FIXME_fetchCheckCardMeta
,
}
from
"
@/valtioStores
"
;
import
{
CardZoneToChinese
}
from
"
./util
"
;
import
{
CardZoneToChinese
}
from
"
./util
"
;
...
@@ -39,7 +42,15 @@ export default (selectCard: MsgSelectCard, dispatch: AppDispatch) => {
...
@@ -39,7 +42,15 @@ export default (selectCard: MsgSelectCard, dispatch: AppDispatch) => {
},
},
})
})
);
);
// FIXME: rename
FIXME_fetchCheckCardMeta
(
card
.
location
.
location
,
{
code
:
card
.
code
,
location
:
card
.
location
,
response
:
card
.
response
,
});
}
}
dispatch
(
setCheckCardModalIsOpen
(
true
));
dispatch
(
setCheckCardModalIsOpen
(
true
));
messageStore
.
checkCardModal
.
isOpen
=
true
;
};
};
src/service/duel/selectChain.ts
View file @
fef43d79
...
@@ -12,8 +12,14 @@ import { fetchCheckCardMeta } from "@/reducers/duel/modal/mod";
...
@@ -12,8 +12,14 @@ import { fetchCheckCardMeta } from "@/reducers/duel/modal/mod";
import
{
AppDispatch
}
from
"
@/store
"
;
import
{
AppDispatch
}
from
"
@/store
"
;
import
{
CardZoneToChinese
}
from
"
./util
"
;
import
{
CardZoneToChinese
}
from
"
./util
"
;
import
MsgSelectChain
=
ygopro
.
StocGameMessage
.
MsgSelectChain
;
import
{
messageStore
,
fetchCheckCardMeta
as
FIXME_fetchCheckCardMeta
,
fetchSelectHintMeta
as
FIXME_fetchSelectHintMeta
,
}
from
"
@/valtioStores
"
;
type
MsgSelectChain
=
ygopro
.
StocGameMessage
.
MsgSelectChain
;
export
default
(
selectChain
:
MsgSelectChain
,
dispatch
:
AppDispatch
)
=>
{
export
default
(
selectChain
:
MsgSelectChain
,
dispatch
:
AppDispatch
)
=>
{
const
player
=
selectChain
.
player
;
const
player
=
selectChain
.
player
;
const
spCount
=
selectChain
.
special_count
;
const
spCount
=
selectChain
.
special_count
;
...
@@ -71,6 +77,12 @@ export default (selectChain: MsgSelectChain, dispatch: AppDispatch) => {
...
@@ -71,6 +77,12 @@ export default (selectChain: MsgSelectChain, dispatch: AppDispatch) => {
dispatch
(
setCheckCardMOdalCancelAble
(
!
forced
));
dispatch
(
setCheckCardMOdalCancelAble
(
!
forced
));
dispatch
(
setCheckCardModalCancelResponse
(
-
1
));
dispatch
(
setCheckCardModalCancelResponse
(
-
1
));
messageStore
.
checkCardModal
.
selectMin
=
1
;
messageStore
.
checkCardModal
.
selectMax
=
1
;
messageStore
.
checkCardModal
.
onSubmit
=
"
sendSelectChainResponse
"
;
messageStore
.
checkCardModal
.
cancelAble
=
!
forced
;
messageStore
.
checkCardModal
.
cancelResponse
=
-
1
;
for
(
const
chain
of
chains
)
{
for
(
const
chain
of
chains
)
{
const
tagName
=
CardZoneToChinese
(
chain
.
location
.
location
);
const
tagName
=
CardZoneToChinese
(
chain
.
location
.
location
);
dispatch
(
dispatch
(
...
@@ -84,14 +96,24 @@ export default (selectChain: MsgSelectChain, dispatch: AppDispatch) => {
...
@@ -84,14 +96,24 @@ export default (selectChain: MsgSelectChain, dispatch: AppDispatch) => {
},
},
})
})
);
);
FIXME_fetchCheckCardMeta
(
chain
.
location
.
location
,
{
code
:
chain
.
code
,
location
:
chain
.
location
,
response
:
chain
.
response
,
effectDescCode
:
chain
.
effect_description
,
});
}
}
dispatch
(
dispatch
(
fetchSelectHintMeta
({
fetchSelectHintMeta
({
selectHintData
:
203
,
selectHintData
:
203
,
})
})
);
);
FIXME_fetchSelectHintMeta
({
selectHintData
:
203
,
});
dispatch
(
setCheckCardModalIsOpen
(
true
));
dispatch
(
setCheckCardModalIsOpen
(
true
));
messageStore
.
checkCardModal
.
isOpen
=
true
;
break
;
break
;
}
}
...
...
src/valtioStores/matStore/index.ts
View file @
fef43d79
export
*
from
"
./types
"
;
export
*
from
"
./types
"
;
export
*
from
"
./store
"
;
import
{
proxy
}
from
"
valtio
"
;
export
*
from
"
./methods
"
;
import
{
type
CardMeta
,
fetchCard
}
from
"
@/api/cards
"
;
import
{
ygopro
}
from
"
@/api/ocgcore/idl/ocgcore
"
;
import
{
DESCRIPTION_LIMIT
,
fetchStrings
,
getStrings
}
from
"
@/api/strings
"
;
import
type
{
BothSide
,
CardsBothSide
,
CardState
,
DuelFieldState
,
InitInfo
,
MatState
,
}
from
"
./types
"
;
import
{
InteractType
}
from
"
./types
"
;
/**
* 生成一个指定长度的卡片数组
*/
const
genBlock
=
(
location
:
ygopro
.
CardZone
,
n
:
number
=
5
):
BothSide
<
DuelFieldState
>
=>
{
return
{
me
:
Array
(
n
)
.
fill
(
null
)
.
map
((
_
)
=>
({
location
:
{
location
,
},
idleInteractivities
:
[],
counters
:
{},
})),
op
:
Array
(
n
)
.
fill
(
null
)
.
map
((
_
)
=>
({
location
:
{
location
,
},
idleInteractivities
:
[],
counters
:
{},
})),
};
};
const
initInfo
:
MatState
[
"
initInfo
"
]
=
proxy
({
me
:
{
masterRule
:
"
UNKNOWN
"
,
life
:
-
1
,
// 特地设置一个不可能的值
deckSize
:
0
,
extraSize
:
0
,
},
op
:
{
masterRule
:
"
UNKNOWN
"
,
life
:
-
1
,
// 特地设置一个不可能的值
deckSize
:
0
,
extraSize
:
0
,
},
set
:
(
controller
:
number
,
obj
:
Partial
<
InitInfo
>
)
=>
{
initInfo
[
getWhom
(
controller
)]
=
{
...
initInfo
[
getWhom
(
controller
)],
...
obj
,
};
},
});
const
hint
:
MatState
[
"
hint
"
]
=
proxy
({
code
:
-
1
,
fetchCommonHintMeta
:
(
code
:
number
)
=>
{
hint
.
code
=
code
;
hint
.
msg
=
fetchStrings
(
"
!system
"
,
code
);
},
fetchSelectHintMeta
:
async
({
selectHintData
,
esHint
})
=>
{
let
selectHintMeta
=
""
;
if
(
selectHintData
>
DESCRIPTION_LIMIT
)
{
// 针对`MSG_SELECT_PLACE`的特化逻辑
const
cardMeta
=
await
fetchCard
(
selectHintData
,
true
);
selectHintMeta
=
fetchStrings
(
"
!system
"
,
569
).
replace
(
"
[%ls]
"
,
cardMeta
.
text
.
name
||
"
[?]
"
);
}
else
{
selectHintMeta
=
await
getStrings
(
selectHintData
);
}
hint
.
code
=
selectHintData
;
if
(
hint
.
code
>
DESCRIPTION_LIMIT
)
{
// 针对`MSG_SELECT_PLACE`的特化逻辑
hint
.
msg
=
selectHintMeta
;
}
else
{
hint
.
esSelectHint
=
selectHintMeta
;
hint
.
esHint
=
esHint
;
}
},
fetchEsHintMeta
:
async
({
originMsg
,
location
,
cardID
})
=>
{
const
newOriginMsg
=
typeof
originMsg
===
"
string
"
?
originMsg
:
fetchStrings
(
"
!system
"
,
originMsg
);
const
cardMeta
=
cardID
?
await
fetchCard
(
cardID
)
:
undefined
;
let
esHint
=
newOriginMsg
;
if
(
cardMeta
?.
text
.
name
)
{
esHint
=
esHint
.
replace
(
"
[?]
"
,
cardMeta
.
text
.
name
);
}
if
(
location
)
{
const
fieldMeta
=
matStore
.
getZone
(
location
.
location
)
.
at
(
location
.
controler
)
.
at
(
location
.
sequence
);
if
(
fieldMeta
?.
occupant
?.
text
.
name
)
{
esHint
=
esHint
.
replace
(
"
[?]
"
,
fieldMeta
.
occupant
.
text
.
name
);
}
}
hint
.
esHint
=
esHint
;
},
});
/**
* 在决斗盘仓库之中,
* 给 `{me: [...], op: [...]}` 这种类型的对象添加一些方法。
* 具体的方法可以看`CardsBothSide`的类型定义
*/
const
wrap
=
<
T
extends
DuelFieldState
>
(
entity
:
BothSide
<
T
>
,
zone
:
ygopro
.
CardZone
):
CardsBothSide
<
T
>
=>
{
/**
* 生成一个卡片,根据`id`获取卡片信息
*/
const
genCard
=
async
(
controller
:
number
,
id
:
number
)
=>
({
occupant
:
await
fetchCard
(
id
,
true
),
location
:
{
controler
:
controller
,
location
:
zone
,
},
counters
:
{},
idleInteractivities
:
[],
});
const
res
:
CardsBothSide
<
T
>
=
proxy
({
...
entity
,
at
:
(
controller
:
number
)
=>
{
return
res
[
getWhom
(
controller
)];
},
remove
:
(
controller
:
number
,
sequence
:
number
)
=>
{
res
[
getWhom
(
controller
)].
splice
(
sequence
,
1
);
},
insert
:
async
(
controller
:
number
,
sequence
:
number
,
id
:
number
)
=>
{
const
card
=
await
genCard
(
controller
,
id
);
res
[
getWhom
(
controller
)].
splice
(
sequence
,
0
,
card
);
},
add
:
async
(
controller
:
number
,
ids
:
number
[])
=>
{
const
cards
=
await
Promise
.
all
(
ids
.
map
(
async
(
id
)
=>
genCard
(
controller
,
id
))
);
res
[
getWhom
(
controller
)].
splice
(
res
[
getWhom
(
controller
)].
length
,
0
,
...
cards
);
},
setOccupant
:
async
(
controller
:
number
,
sequence
:
number
,
id
:
number
,
position
?:
ygopro
.
CardPosition
)
=>
{
const
meta
=
await
fetchCard
(
id
);
const
target
=
res
[
getWhom
(
controller
)][
sequence
];
target
.
occupant
=
meta
;
if
(
position
)
{
target
.
location
.
position
=
position
;
}
},
removeOccupant
:
(
controller
:
number
,
sequence
:
number
)
=>
{
res
[
getWhom
(
controller
)][
sequence
].
occupant
=
undefined
;
},
addIdleInteractivity
:
(
controller
:
number
,
sequence
:
number
,
interactivity
:
CardState
[
"
idleInteractivities
"
][
number
]
)
=>
{
res
[
getWhom
(
controller
)][
sequence
].
idleInteractivities
.
push
(
interactivity
);
},
clearIdleInteractivities
:
(
controller
:
number
,
sequence
:
number
)
=>
{
res
[
getWhom
(
controller
)][
sequence
].
idleInteractivities
=
[];
},
setPlaceInteractivityType
:
(
controller
:
number
,
sequence
:
number
,
interactType
:
InteractType
)
=>
{
res
[
getWhom
(
controller
)][
sequence
].
placeInteractivity
=
{
interactType
:
interactType
,
response
:
{
controler
:
controller
,
zone
,
sequence
,
},
};
},
clearPlaceInteractivity
:
(
controller
:
number
,
sequence
:
number
)
=>
{
res
[
getWhom
(
controller
)][
sequence
].
placeInteractivity
=
undefined
;
},
});
return
res
;
};
/**
* zone -> matStore
*/
const
getZone
=
(
zone
:
ygopro
.
CardZone
)
=>
{
switch
(
zone
)
{
case
ygopro
.
CardZone
.
MZONE
:
return
matStore
.
monsters
;
case
ygopro
.
CardZone
.
SZONE
:
return
matStore
.
magics
;
case
ygopro
.
CardZone
.
HAND
:
return
matStore
.
hands
;
case
ygopro
.
CardZone
.
DECK
:
return
matStore
.
decks
;
case
ygopro
.
CardZone
.
GRAVE
:
return
matStore
.
graveyards
;
case
ygopro
.
CardZone
.
REMOVED
:
return
matStore
.
banishedZones
;
case
ygopro
.
CardZone
.
EXTRA
:
return
matStore
.
extraDecks
;
default
:
console
.
error
(
"
in error
"
,
zone
);
return
matStore
.
extraDecks
;
}
};
/**
* 💡 决斗盘状态仓库,本文件核心,
* 具体介绍可以点进`PlayMatState`去看
*/
export
const
matStore
:
MatState
=
proxy
<
MatState
>
({
magics
:
wrap
(
genBlock
(
ygopro
.
CardZone
.
SZONE
,
6
),
ygopro
.
CardZone
.
SZONE
),
monsters
:
wrap
(
genBlock
(
ygopro
.
CardZone
.
MZONE
,
7
),
ygopro
.
CardZone
.
MZONE
),
graveyards
:
wrap
({
me
:
[],
op
:
[]
},
ygopro
.
CardZone
.
GRAVE
),
banishedZones
:
wrap
({
me
:
[],
op
:
[]
},
ygopro
.
CardZone
.
REMOVED
),
hands
:
wrap
({
me
:
[],
op
:
[]
},
ygopro
.
CardZone
.
HAND
),
decks
:
wrap
({
me
:
[],
op
:
[]
},
ygopro
.
CardZone
.
DECK
),
extraDecks
:
wrap
({
me
:
[],
op
:
[]
},
ygopro
.
CardZone
.
EXTRA
),
timeLimits
:
{
// 时间限制
me
:
0
,
op
:
0
,
},
initInfo
,
selfType
:
ygopro
.
StocTypeChange
.
SelfType
.
UNKNOWN
,
hint
,
currentPlayer
:
-
1
,
phase
:
{
currentPhase
:
"
UNKNOWN
"
,
// TODO 当前的阶段 应该改成enum
enableBp
:
false
,
// 允许进入战斗阶段
enableM2
:
false
,
// 允许进入M2阶段
enableEp
:
false
,
// 允许回合结束
},
result
:
ygopro
.
StocGameMessage
.
MsgWin
.
ActionType
.
UNKNOWN
,
waiting
:
false
,
unimplemented
:
0
,
// methods
getZone
,
});
/**
* 根据controller判断是自己还是对方
* 不要往外export,尽量逻辑收拢在store内部
*/
const
getWhom
=
(
controller
:
number
):
"
me
"
|
"
op
"
=>
judgeSelf
(
controller
,
matStore
.
selfType
)
?
"
me
"
:
"
op
"
;
const
judgeSelf
=
(
player
:
number
,
selfType
:
number
):
boolean
=>
{
switch
(
selfType
)
{
case
1
:
// 自己是先攻
return
player
===
0
;
case
2
:
// 自己是后攻
return
player
===
1
;
default
:
// 目前不可能出现这种情况
console
.
error
(
"
judgeSelf error
"
,
player
,
selfType
);
return
false
;
}
};
src/valtioStores/matStore/methods/fetchCheckCardMeta.ts
0 → 100644
View file @
fef43d79
import
{
ygopro
}
from
"
@/api/ocgcore/idl/ocgcore
"
;
import
{
matStore
,
messageStore
}
from
"
@/valtioStores
"
;
import
{
fetchCard
,
getCardStr
}
from
"
@/api/cards
"
;
function
CardZoneToChinese
(
zone
:
ygopro
.
CardZone
):
string
{
switch
(
zone
)
{
case
ygopro
.
CardZone
.
DECK
:
{
return
"
卡组
"
;
}
case
ygopro
.
CardZone
.
HAND
:
{
return
"
手牌
"
;
}
case
ygopro
.
CardZone
.
EXTRA
:
{
return
"
额外卡组
"
;
}
case
ygopro
.
CardZone
.
GRAVE
:
{
return
"
墓地
"
;
}
case
ygopro
.
CardZone
.
FZONE
:
{
return
"
FZONE
"
;
}
case
ygopro
.
CardZone
.
MZONE
:
{
return
"
怪兽区
"
;
}
case
ygopro
.
CardZone
.
SZONE
:
{
return
"
魔法陷阱区
"
;
}
case
ygopro
.
CardZone
.
REMOVED
:
{
return
"
除外区
"
;
}
case
ygopro
.
CardZone
.
OVERLAY
:
{
return
"
超量区
"
;
}
case
ygopro
.
CardZone
.
PZONE
:
{
return
"
灵摆区
"
;
}
case
ygopro
.
CardZone
.
ONFIELD
:
{
return
"
场地区
"
;
}
default
:
{
return
"
未知区域
"
;
}
}
}
type
Location
=
|
ygopro
.
CardLocation
|
ReturnType
<
typeof
ygopro
.
CardLocation
.
prototype
.
toObject
>
;
function
cmpCardLocation
(
left
:
Location
,
right
?:
Location
,
strict
?:
boolean
):
boolean
{
if
(
strict
)
{
return
JSON
.
stringify
(
left
)
===
JSON
.
stringify
(
right
);
}
else
{
return
(
left
.
controler
===
right
?.
controler
&&
left
.
location
===
right
?.
location
&&
left
.
sequence
===
right
?.
sequence
);
}
}
/**
* 这段代码定义了一个异步函数 fetchCheckCardMeta,它的作用是获取一张卡片的元数据并将其添加到某个名为 messageStore.checkCardModal 的对象上。
该函数的第一个参数是一个枚举值 ygopro.CardZone,表示卡片所在的区域。其余参数是一个包含卡片编号、位置、响应码和效果描述代码等信息的对象。
首先,这个函数会根据区域类型调用 CardZoneToChinese() 函数生成一个中文名称。然后,它会调用 fetchCard() 异步函数来获取指定卡片的元数据 meta。
接下来,函数会根据传递进来的 location 对象获取卡片所属的控制者,并根据控制者判断这张卡片是我方的还是对方的。然后,它会根据卡片的位置信息获取卡片的实际 ID,并构造一个新的选项 newOption。
接着,函数会遍历已有的 messageStore.checkCardModal.tags,查找是否存在名为 combinedTagName 的标签。如果找到了,则将新选项 newOption 加入该标签的选项列表中并立即返回。如果找不到,则创建一个新标签,并将新选项 newOption 添加到其中。
最后,函数会再次遍历所有标签,查找是否存在名为 combinedTagName 的标签。如果找到了,则遍历该标签中的所有选项,并查找是否存在与 location 对象中指定的卡片位置信息完全相同的选项。如果找到了,则更新该选项的元数据和效果描述等信息。
*/
export
const
fetchCheckCardMeta
=
async
(
zone
:
ygopro
.
CardZone
,
{
code
,
location
,
response
,
effectDescCode
,
}:
{
code
:
number
;
location
:
ygopro
.
CardLocation
;
response
:
number
;
effectDescCode
?:
number
;
}
)
=>
{
const
tagName
=
CardZoneToChinese
(
zone
);
const
meta
=
await
fetchCard
(
code
);
const
controller
=
location
.
controler
;
const
combinedTagName
=
matStore
.
isMe
(
controller
)
?
`我方的
${
tagName
}
`
:
`对方的
${
tagName
}
`
;
const
newID
=
code
!=
0
?
code
:
matStore
.
getZone
(
location
.
location
).
at
(
controller
)[
location
.
sequence
]
?.
occupant
?.
id
||
0
;
const
newOption
=
{
meta
:
{
id
:
newID
,
data
:
{},
text
:
{}
},
location
:
location
.
toObject
(),
effectDescCode
,
response
,
};
for
(
const
tag
of
messageStore
.
checkCardModal
.
tags
)
{
if
(
tag
.
tagName
===
combinedTagName
)
{
tag
.
options
.
push
(
newOption
);
return
;
}
}
messageStore
.
checkCardModal
.
tags
.
push
({
tagName
:
combinedTagName
,
options
:
[
newOption
],
});
for
(
const
tag
of
messageStore
.
checkCardModal
.
tags
)
{
if
(
tag
.
tagName
===
combinedTagName
)
{
for
(
const
old
of
tag
.
options
)
{
if
(
meta
.
id
==
old
.
meta
.
id
&&
cmpCardLocation
(
location
,
old
.
location
))
{
const
cardID
=
old
.
meta
.
id
;
old
.
meta
=
meta
;
old
.
meta
.
id
=
cardID
;
const
effectDescCode
=
old
.
effectDescCode
;
const
effectDesc
=
effectDescCode
?
getCardStr
(
old
.
meta
,
effectDescCode
&
0xf
)
:
undefined
;
old
.
effectDesc
=
effectDesc
;
}
}
}
}
};
src/valtioStores/matStore/methods/fetchHint.ts
0 → 100644
View file @
fef43d79
import
{
matStore
}
from
"
@/valtioStores
"
;
import
{
fetchCard
}
from
"
@/api/cards
"
;
import
{
DESCRIPTION_LIMIT
,
fetchStrings
,
getStrings
}
from
"
@/api/strings
"
;
import
type
{
ygopro
}
from
"
@/api/ocgcore/idl/ocgcore
"
;
const
{
hint
}
=
matStore
;
export
const
fetchCommonHintMeta
=
(
code
:
number
)
=>
{
hint
.
code
=
code
;
hint
.
msg
=
fetchStrings
(
"
!system
"
,
code
);
};
export
const
fetchSelectHintMeta
=
async
({
selectHintData
,
esHint
,
}:
{
selectHintData
:
number
;
esHint
?:
string
;
})
=>
{
let
selectHintMeta
=
""
;
if
(
selectHintData
>
DESCRIPTION_LIMIT
)
{
// 针对`MSG_SELECT_PLACE`的特化逻辑
const
cardMeta
=
await
fetchCard
(
selectHintData
,
true
);
selectHintMeta
=
fetchStrings
(
"
!system
"
,
569
).
replace
(
"
[%ls]
"
,
cardMeta
.
text
.
name
||
"
[?]
"
);
}
else
{
selectHintMeta
=
await
getStrings
(
selectHintData
);
}
hint
.
code
=
selectHintData
;
if
(
hint
.
code
>
DESCRIPTION_LIMIT
)
{
// 针对`MSG_SELECT_PLACE`的特化逻辑
hint
.
msg
=
selectHintMeta
;
}
else
{
hint
.
esSelectHint
=
selectHintMeta
;
hint
.
esHint
=
esHint
;
}
};
export
const
fetchEsHintMeta
=
async
({
originMsg
,
location
,
cardID
,
}:
{
originMsg
:
string
|
number
;
location
?:
ygopro
.
CardLocation
;
cardID
?:
number
;
})
=>
{
const
newOriginMsg
=
typeof
originMsg
===
"
string
"
?
originMsg
:
fetchStrings
(
"
!system
"
,
originMsg
);
const
cardMeta
=
cardID
?
await
fetchCard
(
cardID
)
:
undefined
;
let
esHint
=
newOriginMsg
;
if
(
cardMeta
?.
text
.
name
)
{
esHint
=
esHint
.
replace
(
"
[?]
"
,
cardMeta
.
text
.
name
);
}
if
(
location
)
{
const
fieldMeta
=
matStore
.
getZone
(
location
.
location
)
.
at
(
location
.
controler
)
.
at
(
location
.
sequence
);
if
(
fieldMeta
?.
occupant
?.
text
.
name
)
{
esHint
=
esHint
.
replace
(
"
[?]
"
,
fieldMeta
.
occupant
.
text
.
name
);
}
}
hint
.
esHint
=
esHint
;
};
src/valtioStores/matStore/methods/index.ts
0 → 100644
View file @
fef43d79
export
*
from
"
./fetchCheckCardMeta
"
;
export
*
from
"
./fetchHint
"
;
src/valtioStores/matStore/store.ts
0 → 100644
View file @
fef43d79
import
{
proxy
}
from
"
valtio
"
;
import
{
fetchCard
}
from
"
@/api/cards
"
;
import
{
ygopro
}
from
"
@/api/ocgcore/idl/ocgcore
"
;
import
type
{
BothSide
,
CardsBothSide
,
CardState
,
DuelFieldState
,
InitInfo
,
MatState
,
}
from
"
./types
"
;
import
{
InteractType
}
from
"
./types
"
;
/**
* 根据controller判断是自己还是对方。
* 这个无需export,尽量逻辑收拢在store内部。
*/
const
getWhom
=
(
controller
:
number
):
"
me
"
|
"
op
"
=>
isMe
(
controller
)
?
"
me
"
:
"
op
"
;
/**
* 根据自己的先后手判断是否是自己
*/
const
isMe
=
(
player
:
number
):
boolean
=>
{
switch
(
matStore
.
selfType
)
{
case
1
:
// 自己是先攻
return
player
===
0
;
case
2
:
// 自己是后攻
return
player
===
1
;
default
:
// 目前不可能出现这种情况
console
.
error
(
"
judgeSelf error
"
,
player
,
matStore
.
selfType
);
return
false
;
}
};
/**
* 生成一个指定长度的卡片数组
*/
const
genBlock
=
(
location
:
ygopro
.
CardZone
,
n
:
number
):
BothSide
<
DuelFieldState
>
=>
{
return
{
me
:
Array
(
n
)
.
fill
(
null
)
.
map
((
_
)
=>
({
location
:
{
location
,
},
idleInteractivities
:
[],
counters
:
{},
})),
op
:
Array
(
n
)
.
fill
(
null
)
.
map
((
_
)
=>
({
location
:
{
location
,
},
idleInteractivities
:
[],
counters
:
{},
})),
};
};
const
initInfo
:
MatState
[
"
initInfo
"
]
=
proxy
({
me
:
{
masterRule
:
"
UNKNOWN
"
,
life
:
-
1
,
// 特地设置一个不可能的值
deckSize
:
0
,
extraSize
:
0
,
},
op
:
{
masterRule
:
"
UNKNOWN
"
,
life
:
-
1
,
// 特地设置一个不可能的值
deckSize
:
0
,
extraSize
:
0
,
},
set
:
(
controller
:
number
,
obj
:
Partial
<
InitInfo
>
)
=>
{
initInfo
[
getWhom
(
controller
)]
=
{
...
initInfo
[
getWhom
(
controller
)],
...
obj
,
};
},
});
const
hint
:
MatState
[
"
hint
"
]
=
proxy
({
code
:
-
1
,
});
/**
* 在决斗盘仓库之中,
* 给 `{me: [...], op: [...]}` 这种类型的对象添加一些方法。
* 具体的方法可以看`CardsBothSide`的类型定义
*/
const
wrap
=
<
T
extends
DuelFieldState
>
(
entity
:
BothSide
<
T
>
,
zone
:
ygopro
.
CardZone
):
CardsBothSide
<
T
>
=>
{
/**
* 生成一个卡片,根据`id`获取卡片信息
*/
const
genCard
=
async
(
controller
:
number
,
id
:
number
)
=>
({
occupant
:
await
fetchCard
(
id
,
true
),
location
:
{
controler
:
controller
,
location
:
zone
,
},
counters
:
{},
idleInteractivities
:
[],
});
const
res
:
CardsBothSide
<
T
>
=
proxy
({
...
entity
,
at
:
(
controller
:
number
)
=>
{
return
res
[
getWhom
(
controller
)];
},
remove
:
(
controller
:
number
,
sequence
:
number
)
=>
{
res
[
getWhom
(
controller
)].
splice
(
sequence
,
1
);
},
insert
:
async
(
controller
:
number
,
sequence
:
number
,
id
:
number
)
=>
{
const
card
=
await
genCard
(
controller
,
id
);
res
[
getWhom
(
controller
)].
splice
(
sequence
,
0
,
card
);
},
add
:
async
(
controller
:
number
,
ids
:
number
[])
=>
{
const
cards
=
await
Promise
.
all
(
ids
.
map
(
async
(
id
)
=>
genCard
(
controller
,
id
))
);
res
[
getWhom
(
controller
)].
splice
(
res
[
getWhom
(
controller
)].
length
,
0
,
...
cards
);
},
setOccupant
:
async
(
controller
:
number
,
sequence
:
number
,
id
:
number
,
position
?:
ygopro
.
CardPosition
)
=>
{
const
meta
=
await
fetchCard
(
id
);
const
target
=
res
[
getWhom
(
controller
)][
sequence
];
target
.
occupant
=
meta
;
if
(
position
)
{
target
.
location
.
position
=
position
;
}
},
removeOccupant
:
(
controller
:
number
,
sequence
:
number
)
=>
{
res
[
getWhom
(
controller
)][
sequence
].
occupant
=
undefined
;
},
addIdleInteractivity
:
(
controller
:
number
,
sequence
:
number
,
interactivity
:
CardState
[
"
idleInteractivities
"
][
number
]
)
=>
{
res
[
getWhom
(
controller
)][
sequence
].
idleInteractivities
.
push
(
interactivity
);
},
clearIdleInteractivities
:
(
controller
:
number
,
sequence
:
number
)
=>
{
res
[
getWhom
(
controller
)][
sequence
].
idleInteractivities
=
[];
},
setPlaceInteractivityType
:
(
controller
:
number
,
sequence
:
number
,
interactType
:
InteractType
)
=>
{
res
[
getWhom
(
controller
)][
sequence
].
placeInteractivity
=
{
interactType
:
interactType
,
response
:
{
controler
:
controller
,
zone
,
sequence
,
},
};
},
clearPlaceInteractivity
:
(
controller
:
number
,
sequence
:
number
)
=>
{
res
[
getWhom
(
controller
)][
sequence
].
placeInteractivity
=
undefined
;
},
});
return
res
;
};
/**
* zone -> matStore
*/
const
getZone
=
(
zone
:
ygopro
.
CardZone
)
=>
{
switch
(
zone
)
{
case
ygopro
.
CardZone
.
MZONE
:
return
matStore
.
monsters
;
case
ygopro
.
CardZone
.
SZONE
:
return
matStore
.
magics
;
case
ygopro
.
CardZone
.
HAND
:
return
matStore
.
hands
;
case
ygopro
.
CardZone
.
DECK
:
return
matStore
.
decks
;
case
ygopro
.
CardZone
.
GRAVE
:
return
matStore
.
graveyards
;
case
ygopro
.
CardZone
.
REMOVED
:
return
matStore
.
banishedZones
;
case
ygopro
.
CardZone
.
EXTRA
:
return
matStore
.
extraDecks
;
default
:
console
.
error
(
"
in error
"
,
zone
);
return
matStore
.
extraDecks
;
}
};
/**
* 💡 决斗盘状态仓库,本文件核心,
* 具体介绍可以点进`PlayMatState`去看
*/
export
const
matStore
:
MatState
=
proxy
<
MatState
>
({
magics
:
wrap
(
genBlock
(
ygopro
.
CardZone
.
SZONE
,
6
),
ygopro
.
CardZone
.
SZONE
),
monsters
:
wrap
(
genBlock
(
ygopro
.
CardZone
.
MZONE
,
7
),
ygopro
.
CardZone
.
MZONE
),
graveyards
:
wrap
({
me
:
[],
op
:
[]
},
ygopro
.
CardZone
.
GRAVE
),
banishedZones
:
wrap
({
me
:
[],
op
:
[]
},
ygopro
.
CardZone
.
REMOVED
),
hands
:
wrap
({
me
:
[],
op
:
[]
},
ygopro
.
CardZone
.
HAND
),
decks
:
wrap
({
me
:
[],
op
:
[]
},
ygopro
.
CardZone
.
DECK
),
extraDecks
:
wrap
({
me
:
[],
op
:
[]
},
ygopro
.
CardZone
.
EXTRA
),
timeLimits
:
{
// 时间限制
me
:
0
,
op
:
0
,
},
initInfo
,
selfType
:
ygopro
.
StocTypeChange
.
SelfType
.
UNKNOWN
,
hint
,
currentPlayer
:
-
1
,
phase
:
{
currentPhase
:
"
UNKNOWN
"
,
// TODO 当前的阶段 应该改成enum
enableBp
:
false
,
// 允许进入战斗阶段
enableM2
:
false
,
// 允许进入M2阶段
enableEp
:
false
,
// 允许回合结束
},
result
:
ygopro
.
StocGameMessage
.
MsgWin
.
ActionType
.
UNKNOWN
,
waiting
:
false
,
unimplemented
:
0
,
// methods
getZone
,
isMe
,
});
src/valtioStores/matStore/types.ts
View file @
fef43d79
...
@@ -67,7 +67,7 @@ export interface MatState {
...
@@ -67,7 +67,7 @@ export interface MatState {
timeLimits
:
BothSide
<
number
>
;
// 双方的时间限制
timeLimits
:
BothSide
<
number
>
;
// 双方的时间限制
hint
:
HintState
&
HintMethods
;
hint
:
HintState
;
currentPlayer
:
number
;
// 当前的操作方
currentPlayer
:
number
;
// 当前的操作方
...
@@ -79,7 +79,11 @@ export interface MatState {
...
@@ -79,7 +79,11 @@ export interface MatState {
unimplemented
:
number
;
// 未处理的`Message`
unimplemented
:
number
;
// 未处理的`Message`
getZone
:
(
zone
:
ygopro
.
CardZone
)
=>
CardsBothSide
<
DuelFieldState
>
;
// 是否在某个区域
// >>> methods >>>
/** 根据zone获取hands/masters/gy... */
getZone
:
(
zone
:
ygopro
.
CardZone
)
=>
CardsBothSide
<
DuelFieldState
>
;
/** 根据自己的先后手判断是否是自己 */
isMe
:
(
player
:
number
)
=>
boolean
;
}
}
export
interface
InitInfo
{
export
interface
InitInfo
{
...
@@ -162,19 +166,6 @@ export interface HintState {
...
@@ -162,19 +166,6 @@ export interface HintState {
esHint
?:
string
;
esHint
?:
string
;
esSelectHint
?:
string
;
esSelectHint
?:
string
;
}
}
// 和hint相关的方法
export
interface
HintMethods
{
fetchCommonHintMeta
:
(
hintData
:
number
)
=>
void
;
fetchSelectHintMeta
:
(
args
:
{
selectHintData
:
number
;
esHint
?:
string
;
})
=>
Promise
<
void
>
;
fetchEsHintMeta
:
(
args
:
{
originMsg
:
string
|
number
;
location
?:
ygopro
.
CardLocation
;
cardID
?:
number
;
})
=>
Promise
<
void
>
;
}
export
type
PhaseName
=
export
type
PhaseName
=
keyof
typeof
ygopro
.
StocGameMessage
.
MsgNewPhase
.
PhaseType
;
keyof
typeof
ygopro
.
StocGameMessage
.
MsgNewPhase
.
PhaseType
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment