Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Donald Haase
Cockatrice
Commits
0bb4ef8b
Commit
0bb4ef8b
authored
Oct 04, 2011
by
unknown
Browse files
added deck hashing
parent
963e8f0d
Changes
31
Expand all
Hide whitespace changes
Inline
Side-by-side
cockatrice/translations/cockatrice_sk.ts
View file @
0bb4ef8b
This diff is collapsed.
Click to expand it.
common/decklist.cpp
View file @
0bb4ef8b
...
@@ -3,6 +3,7 @@
...
@@ -3,6 +3,7 @@
#include
<QXmlStreamReader>
#include
<QXmlStreamReader>
#include
<QXmlStreamWriter>
#include
<QXmlStreamWriter>
#include
<QVariant>
#include
<QVariant>
#include
<QCryptographicHash>
#include
"decklist.h"
#include
"decklist.h"
MoveCardToZone
::
MoveCardToZone
(
const
QString
&
_cardName
,
const
QString
&
_startZone
,
const
QString
&
_targetZone
)
MoveCardToZone
::
MoveCardToZone
(
const
QString
&
_cardName
,
const
QString
&
_startZone
,
const
QString
&
_targetZone
)
...
@@ -263,6 +264,7 @@ DeckList::DeckList(DeckList *other)
...
@@ -263,6 +264,7 @@ DeckList::DeckList(DeckList *other)
newMoveList
.
append
(
new
MoveCardToZone
(
oldMoveList
[
i
]));
newMoveList
.
append
(
new
MoveCardToZone
(
oldMoveList
[
i
]));
sideboardPlans
.
insert
(
spIterator
.
key
(),
new
SideboardPlan
(
spIterator
.
key
(),
newMoveList
));
sideboardPlans
.
insert
(
spIterator
.
key
(),
new
SideboardPlan
(
spIterator
.
key
(),
newMoveList
));
}
}
updateDeckHash
();
}
}
DeckList
::~
DeckList
()
DeckList
::~
DeckList
()
...
@@ -453,8 +455,10 @@ bool DeckList::loadFromFile(const QString &fileName, FileFormat fmt)
...
@@ -453,8 +455,10 @@ bool DeckList::loadFromFile(const QString &fileName, FileFormat fmt)
case
PlainTextFormat
:
result
=
loadFromFile_Plain
(
&
file
);
break
;
case
PlainTextFormat
:
result
=
loadFromFile_Plain
(
&
file
);
break
;
case
CockatriceFormat
:
result
=
loadFromFile_Native
(
&
file
);
break
;
case
CockatriceFormat
:
result
=
loadFromFile_Native
(
&
file
);
break
;
}
}
if
(
result
)
if
(
result
)
{
updateDeckHash
();
emit
deckLoaded
();
emit
deckLoaded
();
}
return
result
;
return
result
;
}
}
...
@@ -486,6 +490,7 @@ void DeckList::cleanList()
...
@@ -486,6 +490,7 @@ void DeckList::cleanList()
root
->
clearTree
();
root
->
clearTree
();
setName
();
setName
();
setComments
();
setComments
();
updateDeckHash
();
}
}
void
DeckList
::
getCardListHelper
(
InnerDecklistNode
*
item
,
QSet
<
QString
>
&
result
)
const
void
DeckList
::
getCardListHelper
(
InnerDecklistNode
*
item
,
QSet
<
QString
>
&
result
)
const
...
@@ -512,28 +517,55 @@ DecklistCardNode *DeckList::addCard(const QString &cardName, const QString &zone
...
@@ -512,28 +517,55 @@ DecklistCardNode *DeckList::addCard(const QString &cardName, const QString &zone
if
(
!
zoneNode
)
if
(
!
zoneNode
)
zoneNode
=
new
InnerDecklistNode
(
zoneName
,
root
);
zoneNode
=
new
InnerDecklistNode
(
zoneName
,
root
);
return
new
DecklistCardNode
(
cardName
,
1
,
zoneNode
);
DecklistCardNode
*
node
=
new
DecklistCardNode
(
cardName
,
1
,
zoneNode
);
updateDeckHash
();
return
node
;
}
}
bool
DeckList
::
deleteNode
(
AbstractDecklistNode
*
node
,
InnerDecklistNode
*
rootNode
)
bool
DeckList
::
deleteNode
(
AbstractDecklistNode
*
node
,
InnerDecklistNode
*
rootNode
)
{
{
if
(
node
==
root
)
if
(
node
==
root
)
return
true
;
return
true
;
if
(
!
rootNode
)
bool
updateHash
=
false
;
if
(
!
rootNode
)
{
rootNode
=
root
;
rootNode
=
root
;
updateHash
=
true
;
}
int
index
=
rootNode
->
indexOf
(
node
);
int
index
=
rootNode
->
indexOf
(
node
);
if
(
index
!=
-
1
)
{
if
(
index
!=
-
1
)
{
delete
rootNode
->
takeAt
(
index
);
delete
rootNode
->
takeAt
(
index
);
if
(
!
rootNode
->
size
())
if
(
!
rootNode
->
size
())
deleteNode
(
rootNode
,
rootNode
->
getParent
());
deleteNode
(
rootNode
,
rootNode
->
getParent
());
if
(
updateHash
)
updateDeckHash
();
return
true
;
return
true
;
}
}
for
(
int
i
=
0
;
i
<
rootNode
->
size
();
i
++
)
{
for
(
int
i
=
0
;
i
<
rootNode
->
size
();
i
++
)
{
InnerDecklistNode
*
inner
=
dynamic_cast
<
InnerDecklistNode
*>
(
rootNode
->
at
(
i
));
InnerDecklistNode
*
inner
=
dynamic_cast
<
InnerDecklistNode
*>
(
rootNode
->
at
(
i
));
if
(
inner
)
if
(
inner
)
if
(
deleteNode
(
node
,
inner
))
if
(
deleteNode
(
node
,
inner
))
{
if
(
updateHash
)
updateDeckHash
();
return
true
;
return
true
;
}
}
}
return
false
;
return
false
;
}
}
void
DeckList
::
updateDeckHash
()
{
QStringList
cardList
;
for
(
int
i
=
0
;
i
<
root
->
size
();
i
++
)
{
InnerDecklistNode
*
node
=
dynamic_cast
<
InnerDecklistNode
*>
(
root
->
at
(
i
));
for
(
int
j
=
0
;
j
<
node
->
size
();
j
++
)
{
DecklistCardNode
*
card
=
dynamic_cast
<
DecklistCardNode
*>
(
node
->
at
(
j
));
for
(
int
k
=
0
;
k
<
card
->
getNumber
();
++
k
)
cardList
.
append
((
node
->
getName
()
==
"side"
?
"SB:"
:
""
)
+
card
->
getName
().
toLower
());
}
}
cardList
.
sort
();
deckHash
=
QCryptographicHash
::
hash
(
cardList
.
join
(
";"
).
toUtf8
(),
QCryptographicHash
::
Sha1
).
toBase64
().
left
(
10
);
emit
deckHashChanged
();
}
common/decklist.h
View file @
0bb4ef8b
...
@@ -118,6 +118,7 @@ public:
...
@@ -118,6 +118,7 @@ public:
private:
private:
QString
name
,
comments
;
QString
name
,
comments
;
QString
lastFileName
;
QString
lastFileName
;
QString
deckHash
;
FileFormat
lastFileFormat
;
FileFormat
lastFileFormat
;
QMap
<
QString
,
SideboardPlan
*>
sideboardPlans
;
QMap
<
QString
,
SideboardPlan
*>
sideboardPlans
;
InnerDecklistNode
*
root
;
InnerDecklistNode
*
root
;
...
@@ -127,6 +128,7 @@ private:
...
@@ -127,6 +128,7 @@ private:
void
getCardListHelper
(
InnerDecklistNode
*
node
,
QSet
<
QString
>
&
result
)
const
;
void
getCardListHelper
(
InnerDecklistNode
*
node
,
QSet
<
QString
>
&
result
)
const
;
signals:
signals:
void
deckLoaded
();
void
deckLoaded
();
void
deckHashChanged
();
public
slots
:
public
slots
:
void
setName
(
const
QString
&
_name
=
QString
())
{
name
=
_name
;
}
void
setName
(
const
QString
&
_name
=
QString
())
{
name
=
_name
;
}
void
setComments
(
const
QString
&
_comments
=
QString
())
{
comments
=
_comments
;
}
void
setComments
(
const
QString
&
_comments
=
QString
())
{
comments
=
_comments
;
}
...
@@ -160,6 +162,9 @@ public:
...
@@ -160,6 +162,9 @@ public:
void
cleanList
();
void
cleanList
();
bool
isEmpty
()
const
{
return
root
->
isEmpty
()
&&
name
.
isEmpty
()
&&
comments
.
isEmpty
()
&&
sideboardPlans
.
isEmpty
();
}
bool
isEmpty
()
const
{
return
root
->
isEmpty
()
&&
name
.
isEmpty
()
&&
comments
.
isEmpty
()
&&
sideboardPlans
.
isEmpty
();
}
QStringList
getCardList
()
const
;
QStringList
getCardList
()
const
;
QString
getDeckHash
()
const
{
return
deckHash
;
}
void
updateDeckHash
();
InnerDecklistNode
*
getRoot
()
const
{
return
root
;
}
InnerDecklistNode
*
getRoot
()
const
{
return
root
;
}
DecklistCardNode
*
addCard
(
const
QString
&
cardName
,
const
QString
&
zoneName
);
DecklistCardNode
*
addCard
(
const
QString
&
cardName
,
const
QString
&
zoneName
);
...
...
common/protocol_datastructures.cpp
View file @
0bb4ef8b
...
@@ -207,7 +207,7 @@ ServerInfo_Arrow::ServerInfo_Arrow(int _id, int _startPlayerId, const QString &_
...
@@ -207,7 +207,7 @@ ServerInfo_Arrow::ServerInfo_Arrow(int _id, int _startPlayerId, const QString &_
insertItem
(
new
SerializableItem_Color
(
"color"
,
_color
));
insertItem
(
new
SerializableItem_Color
(
"color"
,
_color
));
}
}
ServerInfo_PlayerProperties
::
ServerInfo_PlayerProperties
(
int
_playerId
,
ServerInfo_User
*
_userInfo
,
bool
_spectator
,
bool
_conceded
,
bool
_readyStart
,
int
_deck
Id
)
ServerInfo_PlayerProperties
::
ServerInfo_PlayerProperties
(
int
_playerId
,
ServerInfo_User
*
_userInfo
,
bool
_spectator
,
bool
_conceded
,
bool
_readyStart
,
const
QString
&
_deck
Hash
)
:
SerializableItem_Map
(
"player_properties"
)
:
SerializableItem_Map
(
"player_properties"
)
{
{
insertItem
(
new
SerializableItem_Int
(
"player_id"
,
_playerId
));
insertItem
(
new
SerializableItem_Int
(
"player_id"
,
_playerId
));
...
@@ -217,7 +217,7 @@ ServerInfo_PlayerProperties::ServerInfo_PlayerProperties(int _playerId, ServerIn
...
@@ -217,7 +217,7 @@ ServerInfo_PlayerProperties::ServerInfo_PlayerProperties(int _playerId, ServerIn
insertItem
(
new
SerializableItem_Bool
(
"spectator"
,
_spectator
));
insertItem
(
new
SerializableItem_Bool
(
"spectator"
,
_spectator
));
insertItem
(
new
SerializableItem_Bool
(
"conceded"
,
_conceded
));
insertItem
(
new
SerializableItem_Bool
(
"conceded"
,
_conceded
));
insertItem
(
new
SerializableItem_Bool
(
"ready_start"
,
_readyStart
));
insertItem
(
new
SerializableItem_Bool
(
"ready_start"
,
_readyStart
));
insertItem
(
new
SerializableItem_
Int
(
"deck_
id
"
,
_deck
Id
));
insertItem
(
new
SerializableItem_
String
(
"deck_
hash
"
,
_deck
Hash
));
}
}
ServerInfo_Player
::
ServerInfo_Player
(
ServerInfo_PlayerProperties
*
_properties
,
DeckList
*
_deck
,
const
QList
<
ServerInfo_Zone
*>
&
_zoneList
,
const
QList
<
ServerInfo_Counter
*>
&
_counterList
,
const
QList
<
ServerInfo_Arrow
*>
&
_arrowList
)
ServerInfo_Player
::
ServerInfo_Player
(
ServerInfo_PlayerProperties
*
_properties
,
DeckList
*
_deck
,
const
QList
<
ServerInfo_Zone
*>
&
_zoneList
,
const
QList
<
ServerInfo_Counter
*>
&
_counterList
,
const
QList
<
ServerInfo_Arrow
*>
&
_arrowList
)
...
...
common/protocol_datastructures.h
View file @
0bb4ef8b
...
@@ -189,14 +189,14 @@ public:
...
@@ -189,14 +189,14 @@ public:
class
ServerInfo_PlayerProperties
:
public
SerializableItem_Map
{
class
ServerInfo_PlayerProperties
:
public
SerializableItem_Map
{
public:
public:
ServerInfo_PlayerProperties
(
int
_playerId
=
-
1
,
ServerInfo_User
*
_userInfo
=
0
,
bool
_spectator
=
false
,
bool
_conceded
=
false
,
bool
_readyStart
=
false
,
int
_deckId
=
-
1
);
ServerInfo_PlayerProperties
(
int
_playerId
=
-
1
,
ServerInfo_User
*
_userInfo
=
0
,
bool
_spectator
=
false
,
bool
_conceded
=
false
,
bool
_readyStart
=
false
,
const
QString
&
_deckHash
=
QString
()
);
static
SerializableItem
*
newItem
()
{
return
new
ServerInfo_PlayerProperties
;
}
static
SerializableItem
*
newItem
()
{
return
new
ServerInfo_PlayerProperties
;
}
int
getPlayerId
()
const
{
return
static_cast
<
SerializableItem_Int
*>
(
itemMap
.
value
(
"player_id"
))
->
getData
();
}
int
getPlayerId
()
const
{
return
static_cast
<
SerializableItem_Int
*>
(
itemMap
.
value
(
"player_id"
))
->
getData
();
}
ServerInfo_User
*
getUserInfo
()
const
{
return
static_cast
<
ServerInfo_User
*>
(
itemMap
.
value
(
"user"
));
}
ServerInfo_User
*
getUserInfo
()
const
{
return
static_cast
<
ServerInfo_User
*>
(
itemMap
.
value
(
"user"
));
}
bool
getSpectator
()
const
{
return
static_cast
<
SerializableItem_Bool
*>
(
itemMap
.
value
(
"spectator"
))
->
getData
();
}
bool
getSpectator
()
const
{
return
static_cast
<
SerializableItem_Bool
*>
(
itemMap
.
value
(
"spectator"
))
->
getData
();
}
bool
getConceded
()
const
{
return
static_cast
<
SerializableItem_Bool
*>
(
itemMap
.
value
(
"conceded"
))
->
getData
();
}
bool
getConceded
()
const
{
return
static_cast
<
SerializableItem_Bool
*>
(
itemMap
.
value
(
"conceded"
))
->
getData
();
}
bool
getReadyStart
()
const
{
return
static_cast
<
SerializableItem_Bool
*>
(
itemMap
.
value
(
"ready_start"
))
->
getData
();
}
bool
getReadyStart
()
const
{
return
static_cast
<
SerializableItem_Bool
*>
(
itemMap
.
value
(
"ready_start"
))
->
getData
();
}
in
t
getDeck
Id
()
const
{
return
static_cast
<
SerializableItem_
Int
*>
(
itemMap
.
value
(
"deck_
id
"
))
->
getData
();
}
QStr
in
g
getDeck
Hash
()
const
{
return
static_cast
<
SerializableItem_
String
*>
(
itemMap
.
value
(
"deck_
hash
"
))
->
getData
();
}
};
};
class
ServerInfo_Player
:
public
SerializableItem_Map
{
class
ServerInfo_Player
:
public
SerializableItem_Map
{
...
...
common/protocol_items.cpp
View file @
0bb4ef8b
...
@@ -461,10 +461,10 @@ Context_Concede::Context_Concede()
...
@@ -461,10 +461,10 @@ Context_Concede::Context_Concede()
:
GameEventContext
(
"concede"
)
:
GameEventContext
(
"concede"
)
{
{
}
}
Context_DeckSelect
::
Context_DeckSelect
(
int
_deck
Id
)
Context_DeckSelect
::
Context_DeckSelect
(
const
QString
&
_deck
Hash
)
:
GameEventContext
(
"deck_select"
)
:
GameEventContext
(
"deck_select"
)
{
{
insertItem
(
new
SerializableItem_
Int
(
"deck_
id
"
,
_deck
Id
));
insertItem
(
new
SerializableItem_
String
(
"deck_
hash
"
,
_deck
Hash
));
}
}
Context_UndoDraw
::
Context_UndoDraw
()
Context_UndoDraw
::
Context_UndoDraw
()
:
GameEventContext
(
"undo_draw"
)
:
GameEventContext
(
"undo_draw"
)
...
...
common/protocol_items.dat
View file @
0bb4ef8b
...
@@ -75,7 +75,7 @@
...
@@ -75,7 +75,7 @@
5:room_say:s,player_name:s,message
5:room_say:s,player_name:s,message
6:ready_start
6:ready_start
6:concede
6:concede
6:deck_select:
i
,deck_
id
6:deck_select:
s
,deck_
hash
6:undo_draw
6:undo_draw
6:move_card
6:move_card
6:mulligan:i,number
6:mulligan:i,number
...
...
common/protocol_items.h
View file @
0bb4ef8b
...
@@ -697,8 +697,8 @@ public:
...
@@ -697,8 +697,8 @@ public:
class
Context_DeckSelect
:
public
GameEventContext
{
class
Context_DeckSelect
:
public
GameEventContext
{
Q_OBJECT
Q_OBJECT
public:
public:
Context_DeckSelect
(
int
_deckId
=
-
1
);
Context_DeckSelect
(
const
QString
&
_deckHash
=
QString
()
);
in
t
getDeck
Id
()
const
{
return
static_cast
<
SerializableItem_
Int
*>
(
itemMap
.
value
(
"deck_
id
"
))
->
getData
();
};
QStr
in
g
getDeck
Hash
()
const
{
return
static_cast
<
SerializableItem_
String
*>
(
itemMap
.
value
(
"deck_
hash
"
))
->
getData
();
};
static
SerializableItem
*
newItem
()
{
return
new
Context_DeckSelect
;
}
static
SerializableItem
*
newItem
()
{
return
new
Context_DeckSelect
;
}
int
getItemId
()
const
{
return
ItemId_Context_DeckSelect
;
}
int
getItemId
()
const
{
return
ItemId_Context_DeckSelect
;
}
};
};
...
...
common/server_player.cpp
View file @
0bb4ef8b
...
@@ -11,7 +11,7 @@
...
@@ -11,7 +11,7 @@
#include
<QDebug>
#include
<QDebug>
Server_Player
::
Server_Player
(
Server_Game
*
_game
,
int
_playerId
,
ServerInfo_User
*
_userInfo
,
bool
_spectator
,
Server_ProtocolHandler
*
_handler
)
Server_Player
::
Server_Player
(
Server_Game
*
_game
,
int
_playerId
,
ServerInfo_User
*
_userInfo
,
bool
_spectator
,
Server_ProtocolHandler
*
_handler
)
:
game
(
_game
),
handler
(
_handler
),
userInfo
(
new
ServerInfo_User
(
_userInfo
)),
deck
(
0
),
playerId
(
_playerId
),
spectator
(
_spectator
),
nextCardId
(
0
),
readyStart
(
false
),
conceded
(
false
)
,
deckId
(
-
2
)
:
game
(
_game
),
handler
(
_handler
),
userInfo
(
new
ServerInfo_User
(
_userInfo
)),
deck
(
0
),
playerId
(
_playerId
),
spectator
(
_spectator
),
nextCardId
(
0
),
readyStart
(
false
),
conceded
(
false
)
{
{
}
}
...
@@ -187,16 +187,15 @@ ServerInfo_PlayerProperties *Server_Player::getProperties()
...
@@ -187,16 +187,15 @@ ServerInfo_PlayerProperties *Server_Player::getProperties()
{
{
QMutexLocker
locker
(
&
game
->
gameMutex
);
QMutexLocker
locker
(
&
game
->
gameMutex
);
return
new
ServerInfo_PlayerProperties
(
playerId
,
new
ServerInfo_User
(
userInfo
),
spectator
,
conceded
,
readyStart
,
deck
Id
);
return
new
ServerInfo_PlayerProperties
(
playerId
,
new
ServerInfo_User
(
userInfo
),
spectator
,
conceded
,
readyStart
,
deck
?
deck
->
getDeckHash
()
:
QString
()
);
}
}
void
Server_Player
::
setDeck
(
DeckList
*
_deck
,
int
_deckId
)
void
Server_Player
::
setDeck
(
DeckList
*
_deck
)
{
{
QMutexLocker
locker
(
&
game
->
gameMutex
);
QMutexLocker
locker
(
&
game
->
gameMutex
);
delete
deck
;
delete
deck
;
deck
=
_deck
;
deck
=
_deck
;
deckId
=
_deckId
;
}
}
void
Server_Player
::
addZone
(
Server_CardZone
*
zone
)
void
Server_Player
::
addZone
(
Server_CardZone
*
zone
)
...
...
common/server_player.h
View file @
0bb4ef8b
...
@@ -39,7 +39,6 @@ private:
...
@@ -39,7 +39,6 @@ private:
int
nextCardId
;
int
nextCardId
;
bool
readyStart
;
bool
readyStart
;
bool
conceded
;
bool
conceded
;
int
deckId
;
public:
public:
Server_Player
(
Server_Game
*
_game
,
int
_playerId
,
ServerInfo_User
*
_userInfo
,
bool
_spectator
,
Server_ProtocolHandler
*
_handler
);
Server_Player
(
Server_Game
*
_game
,
int
_playerId
,
ServerInfo_User
*
_userInfo
,
bool
_spectator
,
Server_ProtocolHandler
*
_handler
);
~
Server_Player
();
~
Server_Player
();
...
@@ -57,9 +56,8 @@ public:
...
@@ -57,9 +56,8 @@ public:
bool
getSpectator
()
const
{
return
spectator
;
}
bool
getSpectator
()
const
{
return
spectator
;
}
bool
getConceded
()
const
{
return
conceded
;
}
bool
getConceded
()
const
{
return
conceded
;
}
void
setConceded
(
bool
_conceded
)
{
conceded
=
_conceded
;
}
void
setConceded
(
bool
_conceded
)
{
conceded
=
_conceded
;
}
int
getDeckId
()
const
{
return
deckId
;
}
ServerInfo_User
*
getUserInfo
()
const
{
return
userInfo
;
}
ServerInfo_User
*
getUserInfo
()
const
{
return
userInfo
;
}
void
setDeck
(
DeckList
*
_deck
,
int
_deckId
);
void
setDeck
(
DeckList
*
_deck
);
DeckList
*
getDeck
()
const
{
return
deck
;
}
DeckList
*
getDeck
()
const
{
return
deck
;
}
Server_Game
*
getGame
()
const
{
return
game
;
}
Server_Game
*
getGame
()
const
{
return
game
;
}
const
QMap
<
QString
,
Server_CardZone
*>
&
getZones
()
const
{
return
zones
;
}
const
QMap
<
QString
,
Server_CardZone
*>
&
getZones
()
const
{
return
zones
;
}
...
...
common/server_protocolhandler.cpp
View file @
0bb4ef8b
...
@@ -595,9 +595,9 @@ ResponseCode Server_ProtocolHandler::cmdDeckSelect(Command_DeckSelect *cmd, Comm
...
@@ -595,9 +595,9 @@ ResponseCode Server_ProtocolHandler::cmdDeckSelect(Command_DeckSelect *cmd, Comm
return
r
;
return
r
;
}
}
}
}
player
->
setDeck
(
deck
,
cmd
->
getDeckId
()
);
player
->
setDeck
(
deck
);
game
->
sendGameEvent
(
new
Event_PlayerPropertiesChanged
(
player
->
getPlayerId
(),
player
->
getProperties
()),
new
Context_DeckSelect
(
cmd
->
getDeck
Id
()));
game
->
sendGameEvent
(
new
Event_PlayerPropertiesChanged
(
player
->
getPlayerId
(),
player
->
getProperties
()),
new
Context_DeckSelect
(
deck
->
getDeck
Hash
()));
cont
->
setResponse
(
new
Response_DeckDownload
(
cont
->
getCmdId
(),
RespOk
,
new
DeckList
(
deck
)));
cont
->
setResponse
(
new
Response_DeckDownload
(
cont
->
getCmdId
(),
RespOk
,
new
DeckList
(
deck
)));
return
RespNothing
;
return
RespNothing
;
...
...
Prev
1
2
Next
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new 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