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
baichixing
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
type
{
DuelState
}
from
"
./types
"
;
import
{
ygopro
}
from
"
@/api/ocgcore/idl/ocgcore
"
;
import
type
{
DuelState
}
from
"
./types
"
;
export
const
playMat
=
proxy
<
DuelState
>
({
opMagics
:
{
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