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
0b6eeba7
Commit
0b6eeba7
authored
Nov 26, 2022
by
Chunchi Che
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'feat/cards/service' into 'main'
Feat/cards/service See merge request
!21
parents
8afb47b7
8723b7d8
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
66 additions
and
100 deletions
+66
-100
src/api/cards.ts
src/api/cards.ts
+2
-2
src/reducers/cardsSlice.ts
src/reducers/cardsSlice.ts
+0
-47
src/reducers/duel/handsSlice.ts
src/reducers/duel/handsSlice.ts
+41
-6
src/reducers/duel/mod.ts
src/reducers/duel/mod.ts
+9
-1
src/service/duel/draw.ts
src/service/duel/draw.ts
+2
-0
src/store.ts
src/store.ts
+0
-2
src/ui/Duel/data.ts
src/ui/Duel/data.ts
+0
-8
src/ui/Duel/duel.ts
src/ui/Duel/duel.ts
+2
-2
src/ui/Duel/main.tsx
src/ui/Duel/main.tsx
+1
-5
src/ui/Duel/simpleDuel/hands.ts
src/ui/Duel/simpleDuel/hands.ts
+3
-10
src/ui/Duel/simpleDuel/mod.tsx
src/ui/Duel/simpleDuel/mod.tsx
+6
-17
No files found.
src/api/cards.ts
View file @
0b6eeba7
...
@@ -5,7 +5,7 @@ export interface CardMeta {
...
@@ -5,7 +5,7 @@ export interface CardMeta {
data
:
{
data
:
{
ot
?:
number
;
ot
?:
number
;
setcode
?:
number
;
setcode
?:
number
;
type
?:
number
;
type
_
?:
number
;
atk
?:
number
;
atk
?:
number
;
def
?:
number
;
def
?:
number
;
level
?:
number
;
level
?:
number
;
...
@@ -27,7 +27,7 @@ export interface CardMeta {
...
@@ -27,7 +27,7 @@ export interface CardMeta {
*
*
* */
* */
export
async
function
fetchCard
(
id
:
number
):
Promise
<
CardMeta
>
{
export
async
function
fetchCard
(
id
:
number
):
Promise
<
CardMeta
>
{
const
res
=
await
axios
.
get
<
CardMeta
>
(
"
http
s://ygocdb.com/api/v0/card
/
"
+
id
);
const
res
=
await
axios
.
get
<
CardMeta
>
(
"
http
://localhost:3030/cards
/
"
+
id
);
return
res
.
data
;
return
res
.
data
;
}
}
src/reducers/cardsSlice.ts
deleted
100644 → 0
View file @
8afb47b7
/*
* 卡牌数据存储
*
* */
import
{
createSlice
,
createAsyncThunk
}
from
"
@reduxjs/toolkit
"
;
import
{
CardMeta
,
fetchCard
}
from
"
../api/cards
"
;
import
{
RootState
}
from
"
../store
"
;
export
const
fetchCardMetaById
=
createAsyncThunk
(
"
cards/fetchByIdStatus
"
,
async
(
cardId
:
number
)
=>
{
return
await
fetchCard
(
cardId
);
}
);
export
interface
Card
{
meta
?:
CardMeta
;
state
:
string
;
}
export
interface
CardMetaState
{
metas
:
Map
<
number
,
Card
>
;
}
const
initialState
:
CardMetaState
=
{
metas
:
new
Map
(),
};
const
cardsSlice
=
createSlice
({
name
:
"
cards
"
,
initialState
,
reducers
:
{},
extraReducers
:
(
builder
)
=>
{
builder
.
addCase
(
fetchCardMetaById
.
fulfilled
,
(
state
,
action
)
=>
{
const
id
=
action
.
payload
.
id
;
const
card
=
{
meta
:
action
.
payload
,
state
:
"
filled
"
,
};
state
.
metas
.
set
(
id
,
card
);
});
// TODO: handle pending and rejected
},
});
export
const
selectCards
=
(
state
:
RootState
)
=>
state
.
cards
.
metas
;
export
default
cardsSlice
.
reducer
;
src/reducers/duel/handsSlice.ts
View file @
0b6eeba7
import
{
PayloadAction
,
CaseReducer
}
from
"
@reduxjs/toolkit
"
;
import
{
PayloadAction
,
CaseReducer
,
createAsyncThunk
,
ActionReducerMapBuilder
,
}
from
"
@reduxjs/toolkit
"
;
import
{
DuelState
}
from
"
./mod
"
;
import
{
DuelState
}
from
"
./mod
"
;
import
{
RootState
}
from
"
../../store
"
;
import
{
RootState
}
from
"
../../store
"
;
import
{
CardMeta
,
fetchCard
}
from
"
../../api/cards
"
;
export
interface
Hands
{
export
interface
Hands
{
cards
:
number
[];
// TODO: use Card struct Unitly
cards
:
CardMeta
[];
}
}
// 自己增加手牌
// 自己增加手牌
...
@@ -11,10 +17,13 @@ export const meAddHandsImpl: CaseReducer<DuelState, PayloadAction<number[]>> = (
...
@@ -11,10 +17,13 @@ export const meAddHandsImpl: CaseReducer<DuelState, PayloadAction<number[]>> = (
state
,
state
,
action
action
)
=>
{
)
=>
{
const
cards
=
action
.
payload
.
map
((
id
)
=>
{
return
{
id
,
data
:
{},
text
:
{}
};
});
if
(
state
.
meHands
)
{
if
(
state
.
meHands
)
{
state
.
meHands
.
cards
=
state
.
meHands
.
cards
.
concat
(
action
.
payload
);
state
.
meHands
.
cards
=
state
.
meHands
.
cards
.
concat
(
cards
);
}
else
{
}
else
{
state
.
meHands
=
{
cards
:
action
.
payload
};
state
.
meHands
=
{
cards
};
}
}
};
};
...
@@ -23,13 +32,39 @@ export const opAddHandsImpl: CaseReducer<DuelState, PayloadAction<number[]>> = (
...
@@ -23,13 +32,39 @@ export const opAddHandsImpl: CaseReducer<DuelState, PayloadAction<number[]>> = (
state
,
state
,
action
action
)
=>
{
)
=>
{
const
cards
=
action
.
payload
.
map
((
id
)
=>
{
return
{
id
,
data
:
{},
text
:
{}
};
});
if
(
state
.
opHands
)
{
if
(
state
.
opHands
)
{
state
.
opHands
.
cards
=
state
.
opHands
.
cards
.
concat
(
action
.
payload
);
state
.
opHands
.
cards
=
state
.
opHands
.
cards
.
concat
(
cards
);
}
else
{
}
else
{
state
.
opHands
=
{
cards
:
action
.
payload
};
state
.
opHands
=
{
cards
};
}
}
};
};
export
const
fetchMeHandsMeta
=
createAsyncThunk
(
"
duel/fetchMeHandsMeta
"
,
async
(
Ids
:
number
[])
=>
{
return
await
Promise
.
all
(
Ids
.
map
(
async
(
id
)
=>
{
return
await
fetchCard
(
id
);
})
);
}
);
export
const
meHandsCase
=
(
builder
:
ActionReducerMapBuilder
<
DuelState
>
)
=>
{
builder
.
addCase
(
fetchMeHandsMeta
.
fulfilled
,
(
state
,
action
)
=>
{
// TODO: 合法性校验
const
cards
=
action
.
payload
;
if
(
state
.
meHands
)
{
state
.
meHands
.
cards
=
cards
;
}
else
{
state
.
meHands
=
{
cards
};
}
});
};
export
const
selectMeHands
=
(
state
:
RootState
)
=>
export
const
selectMeHands
=
(
state
:
RootState
)
=>
state
.
duel
.
meHands
||
{
cards
:
[]
};
state
.
duel
.
meHands
||
{
cards
:
[]
};
export
const
selectOpHands
=
(
state
:
RootState
)
=>
export
const
selectOpHands
=
(
state
:
RootState
)
=>
...
...
src/reducers/duel/mod.ts
View file @
0b6eeba7
...
@@ -5,7 +5,12 @@
...
@@ -5,7 +5,12 @@
import
{
createSlice
}
from
"
@reduxjs/toolkit
"
;
import
{
createSlice
}
from
"
@reduxjs/toolkit
"
;
import
{
InitInfo
,
meInfoInitImpl
,
opInfoInitImpl
}
from
"
./initInfoSlice
"
;
import
{
InitInfo
,
meInfoInitImpl
,
opInfoInitImpl
}
from
"
./initInfoSlice
"
;
import
{
Hands
,
meAddHandsImpl
,
opAddHandsImpl
}
from
"
./handsSlice
"
;
import
{
Hands
,
meAddHandsImpl
,
opAddHandsImpl
,
meHandsCase
,
}
from
"
./handsSlice
"
;
import
{
RootState
}
from
"
../../store
"
;
import
{
RootState
}
from
"
../../store
"
;
export
interface
DuelState
{
export
interface
DuelState
{
...
@@ -26,6 +31,9 @@ const duelSlice = createSlice({
...
@@ -26,6 +31,9 @@ const duelSlice = createSlice({
meAddHands
:
meAddHandsImpl
,
meAddHands
:
meAddHandsImpl
,
opAddHands
:
opAddHandsImpl
,
opAddHands
:
opAddHandsImpl
,
},
},
extraReducers
(
builder
)
{
meHandsCase
(
builder
);
},
});
});
export
const
{
meInfoInit
,
opInfoInit
,
meAddHands
,
opAddHands
}
=
export
const
{
meInfoInit
,
opInfoInit
,
meAddHands
,
opAddHands
}
=
...
...
src/service/duel/draw.ts
View file @
0b6eeba7
import
{
ygopro
}
from
"
../../api/ocgcore/idl/ocgcore
"
;
import
{
ygopro
}
from
"
../../api/ocgcore/idl/ocgcore
"
;
import
{
AppDispatch
}
from
"
../../store
"
;
import
{
AppDispatch
}
from
"
../../store
"
;
import
{
meAddHands
,
opAddHands
}
from
"
../../reducers/duel/mod
"
;
import
{
meAddHands
,
opAddHands
}
from
"
../../reducers/duel/mod
"
;
import
{
fetchMeHandsMeta
}
from
"
../../reducers/duel/handsSlice
"
;
export
default
(
export
default
(
draw
:
ygopro
.
StocGameMessage
.
MsgDraw
,
draw
:
ygopro
.
StocGameMessage
.
MsgDraw
,
...
@@ -9,6 +10,7 @@ export default (
...
@@ -9,6 +10,7 @@ export default (
// FIXME: draw.player 和先后攻有关系
// FIXME: draw.player 和先后攻有关系
if
(
draw
.
player
===
0
)
{
if
(
draw
.
player
===
0
)
{
dispatch
(
meAddHands
(
draw
.
cards
));
dispatch
(
meAddHands
(
draw
.
cards
));
dispatch
(
fetchMeHandsMeta
(
draw
.
cards
));
}
else
if
(
draw
.
player
===
1
)
{
}
else
if
(
draw
.
player
===
1
)
{
dispatch
(
opAddHands
(
draw
.
cards
));
dispatch
(
opAddHands
(
draw
.
cards
));
}
else
{
}
else
{
...
...
src/store.ts
View file @
0b6eeba7
...
@@ -7,7 +7,6 @@ import chatReducer from "./reducers/chatSlice";
...
@@ -7,7 +7,6 @@ import chatReducer from "./reducers/chatSlice";
import
playerReducer
from
"
./reducers/playerSlice
"
;
import
playerReducer
from
"
./reducers/playerSlice
"
;
import
moraReducer
from
"
./reducers/moraSlice
"
;
import
moraReducer
from
"
./reducers/moraSlice
"
;
import
duelReducer
from
"
./reducers/duel/mod
"
;
import
duelReducer
from
"
./reducers/duel/mod
"
;
import
cardsReducer
from
"
./reducers/cardsSlice
"
;
export
const
store
=
configureStore
({
export
const
store
=
configureStore
({
reducer
:
{
reducer
:
{
...
@@ -16,7 +15,6 @@ export const store = configureStore({
...
@@ -16,7 +15,6 @@ export const store = configureStore({
player
:
playerReducer
,
player
:
playerReducer
,
mora
:
moraReducer
,
mora
:
moraReducer
,
duel
:
duelReducer
,
duel
:
duelReducer
,
cards
:
cardsReducer
,
},
},
});
});
...
...
src/ui/Duel/data.ts
deleted
100644 → 0
View file @
8afb47b7
/*
* 决斗界面渲染需要的数据结构
*
* */
export
interface
Hand
{
code
:
number
;
// Currently only code
}
src/ui/Duel/duel.ts
View file @
0b6eeba7
...
@@ -14,9 +14,9 @@
...
@@ -14,9 +14,9 @@
*
*
* */
* */
import
*
as
DuelData
from
"
./data
"
;
import
React
from
"
react
"
;
import
React
from
"
react
"
;
import
type
{
RootState
}
from
"
../../store
"
;
import
type
{
RootState
}
from
"
../../store
"
;
import
{
CardMeta
}
from
"
../../api/cards
"
;
/*
/*
* 通用的决斗界面抽象接口
* 通用的决斗界面抽象接口
...
@@ -26,7 +26,7 @@ export interface IDuelPlate {
...
@@ -26,7 +26,7 @@ export interface IDuelPlate {
// 渲染接口,返回一个React组件
// 渲染接口,返回一个React组件
render
():
React
.
ReactElement
;
render
():
React
.
ReactElement
;
// 注册手牌selector
// 注册手牌selector
registerHands
(
selector
:
TypeSelector
<
DuelData
.
Hand
[]
>
):
void
;
registerHands
(
selector
:
TypeSelector
<
CardMeta
[]
>
):
void
;
}
}
export
interface
TypeSelector
<
T
>
{
export
interface
TypeSelector
<
T
>
{
...
...
src/ui/Duel/main.tsx
View file @
0b6eeba7
...
@@ -12,11 +12,7 @@ export default function Duel() {
...
@@ -12,11 +12,7 @@ export default function Duel() {
// TODO: opHands
// TODO: opHands
const
handsSelector
=
(
state
:
RootState
)
=>
{
const
handsSelector
=
(
state
:
RootState
)
=>
{
const
cards
=
selectMeHands
(
state
).
cards
;
return
selectMeHands
(
state
).
cards
;
return
cards
.
map
((
item
)
=>
{
return
{
code
:
item
};
});
};
};
simpleDuelPlate
.
registerHands
(
handsSelector
);
simpleDuelPlate
.
registerHands
(
handsSelector
);
...
...
src/ui/Duel/simpleDuel/hands.ts
View file @
0b6eeba7
import
{
Hand
}
from
"
../data
"
;
import
*
as
BABYLON
from
"
@babylonjs/core
"
;
import
*
as
BABYLON
from
"
@babylonjs/core
"
;
import
*
as
CONFIG
from
"
./config
"
;
import
*
as
CONFIG
from
"
./config
"
;
import
{
Card
}
from
"
../../../reducers/cardsSlice
"
;
import
{
Card
Meta
}
from
"
../../../api/cards
"
;
export
default
(
export
default
(
hands
:
CardMeta
[],
scene
:
BABYLON
.
Scene
)
=>
{
hands
:
Hand
[],
cardMetas
:
Map
<
number
,
Card
>
,
scene
:
BABYLON
.
Scene
)
=>
{
const
groundShape
=
CONFIG
.
GroundShape
();
const
groundShape
=
CONFIG
.
GroundShape
();
const
handShape
=
CONFIG
.
HandShape
();
const
handShape
=
CONFIG
.
HandShape
();
const
gap
=
groundShape
.
width
/
hands
.
length
;
const
gap
=
groundShape
.
width
/
hands
.
length
;
...
@@ -36,9 +31,7 @@ export default (
...
@@ -36,9 +31,7 @@ export default (
new
BABYLON
.
ExecuteCodeAction
(
new
BABYLON
.
ExecuteCodeAction
(
BABYLON
.
ActionManager
.
OnPickTrigger
,
BABYLON
.
ActionManager
.
OnPickTrigger
,
(
event
)
=>
{
(
event
)
=>
{
const
meta
=
cardMetas
.
get
(
item
.
code
);
console
.
log
(
`<Click>hand:
${
idx
}
`
,
"
card:
"
,
item
,
"
event:
"
,
event
);
console
.
log
(
`<Click>hand:
${
idx
}
`
,
"
card:
"
,
meta
,
"
event:
"
,
event
);
}
}
)
)
);
);
...
...
src/ui/Duel/simpleDuel/mod.tsx
View file @
0b6eeba7
...
@@ -4,7 +4,6 @@
...
@@ -4,7 +4,6 @@
* */
* */
import
{
IDuelPlate
,
TypeSelector
}
from
"
../duel
"
;
import
{
IDuelPlate
,
TypeSelector
}
from
"
../duel
"
;
import
*
as
DuelData
from
"
../data
"
;
import
{
useAppSelector
}
from
"
../../../hook
"
;
import
{
useAppSelector
}
from
"
../../../hook
"
;
import
React
,
{
useEffect
,
useRef
}
from
"
react
"
;
import
React
,
{
useEffect
,
useRef
}
from
"
react
"
;
import
type
{
RootState
}
from
"
../../../store
"
;
import
type
{
RootState
}
from
"
../../../store
"
;
...
@@ -14,34 +13,24 @@ import renderMonsters from "./monsters";
...
@@ -14,34 +13,24 @@ import renderMonsters from "./monsters";
import
renderExtraMonsters
from
"
./extraMonsters
"
;
import
renderExtraMonsters
from
"
./extraMonsters
"
;
import
renderMagics
from
"
./magics
"
;
import
renderMagics
from
"
./magics
"
;
import
*
as
CONFIG
from
"
./config
"
;
import
*
as
CONFIG
from
"
./config
"
;
import
{
fetchCardMetaById
}
from
"
../../../reducers/cardsSlice
"
;
import
{
CardMeta
}
from
"
../../../api/cards
"
;
import
{
store
}
from
"
../../../store
"
;
import
{
selectCards
}
from
"
../../../reducers/cardsSlice
"
;
// CONFIG
// CONFIG
export
default
class
SimpleDuelPlateImpl
implements
IDuelPlate
{
export
default
class
SimpleDuelPlateImpl
implements
IDuelPlate
{
handsSelector
?:
TypeSelector
<
DuelData
.
Hand
[]
>
;
handsSelector
?:
TypeSelector
<
CardMeta
[]
>
;
constructor
()
{}
constructor
()
{}
render
():
React
.
ReactElement
{
render
():
React
.
ReactElement
{
const
dispatch
=
store
.
dispatch
;
// ----- 数据获取 -----
// ----- 数据获取 -----
// 默认的手牌Selector,返回五个code为-1的Card。
// 默认的手牌Selector,返回五个code为-1的Card。
const
defaultHandsSelector
=
(
_
:
RootState
)
=>
{
const
defaultHandsSelector
=
(
_
:
RootState
)
=>
{
return
new
Array
(
5
).
fill
({
code
:
-
1
})
;
return
[]
;
};
};
const
hands
=
useAppSelector
(
this
.
handsSelector
||
defaultHandsSelector
);
const
hands
=
useAppSelector
(
this
.
handsSelector
||
defaultHandsSelector
);
// TODO: 这里应该思考更合理的处理方式
hands
.
forEach
((
item
)
=>
{
dispatch
(
fetchCardMetaById
(
item
.
code
));
});
const
cardMetas
=
useAppSelector
(
selectCards
);
// ----- WebGL渲染 -----
// ----- WebGL渲染 -----
const
canvasRef
=
useRef
<
HTMLCanvasElement
>
(
null
);
const
canvasRef
=
useRef
<
HTMLCanvasElement
>
(
null
);
...
@@ -77,7 +66,7 @@ export default class SimpleDuelPlateImpl implements IDuelPlate {
...
@@ -77,7 +66,7 @@ export default class SimpleDuelPlateImpl implements IDuelPlate {
renderExtraMonsters
(
scene
);
renderExtraMonsters
(
scene
);
// 创建手牌
// 创建手牌
renderHands
(
hands
,
cardMetas
,
scene
);
renderHands
(
hands
,
scene
);
// 创建地板
// 创建地板
const
ground
=
BABYLON
.
MeshBuilder
.
CreateGround
(
const
ground
=
BABYLON
.
MeshBuilder
.
CreateGround
(
...
@@ -90,7 +79,7 @@ export default class SimpleDuelPlateImpl implements IDuelPlate {
...
@@ -90,7 +79,7 @@ export default class SimpleDuelPlateImpl implements IDuelPlate {
engine
.
runRenderLoop
(()
=>
{
engine
.
runRenderLoop
(()
=>
{
scene
.
render
();
scene
.
render
();
});
});
},
[
canvasRef
,
hands
,
cardMetas
]);
},
[
canvasRef
,
hands
]);
return
(
return
(
<
canvas
<
canvas
...
@@ -101,7 +90,7 @@ export default class SimpleDuelPlateImpl implements IDuelPlate {
...
@@ -101,7 +90,7 @@ export default class SimpleDuelPlateImpl implements IDuelPlate {
);
);
}
}
registerHands
(
selector
:
TypeSelector
<
DuelData
.
Hand
[]
>
):
void
{
registerHands
(
selector
:
TypeSelector
<
CardMeta
[]
>
):
void
{
this
.
handsSelector
=
selector
;
this
.
handsSelector
=
selector
;
}
}
}
}
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