Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
S
srvpro2
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
nanahira
srvpro2
Commits
1f674096
Commit
1f674096
authored
Feb 13, 2026
by
nanahira
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
firstgo
parent
9efdf131
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
215 additions
and
1 deletion
+215
-1
src/room/room.ts
src/room/room.ts
+215
-1
No files found.
src/room/room.ts
View file @
1f674096
...
@@ -5,8 +5,17 @@ import {
...
@@ -5,8 +5,17 @@ import {
NetPlayerType
,
NetPlayerType
,
PlayerChangeState
,
PlayerChangeState
,
YGOProStocDuelStart
,
YGOProStocDuelStart
,
YGOProStocHsPlayerChange
,
YGOProStocHsWatchChange
,
YGOProStocHsWatchChange
,
YGOProStocJoinGame
,
YGOProStocJoinGame
,
YGOProCtosHsToObserver
,
YGOProCtosHsToDuelist
,
YGOProCtosKick
,
YGOProCtosHsNotReady
,
YGOProStocDeckCount
,
YGOProStocDeckCount_DeckInfo
,
YGOProStocSelectTp
,
YGOProStocSelectHand
,
}
from
'
ygopro-msg-encode
'
;
}
from
'
ygopro-msg-encode
'
;
import
{
DefaultHostInfoProvider
}
from
'
./default-hostinfo-provder
'
;
import
{
DefaultHostInfoProvider
}
from
'
./default-hostinfo-provder
'
;
import
{
CardReaderFinalized
}
from
'
koishipro-core.js
'
;
import
{
CardReaderFinalized
}
from
'
koishipro-core.js
'
;
...
@@ -19,6 +28,7 @@ import { DuelStage } from './duel-stage';
...
@@ -19,6 +28,7 @@ import { DuelStage } from './duel-stage';
import
{
OnRoomJoin
}
from
'
./room-event/on-room-join
'
;
import
{
OnRoomJoin
}
from
'
./room-event/on-room-join
'
;
import
{
OnRoomLeave
}
from
'
./room-event/on-room-leave
'
;
import
{
OnRoomLeave
}
from
'
./room-event/on-room-leave
'
;
import
{
OnRoomWin
}
from
'
./room-event/on-room-win
'
;
import
{
OnRoomWin
}
from
'
./room-event/on-room-win
'
;
import
YGOProDeck
from
'
ygopro-deck-encode
'
;
export
type
RoomFinalizor
=
(
self
:
Room
)
=>
Awaitable
<
any
>
;
export
type
RoomFinalizor
=
(
self
:
Room
)
=>
Awaitable
<
any
>
;
...
@@ -215,7 +225,7 @@ export class Room {
...
@@ -215,7 +225,7 @@ export class Room {
}
}
@
RoomMethod
()
@
RoomMethod
()
async
onDisconnect
(
client
:
Client
,
_msg
:
YGOProCtosDisconnect
)
{
private
async
onDisconnect
(
client
:
Client
,
_msg
:
YGOProCtosDisconnect
)
{
if
(
client
.
pos
===
NetPlayerType
.
OBSERVER
)
{
if
(
client
.
pos
===
NetPlayerType
.
OBSERVER
)
{
this
.
watchers
.
delete
(
client
);
this
.
watchers
.
delete
(
client
);
for
(
const
p
of
this
.
allPlayers
)
{
for
(
const
p
of
this
.
allPlayers
)
{
...
@@ -241,4 +251,208 @@ export class Room {
...
@@ -241,4 +251,208 @@ export class Room {
await
this
.
ctx
.
dispatch
(
new
OnRoomLeave
(
this
),
client
);
await
this
.
ctx
.
dispatch
(
new
OnRoomLeave
(
this
),
client
);
client
.
roomName
=
undefined
;
client
.
roomName
=
undefined
;
}
}
@
RoomMethod
()
private
async
onToObserver
(
client
:
Client
,
_msg
:
YGOProCtosHsToObserver
)
{
// 游戏已经开始,不允许切换
if
(
this
.
duelStage
!==
DuelStage
.
Begin
)
{
return
;
}
// 如果已经是观战者,直接返回
if
(
client
.
pos
===
NetPlayerType
.
OBSERVER
)
{
return
;
}
// 保存原位置
const
oldPos
=
client
.
pos
;
// 发送 PlayerChange 给所有人
const
changeMsg
=
new
YGOProStocHsPlayerChange
().
fromPartial
({
playerPosition
:
oldPos
,
playerState
:
PlayerChangeState
.
OBSERVE
,
});
this
.
allPlayers
.
forEach
((
p
)
=>
p
.
send
(
changeMsg
));
// 从 players 移除
this
.
players
[
client
.
pos
]
=
undefined
;
client
.
pos
=
NetPlayerType
.
OBSERVER
;
// 添加到观战者
this
.
watchers
.
add
(
client
);
// 发送 TypeChange 给客户端
await
client
.
sendTypeChange
();
// 发送观战者数量更新
this
.
allPlayers
.
forEach
((
p
)
=>
p
.
send
(
this
.
watcherSizeMessage
));
}
@
RoomMethod
()
private
async
onToDuelist
(
client
:
Client
,
_msg
:
YGOProCtosHsToDuelist
)
{
// 游戏已经开始,不允许切换
if
(
this
.
duelStage
!==
DuelStage
.
Begin
)
{
return
;
}
// 查找空位
const
firstEmptyPlayerSlot
=
this
.
players
.
findIndex
((
p
)
=>
!
p
);
if
(
firstEmptyPlayerSlot
<
0
)
{
// 没有空位
return
;
}
if
(
client
.
pos
===
NetPlayerType
.
OBSERVER
)
{
// 从观战者切换到玩家
this
.
watchers
.
delete
(
client
);
// 添加到玩家
this
.
players
[
firstEmptyPlayerSlot
]
=
client
;
client
.
pos
=
firstEmptyPlayerSlot
;
// 发送 PlayerEnter 给所有人
const
enterMsg
=
client
.
prepareEnterPacket
();
this
.
allPlayers
.
forEach
((
p
)
=>
p
.
send
(
enterMsg
));
// 发送 TypeChange 给客户端
await
client
.
sendTypeChange
();
// 发送观战者数量更新
this
.
allPlayers
.
forEach
((
p
)
=>
p
.
send
(
this
.
watcherSizeMessage
));
}
else
if
(
this
.
isTag
)
{
// TAG 模式下,已经是玩家,切换到另一个空位
// 如果已经 ready,不允许切换
if
(
client
.
deck
)
{
return
;
}
const
oldPos
=
client
.
pos
;
// 移动到新位置
this
.
players
[
oldPos
]
=
undefined
;
this
.
players
[
firstEmptyPlayerSlot
]
=
client
;
client
.
pos
=
firstEmptyPlayerSlot
;
// 发送 PlayerChange 给所有人
const
changeMsg
=
new
YGOProStocHsPlayerChange
().
fromPartial
({
playerPosition
:
oldPos
,
playerState
:
firstEmptyPlayerSlot
,
});
this
.
allPlayers
.
forEach
((
p
)
=>
p
.
send
(
changeMsg
));
// 发送 TypeChange 给客户端
await
client
.
sendTypeChange
();
}
}
@
RoomMethod
()
private
async
onKick
(
client
:
Client
,
msg
:
YGOProCtosKick
)
{
// 游戏已经开始,不允许踢人
if
(
this
.
duelStage
!==
DuelStage
.
Begin
)
{
return
;
}
// 只有 host 可以踢人
if
(
!
client
.
isHost
)
{
return
;
}
// 不能踢自己
if
(
client
.
pos
===
msg
.
pos
)
{
return
;
}
// 获取要踢的玩家
const
targetPlayer
=
this
.
players
[
msg
.
pos
];
if
(
!
targetPlayer
)
{
return
;
}
// 踢出玩家
targetPlayer
.
disconnect
();
}
@
RoomMethod
()
private
async
onUnready
(
client
:
Client
,
_msg
:
YGOProCtosHsNotReady
)
{
// 游戏已经开始,不允许取消准备
if
(
this
.
duelStage
!==
DuelStage
.
Begin
)
{
return
;
}
// 只有玩家可以取消准备
if
(
client
.
pos
===
NetPlayerType
.
OBSERVER
)
{
return
;
}
// 清除 deck
client
.
deck
=
undefined
;
client
.
startDeck
=
undefined
;
// 发送 PlayerChange 给所有人
const
changeMsg
=
client
.
prepareChangePacket
(
PlayerChangeState
.
NOTREADY
);
this
.
allPlayers
.
forEach
((
p
)
=>
p
.
send
(
changeMsg
));
}
duelCount
=
0
;
firstgoPlayer
?:
Client
;
private
async
toFirstGo
(
firstgoPos
:
number
)
{
this
.
firstgoPlayer
=
this
.
getPosPlayers
(
firstgoPos
)[
0
];
this
.
duelStage
=
DuelStage
.
FirstGo
;
this
.
firstgoPlayer
.
send
(
new
YGOProStocSelectTp
());
}
private
async
toFinger
()
{
this
.
duelStage
=
DuelStage
.
Finger
;
const
fingerPlayers
=
[
0
,
1
].
map
((
p
)
=>
this
.
getPosPlayers
(
p
)[
0
]);
fingerPlayers
.
forEach
((
p
)
=>
{
p
.
send
(
new
YGOProStocSelectHand
());
});
}
async
startGame
(
firstgoPos
?:
number
)
{
if
(
!
[
DuelStage
.
Finger
,
DuelStage
.
Siding
].
includes
(
this
.
duelStage
))
{
return
false
;
}
++
this
.
duelCount
;
this
.
allPlayers
.
forEach
((
p
)
=>
p
.
send
(
new
YGOProStocDuelStart
()));
if
(
this
.
duelCount
===
1
)
{
const
displayCountDecks
=
[
0
,
1
].
map
(
(
p
)
=>
this
.
getPosPlayers
(
p
)[
0
].
deck
,
);
const
toDeckCount
=
(
d
:
YGOProDeck
)
=>
{
const
res
=
new
YGOProStocDeckCount_DeckInfo
();
res
.
main
=
d
.
main
.
length
;
res
.
extra
=
d
.
extra
.
length
;
res
.
side
=
d
.
side
.
length
;
return
res
;
};
[
0
,
1
].
forEach
((
p
)
=>
{
const
selfDeck
=
displayCountDecks
[
p
];
const
otherDeck
=
displayCountDecks
[
1
-
p
];
this
.
getPosPlayers
(
p
).
forEach
((
c
)
=>
{
c
.
send
(
new
YGOProStocDeckCount
().
fromPartial
({
player0DeckCount
:
toDeckCount
(
selfDeck
),
player1DeckCount
:
toDeckCount
(
otherDeck
),
}),
);
});
});
this
.
watchers
.
forEach
((
c
)
=>
{
c
.
send
(
new
YGOProStocDeckCount
().
fromPartial
({
player0DeckCount
:
toDeckCount
(
displayCountDecks
[
0
]),
player1DeckCount
:
toDeckCount
(
displayCountDecks
[
1
]),
}),
);
});
}
if
(
firstgoPos
!=
null
)
{
await
this
.
toFirstGo
(
firstgoPos
);
}
else
{
this
.
duelStage
=
DuelStage
.
Finger
;
}
return
true
;
}
}
}
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