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
ae0cafb9
Commit
ae0cafb9
authored
Jan 01, 2023
by
Chunchi Che
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'feat/ui/grave' into 'main'
Feat/ui/grave See merge request
!59
parents
04463686
471d1f17
Changes
10
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
322 additions
and
38 deletions
+322
-38
src/reducers/duel/cemeretySlice.ts
src/reducers/duel/cemeretySlice.ts
+96
-0
src/reducers/duel/mod.ts
src/reducers/duel/mod.ts
+16
-0
src/reducers/duel/modalSlice.ts
src/reducers/duel/modalSlice.ts
+31
-0
src/reducers/duel/util.ts
src/reducers/duel/util.ts
+5
-0
src/service/duel/move.ts
src/service/duel/move.ts
+12
-0
src/service/duel/start.ts
src/service/duel/start.ts
+3
-0
src/ui/Duel/cardListModal.tsx
src/ui/Duel/cardListModal.tsx
+51
-0
src/ui/Duel/cardModal.tsx
src/ui/Duel/cardModal.tsx
+24
-26
src/ui/Duel/cemetery.tsx
src/ui/Duel/cemetery.tsx
+80
-12
src/ui/Duel/main.tsx
src/ui/Duel/main.tsx
+4
-0
No files found.
src/reducers/duel/cemeretySlice.ts
0 → 100644
View file @
ae0cafb9
import
{
judgeSelf
,
Cemetery
}
from
"
./util
"
;
import
{
PayloadAction
,
CaseReducer
,
createAsyncThunk
,
ActionReducerMapBuilder
,
}
from
"
@reduxjs/toolkit
"
;
import
{
DuelState
}
from
"
./mod
"
;
import
{
RootState
}
from
"
../../store
"
;
import
{
fetchCard
}
from
"
../../api/cards
"
;
export
interface
CemeteryState
{
cemetery
:
Cemetery
[];
}
// 初始化墓地状态
export
const
initCemeteryImpl
:
CaseReducer
<
DuelState
,
PayloadAction
<
number
>>
=
(
state
,
action
)
=>
{
const
player
=
action
.
payload
;
if
(
judgeSelf
(
player
,
state
))
{
state
.
meCemetery
=
{
cemetery
:
[]
};
}
else
{
state
.
opCemetery
=
{
cemetery
:
[]
};
}
};
// 增加墓地
export
const
fetchCemeteryMeta
=
createAsyncThunk
(
"
duel/fetchCemeteryMeta
"
,
async
(
param
:
{
controler
:
number
;
sequence
:
number
;
code
:
number
})
=>
{
const
code
=
param
.
code
;
const
meta
=
await
fetchCard
(
code
);
const
response
=
{
controler
:
param
.
controler
,
sequence
:
param
.
sequence
,
meta
,
};
return
response
;
}
);
export
const
cemeteryCase
=
(
builder
:
ActionReducerMapBuilder
<
DuelState
>
)
=>
{
builder
.
addCase
(
fetchCemeteryMeta
.
pending
,
(
state
,
action
)
=>
{
// Meta结果没返回之前先更新`ID`
const
controler
=
action
.
meta
.
arg
.
controler
;
const
sequence
=
action
.
meta
.
arg
.
sequence
;
const
code
=
action
.
meta
.
arg
.
code
;
const
meta
=
{
id
:
code
,
data
:
{},
text
:
{}
};
if
(
judgeSelf
(
controler
,
state
))
{
if
(
state
.
meCemetery
)
{
state
.
meCemetery
.
cemetery
.
push
({
sequence
,
meta
});
}
else
{
state
.
meCemetery
=
{
cemetery
:
[{
sequence
,
meta
}]
};
}
}
else
{
if
(
state
.
opCemetery
)
{
state
.
opCemetery
.
cemetery
.
push
({
sequence
,
meta
});
}
else
{
state
.
opCemetery
=
{
cemetery
:
[{
sequence
,
meta
}]
};
}
}
});
builder
.
addCase
(
fetchCemeteryMeta
.
fulfilled
,
(
state
,
action
)
=>
{
const
controler
=
action
.
payload
.
controler
;
const
sequence
=
action
.
payload
.
sequence
;
const
meta
=
action
.
payload
.
meta
;
if
(
judgeSelf
(
controler
,
state
))
{
if
(
state
.
meCemetery
)
{
for
(
const
cemetery
of
state
.
meCemetery
.
cemetery
)
{
if
(
cemetery
.
sequence
==
sequence
)
{
cemetery
.
meta
=
meta
;
}
}
}
}
else
{
if
(
state
.
opCemetery
)
{
for
(
const
cemetery
of
state
.
opCemetery
.
cemetery
)
{
if
(
cemetery
.
sequence
==
sequence
)
{
cemetery
.
meta
=
meta
;
}
}
}
}
});
};
export
const
selectMeCemetery
=
(
state
:
RootState
)
=>
state
.
duel
.
meCemetery
||
{
cemetery
:
[]
};
export
const
selectOpCemetery
=
(
state
:
RootState
)
=>
state
.
duel
.
opCemetery
||
{
cemetery
:
[]
};
src/reducers/duel/mod.ts
View file @
ae0cafb9
...
...
@@ -23,6 +23,8 @@ import {
setCardModalTextImpl
,
setCardModalImgUrlImpl
,
setCardModalInteractiviesImpl
,
setCardListModalIsOpenImpl
,
setCardListModalInfoImpl
,
}
from
"
./modalSlice
"
;
import
{
MonsterState
,
...
...
@@ -38,6 +40,7 @@ import {
clearMagicSelectInfoImpl
,
magicCase
,
}
from
"
./magicSlice
"
;
import
{
CemeteryState
,
initCemeteryImpl
,
cemeteryCase
}
from
"
./cemeretySlice
"
;
export
interface
DuelState
{
selfType
?:
number
;
...
...
@@ -53,6 +56,9 @@ export interface DuelState {
meMagics
?:
MagicState
;
// 自己的魔法陷阱区状态
opMagics
?:
MagicState
;
// 对手的魔法陷阱区状态
meCemetery
?:
CemeteryState
;
// 自己的墓地状态
opCemetery
?:
CemeteryState
;
// 对手的墓地状态
meTimeLimit
?:
TimeLimit
;
// 自己的计时
opTimeLimit
?:
TimeLimit
;
// 对手的计时
...
...
@@ -69,6 +75,7 @@ export interface DuelState {
const
initialState
:
DuelState
=
{
modalState
:
{
cardModal
:
{
isOpen
:
false
,
interactivies
:
[]
},
cardListModal
:
{
isOpen
:
false
,
list
:
[]
},
},
};
...
...
@@ -99,17 +106,23 @@ const duelSlice = createSlice({
addMagicPlaceSelectAble
:
addMagicPlaceSelectAbleImpl
,
clearMagicSelectInfo
:
clearMagicSelectInfoImpl
,
// 墓地相关`Reducer`
initCemetery
:
initCemeteryImpl
,
// UI相关`Reducer`
setCardModalIsOpen
:
setCardModalIsOpenImpl
,
setCardModalText
:
setCardModalTextImpl
,
setCardModalImgUrl
:
setCardModalImgUrlImpl
,
setCardModalInteractivies
:
setCardModalInteractiviesImpl
,
setCardListModalIsOpen
:
setCardListModalIsOpenImpl
,
setCardListModalInfo
:
setCardListModalInfoImpl
,
},
extraReducers
(
builder
)
{
handsCase
(
builder
);
hintCase
(
builder
);
monsterCase
(
builder
);
magicCase
(
builder
);
cemeteryCase
(
builder
);
},
});
...
...
@@ -132,6 +145,9 @@ export const {
addMagicPlaceSelectAble
,
clearMagicSelectInfo
,
removeHand
,
initCemetery
,
setCardListModalIsOpen
,
setCardListModalInfo
,
}
=
duelSlice
.
actions
;
export
const
selectDuelHsStart
=
(
state
:
RootState
)
=>
{
return
state
.
duel
.
meInitInfo
!=
null
;
...
...
src/reducers/duel/modalSlice.ts
View file @
ae0cafb9
...
...
@@ -11,6 +11,15 @@ export interface ModalState {
imgUrl
?:
string
;
interactivies
:
{
desc
:
string
;
response
:
number
}[];
};
// 卡牌列表弹窗
cardListModal
:
{
isOpen
:
boolean
;
list
:
{
name
?:
string
;
desc
?:
string
;
imgUrl
?:
string
;
}[];
};
}
// 更新卡牌弹窗打开状态
...
...
@@ -49,6 +58,24 @@ export const setCardModalInteractiviesImpl: CaseReducer<
state
.
modalState
.
cardModal
.
interactivies
=
action
.
payload
;
};
// 更新卡牌列表弹窗打开状态
export
const
setCardListModalIsOpenImpl
:
CaseReducer
<
DuelState
,
PayloadAction
<
boolean
>
>
=
(
state
,
action
)
=>
{
state
.
modalState
.
cardListModal
.
isOpen
=
action
.
payload
;
};
// 更新卡牌列表文本
export
const
setCardListModalInfoImpl
:
CaseReducer
<
DuelState
,
PayloadAction
<
{
name
?:
string
;
desc
?:
string
;
imgUrl
?:
string
}[]
>
>
=
(
state
,
action
)
=>
{
const
list
=
action
.
payload
;
state
.
modalState
.
cardListModal
.
list
=
list
;
};
export
const
selectCardModalIsOpen
=
(
state
:
RootState
)
=>
state
.
duel
.
modalState
.
cardModal
.
isOpen
;
export
const
selectCardModalName
=
(
state
:
RootState
)
=>
...
...
@@ -59,3 +86,7 @@ export const selectCardModalImgUrl = (state: RootState) =>
state
.
duel
.
modalState
.
cardModal
.
imgUrl
;
export
const
selectCardModalInteractivies
=
(
state
:
RootState
)
=>
state
.
duel
.
modalState
.
cardModal
.
interactivies
;
export
const
selectCardListModalIsOpen
=
(
state
:
RootState
)
=>
state
.
duel
.
modalState
.
cardListModal
.
isOpen
;
export
const
selectCardListModalInfo
=
(
state
:
RootState
)
=>
state
.
duel
.
modalState
.
cardListModal
.
list
;
src/reducers/duel/util.ts
View file @
ae0cafb9
...
...
@@ -69,3 +69,8 @@ export interface SlotState {
export
type
Monster
=
SlotState
;
export
type
Magic
=
SlotState
;
export
interface
Cemetery
{
sequence
:
number
;
meta
:
CardMeta
;
}
src/service/duel/move.ts
View file @
ae0cafb9
...
...
@@ -4,6 +4,7 @@ import { AppDispatch } from "../../store";
import
{
fetchMonsterMeta
}
from
"
../../reducers/duel/monstersSlice
"
;
import
{
removeHand
}
from
"
../../reducers/duel/mod
"
;
import
{
fetchMagicMeta
}
from
"
../../reducers/duel/magicSlice
"
;
import
{
fetchCemeteryMeta
}
from
"
../../reducers/duel/cemeretySlice
"
;
export
default
(
move
:
MsgMove
,
dispatch
:
AppDispatch
)
=>
{
const
code
=
move
.
code
;
...
...
@@ -48,6 +49,17 @@ export default (move: MsgMove, dispatch: AppDispatch) => {
break
;
}
case
ygopro
.
CardZone
.
GRAVE
:
{
dispatch
(
fetchCemeteryMeta
({
controler
:
to
.
controler
,
sequence
:
to
.
sequence
,
code
,
})
);
break
;
}
default
:
{
console
.
log
(
`Unhandled zone type
${
to
.
location
}
`
);
...
...
src/service/duel/start.ts
View file @
ae0cafb9
...
...
@@ -5,6 +5,7 @@ import {
setSelfType
,
initMonsters
,
initMagics
,
initCemetery
,
}
from
"
../../reducers/duel/mod
"
;
export
default
(
...
...
@@ -36,4 +37,6 @@ export default (
dispatch
(
initMonsters
(
1
));
dispatch
(
initMagics
(
0
));
dispatch
(
initMagics
(
1
));
dispatch
(
initCemetery
(
0
));
dispatch
(
initCemetery
(
1
));
};
src/ui/Duel/cardListModal.tsx
0 → 100644
View file @
ae0cafb9
import
React
from
"
react
"
;
import
{
useAppSelector
}
from
"
../../hook
"
;
import
{
store
}
from
"
../../store
"
;
import
{
selectCardListModalIsOpen
,
selectCardListModalInfo
,
}
from
"
../../reducers/duel/modalSlice
"
;
import
{
setCardListModalIsOpen
}
from
"
../../reducers/duel/mod
"
;
import
{
Modal
,
List
,
Popover
,
Card
}
from
"
antd
"
;
const
{
Meta
}
=
Card
;
const
CARD_WIDTH
=
100
;
const
CardListModal
=
()
=>
{
const
dispatch
=
store
.
dispatch
;
const
isOpen
=
useAppSelector
(
selectCardListModalIsOpen
);
const
list
=
useAppSelector
(
selectCardListModalInfo
);
const
handleOkOrCancel
=
()
=>
{
dispatch
(
setCardListModalIsOpen
(
false
));
};
return
(
<
Modal
open=
{
isOpen
}
onOk=
{
handleOkOrCancel
}
onCancel=
{
handleOkOrCancel
}
>
<
List
itemLayout=
"horizontal"
dataSource=
{
list
}
renderItem=
{
(
item
)
=>
(
<
Popover
content=
{
<
Card
hoverable
style=
{
{
width
:
CARD_WIDTH
}
}
cover=
{
<
img
alt=
{
item
.
name
}
src=
{
item
.
imgUrl
}
/>
}
>
<
Meta
title=
{
item
.
name
}
/>
<
p
>
{
item
.
desc
}
</
p
>
</
Card
>
}
>
<
List
.
Item
>
<
List
.
Item
.
Meta
title=
{
item
.
name
}
description=
{
item
.
desc
}
/>
</
List
.
Item
>
</
Popover
>
)
}
></
List
>
</
Modal
>
);
};
export
default
CardListModal
;
src/ui/Duel/cardModal.tsx
View file @
ae0cafb9
...
...
@@ -31,7 +31,6 @@ const CardModal = () => {
};
return
(
<>
<
Modal
open=
{
isOpen
}
onOk=
{
handleOkOrCancel
}
onCancel=
{
handleOkOrCancel
}
>
<
Card
hoverable
...
...
@@ -56,7 +55,6 @@ const CardModal = () => {
);
})
}
</
Modal
>
</>
);
};
...
...
src/ui/Duel/cemetery.tsx
View file @
ae0cafb9
import
*
as
BABYLON
from
"
@babylonjs/core
"
;
import
*
as
CONFIG
from
"
../../config/ui
"
;
import
{
Cemetery
}
from
"
../../reducers/duel/util
"
;
import
{
selectMeCemetery
,
selectOpCemetery
,
}
from
"
../../reducers/duel/cemeretySlice
"
;
import
{
store
}
from
"
../../store
"
;
import
{
useAppSelector
}
from
"
../../hook
"
;
import
{
useClick
}
from
"
./hook
"
;
import
{
useRef
}
from
"
react
"
;
import
{
setCardListModalInfo
,
setCardListModalIsOpen
,
}
from
"
../../reducers/duel/mod
"
;
const
Cemetery
=
()
=>
{
const
shape
=
CONFIG
.
CemeterySlotShape
();
const
position
=
new
BABYLON
.
Vector3
(
3.2
,
shape
.
depth
/
2
+
CONFIG
.
Floating
,
-
2.0
const
shape
=
CONFIG
.
CemeterySlotShape
();
const
depth
=
0.02
;
const
Cemeteries
=
()
=>
{
const
meCemetery
=
useAppSelector
(
selectMeCemetery
).
cemetery
;
const
opCemetery
=
useAppSelector
(
selectOpCemetery
).
cemetery
;
return
(
<>
<
CCemetery
state=
{
meCemetery
}
position=
{
cemeteryPosition
(
0
,
meCemetery
.
length
)
}
rotation=
{
CONFIG
.
CardSlotRotation
(
false
)
}
/>
<
CCemetery
state=
{
opCemetery
}
position=
{
cemeteryPosition
(
1
,
opCemetery
.
length
)
}
rotation=
{
CONFIG
.
CardSlotRotation
(
true
)
}
/>
</>
);
};
const
CCemetery
=
(
props
:
{
state
:
Cemetery
[];
position
:
BABYLON
.
Vector3
;
rotation
:
BABYLON
.
Vector3
;
})
=>
{
const
boxRef
=
useRef
(
null
);
const
dispatch
=
store
.
dispatch
;
useClick
(
(
_event
)
=>
{
if
(
props
.
state
.
length
!=
0
)
{
dispatch
(
setCardListModalInfo
(
props
.
state
.
map
((
cemetery
)
=>
{
return
{
name
:
cemetery
.
meta
.
text
.
name
,
desc
:
cemetery
.
meta
.
text
.
desc
,
imgUrl
:
`https://cdn02.moecube.com:444/images/ygopro-images-zh-CN/
${
cemetery
.
meta
.
id
}
.jpg`
,
};
})
)
);
dispatch
(
setCardListModalIsOpen
(
true
));
}
},
boxRef
,
[
props
.
state
]
);
const
rotation
=
CONFIG
.
CemeterySlotRotation
();
return
(
<
box
name=
"cemetery"
ref=
{
boxRef
}
width=
{
shape
.
width
}
height=
{
shape
.
height
}
depth=
{
shape
.
dep
th
}
position=
{
position
}
rotation=
{
rotation
}
depth=
{
depth
*
props
.
state
.
leng
th
}
position=
{
p
rops
.
p
osition
}
rotation=
{
props
.
rotation
}
>
<
standardMaterial
name=
"cemetery-mat"
diffuseColor=
{
CONFIG
.
CemeteryColor
()
}
diffuseTexture=
{
new
BABYLON
.
Texture
(
`http://localhost:3030/images/card_back.jpg`
)
}
alpha=
{
props
.
state
.
length
==
0
?
0
:
1
}
/>
</
box
>
);
};
export
default
Cemetery
;
const
cemeteryPosition
=
(
player
:
number
,
cemeteryLength
:
number
)
=>
{
const
x
=
player
==
0
?
3.2
:
-
3.2
;
const
y
=
(
depth
*
cemeteryLength
)
/
2
+
CONFIG
.
Floating
;
const
z
=
player
==
0
?
-
2.0
:
2.0
;
return
new
BABYLON
.
Vector3
(
x
,
y
,
z
);
};
export
default
Cemeteries
;
src/ui/Duel/main.tsx
View file @
ae0cafb9
...
...
@@ -11,6 +11,8 @@ import Magics from "./magics";
import
Field
from
"
./field
"
;
import
Deck
from
"
./deck
"
;
import
Exclusion
from
"
./exclusion
"
;
import
Cemeteries
from
"
./cemetery
"
;
import
CardListModal
from
"
./cardListModal
"
;
// Ref: https://github.com/brianzinn/react-babylonjs/issues/126
const
NeosDuel
=
()
=>
(
...
...
@@ -27,6 +29,7 @@ const NeosDuel = () => (
<
Magics
/>
<
Field
/>
<
Deck
/>
<
Cemeteries
/>
<
Exclusion
/>
<
Ground
/>
</
Provider
>
...
...
@@ -35,6 +38,7 @@ const NeosDuel = () => (
)
}
</
ReactReduxContext
.
Consumer
>
<
CardModal
/>
<
CardListModal
/>
<
HintNotification
/>
</>
);
...
...
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