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
bdd10692
Commit
bdd10692
authored
Apr 16, 2023
by
timel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix: case ploblem
parent
c554497c
Changes
28
Hide whitespace changes
Inline
Side-by-side
Showing
28 changed files
with
3 additions
and
2391 deletions
+3
-2391
src/ui/Duel/Message/alert.tsx
src/ui/Duel/Message/alert.tsx
+0
-34
src/ui/Duel/Message/cardListModal.tsx
src/ui/Duel/Message/cardListModal.tsx
+0
-67
src/ui/Duel/Message/cardModal.tsx
src/ui/Duel/Message/cardModal.tsx
+0
-165
src/ui/Duel/Message/checkCardModal.tsx
src/ui/Duel/Message/checkCardModal.tsx
+0
-170
src/ui/Duel/Message/checkCardModalV2.tsx
src/ui/Duel/Message/checkCardModalV2.tsx
+0
-128
src/ui/Duel/Message/checkCardModalV3.tsx
src/ui/Duel/Message/checkCardModalV3.tsx
+0
-125
src/ui/Duel/Message/checkCounterModal.tsx
src/ui/Duel/Message/checkCounterModal.tsx
+0
-74
src/ui/Duel/Message/dragModal.tsx
src/ui/Duel/Message/dragModal.tsx
+0
-43
src/ui/Duel/Message/hintNotification.tsx
src/ui/Duel/Message/hintNotification.tsx
+0
-71
src/ui/Duel/Message/optionModal.tsx
src/ui/Duel/Message/optionModal.tsx
+0
-56
src/ui/Duel/Message/phase.tsx
src/ui/Duel/Message/phase.tsx
+0
-144
src/ui/Duel/Message/positionModal.tsx
src/ui/Duel/Message/positionModal.tsx
+0
-86
src/ui/Duel/Message/sendBox.tsx
src/ui/Duel/Message/sendBox.tsx
+0
-35
src/ui/Duel/Message/sortCardModal.tsx
src/ui/Duel/Message/sortCardModal.tsx
+0
-116
src/ui/Duel/Message/status.tsx
src/ui/Duel/Message/status.tsx
+0
-66
src/ui/Duel/Message/timeLine.tsx
src/ui/Duel/Message/timeLine.tsx
+0
-32
src/ui/Duel/Message/yesNoModal.tsx
src/ui/Duel/Message/yesNoModal.tsx
+0
-50
src/ui/Duel/PlayMat/deck.tsx
src/ui/Duel/PlayMat/deck.tsx
+0
-37
src/ui/Duel/PlayMat/extraDeck.tsx
src/ui/Duel/PlayMat/extraDeck.tsx
+0
-41
src/ui/Duel/PlayMat/field.tsx
src/ui/Duel/PlayMat/field.tsx
+0
-55
src/ui/Duel/PlayMat/fixedSlot.tsx
src/ui/Duel/PlayMat/fixedSlot.tsx
+0
-134
src/ui/Duel/PlayMat/hands.tsx
src/ui/Duel/PlayMat/hands.tsx
+0
-174
src/ui/Duel/PlayMat/magics.tsx
src/ui/Duel/PlayMat/magics.tsx
+0
-65
src/ui/Duel/PlayMat/monsters.tsx
src/ui/Duel/PlayMat/monsters.tsx
+0
-139
src/ui/Duel/PlayMat/singleSlot.tsx
src/ui/Duel/PlayMat/singleSlot.tsx
+0
-88
src/ui/Duel/layout.tsx
src/ui/Duel/layout.tsx
+0
-62
src/ui/Duel/main.tsx
src/ui/Duel/main.tsx
+0
-133
src/valtioStores/duelStore/duel.ts
src/valtioStores/duelStore/duel.ts
+3
-1
No files found.
src/ui/Duel/Message/alert.tsx
deleted
100644 → 0
View file @
c554497c
import
{
Alert
as
AntdAlert
}
from
"
antd
"
;
import
React
from
"
react
"
;
import
{
useNavigate
}
from
"
react-router-dom
"
;
import
{
sendSurrender
}
from
"
@/api/ocgcore/ocgHelper
"
;
import
{
useAppSelector
}
from
"
@/hook
"
;
import
{
selectUnimplemented
}
from
"
@/reducers/duel/mod
"
;
export
const
Alert
=
()
=>
{
const
unimplemented
=
useAppSelector
(
selectUnimplemented
);
const
navigate
=
useNavigate
();
return
(
<>
{
unimplemented
?
(
<
AntdAlert
message=
{
`Unimplemented message with code=${unimplemented}`
}
description=
"It seems that there's something unimplemented by Neos. Sincerely apologize for that. Contact use to fix this issue: <ccc@neos.moe>"
showIcon
type=
"error"
closable
banner
afterClose=
{
()
=>
{
// 发送投降信号
sendSurrender
();
navigate
(
"
/
"
);
}
}
/>
)
:
(
<></>
)
}
</>
);
};
src/ui/Duel/Message/cardListModal.tsx
deleted
100644 → 0
View file @
c554497c
import
{
Button
,
Drawer
,
List
}
from
"
antd
"
;
import
React
from
"
react
"
;
import
{
sendSelectIdleCmdResponse
}
from
"
@/api/ocgcore/ocgHelper
"
;
import
{
useConfig
}
from
"
@/config
"
;
import
{
useAppSelector
}
from
"
@/hook
"
;
import
{
clearAllIdleInteractivities
,
setCardListModalIsOpen
,
}
from
"
@/reducers/duel/mod
"
;
import
{
selectCardListModalInfo
,
selectCardListModalIsOpen
,
}
from
"
@/reducers/duel/modal/mod
"
;
import
{
store
}
from
"
@/store
"
;
const
NeosConfig
=
useConfig
();
const
CARD_WIDTH
=
100
;
export
const
CardListModal
=
()
=>
{
const
dispatch
=
store
.
dispatch
;
const
isOpen
=
useAppSelector
(
selectCardListModalIsOpen
);
const
list
=
useAppSelector
(
selectCardListModalInfo
);
const
handleOkOrCancel
=
()
=>
{
dispatch
(
setCardListModalIsOpen
(
false
));
};
return
(
<
Drawer
open=
{
isOpen
}
onClose=
{
handleOkOrCancel
}
>
<
List
itemLayout=
"horizontal"
dataSource=
{
list
}
renderItem=
{
(
item
)
=>
(
<
List
.
Item
actions=
{
item
.
interactivies
.
map
((
interactivy
,
idx
)
=>
(
<
Button
key=
{
idx
}
onClick=
{
()
=>
{
sendSelectIdleCmdResponse
(
interactivy
.
response
);
dispatch
(
setCardListModalIsOpen
(
false
));
dispatch
(
clearAllIdleInteractivities
(
0
));
dispatch
(
clearAllIdleInteractivities
(
1
));
}
}
>
{
interactivy
.
desc
}
</
Button
>
))
}
extra=
{
<
img
alt=
{
item
.
meta
?.
text
.
name
}
src=
{
`${NeosConfig.cardImgUrl}/${item.meta?.id}.jpg`
}
style=
{
{
width
:
CARD_WIDTH
}
}
/>
}
>
<
List
.
Item
.
Meta
title=
{
item
.
meta
?.
text
.
name
}
description=
{
item
.
meta
?.
text
.
desc
}
/>
</
List
.
Item
>
)
}
></
List
>
</
Drawer
>
);
};
src/ui/Duel/Message/cardModal.tsx
deleted
100644 → 0
View file @
c554497c
import
Icon
,
{
StarOutlined
}
from
"
@ant-design/icons
"
;
import
{
Button
,
Card
,
Col
,
Modal
,
Row
}
from
"
antd
"
;
import
{
ReactComponent
as
BattleSvg
}
from
"
neos-assets/battle-axe.svg
"
;
import
{
ReactComponent
as
DefenceSvg
}
from
"
neos-assets/checked-shield.svg
"
;
import
React
from
"
react
"
;
import
{
sendSelectIdleCmdResponse
}
from
"
@/api/ocgcore/ocgHelper
"
;
import
{
fetchStrings
}
from
"
@/api/strings
"
;
import
{
useConfig
}
from
"
@/config
"
;
import
{
useAppSelector
}
from
"
@/hook
"
;
import
{
clearAllIdleInteractivities
,
setCardModalIsOpen
,
}
from
"
@/reducers/duel/mod
"
;
import
{
selectCardModalCounters
,
selectCardModalInteractivies
,
selectCardModalIsOpen
,
selectCardModalMeta
,
}
from
"
@/reducers/duel/modal/mod
"
;
import
{
store
}
from
"
@/store
"
;
import
{
Attribute2StringCodeMap
,
extraCardTypes
,
Race2StringCodeMap
,
Type2StringCodeMap
,
}
from
"
../../../common
"
;
const
NeosConfig
=
useConfig
();
const
{
Meta
}
=
Card
;
const
CARD_WIDTH
=
240
;
export
const
CardModal
=
()
=>
{
const
dispatch
=
store
.
dispatch
;
const
isOpen
=
useAppSelector
(
selectCardModalIsOpen
);
const
meta
=
useAppSelector
(
selectCardModalMeta
);
const
name
=
meta
?.
text
.
name
;
const
types
=
meta
?.
data
.
type
;
const
race
=
meta
?.
data
.
race
;
const
attribute
=
meta
?.
data
.
attribute
;
const
level
=
meta
?.
data
.
level
;
const
desc
=
meta
?.
text
.
desc
;
const
atk
=
meta
?.
data
.
atk
;
const
def
=
meta
?.
data
.
def
;
const
counters
=
useAppSelector
(
selectCardModalCounters
);
const
imgUrl
=
meta
?.
id
?
`
${
NeosConfig
.
cardImgUrl
}
/
${
meta
.
id
}
.jpg`
:
undefined
;
const
interactivies
=
useAppSelector
(
selectCardModalInteractivies
);
const
handleOkOrCancel
=
()
=>
{
dispatch
(
setCardModalIsOpen
(
false
));
};
return
(
<
Modal
open=
{
isOpen
}
onOk=
{
handleOkOrCancel
}
onCancel=
{
handleOkOrCancel
}
>
<
Card
hoverable
style=
{
{
width
:
CARD_WIDTH
}
}
cover=
{
<
img
alt=
{
name
}
src=
{
imgUrl
}
/>
}
>
<
Meta
title=
{
name
}
/>
<
AttLine
types=
{
extraCardTypes
(
types
||
0
)
}
race=
{
race
}
attribute=
{
attribute
}
/>
<
AtkLine
level=
{
level
}
atk=
{
atk
}
def=
{
def
}
/>
<
CounterLine
counters=
{
counters
}
/>
<
p
>
{
desc
}
</
p
>
</
Card
>
{
interactivies
.
map
((
interactive
,
idx
)
=>
{
return
(
<
Button
key=
{
idx
}
onClick=
{
()
=>
{
sendSelectIdleCmdResponse
(
interactive
.
response
);
dispatch
(
setCardModalIsOpen
(
false
));
dispatch
(
clearAllIdleInteractivities
(
0
));
dispatch
(
clearAllIdleInteractivities
(
1
));
}
}
>
{
interactive
.
desc
}
</
Button
>
);
})
}
</
Modal
>
);
};
const
AtkLine
=
(
props
:
{
level
?:
number
;
atk
?:
number
;
def
?:
number
})
=>
(
<
Row
gutter=
{
8
}
>
{
props
.
level
?
(
<
Col
>
<
StarOutlined
/>
{
props
.
level
}
</
Col
>
)
:
(
<></>
)
}
{
props
.
atk
?
(
<
Col
>
<
Icon
component=
{
BattleSvg
}
/>
<
a
>
{
props
.
atk
}
</
a
>
</
Col
>
)
:
(
<></>
)
}
<
Col
>
/
</
Col
>
{
props
.
def
?
(
<
Col
>
<
Icon
component=
{
DefenceSvg
}
/>
<
a
>
{
props
.
def
}
</
a
>
</
Col
>
)
:
(
<></>
)
}
</
Row
>
);
const
AttLine
=
(
props
:
{
types
:
number
[];
race
?:
number
;
attribute
?:
number
;
})
=>
{
const
race
=
props
.
race
?
fetchStrings
(
"
!system
"
,
Race2StringCodeMap
.
get
(
props
.
race
)
||
0
)
:
undefined
;
const
attribute
=
props
.
attribute
?
fetchStrings
(
"
!system
"
,
Attribute2StringCodeMap
.
get
(
props
.
attribute
)
||
0
)
:
undefined
;
const
types
=
props
.
types
.
map
((
t
)
=>
fetchStrings
(
"
!system
"
,
Type2StringCodeMap
.
get
(
t
)
||
0
))
.
join
(
"
|
"
);
return
(
<
Row
gutter=
{
8
}
>
<
Col
>
{
`[${types}]`
}
</
Col
>
{
race
?
<
Col
>
{
race
}
</
Col
>
:
<></>
}
<
Col
>
/
</
Col
>
{
attribute
?
<
Col
>
{
attribute
}
</
Col
>
:
<></>
}
</
Row
>
);
};
const
CounterLine
=
(
props
:
{
counters
:
{
[
type
:
number
]:
number
}
})
=>
{
const
counters
=
[];
for
(
const
counterType
in
props
.
counters
)
{
const
count
=
props
.
counters
[
counterType
];
if
(
count
>
0
)
{
const
counterStr
=
fetchStrings
(
"
!counter
"
,
`0x
${
counterType
}
`
);
counters
.
push
(
`
${
counterStr
}
:
${
count
}
`
);
}
}
return
counters
.
length
>
0
?
(
<
Row
gutter=
{
8
}
>
{
counters
.
map
((
counter
)
=>
(
<
Col
>
{
counter
}
</
Col
>
))
}
</
Row
>
)
:
(
<></>
);
};
src/ui/Duel/Message/checkCardModal.tsx
deleted
100644 → 0
View file @
c554497c
import
{
ThunderboltOutlined
}
from
"
@ant-design/icons
"
;
import
{
CheckCard
,
CheckCardProps
}
from
"
@ant-design/pro-components
"
;
import
{
Button
,
Col
,
Popover
,
Row
}
from
"
antd
"
;
import
React
,
{
useState
}
from
"
react
"
;
import
{
sendSelectCardResponse
,
sendSelectChainResponse
,
}
from
"
@/api/ocgcore/ocgHelper
"
;
import
{
useConfig
}
from
"
@/config
"
;
import
{
useAppSelector
}
from
"
@/hook
"
;
import
{
selectHint
}
from
"
@/reducers/duel/hintSlice
"
;
import
{
resetCheckCardModal
,
setCheckCardModalIsOpen
,
}
from
"
@/reducers/duel/mod
"
;
import
{
selectCheckCardModalCacnelResponse
,
selectCheckCardModalCancelAble
,
selectCheckCardModalIsOpen
,
selectCheckCardModalMinMax
,
selectCheckCardModalOnSubmit
,
selectCheckCardModalTags
,
}
from
"
@/reducers/duel/modal/mod
"
;
import
{
store
}
from
"
@/store
"
;
import
{
DragModal
}
from
"
./DragModal
"
;
const
NeosConfig
=
useConfig
();
export
const
CheckCardModal
=
()
=>
{
const
dispatch
=
store
.
dispatch
;
const
isOpen
=
useAppSelector
(
selectCheckCardModalIsOpen
);
const
{
min
,
max
}
=
useAppSelector
(
selectCheckCardModalMinMax
);
const
tabs
=
useAppSelector
(
selectCheckCardModalTags
);
const
onSubmit
=
useAppSelector
(
selectCheckCardModalOnSubmit
);
const
cancelAble
=
useAppSelector
(
selectCheckCardModalCancelAble
);
const
cancelResponse
=
useAppSelector
(
selectCheckCardModalCacnelResponse
);
const
[
response
,
setResponse
]
=
useState
<
number
[]
>
([]);
const
defaultValue
:
number
[]
=
[];
const
hint
=
useAppSelector
(
selectHint
);
const
preHintMsg
=
hint
?.
esHint
||
""
;
const
selectHintMsg
=
hint
?.
esSelectHint
||
"
请选择卡片
"
;
// TODO: 这里可以考虑更好地封装
const
sendResponseHandler
=
(
handlerName
:
string
|
undefined
,
response
:
number
[]
)
=>
{
switch
(
handlerName
)
{
case
"
sendSelectChainResponse
"
:
{
sendSelectChainResponse
(
response
[
0
]);
break
;
}
case
"
sendSelectCardResponse
"
:
{
sendSelectCardResponse
(
response
);
break
;
}
default
:
{
}
}
};
return
(
<
DragModal
title=
{
`${preHintMsg} ${selectHintMsg} ${min}-${max}`
}
open=
{
isOpen
}
closable=
{
false
}
footer=
{
<>
<
Button
disabled=
{
response
.
length
<
min
||
response
.
length
>
max
}
onClick=
{
()
=>
{
sendResponseHandler
(
onSubmit
,
response
);
dispatch
(
setCheckCardModalIsOpen
(
false
));
dispatch
(
resetCheckCardModal
());
}
}
onFocus=
{
()
=>
{}
}
onBlur=
{
()
=>
{}
}
>
submit
</
Button
>
{
cancelAble
?
(
<
Button
onClick=
{
()
=>
{
if
(
cancelResponse
)
{
sendResponseHandler
(
onSubmit
,
[
cancelResponse
]);
}
dispatch
(
setCheckCardModalIsOpen
(
false
));
dispatch
(
resetCheckCardModal
());
}
}
onFocus=
{
()
=>
{}
}
onBlur=
{
()
=>
{}
}
>
cancel
</
Button
>
)
:
(
<></>
)
}
</>
}
width=
{
800
}
>
<
CheckCard
.
Group
multiple
bordered
size=
"small"
defaultValue=
{
defaultValue
}
onChange=
{
(
value
)
=>
{
// @ts-ignore
setResponse
(
value
);
}
}
>
{
tabs
.
map
((
tab
,
idx
)
=>
{
return
(
<
Row
key=
{
idx
}
>
{
tab
.
options
.
map
((
option
,
idx
)
=>
{
return
(
<
Col
span=
{
4
}
key=
{
idx
}
>
<
HoverCheckCard
hoverContent=
{
option
.
effectDesc
}
title=
{
option
.
meta
.
text
.
name
}
description=
{
option
.
meta
.
text
.
desc
}
style=
{
{
width
:
120
}
}
cover=
{
<
img
alt=
{
option
.
meta
.
id
.
toString
()
}
src=
{
option
.
meta
.
id
?
`${NeosConfig.cardImgUrl}/${option.meta.id}.jpg`
:
`${NeosConfig.assetsPath}/card_back.jpg`
}
style=
{
{
width
:
100
}
}
/>
}
value=
{
option
.
response
}
/>
</
Col
>
);
})
}
</
Row
>
);
})
}
</
CheckCard
.
Group
>
</
DragModal
>
);
};
const
HoverCheckCard
=
(
props
:
CheckCardProps
&
{
hoverContent
?:
string
})
=>
{
const
[
hover
,
setHover
]
=
useState
(
false
);
const
onMouseEnter
=
()
=>
setHover
(
true
);
const
onMouseLeave
=
()
=>
setHover
(
false
);
return
(
<>
<
CheckCard
{
...
props
}
/>
{
props
.
hoverContent
?
(
<
Popover
content=
{
<
p
>
{
props
.
hoverContent
}
</
p
>
}
open=
{
hover
}
>
<
Button
icon=
{
<
ThunderboltOutlined
/>
}
onMouseEnter=
{
onMouseEnter
}
onMouseLeave=
{
onMouseLeave
}
></
Button
>
</
Popover
>
)
:
(
<></>
)
}
</>
);
};
src/ui/Duel/Message/checkCardModalV2.tsx
deleted
100644 → 0
View file @
c554497c
import
{
CheckCard
}
from
"
@ant-design/pro-components
"
;
import
{
Button
,
Card
,
Col
,
Row
}
from
"
antd
"
;
import
React
from
"
react
"
;
import
{
sendSelectUnselectCardResponse
}
from
"
@/api/ocgcore/ocgHelper
"
;
import
{
useConfig
}
from
"
@/config
"
;
import
{
useAppSelector
}
from
"
@/hook
"
;
import
{
selectHint
}
from
"
@/reducers/duel/hintSlice
"
;
import
{
resetCheckCardModalV2
,
setCheckCardModalV2IsOpen
,
setCheckCardModalV2ResponseAble
,
}
from
"
@/reducers/duel/mod
"
;
import
{
selectCheckCardModalV2CancelAble
,
selectCheckCardModalV2FinishAble
,
selectCheckCardModalV2IsOpen
,
selectCheckCardModalV2MinMax
,
selectCheckCardModalV2ResponseAble
,
selectCheckCardModalV2SelectAbleOptions
,
selectCheckCardModalV2SelectedOptions
,
}
from
"
@/reducers/duel/modal/checkCardModalV2Slice
"
;
import
{
store
}
from
"
@/store
"
;
import
{
DragModal
}
from
"
./DragModal
"
;
const
NeosConfig
=
useConfig
();
export
const
CheckCardModalV2
=
()
=>
{
const
dispatch
=
store
.
dispatch
;
const
isOpen
=
useAppSelector
(
selectCheckCardModalV2IsOpen
);
const
{
min
,
max
}
=
useAppSelector
(
selectCheckCardModalV2MinMax
);
const
cancelable
=
useAppSelector
(
selectCheckCardModalV2CancelAble
);
const
finishable
=
useAppSelector
(
selectCheckCardModalV2FinishAble
);
const
selectableOptions
=
useAppSelector
(
selectCheckCardModalV2SelectAbleOptions
);
const
selectedOptions
=
useAppSelector
(
selectCheckCardModalV2SelectedOptions
);
const
responseable
=
useAppSelector
(
selectCheckCardModalV2ResponseAble
);
const
hint
=
useAppSelector
(
selectHint
);
const
preHintMsg
=
hint
?.
esHint
||
""
;
const
selectHintMsg
=
hint
?.
esSelectHint
||
"
请选择卡片
"
;
const
onFinishOrCancel
=
()
=>
{
sendSelectUnselectCardResponse
({
cancel_or_finish
:
true
});
dispatch
(
setCheckCardModalV2IsOpen
(
false
));
dispatch
(
resetCheckCardModalV2
());
dispatch
(
setCheckCardModalV2ResponseAble
(
false
));
};
return
(
<
DragModal
title=
{
`${preHintMsg} ${selectHintMsg} ${min}-${max}`
}
open=
{
isOpen
}
closable=
{
false
}
footer=
{
<>
<
Button
disabled=
{
!
finishable
||
!
responseable
}
onClick=
{
onFinishOrCancel
}
>
finish
</
Button
>
<
Button
disabled=
{
!
cancelable
||
!
responseable
}
onClick=
{
onFinishOrCancel
}
>
cancel
</
Button
>
</>
}
width=
{
800
}
>
<
CheckCard
.
Group
bordered
size=
"small"
onChange=
{
(
value
)
=>
{
if
(
responseable
)
{
dispatch
(
setCheckCardModalV2IsOpen
(
false
));
// @ts-ignore
sendSelectUnselectCardResponse
({
selected_ptr
:
value
});
dispatch
(
setCheckCardModalV2ResponseAble
(
false
));
}
}
}
>
<
Row
>
{
selectableOptions
.
map
((
option
,
idx
)
=>
{
return
(
<
Col
span=
{
4
}
key=
{
idx
}
>
<
CheckCard
title=
{
option
.
name
}
description=
{
option
.
desc
}
style=
{
{
width
:
120
}
}
cover=
{
<
img
alt=
{
option
.
code
.
toString
()
}
src=
{
`${NeosConfig.cardImgUrl}/${option.code}.jpg`
}
style=
{
{
width
:
100
}
}
/>
}
value=
{
option
.
response
}
/>
</
Col
>
);
})
}
</
Row
>
</
CheckCard
.
Group
>
<
p
>
已经选择的卡片
</
p
>
<
Row
>
{
selectedOptions
.
map
((
option
,
idx
)
=>
{
return
(
<
Col
span=
{
4
}
key=
{
idx
}
>
<
Card
hoverable
style=
{
{
width
:
120
}
}
cover=
{
<
img
alt=
{
option
.
code
.
toString
()
}
src=
{
`${NeosConfig.cardImgUrl}/${option.code}.jpg`
}
/>
}
/>
</
Col
>
);
})
}
</
Row
>
</
DragModal
>
);
};
src/ui/Duel/Message/checkCardModalV3.tsx
deleted
100644 → 0
View file @
c554497c
import
{
CheckCard
}
from
"
@ant-design/pro-components
"
;
import
{
Button
,
Card
,
Col
,
Row
}
from
"
antd
"
;
import
React
,
{
useState
}
from
"
react
"
;
import
{
sendSelectCardResponse
}
from
"
@/api/ocgcore/ocgHelper
"
;
import
{
useConfig
}
from
"
@/config
"
;
import
{
useAppSelector
}
from
"
@/hook
"
;
import
{
selectHint
}
from
"
@/reducers/duel/hintSlice
"
;
import
{
resetCheckCardModalV3
,
setCheckCardModalV3IsOpen
,
setCheckCardModalV3ResponseAble
,
}
from
"
@/reducers/duel/mod
"
;
import
{
selectCheckCardModalV3
}
from
"
@/reducers/duel/modal/checkCardModalV3Slice
"
;
import
{
store
}
from
"
@/store
"
;
import
{
DragModal
}
from
"
./DragModal
"
;
const
NeosConfig
=
useConfig
();
export
const
CheckCardModalV3
=
()
=>
{
const
dispatch
=
store
.
dispatch
;
const
state
=
useAppSelector
(
selectCheckCardModalV3
);
const
isOpen
=
state
.
isOpen
;
const
min
=
state
.
selectMin
||
0
;
const
max
=
state
.
selectMax
||
0
;
const
mustSelectOptions
=
state
.
mustSelectList
;
const
selectAbleOptions
=
state
.
selectAbleList
;
const
[
selectedOptions
,
setSelectedOptions
]
=
useState
([]);
const
overflow
=
state
.
overflow
;
const
LevelSum
=
state
.
allLevel
;
const
Level1Sum
=
mustSelectOptions
.
concat
(
selectedOptions
)
.
map
((
option
)
=>
option
.
level1
)
.
reduce
((
sum
,
current
)
=>
sum
+
current
,
0
);
const
Level2Sum
=
mustSelectOptions
.
concat
(
selectedOptions
)
.
map
((
option
)
=>
option
.
level2
)
.
reduce
((
sum
,
current
)
=>
sum
+
current
,
0
);
const
hint
=
useAppSelector
(
selectHint
);
const
preHintMsg
=
hint
?.
esHint
||
""
;
const
selectHintMsg
=
hint
?.
esSelectHint
||
"
请选择卡片
"
;
const
responseable
=
(
overflow
?
Level1Sum
>=
LevelSum
||
Level2Sum
>=
LevelSum
:
Level1Sum
==
LevelSum
||
Level2Sum
==
LevelSum
)
&&
selectedOptions
.
length
<=
max
&&
selectedOptions
.
length
>=
min
;
const
onFinish
=
()
=>
{
sendSelectCardResponse
(
mustSelectOptions
.
concat
(
selectedOptions
).
map
((
option
)
=>
option
.
response
)
);
dispatch
(
setCheckCardModalV3IsOpen
(
false
));
dispatch
(
resetCheckCardModalV3
());
dispatch
(
setCheckCardModalV3ResponseAble
(
false
));
};
return
(
<
DragModal
title=
{
`${preHintMsg} ${selectHintMsg} ${min}-${max}`
}
open=
{
isOpen
}
closable=
{
false
}
footer=
{
<>
<
Button
disabled=
{
!
responseable
}
onClick=
{
onFinish
}
>
finish
</
Button
>
</>
}
width=
{
800
}
>
<
CheckCard
.
Group
bordered
size=
"small"
multiple=
{
true
}
onChange=
{
(
values
:
any
)
=>
{
console
.
log
(
values
);
setSelectedOptions
(
values
);
}
}
>
<
Row
>
{
selectAbleOptions
.
map
((
option
,
idx
)
=>
{
return
(
<
Col
span=
{
4
}
key=
{
idx
}
>
<
CheckCard
title=
{
option
.
meta
.
text
.
name
}
description=
{
option
.
meta
.
text
.
desc
}
style=
{
{
width
:
120
}
}
cover=
{
<
img
alt=
{
option
.
meta
.
id
.
toString
()
}
src=
{
`${NeosConfig.cardImgUrl}/${option.meta.id}.jpg`
}
style=
{
{
width
:
100
}
}
/>
}
value=
{
option
}
/>
</
Col
>
);
})
}
</
Row
>
</
CheckCard
.
Group
>
<
p
>
必须选择的卡片
</
p
>
<
Row
>
{
mustSelectOptions
.
map
((
option
,
idx
)
=>
{
return
(
<
Col
span=
{
4
}
key=
{
idx
}
>
<
Card
hoverable
style=
{
{
width
:
120
}
}
cover=
{
<
img
alt=
{
option
.
meta
.
id
.
toString
()
}
src=
{
`${NeosConfig.cardImgUrl}/${option.meta.id}.jpg`
}
/>
}
/>
</
Col
>
);
})
}
</
Row
>
</
DragModal
>
);
};
src/ui/Duel/Message/checkCounterModal.tsx
deleted
100644 → 0
View file @
c554497c
import
{
Button
,
Card
,
Col
,
InputNumber
,
Row
}
from
"
antd
"
;
import
React
,
{
useState
}
from
"
react
"
;
import
{
sendSelectCounterResponse
}
from
"
@/api/ocgcore/ocgHelper
"
;
import
{
fetchStrings
}
from
"
@/api/strings
"
;
import
{
useConfig
}
from
"
@/config
"
;
import
{
useAppSelector
}
from
"
@/hook
"
;
import
{
clearCheckCounter
}
from
"
@/reducers/duel/mod
"
;
import
{
selectCheckCounterModal
}
from
"
@/reducers/duel/modal/checkCounterModalSlice
"
;
import
{
store
}
from
"
@/store
"
;
import
{
DragModal
}
from
"
./DragModal
"
;
const
NeosConfig
=
useConfig
();
export
const
CheckCounterModal
=
()
=>
{
const
dispatch
=
store
.
dispatch
;
const
state
=
useAppSelector
(
selectCheckCounterModal
);
const
isOpen
=
state
.
isOpen
;
const
counterName
=
fetchStrings
(
"
!counter
"
,
`0x
${
state
.
counterType
!
}
`
);
const
min
=
state
.
min
||
0
;
const
options
=
state
.
options
;
const
[
selected
,
setSelected
]
=
useState
(
new
Array
(
options
.
length
));
const
sum
=
selected
.
reduce
((
sum
,
current
)
=>
sum
+
current
,
0
);
const
finishable
=
sum
==
min
;
const
onFinish
=
()
=>
{
sendSelectCounterResponse
(
selected
);
dispatch
(
clearCheckCounter
());
};
return
(
<
DragModal
title=
{
`请移除${min}个${counterName}`
}
open=
{
isOpen
}
closable=
{
false
}
footer=
{
<
Button
disabled=
{
!
finishable
}
onClick=
{
onFinish
}
>
finish
</
Button
>
}
>
<
Row
>
{
options
.
map
((
option
,
idx
)
=>
{
return
(
<
Col
span=
{
4
}
key=
{
idx
}
>
<
Card
hoverable
style=
{
{
width
:
120
}
}
cover=
{
<
img
alt=
{
option
.
code
.
toString
()
}
src=
{
`${NeosConfig.cardImgUrl}/${option.code}.jpg`
}
/>
}
>
<
InputNumber
min=
{
0
}
max=
{
option
.
max
}
defaultValue=
{
0
}
onChange=
{
(
value
)
=>
{
let
newSelected
=
[...
selected
];
newSelected
[
idx
]
=
value
||
0
;
setSelected
(
newSelected
);
}
}
/>
</
Card
>
</
Col
>
);
})
}
</
Row
>
</
DragModal
>
);
};
src/ui/Duel/Message/dragModal.tsx
deleted
100644 → 0
View file @
c554497c
// 经过封装的可拖拽`Modal`
import
{
Modal
,
ModalProps
}
from
"
antd
"
;
import
React
,
{
useRef
,
useState
}
from
"
react
"
;
import
type
{
DraggableData
,
DraggableEvent
}
from
"
react-draggable
"
;
import
Draggable
from
"
react-draggable
"
;
export
interface
DragModalProps
extends
ModalProps
{}
export
const
DragModal
=
(
props
:
DragModalProps
)
=>
{
const
dragRef
=
useRef
<
HTMLDivElement
>
(
null
);
const
[
bounds
,
setBounds
]
=
useState
({
left
:
0
,
top
:
0
,
bottom
:
0
,
right
:
0
,
});
const
onStart
=
(
_event
:
DraggableEvent
,
uiData
:
DraggableData
)
=>
{
const
{
clientWidth
,
clientHeight
}
=
window
.
document
.
documentElement
;
const
targetRect
=
dragRef
.
current
?.
getBoundingClientRect
();
if
(
!
targetRect
)
{
return
;
}
setBounds
({
left
:
-
targetRect
.
left
+
uiData
.
x
,
right
:
clientWidth
-
(
targetRect
.
right
-
uiData
.
x
),
top
:
-
targetRect
.
top
+
uiData
.
y
,
bottom
:
clientHeight
-
(
targetRect
.
bottom
-
uiData
.
y
),
});
};
return
(
<
Modal
{
...
props
}
modalRender=
{
(
modal
)
=>
(
<
Draggable
bounds=
{
bounds
}
onStart=
{
onStart
}
>
<
div
ref=
{
dragRef
}
>
{
modal
}
</
div
>
</
Draggable
>
)
}
>
{
props
.
children
}
</
Modal
>
);
};
src/ui/Duel/Message/hintNotification.tsx
deleted
100644 → 0
View file @
c554497c
import
{
notification
}
from
"
antd
"
;
import
React
,
{
useEffect
}
from
"
react
"
;
import
{
useNavigate
}
from
"
react-router-dom
"
;
import
{
ygopro
}
from
"
@/api/ocgcore/idl/ocgcore
"
;
import
{
useAppSelector
}
from
"
@/hook
"
;
import
{
selectHint
}
from
"
@/reducers/duel/hintSlice
"
;
import
{
selectDuelResult
,
selectWaiting
}
from
"
@/reducers/duel/mod
"
;
import
{
selectCurrentPhase
}
from
"
@/reducers/duel/phaseSlice
"
;
import
MsgWin
=
ygopro
.
StocGameMessage
.
MsgWin
;
import
{
useConfig
}
from
"
@/config
"
;
const
NeosConfig
=
useConfig
();
export
const
HintNotification
=
()
=>
{
const
hint
=
useAppSelector
(
selectHint
);
const
currentPhase
=
useAppSelector
(
selectCurrentPhase
);
const
waiting
=
useAppSelector
(
selectWaiting
);
const
result
=
useAppSelector
(
selectDuelResult
);
const
navigate
=
useNavigate
();
const
[
api
,
contextHolder
]
=
notification
.
useNotification
({
maxCount
:
NeosConfig
.
ui
.
hint
.
maxCount
,
});
useEffect
(()
=>
{
if
(
hint
&&
hint
.
msg
)
{
api
.
info
({
message
:
`
${
hint
.
msg
}
`
,
placement
:
"
bottom
"
,
});
}
},
[
hint
?.
msg
]);
useEffect
(()
=>
{
if
(
currentPhase
)
{
api
.
info
({
message
:
`<当前阶段>
${
currentPhase
}
`
,
placement
:
"
topRight
"
,
});
}
},
[
currentPhase
]);
useEffect
(()
=>
{
if
(
waiting
)
{
api
.
info
({
message
:
"
...等待对方行动中...
"
,
placement
:
"
top
"
,
duration
:
NeosConfig
.
ui
.
hint
.
waitingDuration
,
});
}
},
[
waiting
]);
useEffect
(()
=>
{
if
(
result
)
{
const
message
=
result
==
MsgWin
.
ActionType
.
Win
?
"
胜利
"
:
MsgWin
.
ActionType
.
Defeated
?
"
失败
"
:
"
未知结果
"
;
api
.
info
({
message
,
placement
:
"
bottom
"
,
onClose
()
{
navigate
(
"
/
"
);
},
});
}
},
[
result
]);
return
<>
{
contextHolder
}
</>;
};
src/ui/Duel/Message/optionModal.tsx
deleted
100644 → 0
View file @
c554497c
import
{
CheckCard
}
from
"
@ant-design/pro-components
"
;
import
{
Button
}
from
"
antd
"
;
import
React
,
{
useState
}
from
"
react
"
;
import
{
sendSelectOptionResponse
}
from
"
@/api/ocgcore/ocgHelper
"
;
import
{
useAppSelector
}
from
"
@/hook
"
;
import
{
resetOptionModal
,
setOptionModalIsOpen
}
from
"
@/reducers/duel/mod
"
;
import
{
selectOptionModalIsOpen
,
selectOptionModalOptions
,
}
from
"
@/reducers/duel/modal/mod
"
;
import
{
store
}
from
"
@/store
"
;
import
{
DragModal
}
from
"
./DragModal
"
;
export
const
OptionModal
=
()
=>
{
const
dispatch
=
store
.
dispatch
;
const
isOpen
=
useAppSelector
(
selectOptionModalIsOpen
);
const
options
=
useAppSelector
(
selectOptionModalOptions
);
const
[
selected
,
setSelected
]
=
useState
<
number
|
undefined
>
(
undefined
);
return
(
<
DragModal
title=
"请选择需要发动的效果"
open=
{
isOpen
}
closable=
{
false
}
footer=
{
<
Button
disabled=
{
selected
===
undefined
}
onClick=
{
()
=>
{
if
(
selected
!==
undefined
)
{
sendSelectOptionResponse
(
selected
);
dispatch
(
setOptionModalIsOpen
(
false
));
dispatch
(
resetOptionModal
());
}
}
}
>
submit
</
Button
>
}
>
<
CheckCard
.
Group
bordered
size=
"small"
onChange=
{
(
value
)
=>
{
// @ts-ignore
setSelected
(
value
);
}
}
>
{
options
.
map
((
option
,
idx
)
=>
(
<
CheckCard
key=
{
idx
}
title=
{
option
.
msg
}
value=
{
option
.
response
}
/>
))
}
</
CheckCard
.
Group
>
</
DragModal
>
);
};
src/ui/Duel/Message/phase.tsx
deleted
100644 → 0
View file @
c554497c
import
Icon
from
"
@ant-design/icons
"
;
import
{
Button
,
Modal
,
Space
}
from
"
antd
"
;
import
{
ReactComponent
as
BattleSvg
}
from
"
neos-assets/crossed-swords.svg
"
;
import
{
ReactComponent
as
EpSvg
}
from
"
neos-assets/power-button.svg
"
;
import
{
ReactComponent
as
Main2Svg
}
from
"
neos-assets/sword-in-stone.svg
"
;
import
{
ReactComponent
as
SurrenderSvg
}
from
"
neos-assets/truce.svg
"
;
import
React
,
{
useState
}
from
"
react
"
;
import
{
sendSelectBattleCmdResponse
,
sendSelectIdleCmdResponse
,
sendSurrender
,
}
from
"
@/api/ocgcore/ocgHelper
"
;
import
{
useAppSelector
}
from
"
@/hook
"
;
import
{
clearAllIdleInteractivities
,
setEnableBp
,
setEnableEp
,
setEnableM2
,
}
from
"
@/reducers/duel/mod
"
;
import
{
selectCurrentPhase
,
selectEnableBp
,
selectEnableEp
,
selectEnableM2
,
}
from
"
@/reducers/duel/phaseSlice
"
;
import
{
store
}
from
"
@/store
"
;
const
IconSize
=
"
150%
"
;
const
SpaceSize
=
16
;
const
PhaseButton
=
(
props
:
{
text
:
string
;
enable
:
boolean
;
onClick
:
()
=>
void
;
icon
?:
React
.
ReactNode
;
})
=>
{
return
(
<
Button
icon=
{
props
.
icon
}
disabled=
{
!
props
.
enable
}
onClick=
{
props
.
onClick
}
size=
"large"
>
{
props
.
text
}
</
Button
>
);
};
export
const
Phase
=
()
=>
{
const
dispatch
=
store
.
dispatch
;
const
enableBp
=
useAppSelector
(
selectEnableBp
);
const
enableM2
=
useAppSelector
(
selectEnableM2
);
const
enableEp
=
useAppSelector
(
selectEnableEp
);
const
currentPhase
=
useAppSelector
(
selectCurrentPhase
);
const
[
modalOpen
,
setModalOpen
]
=
useState
(
false
);
const
response
=
currentPhase
===
"
BATTLE_START
"
||
currentPhase
===
"
BATTLE_STEP
"
||
currentPhase
===
"
DAMAGE
"
||
currentPhase
===
"
DAMAGE_GAL
"
||
currentPhase
===
"
BATTLE
"
?
3
:
7
;
const
onBp
=
()
=>
{
dispatch
(
clearAllIdleInteractivities
(
0
));
dispatch
(
clearAllIdleInteractivities
(
0
));
sendSelectIdleCmdResponse
(
6
);
dispatch
(
setEnableBp
(
false
));
};
const
onM2
=
()
=>
{
dispatch
(
clearAllIdleInteractivities
(
0
));
dispatch
(
clearAllIdleInteractivities
(
0
));
sendSelectBattleCmdResponse
(
2
);
dispatch
(
setEnableM2
(
false
));
};
const
onEp
=
()
=>
{
dispatch
(
clearAllIdleInteractivities
(
0
));
dispatch
(
clearAllIdleInteractivities
(
0
));
sendSelectIdleCmdResponse
(
response
);
dispatch
(
setEnableEp
(
false
));
};
const
onSurrender
=
()
=>
{
setModalOpen
(
true
);
};
return
(
<
Space
wrap
size=
{
SpaceSize
}
>
<
PhaseButton
icon=
{
<
Icon
component=
{
BattleSvg
}
style=
{
{
fontSize
:
IconSize
}
}
/>
}
enable=
{
enableBp
}
text=
"战斗阶段"
onClick=
{
onBp
}
/>
<
PhaseButton
icon=
{
<
Icon
component=
{
Main2Svg
}
style=
{
{
fontSize
:
IconSize
}
}
/>
}
enable=
{
enableM2
}
text=
"主要阶段2"
onClick=
{
onM2
}
/>
<
PhaseButton
icon=
{
<
Icon
component=
{
EpSvg
}
style=
{
{
fontSize
:
IconSize
}
}
/>
}
enable=
{
enableEp
}
text=
"结束回合"
onClick=
{
onEp
}
/>
<
PhaseButton
icon=
{
<
Icon
component=
{
SurrenderSvg
}
style=
{
{
fontSize
:
IconSize
}
}
/>
}
enable=
{
true
}
text=
"投降"
onClick=
{
onSurrender
}
/>
<
Modal
title=
"是否确认要投降?"
open=
{
modalOpen
}
closable=
{
false
}
footer=
{
<>
<
Button
onClick=
{
()
=>
{
sendSurrender
();
setModalOpen
(
false
);
}
}
>
Yes
</
Button
>
<
Button
onClick=
{
()
=>
{
setModalOpen
(
false
);
}
}
>
No
</
Button
>
</>
}
/>
</
Space
>
);
};
src/ui/Duel/Message/positionModal.tsx
deleted
100644 → 0
View file @
c554497c
import
{
CheckCard
}
from
"
@ant-design/pro-components
"
;
import
{
Button
}
from
"
antd
"
;
import
React
,
{
useState
}
from
"
react
"
;
import
{
ygopro
}
from
"
@/api/ocgcore/idl/ocgcore
"
;
import
{
sendSelectPositionResponse
}
from
"
@/api/ocgcore/ocgHelper
"
;
import
{
useAppSelector
}
from
"
@/hook
"
;
import
{
resetPositionModal
,
setPositionModalIsOpen
,
}
from
"
@/reducers/duel/mod
"
;
import
{
selectPositionModalIsOpen
,
selectPositionModalPositions
,
}
from
"
@/reducers/duel/modal/mod
"
;
import
{
store
}
from
"
@/store
"
;
import
{
DragModal
}
from
"
./DragModal
"
;
export
const
PositionModal
=
()
=>
{
const
dispatch
=
store
.
dispatch
;
const
isOpen
=
useAppSelector
(
selectPositionModalIsOpen
);
const
positions
=
useAppSelector
(
selectPositionModalPositions
);
const
[
selected
,
setSelected
]
=
useState
<
ygopro
.
CardPosition
|
undefined
>
(
undefined
);
return
(
<
DragModal
title=
"请选择表示形式"
open=
{
isOpen
}
closable=
{
false
}
footer=
{
<
Button
disabled=
{
selected
===
undefined
}
onClick=
{
()
=>
{
if
(
selected
!==
undefined
)
{
sendSelectPositionResponse
(
selected
);
dispatch
(
setPositionModalIsOpen
(
false
));
dispatch
(
resetPositionModal
());
}
}
}
>
submit
</
Button
>
}
>
<
CheckCard
.
Group
bordered
size=
"small"
onChange=
{
(
value
)
=>
{
// @ts-ignore
setSelected
(
value
);
}
}
>
{
positions
.
map
((
position
,
idx
)
=>
(
<
CheckCard
key=
{
idx
}
title=
{
cardPositionToChinese
(
position
)
}
value=
{
position
}
/>
))
}
</
CheckCard
.
Group
>
</
DragModal
>
);
};
function
cardPositionToChinese
(
position
:
ygopro
.
CardPosition
):
string
{
switch
(
position
)
{
case
ygopro
.
CardPosition
.
FACEUP_ATTACK
:
{
return
"
正面攻击形式
"
;
}
case
ygopro
.
CardPosition
.
FACEUP_DEFENSE
:
{
return
"
正面防守形式
"
;
}
case
ygopro
.
CardPosition
.
FACEDOWN_ATTACK
:
{
return
"
背面攻击形式
"
;
}
case
ygopro
.
CardPosition
.
FACEDOWN_DEFENSE
:
{
return
"
背面防守形式
"
;
}
default
:
{
return
"
[?]
"
;
}
}
}
src/ui/Duel/Message/sendBox.tsx
deleted
100644 → 0
View file @
c554497c
import
{
SendOutlined
}
from
"
@ant-design/icons
"
;
import
{
Button
,
Col
,
Input
,
Row
}
from
"
antd
"
;
import
React
,
{
useState
}
from
"
react
"
;
import
{
sendChat
}
from
"
@/api/ocgcore/ocgHelper
"
;
export
const
SendBox
=
()
=>
{
const
[
content
,
setContent
]
=
useState
(
""
);
return
(
<>
<
Row
>
<
Input
.
TextArea
placeholder=
"Message to sent..."
autoSize=
{
{
minRows
:
3
,
maxRows
:
4
}
}
value=
{
content
}
onChange=
{
(
e
)
=>
{
setContent
(
e
.
target
.
value
);
}
}
/>
</
Row
>
<
Row
>
<
Col
>
<
Button
icon=
{
<
SendOutlined
/>
}
onClick=
{
()
=>
{
sendChat
(
content
);
setContent
(
""
);
}
}
disabled=
{
!
content
}
/>
</
Col
>
</
Row
>
</>
);
};
src/ui/Duel/Message/sortCardModal.tsx
deleted
100644 → 0
View file @
c554497c
import
{
closestCenter
,
DndContext
,
DragEndEvent
,
KeyboardSensor
,
PointerSensor
,
useSensor
,
useSensors
,
}
from
"
@dnd-kit/core
"
;
import
{
arrayMove
,
SortableContext
,
sortableKeyboardCoordinates
,
useSortable
,
verticalListSortingStrategy
,
}
from
"
@dnd-kit/sortable
"
;
import
{
CSS
}
from
"
@dnd-kit/utilities
"
;
import
{
Button
,
Card
,
Modal
}
from
"
antd
"
;
import
React
,
{
useEffect
,
useState
}
from
"
react
"
;
import
{
CardMeta
}
from
"
@/api/cards
"
;
import
{
sendSortCardResponse
}
from
"
@/api/ocgcore/ocgHelper
"
;
import
{
useConfig
}
from
"
@/config
"
;
import
{
useAppSelector
}
from
"
@/hook
"
;
import
{
resetSortCardModal
}
from
"
@/reducers/duel/mod
"
;
import
{
selectSortCardModal
}
from
"
@/reducers/duel/modal/sortCardModalSlice
"
;
import
{
store
}
from
"
@/store
"
;
const
NeosConfig
=
useConfig
();
export
const
SortCardModal
=
()
=>
{
const
dispatch
=
store
.
dispatch
;
const
state
=
useAppSelector
(
selectSortCardModal
);
const
isOpen
=
state
.
isOpen
;
const
options
=
state
.
options
;
const
[
items
,
setItems
]
=
useState
(
options
);
const
sensors
=
useSensors
(
useSensor
(
PointerSensor
),
useSensor
(
KeyboardSensor
,
{
coordinateGetter
:
sortableKeyboardCoordinates
,
})
);
const
onFinish
=
()
=>
{
sendSortCardResponse
(
items
.
map
((
item
)
=>
item
.
response
));
dispatch
(
resetSortCardModal
());
};
const
onDragEnd
=
(
event
:
DragEndEvent
)
=>
{
const
{
active
,
over
}
=
event
;
if
(
active
.
id
!==
over
?.
id
)
{
setItems
((
items
)
=>
{
const
oldIndex
=
items
.
findIndex
((
item
)
=>
item
.
response
==
active
.
id
);
const
newIndex
=
items
.
findIndex
((
item
)
=>
item
.
response
===
over
?.
id
);
return
arrayMove
(
items
,
oldIndex
,
newIndex
);
});
}
};
useEffect
(()
=>
{
setItems
(
options
);
},
[
options
]);
return
(
<
Modal
title=
"请为下列卡牌排序"
open=
{
isOpen
}
closable=
{
false
}
footer=
{
<
Button
onClick=
{
onFinish
}
>
finish
</
Button
>
}
>
<
DndContext
sensors=
{
sensors
}
collisionDetection=
{
closestCenter
}
onDragEnd=
{
onDragEnd
}
>
<
SortableContext
items=
{
items
.
map
((
item
)
=>
item
.
response
)
}
strategy=
{
verticalListSortingStrategy
}
>
{
items
.
map
((
item
)
=>
(
<
SortableItem
key=
{
item
.
response
}
id=
{
item
.
response
}
meta=
{
item
.
meta
}
/>
))
}
</
SortableContext
>
</
DndContext
>
</
Modal
>
);
};
const
SortableItem
=
(
props
:
{
id
:
number
;
meta
:
CardMeta
})
=>
{
const
{
attributes
,
listeners
,
setNodeRef
,
transform
,
transition
}
=
useSortable
({
id
:
props
.
id
});
const
style
=
{
transform
:
CSS
.
Transform
.
toString
(
transform
),
transition
,
};
return
(
<
div
ref=
{
setNodeRef
}
style=
{
style
}
{
...
attributes
}
{
...
listeners
}
>
<
Card
style=
{
{
width
:
100
}
}
cover=
{
<
img
alt=
{
props
.
meta
.
id
.
toString
()
}
src=
{
`${NeosConfig.cardImgUrl}/${props.meta.id}.jpg`
}
/>
}
/>
</
div
>
);
};
src/ui/Duel/Message/status.tsx
deleted
100644 → 0
View file @
c554497c
import
{
UserOutlined
}
from
"
@ant-design/icons
"
;
import
{
CheckCard
}
from
"
@ant-design/pro-components
"
;
import
{
Avatar
}
from
"
antd
"
;
import
React
from
"
react
"
;
import
{
useConfig
}
from
"
@/config
"
;
import
{
useAppSelector
}
from
"
@/hook
"
;
import
{
selectMeInitInfo
,
selectOpInitInfo
,
}
from
"
@/reducers/duel/initInfoSlice
"
;
import
{
selectWaiting
}
from
"
@/reducers/duel/mod
"
;
const
NeosConfig
=
useConfig
();
const
Config
=
NeosConfig
.
ui
.
status
;
const
avatarSize
=
40
;
const
ME_VALUE
=
"
myself
"
;
const
OP_VALUE
=
"
opponent
"
;
export
const
PlayerStatus
=
()
=>
{
const
meInfo
=
useAppSelector
(
selectMeInitInfo
);
const
opInfo
=
useAppSelector
(
selectOpInitInfo
);
const
waiting
=
useAppSelector
(
selectWaiting
)
||
false
;
return
(
<
CheckCard
.
Group
bordered
style=
{
{
height
:
`${NeosConfig.ui.layout.header.height}`
}
}
value=
{
waiting
?
OP_VALUE
:
ME_VALUE
}
>
<
CheckCard
avatar=
{
<
Avatar
size=
{
avatarSize
}
style=
{
{
backgroundColor
:
Config
.
opAvatarColor
}
}
icon=
{
<
UserOutlined
/>
}
/>
}
title=
{
OP_VALUE
}
description=
{
`Lp: ${opInfo?.life || 0}`
}
value=
{
OP_VALUE
}
style=
{
{
position
:
"
absolute
"
,
left
:
`${NeosConfig.ui.layout.sider.width}px`
,
}
}
/>
<
CheckCard
avatar=
{
<
Avatar
size=
{
avatarSize
}
style=
{
{
backgroundColor
:
Config
.
meAvatarColor
}
}
icon=
{
<
UserOutlined
/>
}
/>
}
title=
{
ME_VALUE
}
description=
{
`Lp: ${meInfo?.life || 0}`
}
value=
{
ME_VALUE
}
style=
{
{
position
:
"
absolute
"
,
right
:
"
0px
"
,
}
}
/>
</
CheckCard
.
Group
>
);
};
src/ui/Duel/Message/timeLine.tsx
deleted
100644 → 0
View file @
c554497c
import
{
MessageOutlined
}
from
"
@ant-design/icons
"
;
import
{
Timeline
,
TimelineItemProps
}
from
"
antd
"
;
import
React
,
{
useContext
,
useEffect
,
useState
}
from
"
react
"
;
import
{
useSnapshot
}
from
"
valtio
"
;
import
{
useAppSelector
}
from
"
@/hook
"
;
import
{
selectChat
}
from
"
@/reducers/chatSlice
"
;
import
{
valtioContext
}
from
"
@/valtioStores
"
;
export
const
DuelTimeLine
=
()
=>
{
const
[
items
,
setItems
]
=
useState
<
TimelineItemProps
[]
>
([]);
const
chat
=
useAppSelector
(
selectChat
);
const
stateChat
=
useContext
(
valtioContext
).
chatStore
;
const
snapChat
=
useSnapshot
(
stateChat
);
// const chat = snapChat.message;
useEffect
(()
=>
{
setItems
((
prev
)
=>
prev
.
concat
([
{
dot
:
<
MessageOutlined
/>,
children
:
chat
,
color
:
"
green
"
,
},
])
);
},
[
chat
]);
return
<
Timeline
items=
{
items
}
/>;
};
src/ui/Duel/Message/yesNoModal.tsx
deleted
100644 → 0
View file @
c554497c
import
{
Button
}
from
"
antd
"
;
import
React
from
"
react
"
;
import
{
sendSelectEffectYnResponse
}
from
"
@/api/ocgcore/ocgHelper
"
;
import
{
useAppSelector
}
from
"
@/hook
"
;
import
{
selectHint
}
from
"
@/reducers/duel/hintSlice
"
;
import
{
setYesNoModalIsOpen
}
from
"
@/reducers/duel/mod
"
;
import
{
selectYesNoModalIsOpen
,
selectYesNOModalMsg
,
}
from
"
@/reducers/duel/modal/mod
"
;
import
{
store
}
from
"
@/store
"
;
import
{
DragModal
}
from
"
./DragModal
"
;
export
const
YesNoModal
=
()
=>
{
const
dispatch
=
store
.
dispatch
;
const
isOpen
=
useAppSelector
(
selectYesNoModalIsOpen
);
const
msg
=
useAppSelector
(
selectYesNOModalMsg
);
const
hint
=
useAppSelector
(
selectHint
);
const
preHintMsg
=
hint
?.
esHint
||
""
;
return
(
<
DragModal
title=
{
`${preHintMsg} ${msg}`
}
open=
{
isOpen
}
closable=
{
false
}
footer=
{
<>
<
Button
onClick=
{
()
=>
{
sendSelectEffectYnResponse
(
true
);
dispatch
(
setYesNoModalIsOpen
(
false
));
}
}
>
Yes
</
Button
>
<
Button
onClick=
{
()
=>
{
sendSelectEffectYnResponse
(
false
);
dispatch
(
setYesNoModalIsOpen
(
false
));
}
}
>
No
</
Button
>
</>
}
/>
);
};
src/ui/Duel/PlayMat/deck.tsx
deleted
100644 → 0
View file @
c554497c
import
*
as
BABYLON
from
"
@babylonjs/core
"
;
import
{
useConfig
}
from
"
@/config
"
;
import
{
useAppSelector
}
from
"
@/hook
"
;
import
{
selectMeDeck
,
selectOpDeck
}
from
"
@/reducers/duel/deckSlice
"
;
import
{
cardSlotRotation
}
from
"
../utils
"
;
import
{
Depth
,
SingleSlot
}
from
"
./SingleSlot
"
;
const
NeosConfig
=
useConfig
();
export
const
CommonDeck
=
()
=>
{
const
meDeck
=
useAppSelector
(
selectMeDeck
).
inner
;
const
opDeck
=
useAppSelector
(
selectOpDeck
).
inner
;
return
(
<>
<
SingleSlot
state=
{
meDeck
}
position=
{
deckPosition
(
0
,
meDeck
.
length
)
}
rotation=
{
cardSlotRotation
(
false
)
}
/>
<
SingleSlot
state=
{
opDeck
}
position=
{
deckPosition
(
1
,
opDeck
.
length
)
}
rotation=
{
cardSlotRotation
(
true
)
}
/>
</>
);
};
const
deckPosition
=
(
player
:
number
,
deckLength
:
number
)
=>
{
const
x
=
player
==
0
?
3.2
:
-
3.2
;
const
y
=
(
Depth
*
deckLength
)
/
2
+
NeosConfig
.
ui
.
card
.
floating
;
const
z
=
player
==
0
?
-
3.3
:
3.3
;
return
new
BABYLON
.
Vector3
(
x
,
y
,
z
);
};
src/ui/Duel/PlayMat/extraDeck.tsx
deleted
100644 → 0
View file @
c554497c
import
*
as
BABYLON
from
"
@babylonjs/core
"
;
import
{
useConfig
}
from
"
@/config
"
;
import
{
useAppSelector
}
from
"
@/hook
"
;
import
{
selectMeExtraDeck
,
selectOpExtraDeck
,
}
from
"
@/reducers/duel/extraDeckSlice
"
;
import
{
cardSlotRotation
}
from
"
../utils
"
;
import
{
Depth
,
SingleSlot
}
from
"
./SingleSlot
"
;
const
NeosConfig
=
useConfig
();
export
const
ExtraDeck
=
()
=>
{
const
meExtraDeck
=
useAppSelector
(
selectMeExtraDeck
).
inner
;
const
opExtraDeck
=
useAppSelector
(
selectOpExtraDeck
).
inner
;
return
(
<>
<
SingleSlot
state=
{
meExtraDeck
}
position=
{
extraDeckPosition
(
0
,
meExtraDeck
.
length
)
}
rotation=
{
cardSlotRotation
(
false
)
}
/>
<
SingleSlot
state=
{
opExtraDeck
}
position=
{
extraDeckPosition
(
1
,
opExtraDeck
.
length
)
}
rotation=
{
cardSlotRotation
(
true
)
}
/>
</>
);
};
const
extraDeckPosition
=
(
player
:
number
,
deckLength
:
number
)
=>
{
const
x
=
player
==
0
?
-
3.3
:
3.3
;
const
y
=
(
Depth
&
deckLength
)
/
2
+
NeosConfig
.
ui
.
card
.
floating
;
const
z
=
player
==
0
?
-
3.3
:
3.3
;
return
new
BABYLON
.
Vector3
(
x
,
y
,
z
);
};
src/ui/Duel/PlayMat/field.tsx
deleted
100644 → 0
View file @
c554497c
import
*
as
BABYLON
from
"
@babylonjs/core
"
;
import
{
useConfig
}
from
"
@/config
"
;
import
{
useAppSelector
}
from
"
@/hook
"
;
import
{
selectMeMagics
,
selectOpMagics
}
from
"
@/reducers/duel/magicSlice
"
;
import
{
clearMagicPlaceInteractivities
}
from
"
@/reducers/duel/mod
"
;
import
{
cardSlotRotation
}
from
"
../utils
"
;
import
{
FixedSlot
}
from
"
./FixedSlot
"
;
import
{
Depth
}
from
"
./SingleSlot
"
;
const
NeosConfig
=
useConfig
();
export
const
Field
=
()
=>
{
const
meField
=
useAppSelector
(
selectMeMagics
).
inner
.
find
(
(
_
,
sequence
)
=>
sequence
==
5
);
const
opField
=
useAppSelector
(
selectOpMagics
).
inner
.
find
(
(
_
,
sequence
)
=>
sequence
==
5
);
return
(
<>
{
meField
?
(
<
FixedSlot
state=
{
meField
}
sequence=
{
0
}
position=
{
fieldPosition
(
0
)
}
rotation=
{
cardSlotRotation
(
false
)
}
clearPlaceInteractivitiesAction=
{
clearMagicPlaceInteractivities
}
/>
)
:
(
<></>
)
}
{
opField
?
(
<
FixedSlot
state=
{
opField
}
sequence=
{
0
}
position=
{
fieldPosition
(
1
)
}
rotation=
{
cardSlotRotation
(
true
)
}
clearPlaceInteractivitiesAction=
{
clearMagicPlaceInteractivities
}
/>
)
:
(
<></>
)
}
</>
);
};
const
fieldPosition
=
(
player
:
number
)
=>
{
const
x
=
player
==
0
?
-
3.3
:
3.3
;
const
y
=
Depth
/
2
+
NeosConfig
.
ui
.
card
.
floating
;
const
z
=
player
==
0
?
-
2.0
:
2.0
;
return
new
BABYLON
.
Vector3
(
x
,
y
,
z
);
};
src/ui/Duel/PlayMat/fixedSlot.tsx
deleted
100644 → 0
View file @
c554497c
import
*
as
BABYLON
from
"
@babylonjs/core
"
;
import
{
ActionCreatorWithPayload
}
from
"
@reduxjs/toolkit
"
;
import
{
useRef
}
from
"
react
"
;
import
{
ygopro
}
from
"
@/api/ocgcore/idl/ocgcore
"
;
import
{
sendSelectPlaceResponse
}
from
"
@/api/ocgcore/ocgHelper
"
;
import
{
useConfig
}
from
"
@/config
"
;
import
{
useClick
}
from
"
@/hook
"
;
import
{
CardState
}
from
"
@/reducers/duel/generic
"
;
import
{
setCardListModalInfo
,
setCardListModalIsOpen
,
setCardModalCounters
,
setCardModalInteractivies
,
setCardModalIsOpen
,
setCardModalMeta
,
}
from
"
@/reducers/duel/mod
"
;
import
{
store
}
from
"
@/store
"
;
import
{
interactTypeToString
}
from
"
../utils
"
;
const
NeosConfig
=
useConfig
();
const
transform
=
NeosConfig
.
ui
.
card
.
transform
;
const
defenceRotation
=
NeosConfig
.
ui
.
card
.
defenceRotation
;
const
cardDefenceRotation
=
new
BABYLON
.
Vector3
(
defenceRotation
.
x
,
defenceRotation
.
y
,
defenceRotation
.
z
);
export
const
FixedSlot
=
(
props
:
{
state
:
CardState
;
sequence
:
number
;
position
:
BABYLON
.
Vector3
;
rotation
:
BABYLON
.
Vector3
;
deffenseRotation
?:
BABYLON
.
Vector3
;
clearPlaceInteractivitiesAction
:
ActionCreatorWithPayload
<
number
,
string
>
;
})
=>
{
const
planeRef
=
useRef
(
null
);
const
rotation
=
props
.
state
.
location
.
position
===
ygopro
.
CardPosition
.
DEFENSE
||
props
.
state
.
location
.
position
===
ygopro
.
CardPosition
.
FACEUP_DEFENSE
||
props
.
state
.
location
.
position
===
ygopro
.
CardPosition
.
FACEDOWN_DEFENSE
?
props
.
deffenseRotation
||
cardDefenceRotation
:
props
.
rotation
;
const
edgesWidth
=
2.0
;
const
edgesColor
=
BABYLON
.
Color4
.
FromColor3
(
BABYLON
.
Color3
.
Yellow
());
const
dispatch
=
store
.
dispatch
;
const
faceDown
=
props
.
state
.
location
.
position
===
ygopro
.
CardPosition
.
FACEDOWN_DEFENSE
||
props
.
state
.
location
.
position
===
ygopro
.
CardPosition
.
FACEDOWN_ATTACK
||
props
.
state
.
location
.
position
===
ygopro
.
CardPosition
.
FACEDOWN
;
useClick
(
(
_event
)
=>
{
if
(
props
.
state
.
placeInteractivities
)
{
sendSelectPlaceResponse
(
props
.
state
.
placeInteractivities
.
response
);
dispatch
(
props
.
clearPlaceInteractivitiesAction
(
0
));
dispatch
(
props
.
clearPlaceInteractivitiesAction
(
1
));
}
else
if
(
props
.
state
.
occupant
)
{
// 中央弹窗展示选中卡牌信息
dispatch
(
setCardModalMeta
(
props
.
state
.
occupant
));
dispatch
(
setCardModalInteractivies
(
props
.
state
.
idleInteractivities
.
map
((
interactivity
)
=>
{
return
{
desc
:
interactTypeToString
(
interactivity
.
interactType
),
response
:
interactivity
.
response
,
};
})
)
);
dispatch
(
setCardModalCounters
(
props
.
state
.
counters
));
dispatch
(
setCardModalIsOpen
(
true
));
// 侧边栏展示超量素材信息
if
(
props
.
state
.
overlay_materials
&&
props
.
state
.
overlay_materials
.
length
>
0
)
{
dispatch
(
setCardListModalInfo
(
props
.
state
.
overlay_materials
?.
map
((
overlay
)
=>
{
return
{
meta
:
overlay
,
interactivies
:
[],
};
})
||
[]
)
);
dispatch
(
setCardListModalIsOpen
(
true
));
}
}
},
planeRef
,
[
props
.
state
]
);
return
(
<
plane
name=
{
`fixedslot-${props.sequence}`
}
ref=
{
planeRef
}
width=
{
transform
.
x
}
height=
{
transform
.
y
}
position=
{
props
.
position
}
rotation=
{
rotation
}
enableEdgesRendering
edgesWidth=
{
props
.
state
.
placeInteractivities
||
props
.
state
.
idleInteractivities
.
length
>
0
?
edgesWidth
:
0
}
edgesColor=
{
edgesColor
}
>
<
standardMaterial
name=
{
`fixedslot-mat-${props.sequence}`
}
diffuseTexture=
{
props
.
state
.
occupant
?
faceDown
?
new
BABYLON
.
Texture
(
`${NeosConfig.assetsPath}/card_back.jpg`
)
:
new
BABYLON
.
Texture
(
`${NeosConfig.cardImgUrl}/${props.state.occupant.id}.jpg`
)
:
new
BABYLON
.
Texture
(
`${NeosConfig.assetsPath}/card_slot.png`
)
}
alpha=
{
props
.
state
.
occupant
?
1
:
0
}
></
standardMaterial
>
</
plane
>
);
};
src/ui/Duel/PlayMat/hands.tsx
deleted
100644 → 0
View file @
c554497c
import
*
as
BABYLON
from
"
@babylonjs/core
"
;
import
{
useEffect
,
useRef
,
useState
}
from
"
react
"
;
import
{
useHover
}
from
"
react-babylonjs
"
;
import
{
useConfig
}
from
"
@/config
"
;
import
{
useAppSelector
,
useClick
}
from
"
@/hook
"
;
import
{
CardState
}
from
"
@/reducers/duel/generic
"
;
import
{
selectMeHands
,
selectOpHands
}
from
"
@/reducers/duel/handsSlice
"
;
import
{
setCardModalInteractivies
,
setCardModalIsOpen
,
setCardModalMeta
,
}
from
"
@/reducers/duel/mod
"
;
import
{
store
}
from
"
@/store
"
;
import
{
animated
,
useSpring
}
from
"
../spring
"
;
import
{
interactTypeToString
,
zip
}
from
"
../utils
"
;
const
NeosConfig
=
useConfig
();
const
groundShape
=
NeosConfig
.
ui
.
ground
;
const
left
=
-
(
groundShape
.
width
/
2
);
const
handShape
=
NeosConfig
.
ui
.
card
.
transform
;
const
rotation
=
NeosConfig
.
ui
.
card
.
handRotation
;
const
handRotation
=
new
BABYLON
.
Vector3
(
rotation
.
x
,
rotation
.
y
,
rotation
.
z
);
const
hoverScaling
=
NeosConfig
.
ui
.
card
.
handHoverScaling
;
export
const
Hands
=
()
=>
{
const
meHands
=
useAppSelector
(
selectMeHands
).
inner
;
const
meHandPositions
=
handPositons
(
0
,
meHands
);
const
opHands
=
useAppSelector
(
selectOpHands
).
inner
;
const
opHandPositions
=
handPositons
(
1
,
opHands
);
return
(
<>
{
zip
(
meHands
,
meHandPositions
).
map
(([
hand
,
position
],
idx
)
=>
{
return
(
<
CHand
key=
{
idx
}
state=
{
hand
}
sequence=
{
idx
}
position=
{
position
}
rotation=
{
handRotation
}
cover=
{
(
id
)
=>
`${NeosConfig.cardImgUrl}/${id}.jpg`
}
/>
);
})
}
{
zip
(
opHands
,
opHandPositions
).
map
(([
hand
,
position
],
idx
)
=>
{
return
(
<
CHand
key=
{
idx
}
state=
{
hand
}
sequence=
{
idx
}
position=
{
position
}
rotation=
{
handRotation
}
cover=
{
(
_
)
=>
`${NeosConfig.assetsPath}/card_back.jpg`
}
/>
);
})
}
</>
);
};
const
CHand
=
(
props
:
{
state
:
CardState
;
sequence
:
number
;
position
:
BABYLON
.
Vector3
;
rotation
:
BABYLON
.
Vector3
;
cover
:
(
id
:
number
)
=>
string
;
})
=>
{
const
hoverScale
=
new
BABYLON
.
Vector3
(
hoverScaling
.
x
,
hoverScaling
.
y
,
hoverScaling
.
z
);
const
defaultScale
=
new
BABYLON
.
Vector3
(
1
,
1
,
1
);
const
edgesWidth
=
2.0
;
const
edgesColor
=
BABYLON
.
Color4
.
FromColor3
(
BABYLON
.
Color3
.
Yellow
());
const
planeRef
=
useRef
(
null
);
const
state
=
props
.
state
;
const
[
hovered
,
setHovered
]
=
useState
(
false
);
const
position
=
props
.
position
;
const
dispatch
=
store
.
dispatch
;
const
[
spring
,
api
]
=
useSpring
(
()
=>
({
from
:
{
position
,
},
config
:
{
mass
:
1.0
,
tension
:
170
,
friction
:
900
,
precision
:
0.01
,
velocity
:
0.0
,
clamp
:
true
,
duration
:
2000
,
},
}),
[]
);
useEffect
(()
=>
{
api
.
start
({
position
,
});
},
[
position
]);
useHover
(
()
=>
setHovered
(
true
),
()
=>
setHovered
(
false
),
planeRef
);
useClick
(
()
=>
{
if
(
state
.
occupant
)
{
dispatch
(
setCardModalMeta
(
state
.
occupant
));
}
dispatch
(
setCardModalInteractivies
(
state
.
idleInteractivities
.
map
((
interactive
)
=>
{
return
{
desc
:
interactTypeToString
(
interactive
.
interactType
),
response
:
interactive
.
response
,
};
})
)
);
dispatch
(
setCardModalIsOpen
(
true
));
},
planeRef
,
[
state
]
);
return
(
// @ts-ignore
<
animated
.
transformNode
name=
""
>
<
animated
.
plane
name=
{
`hand-${props.sequence}`
}
ref=
{
planeRef
}
width=
{
handShape
.
x
}
height=
{
handShape
.
y
}
scaling=
{
hovered
?
hoverScale
:
defaultScale
}
position=
{
spring
.
position
}
rotation=
{
props
.
rotation
}
enableEdgesRendering
edgesWidth=
{
state
.
idleInteractivities
.
length
>
0
||
state
.
placeInteractivities
?
edgesWidth
:
0
}
edgesColor=
{
edgesColor
}
>
<
animated
.
standardMaterial
name=
{
`hand-mat-${props.sequence}`
}
diffuseTexture=
{
new
BABYLON
.
Texture
(
props
.
cover
(
state
.
occupant
?.
id
||
0
))
}
/>
</
animated
.
plane
>
</
animated
.
transformNode
>
);
};
const
handPositons
=
(
player
:
number
,
hands
:
CardState
[])
=>
{
const
gap
=
groundShape
.
width
/
(
hands
.
length
-
1
);
const
x
=
(
idx
:
number
)
=>
player
==
0
?
left
+
gap
*
idx
:
-
left
-
gap
*
idx
;
const
y
=
handShape
.
y
/
2
;
const
z
=
player
==
0
?
-
(
groundShape
.
height
/
2
)
-
1
:
groundShape
.
height
/
2
+
1
;
return
hands
.
map
((
_
,
idx
)
=>
new
BABYLON
.
Vector3
(
x
(
idx
),
y
,
z
));
};
src/ui/Duel/PlayMat/magics.tsx
deleted
100644 → 0
View file @
c554497c
import
*
as
BABYLON
from
"
@babylonjs/core
"
;
import
{
useConfig
}
from
"
@/config
"
;
import
{
useAppSelector
}
from
"
@/hook
"
;
import
{
CardState
}
from
"
@/reducers/duel/generic
"
;
import
{
selectMeMagics
,
selectOpMagics
}
from
"
@/reducers/duel/magicSlice
"
;
import
{
clearMagicPlaceInteractivities
}
from
"
@/reducers/duel/mod
"
;
import
{
cardSlotRotation
,
zip
}
from
"
../utils
"
;
import
{
FixedSlot
}
from
"
./FixedSlot
"
;
const
NeosConfig
=
useConfig
();
// TODO: use config
const
left
=
-
2.15
;
const
gap
=
1.05
;
const
transform
=
NeosConfig
.
ui
.
card
.
transform
;
export
const
Magics
=
()
=>
{
const
meMagics
=
useAppSelector
(
selectMeMagics
).
inner
;
const
meMagicPositions
=
magicPositions
(
0
,
meMagics
);
const
opMagics
=
useAppSelector
(
selectOpMagics
).
inner
;
const
opMagicPositions
=
magicPositions
(
1
,
opMagics
);
return
(
<>
{
zip
(
meMagics
,
meMagicPositions
)
.
slice
(
0
,
5
)
.
map
(([
magic
,
position
],
sequence
)
=>
{
return
(
<
FixedSlot
state=
{
magic
}
key=
{
sequence
}
sequence=
{
sequence
}
position=
{
position
}
rotation=
{
cardSlotRotation
(
false
)
}
clearPlaceInteractivitiesAction=
{
clearMagicPlaceInteractivities
}
/>
);
})
}
{
zip
(
opMagics
,
opMagicPositions
)
.
slice
(
0
,
5
)
.
map
(([
magic
,
position
],
sequence
)
=>
{
return
(
<
FixedSlot
state=
{
magic
}
key=
{
sequence
}
sequence=
{
sequence
}
position=
{
position
}
rotation=
{
cardSlotRotation
(
true
)
}
clearPlaceInteractivitiesAction=
{
clearMagicPlaceInteractivities
}
/>
);
})
}
</>
);
};
const
magicPositions
=
(
player
:
number
,
magics
:
CardState
[])
=>
{
const
x
=
(
sequence
:
number
)
=>
player
==
0
?
left
+
gap
*
sequence
:
-
left
-
gap
*
sequence
;
const
y
=
transform
.
z
/
2
+
NeosConfig
.
ui
.
card
.
floating
;
const
z
=
player
==
0
?
-
2.6
:
2.6
;
return
magics
.
map
((
_
,
sequence
)
=>
new
BABYLON
.
Vector3
(
x
(
sequence
),
y
,
z
));
};
src/ui/Duel/PlayMat/monsters.tsx
deleted
100644 → 0
View file @
c554497c
import
"
react-babylonjs
"
;
import
*
as
BABYLON
from
"
@babylonjs/core
"
;
import
{
useConfig
}
from
"
@/config
"
;
import
{
useAppSelector
}
from
"
@/hook
"
;
import
{
CardState
}
from
"
@/reducers/duel/generic
"
;
import
{
clearMonsterPlaceInteractivities
}
from
"
@/reducers/duel/mod
"
;
import
{
selectMeMonsters
,
selectOpMonsters
,
}
from
"
@/reducers/duel/monstersSlice
"
;
import
{
cardSlotDefenceRotation
,
cardSlotRotation
,
zip
}
from
"
../utils
"
;
import
{
FixedSlot
}
from
"
./FixedSlot
"
;
const
NeosConfig
=
useConfig
();
const
transform
=
NeosConfig
.
ui
.
card
.
transform
;
const
floating
=
NeosConfig
.
ui
.
card
.
floating
;
const
left
=
-
2.15
;
// TODO: config
const
gap
=
1.05
;
export
const
Monsters
=
()
=>
{
const
meMonsters
=
useAppSelector
(
selectMeMonsters
).
inner
;
const
meMonsterPositions
=
monsterPositions
(
0
,
meMonsters
);
const
opMonsters
=
useAppSelector
(
selectOpMonsters
).
inner
;
const
opMonsterPositions
=
monsterPositions
(
1
,
opMonsters
);
return
(
<>
{
zip
(
meMonsters
,
meMonsterPositions
)
.
slice
(
0
,
5
)
.
map
(([
monster
,
position
],
sequence
)
=>
(
<
FixedSlot
state=
{
monster
}
key=
{
sequence
}
sequence=
{
sequence
}
position=
{
position
}
rotation=
{
cardSlotRotation
(
false
)
}
deffenseRotation=
{
cardSlotDefenceRotation
()
}
clearPlaceInteractivitiesAction=
{
clearMonsterPlaceInteractivities
}
/>
))
}
{
zip
(
opMonsters
,
opMonsterPositions
)
.
slice
(
0
,
5
)
.
map
(([
monster
,
position
],
sequence
)
=>
(
<
FixedSlot
state=
{
monster
}
key=
{
sequence
}
sequence=
{
sequence
}
position=
{
position
}
rotation=
{
cardSlotRotation
(
true
)
}
deffenseRotation=
{
cardSlotDefenceRotation
()
}
clearPlaceInteractivitiesAction=
{
clearMonsterPlaceInteractivities
}
/>
))
}
<
ExtraMonsters
meMonsters=
{
meMonsters
}
opMonsters=
{
opMonsters
}
/>
</>
);
};
// TODO: use props and redux
const
ExtraMonsters
=
(
props
:
{
meMonsters
:
CardState
[];
opMonsters
:
CardState
[];
})
=>
{
const
meLeft
=
props
.
meMonsters
.
find
((
_
,
sequence
)
=>
sequence
==
5
);
const
meRight
=
props
.
meMonsters
.
find
((
_
,
sequence
)
=>
sequence
==
6
);
const
opLeft
=
props
.
opMonsters
.
find
((
_
,
sequence
)
=>
sequence
==
5
);
const
opRight
=
props
.
opMonsters
.
find
((
_
,
sequence
)
=>
sequence
==
6
);
const
leftPosition
=
new
BABYLON
.
Vector3
(
-
1.1
,
transform
.
z
/
2
+
floating
,
0
);
const
rightPosition
=
new
BABYLON
.
Vector3
(
1.1
,
transform
.
z
/
2
+
floating
,
0
);
const
meRotation
=
cardSlotRotation
(
false
);
const
opRotation
=
cardSlotRotation
(
true
);
return
(
<>
{
meLeft
?
(
<
FixedSlot
state=
{
meLeft
}
sequence=
{
5
}
position=
{
leftPosition
}
rotation=
{
meRotation
}
deffenseRotation=
{
cardSlotDefenceRotation
()
}
clearPlaceInteractivitiesAction=
{
clearMonsterPlaceInteractivities
}
/>
)
:
(
<></>
)
}
{
meRight
?
(
<
FixedSlot
state=
{
meRight
}
sequence=
{
6
}
position=
{
rightPosition
}
rotation=
{
meRotation
}
deffenseRotation=
{
cardSlotDefenceRotation
()
}
clearPlaceInteractivitiesAction=
{
clearMonsterPlaceInteractivities
}
/>
)
:
(
<></>
)
}
{
opLeft
?
(
<
FixedSlot
state=
{
opLeft
}
sequence=
{
5
}
position=
{
rightPosition
}
rotation=
{
opRotation
}
deffenseRotation=
{
cardSlotDefenceRotation
()
}
clearPlaceInteractivitiesAction=
{
clearMonsterPlaceInteractivities
}
/>
)
:
(
<></>
)
}
{
opRight
?
(
<
FixedSlot
state=
{
opRight
}
sequence=
{
6
}
position=
{
leftPosition
}
rotation=
{
opRotation
}
deffenseRotation=
{
cardSlotDefenceRotation
()
}
clearPlaceInteractivitiesAction=
{
clearMonsterPlaceInteractivities
}
/>
)
:
(
<></>
)
}
</>
);
};
const
monsterPositions
=
(
player
:
number
,
monsters
:
CardState
[])
=>
{
const
x
=
(
sequence
:
number
)
=>
player
==
0
?
left
+
gap
*
sequence
:
-
left
-
gap
*
sequence
;
const
y
=
transform
.
z
/
2
+
floating
;
const
z
=
player
==
0
?
-
1.35
:
1.35
;
return
monsters
.
map
((
_
,
sequence
)
=>
new
BABYLON
.
Vector3
(
x
(
sequence
),
y
,
z
));
};
src/ui/Duel/PlayMat/singleSlot.tsx
deleted
100644 → 0
View file @
c554497c
import
*
as
BABYLON
from
"
@babylonjs/core
"
;
import
{
useRef
}
from
"
react
"
;
import
{
useConfig
}
from
"
@/config
"
;
import
{
useClick
}
from
"
@/hook
"
;
import
{
CardState
}
from
"
@/reducers/duel/generic
"
;
import
{
setCardListModalInfo
,
setCardListModalIsOpen
,
}
from
"
@/reducers/duel/mod
"
;
import
{
store
}
from
"
@/store
"
;
import
{
interactTypeToString
}
from
"
../utils
"
;
const
NeosConfig
=
useConfig
();
const
transform
=
NeosConfig
.
ui
.
card
.
transform
;
export
const
Depth
=
0.005
;
export
const
SingleSlot
=
(
props
:
{
state
:
CardState
[];
position
:
BABYLON
.
Vector3
;
rotation
:
BABYLON
.
Vector3
;
})
=>
{
const
boxRef
=
useRef
(
null
);
const
dispatch
=
store
.
dispatch
;
const
edgeRender
=
props
.
state
.
find
((
item
)
=>
item
===
undefined
?
false
:
item
.
idleInteractivities
.
length
>
0
)
!==
undefined
;
const
edgesWidth
=
2.0
;
const
edgesColor
=
BABYLON
.
Color4
.
FromColor3
(
BABYLON
.
Color3
.
Yellow
());
useClick
(
(
_event
)
=>
{
if
(
props
.
state
.
length
!=
0
)
{
dispatch
(
setCardListModalInfo
(
props
.
state
.
filter
(
(
item
)
=>
item
.
occupant
!==
undefined
&&
item
.
occupant
.
id
!==
0
)
.
map
((
item
)
=>
{
return
{
meta
:
item
.
occupant
,
interactivies
:
item
.
idleInteractivities
.
map
((
interactivy
)
=>
{
return
{
desc
:
interactTypeToString
(
interactivy
.
interactType
),
response
:
interactivy
.
response
,
};
}),
};
})
)
);
dispatch
(
setCardListModalIsOpen
(
true
));
}
},
boxRef
,
[
props
.
state
]
);
return
(
<
box
name=
"single-slot"
ref=
{
boxRef
}
scaling=
{
new
BABYLON
.
Vector3
(
transform
.
x
,
transform
.
y
,
Depth
*
props
.
state
.
length
)
}
position=
{
props
.
position
}
rotation=
{
props
.
rotation
}
enableEdgesRendering
edgesWidth=
{
edgeRender
?
edgesWidth
:
0
}
edgesColor=
{
edgesColor
}
>
<
standardMaterial
name=
"single-slot-mat"
diffuseTexture=
{
new
BABYLON
.
Texture
(
`${NeosConfig.assetsPath}/card_back.jpg`
)
}
alpha=
{
props
.
state
.
length
==
0
?
0
:
1
}
/>
</
box
>
);
};
src/ui/Duel/layout.tsx
deleted
100644 → 0
View file @
c554497c
import
{
Layout
}
from
"
antd
"
;
import
React
from
"
react
"
;
import
{
useConfig
}
from
"
@/config
"
;
const
NeosConfig
=
useConfig
();
const
layoutConfig
=
NeosConfig
.
ui
.
layout
;
const
{
Header
,
Footer
,
Sider
,
Content
}
=
Layout
;
const
headerStyle
:
React
.
CSSProperties
=
{
textAlign
:
"
center
"
,
alignContent
:
"
center
"
,
color
:
"
#fff
"
,
height
:
layoutConfig
.
header
.
height
,
};
const
contentStyle
:
React
.
CSSProperties
=
{
textAlign
:
"
center
"
,
minHeight
:
120
,
height
:
layoutConfig
.
content
.
height
,
lineHeight
:
"
120px
"
,
paddingLeft
:
`
${
layoutConfig
.
sider
.
width
}
px`
,
};
const
siderStyle
:
React
.
CSSProperties
=
{
lineHeight
:
"
120px
"
,
position
:
"
fixed
"
,
overflow
:
"
auto
"
,
height
:
"
100vh
"
,
padding
:
"
50px 20px
"
,
color
:
"
#fff
"
,
};
const
footerStyle
:
React
.
CSSProperties
=
{
textAlign
:
"
center
"
,
height
:
layoutConfig
.
footer
.
height
,
color
:
"
#fff
"
,
paddingLeft
:
`
${
layoutConfig
.
sider
.
width
}
px`
,
};
const
NeosLayout
=
(
props
:
{
sider
:
React
.
ReactNode
;
header
:
React
.
ReactNode
;
content
:
React
.
ReactNode
;
footer
:
React
.
ReactNode
;
})
=>
{
return
(
<
Layout
hasSider
>
<
Sider
style=
{
siderStyle
}
width=
{
layoutConfig
.
sider
.
width
}
>
{
props
.
sider
}
</
Sider
>
<
Layout
>
<
Header
style=
{
headerStyle
}
>
{
props
.
header
}
</
Header
>
<
Content
style=
{
contentStyle
}
>
{
props
.
content
}
</
Content
>
<
Footer
style=
{
footerStyle
}
>
{
props
.
footer
}
</
Footer
>
</
Layout
>
</
Layout
>
);
};
export
default
NeosLayout
;
src/ui/Duel/main.tsx
deleted
100644 → 0
View file @
c554497c
import
*
as
BABYLON
from
"
@babylonjs/core
"
;
import
{
Row
}
from
"
antd
"
;
import
React
from
"
react
"
;
import
{
Engine
,
Scene
}
from
"
react-babylonjs
"
;
import
{
Provider
,
ReactReduxContext
}
from
"
react-redux
"
;
import
{
useConfig
}
from
"
@/config
"
;
import
NeosLayout
from
"
./Layout
"
;
import
{
Alert
,
CardListModal
,
CardModal
,
CheckCardModal
,
CheckCardModalV2
,
CheckCardModalV3
,
CheckCounterModal
,
DuelTimeLine
,
HintNotification
,
OptionModal
,
Phase
,
PlayerStatus
,
PositionModal
,
SendBox
,
SortCardModal
,
YesNoModal
,
}
from
"
./Message
"
;
import
{
ExtraDeck
,
Field
,
Graveyard
,
Hands
,
Magics
,
Monsters
,
}
from
"
./PlayMat
"
;
import
{
BanishedZone
}
from
"
./PlayMat/BanishedZone
"
;
import
{
CommonDeck
}
from
"
./PlayMat/Deck
"
;
const
NeosConfig
=
useConfig
();
// Ref: https://github.com/brianzinn/react-babylonjs/issues/126
const
NeosDuel
=
()
=>
{
return
(
<>
<
Alert
/>
<
NeosLayout
sider=
{
<
NeosSider
/>
}
header=
{
<
PlayerStatus
/>
}
content=
{
<
NeosCanvas
/>
}
footer=
{
<
Phase
/>
}
/>
<
CardModal
/>
<
CardListModal
/>
<
HintNotification
/>
<
CheckCardModal
/>
<
YesNoModal
/>
<
PositionModal
/>
<
OptionModal
/>
<
CheckCardModalV2
/>
<
CheckCardModalV3
/>
<
CheckCounterModal
/>
<
SortCardModal
/>
</>
);
};
const
NeosSider
=
()
=>
(
<>
<
Row
>
<
DuelTimeLine
/>
</
Row
>
<
Row
>
<
SendBox
/>
</
Row
>
</>
);
const
NeosCanvas
=
()
=>
(
<
ReactReduxContext
.
Consumer
>
{
({
store
})
=>
(
<
Engine
antialias
adaptToDeviceRatio
canvasId=
"babylonJS"
>
<
Scene
>
<
Provider
store=
{
store
}
>
<
Camera
/>
<
Light
/>
<
Hands
/>
<
Monsters
/>
<
Magics
/>
<
Field
/>
<
CommonDeck
/>
<
ExtraDeck
/>
<
Graveyard
/>
<
BanishedZone
/>
<
Field
/>
<
Ground
/>
</
Provider
>
</
Scene
>
</
Engine
>
)
}
</
ReactReduxContext
.
Consumer
>
);
const
Camera
=
()
=>
(
<
freeCamera
name=
"duel-camera"
position=
{
new
BABYLON
.
Vector3
(
0
,
8
,
-
10
)
}
target=
{
BABYLON
.
Vector3
.
Zero
()
}
></
freeCamera
>
);
const
Light
=
()
=>
(
<
hemisphericLight
name=
"duel-light"
direction=
{
new
BABYLON
.
Vector3
(
1
,
2.5
,
1
)
}
intensity=
{
0.7
}
></
hemisphericLight
>
);
const
Ground
=
()
=>
{
const
shape
=
NeosConfig
.
ui
.
ground
;
const
texture
=
new
BABYLON
.
Texture
(
`
${
NeosConfig
.
assetsPath
}
/newfield.png`
);
texture
.
hasAlpha
=
true
;
return
(
<
ground
name=
"duel-ground"
width=
{
shape
.
width
}
height=
{
shape
.
height
}
>
<
standardMaterial
name=
"duel-ground-mat"
diffuseTexture=
{
texture
}
></
standardMaterial
>
</
ground
>
);
};
export
default
NeosDuel
;
src/valtioStores/duelStore/duel.ts
View file @
bdd10692
import
{
proxy
}
from
"
valtio
"
;
import
{
proxy
}
from
"
valtio
"
;
import
type
{
DuelState
}
from
"
./types
"
;
import
{
ygopro
}
from
"
@/api/ocgcore/idl/ocgcore
"
;
import
{
ygopro
}
from
"
@/api/ocgcore/idl/ocgcore
"
;
import
type
{
DuelState
}
from
"
./types
"
;
export
const
playMat
=
proxy
<
DuelState
>
({
export
const
playMat
=
proxy
<
DuelState
>
({
opMagics
:
{
opMagics
:
{
inner
:
Array
(
5
)
inner
:
Array
(
5
)
...
...
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