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
1
Issues
1
List
Boards
Labels
Service Desk
Milestones
Merge Requests
2
Merge Requests
2
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
MyCard
Neos
Commits
5226ac18
Commit
5226ac18
authored
Apr 06, 2023
by
timel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: auto mode
parent
d43799ce
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
97 additions
and
21 deletions
+97
-21
src/hook/index.ts
src/hook/index.ts
+2
-0
src/hook/useApp.ts
src/hook/useApp.ts
+1
-1
src/hook/useAutoMode.ts
src/hook/useAutoMode.ts
+38
-0
src/ui/Login.tsx
src/ui/Login.tsx
+15
-7
src/ui/Mora.tsx
src/ui/Mora.tsx
+15
-1
src/ui/WaitRoom.tsx
src/ui/WaitRoom.tsx
+26
-12
No files found.
src/hook/index.ts
0 → 100644
View file @
5226ac18
export
*
from
"
./useApp
"
;
export
*
from
"
./useAutoMode
"
;
src/hook.ts
→
src/hook
/useApp
.ts
View file @
5226ac18
import
{
TypedUseSelectorHook
,
useDispatch
,
useSelector
}
from
"
react-redux
"
;
import
type
{
RootState
,
AppDispatch
}
from
"
./store
"
;
import
type
{
RootState
,
AppDispatch
}
from
"
.
.
/store
"
;
// Use throughout your app instead of plain `useDispatch` and `useSelector`
export
const
useAppDispatch
:
()
=>
AppDispatch
=
useDispatch
;
...
...
src/hook/useAutoMode.ts
0 → 100644
View file @
5226ac18
/*
* 旨在跳过登录界面,直接进入游戏(和AI对战、后续可能增加自动的PVP)。
* 仅在开发环境下生效,便于开发者快速调节决斗界面。
*/
interface
AutoModeConfig
{
defaultPlayer
?:
string
;
defaultDeck
?:
string
;
defaultPassword
?:
string
;
defaultMora
?:
string
;
isAiMode
?:
boolean
;
isAiFirst
?:
boolean
;
}
const
autoModeConfig
:
AutoModeConfig
=
{
defaultPlayer
:
""
,
defaultDeck
:
""
,
defaultPassword
:
""
,
};
const
aiModeConfig
:
AutoModeConfig
=
{
defaultPlayer
:
"
AiKiller
"
,
defaultDeck
:
import
.
meta
.
env
.
VITE_AI_MODE_DEFAULT_DECK
??
"
hero
"
,
defaultPassword
:
"
AI
"
,
defaultMora
:
"
scissors
"
,
isAiMode
:
true
,
isAiFirst
:
import
.
meta
.
env
.
VITE_IS_AI_FIRST
===
"
true
"
,
};
export
function
useAutoMode
():
AutoModeConfig
{
if
(
!
import
.
meta
.
env
.
DEV
)
return
{};
if
(
import
.
meta
.
env
.
VITE_IS_AI_MODE
===
"
true
"
)
{
return
aiModeConfig
;
}
return
autoModeConfig
;
}
src/ui/Login.tsx
View file @
5226ac18
...
...
@@ -7,16 +7,18 @@
*
* */
import
{
Input
}
from
"
antd
"
;
import
React
,
{
useState
,
ChangeEvent
}
from
"
react
"
;
import
React
,
{
useState
,
ChangeEvent
,
useEffect
}
from
"
react
"
;
import
{
useNavigate
}
from
"
react-router-dom
"
;
import
"
../styles/core.scss
"
;
import
NeosConfig
from
"
../../neos.config.json
"
;
import
{
useAutoMode
}
from
"
../hook
"
;
const
serverConfig
=
NeosConfig
.
servers
;
const
{
isAiMode
,
defaultPlayer
,
defaultPassword
}
=
useAutoMode
();
export
default
function
Login
()
{
const
[
player
,
setPlayer
]
=
useState
(
""
);
const
[
passWd
,
setPasswd
]
=
useState
(
""
);
const
[
player
,
setPlayer
]
=
useState
(
isAiMode
?
defaultPlayer
:
""
);
const
[
passWd
,
setPasswd
]
=
useState
(
isAiMode
?
defaultPassword
:
""
);
const
[
ip
,
setIp
]
=
useState
(
`
${
serverConfig
[
0
].
ip
}
:
${
serverConfig
[
0
].
port
}
`
);
const
navigate
=
useNavigate
();
...
...
@@ -30,13 +32,19 @@ export default function Login() {
setIp
(
event
.
target
.
value
);
};
const
handleSubmit
=
()
=>
navigate
(
`/room/
${
player
}
/
${
passWd
}
/
${
ip
}
`
);
useEffect
(()
=>
{
// 如果开启了AI模式,直接进入房间
if
(
isAiMode
)
{
handleSubmit
();
}
},
[]);
return
(
<
div
className=
"container"
>
<
div
id=
"login"
>
<
form
className=
"login-form"
onSubmit=
{
()
=>
navigate
(
`/room/${player}/${passWd}/${ip}`
)
}
>
<
form
className=
"login-form"
onSubmit=
{
handleSubmit
}
>
<
span
className=
"fa fa-user"
></
span
>
<
Input
autoFocus
...
...
src/ui/Mora.tsx
View file @
5226ac18
import
React
from
"
react
"
;
import
{
sendHandResult
,
sendTpResult
}
from
"
../api/ocgcore/ocgHelper
"
;
import
{
useAppSelector
}
from
"
../hook
"
;
import
{
useAppSelector
,
useAutoMode
}
from
"
../hook
"
;
import
{
selectHandSelectAble
,
unSelectHandAble
,
...
...
@@ -18,6 +18,8 @@ import {
TableOutlined
,
}
from
"
@ant-design/icons
"
;
const
{
isAiMode
,
isAiFirst
,
defaultMora
}
=
useAutoMode
();
const
Mora
=
()
=>
{
const
dispatch
=
store
.
dispatch
;
const
selectHandAble
=
useAppSelector
(
selectHandSelectAble
);
...
...
@@ -37,6 +39,18 @@ const Mora = () => {
}
},
[
duelHsStart
]);
useEffect
(()
=>
{
if
(
isAiMode
)
{
handleSelectMora
(
defaultMora
!
);
}
},
[
selectHandAble
]);
useEffect
(()
=>
{
if
(
isAiMode
&&
!
selectHandAble
&&
selectTpAble
)
{
handleSelectTp
(
!
isAiFirst
);
}
},
[
selectHandAble
,
selectTpAble
]);
const
handleSelectMora
=
(
selected
:
string
)
=>
{
sendHandResult
(
selected
);
dispatch
(
unSelectHandAble
());
...
...
src/ui/WaitRoom.tsx
View file @
5226ac18
...
...
@@ -19,7 +19,7 @@ import {
selectPlayer0
,
selectPlayer1
,
}
from
"
../reducers/playerSlice
"
;
import
{
useAppSelector
}
from
"
../hook
"
;
import
{
useAppSelector
,
useAutoMode
}
from
"
../hook
"
;
import
{
selectJoined
}
from
"
../reducers/joinSlice
"
;
import
{
selectChat
}
from
"
../reducers/chatSlice
"
;
import
{
fetchDeck
,
IDeck
}
from
"
../api/deck
"
;
...
...
@@ -50,6 +50,8 @@ import { initStrings } from "../api/strings";
const
READY_STATE
=
"
ready
"
;
const
{
isAiMode
,
defaultDeck
}
=
useAutoMode
();
const
WaitRoom
=
()
=>
{
const
params
=
useParams
<
{
player
?:
string
;
...
...
@@ -90,7 +92,20 @@ const WaitRoom = () => {
await
rustInit
(
url
);
};
init
();
/** 如果是开发者模式下的人机对战,应该自动选择卡组,并自动准备和开始 */
const
runAiMode
=
async
()
=>
{
await
new
Promise
((
resolve
)
=>
setTimeout
(
resolve
,
500
));
await
handleChoseDeck
(
defaultDeck
!
);
handleChoseReady
();
handleChoseStart
();
};
(
async
()
=>
{
await
init
();
if
(
isAiMode
)
{
await
runAiMode
();
}
})();
}
},
[]);
...
...
@@ -103,12 +118,14 @@ const WaitRoom = () => {
const
duelStart
=
useAppSelector
(
selectDuelStart
);
const
[
api
,
contextHolder
]
=
notification
.
useNotification
();
const
[
deckTitle
,
setDeckTitle
]
=
useState
(
"
请选择卡组
"
);
// FIXME: 这些数据应该从`store`中获取
// TODO: 云卡组
const
DEFAULT_DECK
=
"
hero
"
;
const
decks
:
MenuProps
[
"
items
"
]
=
[
{
label
:
"
hero
"
,
key
:
"
hero
"
,
label
:
DEFAULT_DECK
,
key
:
DEFAULT_DECK
,
},
];
const
[
uploadState
,
setUploadState
]
=
useState
(
""
);
...
...
@@ -145,9 +162,9 @@ const WaitRoom = () => {
},
};
const
onDeckReady
=
(
deck
:
IDeck
)
=>
{
const
onDeckReady
=
async
(
deck
:
IDeck
)
=>
{
sendUpdateDeck
(
deck
);
dispatch
(
await
dispatch
(
initMeExtraDeckMeta
({
controler
:
0
,
codes
:
deck
.
extra
?.
reverse
()
||
[]
})
);
setChoseDeck
(
true
);
...
...
@@ -155,8 +172,8 @@ const WaitRoom = () => {
const
handleChoseDeck
=
async
(
deckName
:
string
)
=>
{
const
deck
=
await
fetchDeck
(
deckName
);
onDeckReady
(
deck
);
await
onDeckReady
(
deck
);
setDeckTitle
(
deckName
);
};
const
handleChoseReady
=
()
=>
{
...
...
@@ -263,10 +280,7 @@ const WaitRoom = () => {
<
Dropdown
menu=
{
{
items
:
decks
,
onClick
:
async
({
key
})
=>
{
await
handleChoseDeck
(
key
);
setDeckTitle
(
key
);
},
onClick
:
({
key
})
=>
handleChoseDeck
(
key
),
}
}
>
<
a
onClick=
{
(
e
)
=>
e
.
preventDefault
()
}
>
...
...
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