Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Y
ygopro
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
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
ygopro
Commits
32389dda
Commit
32389dda
authored
Dec 14, 2023
by
Chen Bill
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
use unsigned char buffer
parent
a887c624
Changes
19
Show whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
109 additions
and
107 deletions
+109
-107
gframe/bufferio.h
gframe/bufferio.h
+7
-7
gframe/client_card.cpp
gframe/client_card.cpp
+1
-1
gframe/client_card.h
gframe/client_card.h
+1
-1
gframe/client_field.cpp
gframe/client_field.cpp
+2
-2
gframe/client_field.h
gframe/client_field.h
+2
-2
gframe/deck_con.cpp
gframe/deck_con.cpp
+2
-2
gframe/duelclient.cpp
gframe/duelclient.cpp
+9
-9
gframe/duelclient.h
gframe/duelclient.h
+8
-8
gframe/menu_handler.cpp
gframe/menu_handler.cpp
+2
-2
gframe/netserver.cpp
gframe/netserver.cpp
+4
-4
gframe/netserver.h
gframe/netserver.h
+6
-6
gframe/replay_mode.cpp
gframe/replay_mode.cpp
+9
-9
gframe/replay_mode.h
gframe/replay_mode.h
+1
-1
gframe/single_duel.cpp
gframe/single_duel.cpp
+22
-21
gframe/single_duel.h
gframe/single_duel.h
+1
-1
gframe/single_mode.cpp
gframe/single_mode.cpp
+9
-9
gframe/single_mode.h
gframe/single_mode.h
+1
-1
gframe/tag_duel.cpp
gframe/tag_duel.cpp
+21
-20
gframe/tag_duel.h
gframe/tag_duel.h
+1
-1
No files found.
gframe/bufferio.h
View file @
32389dda
...
...
@@ -7,35 +7,35 @@
class
BufferIO
{
public:
inline
static
int
ReadInt32
(
char
*&
p
)
{
inline
static
int
ReadInt32
(
unsigned
char
*&
p
)
{
int
ret
=
*
(
int
*
)
p
;
p
+=
4
;
return
ret
;
}
inline
static
short
ReadInt16
(
char
*&
p
)
{
inline
static
short
ReadInt16
(
unsigned
char
*&
p
)
{
short
ret
=
*
(
short
*
)
p
;
p
+=
2
;
return
ret
;
}
inline
static
char
ReadInt8
(
char
*&
p
)
{
inline
static
char
ReadInt8
(
unsigned
char
*&
p
)
{
char
ret
=
*
(
char
*
)
p
;
p
++
;
return
ret
;
}
inline
static
unsigned
char
ReadUInt8
(
char
*&
p
)
{
inline
static
unsigned
char
ReadUInt8
(
unsigned
char
*&
p
)
{
unsigned
char
ret
=
*
(
unsigned
char
*
)
p
;
p
++
;
return
ret
;
}
inline
static
void
WriteInt32
(
char
*&
p
,
int
val
)
{
inline
static
void
WriteInt32
(
unsigned
char
*&
p
,
int
val
)
{
(
*
(
int
*
)
p
)
=
val
;
p
+=
4
;
}
inline
static
void
WriteInt16
(
char
*&
p
,
short
val
)
{
inline
static
void
WriteInt16
(
unsigned
char
*&
p
,
short
val
)
{
(
*
(
short
*
)
p
)
=
val
;
p
+=
2
;
}
inline
static
void
WriteInt8
(
char
*&
p
,
char
val
)
{
inline
static
void
WriteInt8
(
unsigned
char
*&
p
,
char
val
)
{
*
p
=
val
;
p
++
;
}
...
...
gframe/client_card.cpp
View file @
32389dda
...
...
@@ -57,7 +57,7 @@ void ClientCard::SetCode(int code) {
}
else
this
->
code
=
code
;
}
void
ClientCard
::
UpdateInfo
(
char
*
buf
)
{
void
ClientCard
::
UpdateInfo
(
unsigned
char
*
buf
)
{
int
flag
=
BufferIO
::
ReadInt32
(
buf
);
if
(
flag
==
0
)
return
;
...
...
gframe/client_card.h
View file @
32389dda
...
...
@@ -112,7 +112,7 @@ public:
ClientCard
();
void
SetCode
(
int
code
);
void
UpdateInfo
(
char
*
buf
);
void
UpdateInfo
(
unsigned
char
*
buf
);
void
ClearTarget
();
static
bool
client_card_sort
(
ClientCard
*
c1
,
ClientCard
*
c2
);
static
bool
deck_sort_lv
(
code_pointer
l1
,
code_pointer
l2
);
...
...
gframe/client_field.cpp
View file @
32389dda
...
...
@@ -303,12 +303,12 @@ ClientCard* ClientField::RemoveCard(int controler, int location, int sequence) {
pcard
->
location
=
0
;
return
pcard
;
}
void
ClientField
::
UpdateCard
(
int
controler
,
int
location
,
int
sequence
,
char
*
data
)
{
void
ClientField
::
UpdateCard
(
int
controler
,
int
location
,
int
sequence
,
unsigned
char
*
data
)
{
ClientCard
*
pcard
=
GetCard
(
controler
,
location
,
sequence
);
if
(
pcard
)
pcard
->
UpdateInfo
(
data
+
4
);
}
void
ClientField
::
UpdateFieldCard
(
int
controler
,
int
location
,
char
*
data
)
{
void
ClientField
::
UpdateFieldCard
(
int
controler
,
int
location
,
unsigned
char
*
data
)
{
std
::
vector
<
ClientCard
*>*
lst
=
0
;
switch
(
location
)
{
case
LOCATION_DECK
:
...
...
gframe/client_field.h
View file @
32389dda
...
...
@@ -92,8 +92,8 @@ public:
ClientCard
*
GetCard
(
int
controler
,
int
location
,
int
sequence
,
int
sub_seq
=
0
);
void
AddCard
(
ClientCard
*
pcard
,
int
controler
,
int
location
,
int
sequence
);
ClientCard
*
RemoveCard
(
int
controler
,
int
location
,
int
sequence
);
void
UpdateCard
(
int
controler
,
int
location
,
int
sequence
,
char
*
data
);
void
UpdateFieldCard
(
int
controler
,
int
location
,
char
*
data
);
void
UpdateCard
(
int
controler
,
int
location
,
int
sequence
,
unsigned
char
*
data
);
void
UpdateFieldCard
(
int
controler
,
int
location
,
unsigned
char
*
data
);
void
ClearCommandFlag
();
void
ClearSelect
();
void
ClearChainSelect
();
...
...
gframe/deck_con.cpp
View file @
32389dda
...
...
@@ -652,8 +652,8 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) {
break
;
}
mainGame
->
ClearCardInfo
();
char
deckbuf
[
1024
];
char
*
pdeck
=
deckbuf
;
unsigned
char
deckbuf
[
1024
];
auto
pdeck
=
deckbuf
;
BufferIO
::
WriteInt32
(
pdeck
,
deckManager
.
current_deck
.
main
.
size
()
+
deckManager
.
current_deck
.
extra
.
size
());
BufferIO
::
WriteInt32
(
pdeck
,
deckManager
.
current_deck
.
side
.
size
());
for
(
size_t
i
=
0
;
i
<
deckManager
.
current_deck
.
main
.
size
();
++
i
)
...
...
gframe/duelclient.cpp
View file @
32389dda
...
...
@@ -19,14 +19,14 @@ unsigned char DuelClient::selftype = 0;
bool
DuelClient
::
is_host
=
false
;
event_base
*
DuelClient
::
client_base
=
0
;
bufferevent
*
DuelClient
::
client_bev
=
0
;
char
DuelClient
::
duel_client_read
[
0x2000
];
char
DuelClient
::
duel_client_write
[
0x2000
];
unsigned
char
DuelClient
::
duel_client_read
[
0x2000
];
unsigned
char
DuelClient
::
duel_client_write
[
0x2000
];
bool
DuelClient
::
is_closing
=
false
;
bool
DuelClient
::
is_swapping
=
false
;
int
DuelClient
::
select_hint
=
0
;
int
DuelClient
::
select_unselect_hint
=
0
;
int
DuelClient
::
last_select_hint
=
0
;
char
DuelClient
::
last_successful_msg
[
0x2000
];
unsigned
char
DuelClient
::
last_successful_msg
[
0x2000
];
unsigned
int
DuelClient
::
last_successful_msg_length
=
0
;
wchar_t
DuelClient
::
event_string
[
256
];
mt19937
DuelClient
::
rnd
;
...
...
@@ -233,8 +233,8 @@ int DuelClient::ClientThread() {
connect_state
=
0
;
return
0
;
}
void
DuelClient
::
HandleSTOCPacketLan
(
char
*
data
,
unsigned
int
len
)
{
char
*
pdata
=
data
;
void
DuelClient
::
HandleSTOCPacketLan
(
unsigned
char
*
data
,
unsigned
int
len
)
{
unsigned
char
*
pdata
=
data
;
unsigned
char
pktType
=
BufferIO
::
ReadUInt8
(
pdata
);
switch
(
pktType
)
{
case
STOC_GAME_MSG
:
{
...
...
@@ -689,7 +689,7 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) {
if
(
mainGame
->
dInfo
.
player_type
<
7
)
mainGame
->
btnLeaveGame
->
setVisible
(
false
);
mainGame
->
CloseGameButtons
();
char
*
prep
=
pdata
;
auto
prep
=
pdata
;
Replay
new_replay
;
memcpy
(
&
new_replay
.
pheader
,
prep
,
sizeof
(
ReplayHeader
));
time_t
starttime
;
...
...
@@ -882,8 +882,8 @@ void DuelClient::HandleSTOCPacketLan(char* data, unsigned int len) {
}
}
}
int
DuelClient
::
ClientAnalyze
(
char
*
msg
,
unsigned
int
len
)
{
char
*
pbuf
=
msg
;
int
DuelClient
::
ClientAnalyze
(
unsigned
char
*
msg
,
unsigned
int
len
)
{
unsigned
char
*
pbuf
=
msg
;
wchar_t
textBuffer
[
256
];
mainGame
->
dInfo
.
curMsg
=
BufferIO
::
ReadUInt8
(
pbuf
);
if
(
mainGame
->
dInfo
.
curMsg
!=
MSG_RETRY
)
{
...
...
@@ -918,7 +918,7 @@ int DuelClient::ClientAnalyze(char * msg, unsigned int len) {
switch
(
mainGame
->
dInfo
.
curMsg
)
{
case
MSG_RETRY
:
{
if
(
last_successful_msg_length
)
{
char
*
p
=
last_successful_msg
;
auto
p
=
last_successful_msg
;
auto
last_msg
=
BufferIO
::
ReadUInt8
(
p
);
int
err_desc
=
1421
;
switch
(
last_msg
)
{
...
...
gframe/duelclient.h
View file @
32389dda
...
...
@@ -27,14 +27,14 @@ private:
static
bool
is_host
;
static
event_base
*
client_base
;
static
bufferevent
*
client_bev
;
static
char
duel_client_read
[
0x2000
];
static
char
duel_client_write
[
0x2000
];
static
unsigned
char
duel_client_read
[
0x2000
];
static
unsigned
char
duel_client_write
[
0x2000
];
static
bool
is_closing
;
static
bool
is_swapping
;
static
int
select_hint
;
static
int
select_unselect_hint
;
static
int
last_select_hint
;
static
char
last_successful_msg
[
0x2000
];
static
unsigned
char
last_successful_msg
[
0x2000
];
static
unsigned
int
last_successful_msg_length
;
static
wchar_t
event_string
[
256
];
static
mt19937
rnd
;
...
...
@@ -45,28 +45,28 @@ public:
static
void
ClientRead
(
bufferevent
*
bev
,
void
*
ctx
);
static
void
ClientEvent
(
bufferevent
*
bev
,
short
events
,
void
*
ctx
);
static
int
ClientThread
();
static
void
HandleSTOCPacketLan
(
char
*
data
,
unsigned
int
len
);
static
int
ClientAnalyze
(
char
*
msg
,
unsigned
int
len
);
static
void
HandleSTOCPacketLan
(
unsigned
char
*
data
,
unsigned
int
len
);
static
int
ClientAnalyze
(
unsigned
char
*
msg
,
unsigned
int
len
);
static
void
SwapField
();
static
void
SetResponseI
(
int
respI
);
static
void
SetResponseB
(
void
*
respB
,
unsigned
char
len
);
static
void
SendResponse
();
static
void
SendPacketToServer
(
unsigned
char
proto
)
{
char
*
p
=
duel_client_write
;
auto
p
=
duel_client_write
;
BufferIO
::
WriteInt16
(
p
,
1
);
BufferIO
::
WriteInt8
(
p
,
proto
);
bufferevent_write
(
client_bev
,
duel_client_write
,
3
);
}
template
<
typename
ST
>
static
void
SendPacketToServer
(
unsigned
char
proto
,
ST
&
st
)
{
char
*
p
=
duel_client_write
;
auto
p
=
duel_client_write
;
BufferIO
::
WriteInt16
(
p
,
1
+
sizeof
(
ST
));
BufferIO
::
WriteInt8
(
p
,
proto
);
memcpy
(
p
,
&
st
,
sizeof
(
ST
));
bufferevent_write
(
client_bev
,
duel_client_write
,
sizeof
(
ST
)
+
3
);
}
static
void
SendBufferToServer
(
unsigned
char
proto
,
void
*
buffer
,
size_t
len
)
{
char
*
p
=
duel_client_write
;
auto
p
=
duel_client_write
;
BufferIO
::
WriteInt16
(
p
,
1
+
len
);
BufferIO
::
WriteInt8
(
p
,
proto
);
memcpy
(
p
,
buffer
,
len
);
...
...
gframe/menu_handler.cpp
View file @
32389dda
...
...
@@ -16,8 +16,8 @@ void UpdateDeck() {
mainGame
->
gameConf
.
lastcategory
,
64
);
BufferIO
::
CopyWStr
(
mainGame
->
cbDeckSelect
->
getItem
(
mainGame
->
cbDeckSelect
->
getSelected
()),
mainGame
->
gameConf
.
lastdeck
,
64
);
char
deckbuf
[
1024
];
char
*
pdeck
=
deckbuf
;
unsigned
char
deckbuf
[
1024
];
auto
pdeck
=
deckbuf
;
BufferIO
::
WriteInt32
(
pdeck
,
deckManager
.
current_deck
.
main
.
size
()
+
deckManager
.
current_deck
.
extra
.
size
());
BufferIO
::
WriteInt32
(
pdeck
,
deckManager
.
current_deck
.
side
.
size
());
for
(
size_t
i
=
0
;
i
<
deckManager
.
current_deck
.
main
.
size
();
++
i
)
...
...
gframe/netserver.cpp
View file @
32389dda
...
...
@@ -9,8 +9,8 @@ event_base* NetServer::net_evbase = 0;
event
*
NetServer
::
broadcast_ev
=
0
;
evconnlistener
*
NetServer
::
listener
=
0
;
DuelMode
*
NetServer
::
duel_mode
=
0
;
char
NetServer
::
net_server_read
[
0x2000
];
char
NetServer
::
net_server_write
[
0x2000
];
unsigned
char
NetServer
::
net_server_read
[
0x2000
];
unsigned
char
NetServer
::
net_server_write
[
0x2000
];
unsigned
short
NetServer
::
last_sent
=
0
;
bool
NetServer
::
StartServer
(
unsigned
short
port
)
{
...
...
@@ -171,8 +171,8 @@ void NetServer::DisconnectPlayer(DuelPlayer* dp) {
users
.
erase
(
bit
);
}
}
void
NetServer
::
HandleCTOSPacket
(
DuelPlayer
*
dp
,
char
*
data
,
unsigned
int
len
)
{
char
*
pdata
=
data
;
void
NetServer
::
HandleCTOSPacket
(
DuelPlayer
*
dp
,
unsigned
char
*
data
,
unsigned
int
len
)
{
auto
pdata
=
data
;
unsigned
char
pktType
=
BufferIO
::
ReadUInt8
(
pdata
);
if
((
pktType
!=
CTOS_SURRENDER
)
&&
(
pktType
!=
CTOS_CHAT
)
&&
(
dp
->
state
==
0xff
||
(
dp
->
state
&&
dp
->
state
!=
pktType
)))
return
;
...
...
gframe/netserver.h
View file @
32389dda
...
...
@@ -18,8 +18,8 @@ private:
static
event
*
broadcast_ev
;
static
evconnlistener
*
listener
;
static
DuelMode
*
duel_mode
;
static
char
net_server_read
[
0x2000
];
static
char
net_server_write
[
0x2000
];
static
unsigned
char
net_server_read
[
0x2000
];
static
unsigned
char
net_server_write
[
0x2000
];
static
unsigned
short
last_sent
;
public:
...
...
@@ -35,9 +35,9 @@ public:
static
void
ServerEchoEvent
(
bufferevent
*
bev
,
short
events
,
void
*
ctx
);
static
int
ServerThread
();
static
void
DisconnectPlayer
(
DuelPlayer
*
dp
);
static
void
HandleCTOSPacket
(
DuelPlayer
*
dp
,
char
*
data
,
unsigned
int
len
);
static
void
HandleCTOSPacket
(
DuelPlayer
*
dp
,
unsigned
char
*
data
,
unsigned
int
len
);
static
void
SendPacketToPlayer
(
DuelPlayer
*
dp
,
unsigned
char
proto
)
{
char
*
p
=
net_server_write
;
auto
p
=
net_server_write
;
BufferIO
::
WriteInt16
(
p
,
1
);
BufferIO
::
WriteInt8
(
p
,
proto
);
last_sent
=
3
;
...
...
@@ -47,7 +47,7 @@ public:
}
template
<
typename
ST
>
static
void
SendPacketToPlayer
(
DuelPlayer
*
dp
,
unsigned
char
proto
,
ST
&
st
)
{
char
*
p
=
net_server_write
;
auto
p
=
net_server_write
;
BufferIO
::
WriteInt16
(
p
,
1
+
sizeof
(
ST
));
BufferIO
::
WriteInt8
(
p
,
proto
);
memcpy
(
p
,
&
st
,
sizeof
(
ST
));
...
...
@@ -56,7 +56,7 @@ public:
bufferevent_write
(
dp
->
bev
,
net_server_write
,
last_sent
);
}
static
void
SendBufferToPlayer
(
DuelPlayer
*
dp
,
unsigned
char
proto
,
void
*
buffer
,
size_t
len
)
{
char
*
p
=
net_server_write
;
auto
p
=
net_server_write
;
BufferIO
::
WriteInt16
(
p
,
1
+
len
);
BufferIO
::
WriteInt8
(
p
,
proto
);
memcpy
(
p
,
buffer
,
len
);
...
...
gframe/replay_mode.cpp
View file @
32389dda
...
...
@@ -73,12 +73,12 @@ int ReplayMode::ReplayThread() {
mainGame
->
dInfo
.
isFinished
=
false
;
mainGame
->
dInfo
.
isReplay
=
true
;
mainGame
->
dInfo
.
isReplaySkiping
=
(
skip_turn
>
0
);
std
::
vector
<
char
>
engineBuffer
;
std
::
vector
<
unsigned
char
>
engineBuffer
;
engineBuffer
.
resize
(
SIZE_MESSAGE_BUFFER
);
is_continuing
=
true
;
skip_step
=
0
;
if
(
mainGame
->
dInfo
.
isSingleMode
)
{
int
len
=
get_message
(
pduel
,
(
byte
*
)
engineBuffer
.
data
());
int
len
=
get_message
(
pduel
,
engineBuffer
.
data
());
if
(
len
>
0
)
is_continuing
=
ReplayAnalyze
(
engineBuffer
.
data
(),
len
);
}
else
{
...
...
@@ -97,7 +97,7 @@ int ReplayMode::ReplayThread() {
if
(
len
>
0
)
{
if
(
len
>
(
int
)
engineBuffer
.
size
())
engineBuffer
.
resize
(
len
);
get_message
(
pduel
,
(
byte
*
)
engineBuffer
.
data
());
get_message
(
pduel
,
engineBuffer
.
data
());
is_continuing
=
ReplayAnalyze
(
engineBuffer
.
data
(),
len
);
if
(
is_restarting
)
{
mainGame
->
gMutex
.
lock
();
...
...
@@ -110,7 +110,7 @@ int ReplayMode::ReplayThread() {
if
(
mainGame
->
dInfo
.
isSingleMode
)
{
is_continuing
=
true
;
skip_step
=
0
;
int
len
=
get_message
(
pduel
,
(
byte
*
)
engineBuffer
.
data
());
int
len
=
get_message
(
pduel
,
engineBuffer
.
data
());
if
(
len
>
0
)
{
is_continuing
=
ReplayAnalyze
(
engineBuffer
.
data
(),
len
);
}
...
...
@@ -296,8 +296,8 @@ void ReplayMode::Undo() {
is_restarting
=
true
;
Pause
(
false
,
false
);
}
bool
ReplayMode
::
ReplayAnalyze
(
char
*
msg
,
unsigned
int
len
)
{
char
*
pbuf
=
msg
;
bool
ReplayMode
::
ReplayAnalyze
(
unsigned
char
*
msg
,
unsigned
int
len
)
{
unsigned
char
*
pbuf
=
msg
;
int
player
,
count
;
is_restarting
=
false
;
while
(
pbuf
-
msg
<
(
int
)
len
)
{
...
...
@@ -313,7 +313,7 @@ bool ReplayMode::ReplayAnalyze(char* msg, unsigned int len) {
mainGame
->
gMutex
.
unlock
();
is_swaping
=
false
;
}
char
*
offset
=
pbuf
;
auto
offset
=
pbuf
;
bool
pauseable
=
true
;
mainGame
->
dInfo
.
curMsg
=
BufferIO
::
ReadUInt8
(
pbuf
);
switch
(
mainGame
->
dInfo
.
curMsg
)
{
...
...
@@ -875,7 +875,7 @@ bool ReplayMode::ReplayAnalyze(char* msg, unsigned int len) {
}
void
ReplayMode
::
ReloadLocation
(
int
player
,
int
location
,
int
flag
,
std
::
vector
<
unsigned
char
>&
queryBuffer
)
{
query_field_card
(
pduel
,
player
,
location
,
flag
,
queryBuffer
.
data
(),
0
);
mainGame
->
dField
.
UpdateFieldCard
(
mainGame
->
LocalPlayer
(
player
),
location
,
(
char
*
)
queryBuffer
.
data
());
mainGame
->
dField
.
UpdateFieldCard
(
mainGame
->
LocalPlayer
(
player
),
location
,
queryBuffer
.
data
());
}
void
ReplayMode
::
RefreshLocation
(
int
player
,
int
location
,
int
flag
)
{
std
::
vector
<
unsigned
char
>
queryBuffer
;
...
...
@@ -908,7 +908,7 @@ void ReplayMode::ReplayRefreshSingle(int player, int location, int sequence, int
std
::
vector
<
unsigned
char
>
queryBuffer
;
queryBuffer
.
reserve
(
SIZE_QUERY_BUFFER
);
/*int len = */
query_card
(
pduel
,
player
,
location
,
sequence
,
flag
,
queryBuffer
.
data
(),
0
);
mainGame
->
dField
.
UpdateCard
(
mainGame
->
LocalPlayer
(
player
),
location
,
sequence
,
(
char
*
)
queryBuffer
.
data
());
mainGame
->
dField
.
UpdateCard
(
mainGame
->
LocalPlayer
(
player
),
location
,
sequence
,
queryBuffer
.
data
());
}
void
ReplayMode
::
ReplayReload
()
{
std
::
vector
<
unsigned
char
>
queryBuffer
;
...
...
gframe/replay_mode.h
View file @
32389dda
...
...
@@ -35,7 +35,7 @@ public:
static
void
EndDuel
();
static
void
Restart
(
bool
refresh
);
static
void
Undo
();
static
bool
ReplayAnalyze
(
char
*
msg
,
unsigned
int
len
);
static
bool
ReplayAnalyze
(
unsigned
char
*
msg
,
unsigned
int
len
);
inline
static
void
ReloadLocation
(
int
player
,
int
location
,
int
flag
,
std
::
vector
<
unsigned
char
>&
queryBuffer
);
inline
static
void
RefreshLocation
(
int
player
,
int
location
,
int
flag
);
...
...
gframe/single_duel.cpp
View file @
32389dda
...
...
@@ -282,7 +282,7 @@ void SingleDuel::PlayerKick(DuelPlayer* dp, unsigned char pos) {
void
SingleDuel
::
UpdateDeck
(
DuelPlayer
*
dp
,
void
*
pdata
,
unsigned
int
len
)
{
if
(
dp
->
type
>
1
||
ready
[
dp
->
type
])
return
;
char
*
deckbuf
=
(
char
*
)
pdata
;
unsigned
char
*
deckbuf
=
(
unsigned
char
*
)
pdata
;
int
mainc
=
BufferIO
::
ReadInt32
(
deckbuf
);
int
sidec
=
BufferIO
::
ReadInt32
(
deckbuf
);
// verify data
...
...
@@ -327,8 +327,8 @@ void SingleDuel::StartDuel(DuelPlayer* dp) {
(
*
oit
)
->
state
=
CTOS_LEAVE_GAME
;
NetServer
::
ReSendToPlayer
(
*
oit
);
}
char
deckbuff
[
12
];
char
*
pbuf
=
deckbuff
;
unsigned
char
deckbuff
[
12
];
auto
pbuf
=
deckbuff
;
BufferIO
::
WriteInt16
(
pbuf
,
pdeck
[
0
].
main
.
size
());
BufferIO
::
WriteInt16
(
pbuf
,
pdeck
[
0
].
extra
.
size
());
BufferIO
::
WriteInt16
(
pbuf
,
pdeck
[
0
].
side
.
size
());
...
...
@@ -463,7 +463,8 @@ void SingleDuel::TPResult(DuelPlayer* dp, unsigned char tp) {
last_replay
.
WriteInt32
(
pdeck
[
1
].
extra
[
i
]
->
first
,
false
);
}
last_replay
.
Flush
();
char
startbuf
[
32
],
*
pbuf
=
startbuf
;
unsigned
char
startbuf
[
32
];
auto
pbuf
=
startbuf
;
BufferIO
::
WriteInt8
(
pbuf
,
MSG_START
);
BufferIO
::
WriteInt8
(
pbuf
,
0
);
BufferIO
::
WriteInt8
(
pbuf
,
host_info
.
duel_rule
);
...
...
@@ -492,7 +493,7 @@ void SingleDuel::TPResult(DuelPlayer* dp, unsigned char tp) {
Process
();
}
void
SingleDuel
::
Process
()
{
std
::
vector
<
char
>
engineBuffer
;
std
::
vector
<
unsigned
char
>
engineBuffer
;
engineBuffer
.
reserve
(
SIZE_MESSAGE_BUFFER
);
unsigned
int
engFlag
=
0
;
int
engLen
=
0
;
...
...
@@ -506,7 +507,7 @@ void SingleDuel::Process() {
if
(
engLen
>
0
)
{
if
(
engLen
>
(
int
)
engineBuffer
.
size
())
engineBuffer
.
resize
(
engLen
);
get_message
(
pduel
,
(
byte
*
)
engineBuffer
.
data
());
get_message
(
pduel
,
engineBuffer
.
data
());
stop
=
Analyze
(
engineBuffer
.
data
(),
engLen
);
}
}
...
...
@@ -578,8 +579,8 @@ void SingleDuel::Surrender(DuelPlayer* dp) {
DuelEndProc
();
event_del
(
etimer
);
}
int
SingleDuel
::
Analyze
(
char
*
msgbuffer
,
unsigned
int
len
)
{
char
*
offset
,
*
pbufw
,
*
pbuf
=
msgbuffer
;
int
SingleDuel
::
Analyze
(
unsigned
char
*
msgbuffer
,
unsigned
int
len
)
{
unsigned
char
*
offset
,
*
pbufw
,
*
pbuf
=
msgbuffer
;
int
player
,
count
,
type
;
while
(
pbuf
-
msgbuffer
<
(
int
)
len
)
{
offset
=
pbuf
;
...
...
@@ -1463,8 +1464,8 @@ void SingleDuel::TimeConfirm(DuelPlayer* dp) {
time_elapsed
=
0
;
}
void
SingleDuel
::
RefreshMzone
(
int
player
,
int
flag
,
int
use_cache
)
{
char
query_buffer
[
0x2000
];
char
*
qbuf
=
query_buffer
;
unsigned
char
query_buffer
[
0x2000
];
auto
qbuf
=
query_buffer
;
BufferIO
::
WriteInt8
(
qbuf
,
MSG_UPDATE_DATA
);
BufferIO
::
WriteInt8
(
qbuf
,
player
);
BufferIO
::
WriteInt8
(
qbuf
,
LOCATION_MZONE
);
...
...
@@ -1485,12 +1486,12 @@ void SingleDuel::RefreshMzone(int player, int flag, int use_cache) {
NetServer
::
ReSendToPlayer
(
*
pit
);
}
void
SingleDuel
::
RefreshSzone
(
int
player
,
int
flag
,
int
use_cache
)
{
char
query_buffer
[
0x2000
];
char
*
qbuf
=
query_buffer
;
unsigned
char
query_buffer
[
0x2000
];
auto
qbuf
=
query_buffer
;
BufferIO
::
WriteInt8
(
qbuf
,
MSG_UPDATE_DATA
);
BufferIO
::
WriteInt8
(
qbuf
,
player
);
BufferIO
::
WriteInt8
(
qbuf
,
LOCATION_SZONE
);
int
len
=
query_field_card
(
pduel
,
player
,
LOCATION_SZONE
,
flag
,
(
unsigned
char
*
)
qbuf
,
use_cache
);
int
len
=
query_field_card
(
pduel
,
player
,
LOCATION_SZONE
,
flag
,
qbuf
,
use_cache
);
NetServer
::
SendBufferToPlayer
(
players
[
player
],
STOC_GAME_MSG
,
query_buffer
,
len
+
3
);
int
qlen
=
0
;
while
(
qlen
<
len
)
{
...
...
@@ -1507,8 +1508,8 @@ void SingleDuel::RefreshSzone(int player, int flag, int use_cache) {
NetServer
::
ReSendToPlayer
(
*
pit
);
}
void
SingleDuel
::
RefreshHand
(
int
player
,
int
flag
,
int
use_cache
)
{
char
query_buffer
[
0x2000
];
char
*
qbuf
=
query_buffer
;
unsigned
char
query_buffer
[
0x2000
];
auto
qbuf
=
query_buffer
;
BufferIO
::
WriteInt8
(
qbuf
,
MSG_UPDATE_DATA
);
BufferIO
::
WriteInt8
(
qbuf
,
player
);
BufferIO
::
WriteInt8
(
qbuf
,
LOCATION_HAND
);
...
...
@@ -1532,8 +1533,8 @@ void SingleDuel::RefreshHand(int player, int flag, int use_cache) {
NetServer
::
ReSendToPlayer
(
*
pit
);
}
void
SingleDuel
::
RefreshGrave
(
int
player
,
int
flag
,
int
use_cache
)
{
char
query_buffer
[
0x2000
];
char
*
qbuf
=
query_buffer
;
unsigned
char
query_buffer
[
0x2000
];
auto
qbuf
=
query_buffer
;
BufferIO
::
WriteInt8
(
qbuf
,
MSG_UPDATE_DATA
);
BufferIO
::
WriteInt8
(
qbuf
,
player
);
BufferIO
::
WriteInt8
(
qbuf
,
LOCATION_GRAVE
);
...
...
@@ -1544,8 +1545,8 @@ void SingleDuel::RefreshGrave(int player, int flag, int use_cache) {
NetServer
::
ReSendToPlayer
(
*
pit
);
}
void
SingleDuel
::
RefreshExtra
(
int
player
,
int
flag
,
int
use_cache
)
{
char
query_buffer
[
0x2000
];
char
*
qbuf
=
query_buffer
;
unsigned
char
query_buffer
[
0x2000
];
auto
qbuf
=
query_buffer
;
BufferIO
::
WriteInt8
(
qbuf
,
MSG_UPDATE_DATA
);
BufferIO
::
WriteInt8
(
qbuf
,
player
);
BufferIO
::
WriteInt8
(
qbuf
,
LOCATION_EXTRA
);
...
...
@@ -1553,8 +1554,8 @@ void SingleDuel::RefreshExtra(int player, int flag, int use_cache) {
NetServer
::
SendBufferToPlayer
(
players
[
player
],
STOC_GAME_MSG
,
query_buffer
,
len
+
3
);
}
void
SingleDuel
::
RefreshSingle
(
int
player
,
int
location
,
int
sequence
,
int
flag
)
{
char
query_buffer
[
0x2000
];
char
*
qbuf
=
query_buffer
;
unsigned
char
query_buffer
[
0x2000
];
auto
qbuf
=
query_buffer
;
BufferIO
::
WriteInt8
(
qbuf
,
MSG_UPDATE_CARD
);
BufferIO
::
WriteInt8
(
qbuf
,
player
);
BufferIO
::
WriteInt8
(
qbuf
,
location
);
...
...
gframe/single_duel.h
View file @
32389dda
...
...
@@ -24,7 +24,7 @@ public:
virtual
void
TPResult
(
DuelPlayer
*
dp
,
unsigned
char
tp
);
virtual
void
Process
();
virtual
void
Surrender
(
DuelPlayer
*
dp
);
virtual
int
Analyze
(
char
*
msgbuffer
,
unsigned
int
len
);
virtual
int
Analyze
(
unsigned
char
*
msgbuffer
,
unsigned
int
len
);
virtual
void
GetResponse
(
DuelPlayer
*
dp
,
void
*
pdata
,
unsigned
int
len
);
virtual
void
TimeConfirm
(
DuelPlayer
*
dp
);
virtual
void
EndDuel
();
...
...
gframe/single_mode.cpp
View file @
32389dda
...
...
@@ -98,11 +98,11 @@ int SingleMode::SinglePlayThread() {
mainGame
->
dInfo
.
isSingleMode
=
true
;
mainGame
->
device
->
setEventReceiver
(
&
mainGame
->
dField
);
mainGame
->
gMutex
.
unlock
();
std
::
vector
<
char
>
engineBuffer
;
std
::
vector
<
unsigned
char
>
engineBuffer
;
engineBuffer
.
resize
(
SIZE_MESSAGE_BUFFER
);
is_closing
=
false
;
is_continuing
=
true
;
int
len
=
get_message
(
pduel
,
(
byte
*
)
engineBuffer
.
data
());
int
len
=
get_message
(
pduel
,
engineBuffer
.
data
());
if
(
len
>
0
)
is_continuing
=
SinglePlayAnalyze
(
engineBuffer
.
data
(),
len
);
last_replay
.
BeginRecord
();
...
...
@@ -126,7 +126,7 @@ int SingleMode::SinglePlayThread() {
if
(
len
>
0
)
{
if
(
len
>
(
int
)
engineBuffer
.
size
())
engineBuffer
.
resize
(
len
);
get_message
(
pduel
,
(
byte
*
)
engineBuffer
.
data
());
get_message
(
pduel
,
engineBuffer
.
data
());
is_continuing
=
SinglePlayAnalyze
(
engineBuffer
.
data
(),
len
);
}
}
...
...
@@ -174,8 +174,8 @@ int SingleMode::SinglePlayThread() {
}
return
0
;
}
bool
SingleMode
::
SinglePlayAnalyze
(
char
*
msg
,
unsigned
int
len
)
{
char
*
offset
,
*
pbuf
=
msg
;
bool
SingleMode
::
SinglePlayAnalyze
(
unsigned
char
*
msg
,
unsigned
int
len
)
{
unsigned
char
*
offset
,
*
pbuf
=
msg
;
int
player
,
count
;
while
(
pbuf
-
msg
<
(
int
)
len
)
{
if
(
is_closing
||
!
is_continuing
)
...
...
@@ -747,7 +747,7 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) {
char
namebuf
[
128
];
wchar_t
wname
[
128
];
int
len
=
BufferIO
::
ReadInt16
(
pbuf
);
char
*
begin
=
pbuf
;
auto
begin
=
pbuf
;
pbuf
+=
len
+
1
;
memcpy
(
namebuf
,
begin
,
len
+
1
);
BufferIO
::
DecodeUTF8
(
namebuf
,
wname
);
...
...
@@ -758,7 +758,7 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) {
char
msgbuf
[
1024
];
wchar_t
msg
[
1024
];
int
len
=
BufferIO
::
ReadInt16
(
pbuf
);
char
*
begin
=
pbuf
;
auto
begin
=
pbuf
;
pbuf
+=
len
+
1
;
memcpy
(
msgbuf
,
begin
,
len
+
1
);
BufferIO
::
DecodeUTF8
(
msgbuf
,
msg
);
...
...
@@ -776,7 +776,7 @@ bool SingleMode::SinglePlayAnalyze(char* msg, unsigned int len) {
}
void
SingleMode
::
ReloadLocation
(
int
player
,
int
location
,
int
flag
,
std
::
vector
<
unsigned
char
>&
queryBuffer
)
{
query_field_card
(
pduel
,
player
,
location
,
flag
,
queryBuffer
.
data
(),
0
);
mainGame
->
dField
.
UpdateFieldCard
(
mainGame
->
LocalPlayer
(
player
),
location
,
(
char
*
)
queryBuffer
.
data
());
mainGame
->
dField
.
UpdateFieldCard
(
mainGame
->
LocalPlayer
(
player
),
location
,
queryBuffer
.
data
());
}
void
SingleMode
::
RefreshLocation
(
int
player
,
int
location
,
int
flag
)
{
std
::
vector
<
unsigned
char
>
queryBuffer
;
...
...
@@ -808,7 +808,7 @@ void SingleMode::SinglePlayRefreshExtra(int player, int flag) {
void
SingleMode
::
SinglePlayRefreshSingle
(
int
player
,
int
location
,
int
sequence
,
int
flag
)
{
unsigned
char
queryBuffer
[
0x2000
];
/*int len = */
query_card
(
pduel
,
player
,
location
,
sequence
,
flag
,
queryBuffer
,
0
);
mainGame
->
dField
.
UpdateCard
(
mainGame
->
LocalPlayer
(
player
),
location
,
sequence
,
(
char
*
)
queryBuffer
);
mainGame
->
dField
.
UpdateCard
(
mainGame
->
LocalPlayer
(
player
),
location
,
sequence
,
queryBuffer
);
}
void
SingleMode
::
SinglePlayReload
()
{
std
::
vector
<
byte
>
queryBuffer
;
...
...
gframe/single_mode.h
View file @
32389dda
...
...
@@ -18,7 +18,7 @@ public:
static
void
StopPlay
(
bool
is_exiting
=
false
);
static
void
SetResponse
(
unsigned
char
*
resp
,
unsigned
int
len
);
static
int
SinglePlayThread
();
static
bool
SinglePlayAnalyze
(
char
*
msg
,
unsigned
int
len
);
static
bool
SinglePlayAnalyze
(
unsigned
char
*
msg
,
unsigned
int
len
);
inline
static
void
ReloadLocation
(
int
player
,
int
location
,
int
flag
,
std
::
vector
<
unsigned
char
>&
queryBuffer
);
inline
static
void
RefreshLocation
(
int
player
,
int
location
,
int
flag
);
...
...
gframe/tag_duel.cpp
View file @
32389dda
...
...
@@ -257,7 +257,7 @@ void TagDuel::PlayerKick(DuelPlayer* dp, unsigned char pos) {
void
TagDuel
::
UpdateDeck
(
DuelPlayer
*
dp
,
void
*
pdata
,
unsigned
int
len
)
{
if
(
dp
->
type
>
3
||
ready
[
dp
->
type
])
return
;
char
*
deckbuf
=
(
char
*
)
pdata
;
unsigned
char
*
deckbuf
=
(
unsigned
char
*
)
pdata
;
int
mainc
=
BufferIO
::
ReadInt32
(
deckbuf
);
int
sidec
=
BufferIO
::
ReadInt32
(
deckbuf
);
// verify data
...
...
@@ -284,8 +284,8 @@ void TagDuel::StartDuel(DuelPlayer* dp) {
(
*
oit
)
->
state
=
CTOS_LEAVE_GAME
;
NetServer
::
ReSendToPlayer
(
*
oit
);
}
char
deckbuff
[
12
];
char
*
pbuf
=
deckbuff
;
unsigned
char
deckbuff
[
12
];
auto
pbuf
=
deckbuff
;
BufferIO
::
WriteInt16
(
pbuf
,
pdeck
[
0
].
main
.
size
());
BufferIO
::
WriteInt16
(
pbuf
,
pdeck
[
0
].
extra
.
size
());
BufferIO
::
WriteInt16
(
pbuf
,
pdeck
[
0
].
side
.
size
());
...
...
@@ -457,7 +457,8 @@ void TagDuel::TPResult(DuelPlayer* dp, unsigned char tp) {
last_replay
.
WriteInt32
(
pdeck
[
2
].
extra
[
i
]
->
first
,
false
);
}
last_replay
.
Flush
();
char
startbuf
[
32
],
*
pbuf
=
startbuf
;
unsigned
char
startbuf
[
32
];
auto
pbuf
=
startbuf
;
BufferIO
::
WriteInt8
(
pbuf
,
MSG_START
);
BufferIO
::
WriteInt8
(
pbuf
,
0
);
BufferIO
::
WriteInt8
(
pbuf
,
host_info
.
duel_rule
);
...
...
@@ -488,7 +489,7 @@ void TagDuel::TPResult(DuelPlayer* dp, unsigned char tp) {
Process
();
}
void
TagDuel
::
Process
()
{
std
::
vector
<
char
>
engineBuffer
;
std
::
vector
<
unsigned
char
>
engineBuffer
;
engineBuffer
.
reserve
(
SIZE_MESSAGE_BUFFER
);
unsigned
int
engFlag
=
0
;
int
engLen
=
0
;
...
...
@@ -502,7 +503,7 @@ void TagDuel::Process() {
if
(
engLen
>
0
)
{
if
(
engLen
>
(
int
)
engineBuffer
.
size
())
engineBuffer
.
resize
(
engLen
);
get_message
(
pduel
,
(
byte
*
)
engineBuffer
.
data
());
get_message
(
pduel
,
engineBuffer
.
data
());
stop
=
Analyze
(
engineBuffer
.
data
(),
engLen
);
}
}
...
...
@@ -521,8 +522,8 @@ void TagDuel::DuelEndProc() {
void
TagDuel
::
Surrender
(
DuelPlayer
*
dp
)
{
return
;
}
int
TagDuel
::
Analyze
(
char
*
msgbuffer
,
unsigned
int
len
)
{
char
*
offset
,
*
pbufw
,
*
pbuf
=
msgbuffer
;
int
TagDuel
::
Analyze
(
unsigned
char
*
msgbuffer
,
unsigned
int
len
)
{
unsigned
char
*
offset
,
*
pbufw
,
*
pbuf
=
msgbuffer
;
int
player
,
count
,
type
;
while
(
pbuf
-
msgbuffer
<
(
int
)
len
)
{
offset
=
pbuf
;
...
...
@@ -1550,8 +1551,8 @@ void TagDuel::TimeConfirm(DuelPlayer* dp) {
time_elapsed
=
0
;
}
void
TagDuel
::
RefreshMzone
(
int
player
,
int
flag
,
int
use_cache
)
{
char
query_buffer
[
0x4000
];
char
*
qbuf
=
query_buffer
;
unsigned
char
query_buffer
[
0x4000
];
auto
qbuf
=
query_buffer
;
BufferIO
::
WriteInt8
(
qbuf
,
MSG_UPDATE_DATA
);
BufferIO
::
WriteInt8
(
qbuf
,
player
);
BufferIO
::
WriteInt8
(
qbuf
,
LOCATION_MZONE
);
...
...
@@ -1576,8 +1577,8 @@ void TagDuel::RefreshMzone(int player, int flag, int use_cache) {
NetServer
::
ReSendToPlayer
(
*
pit
);
}
void
TagDuel
::
RefreshSzone
(
int
player
,
int
flag
,
int
use_cache
)
{
char
query_buffer
[
0x4000
];
char
*
qbuf
=
query_buffer
;
unsigned
char
query_buffer
[
0x4000
];
auto
qbuf
=
query_buffer
;
BufferIO
::
WriteInt8
(
qbuf
,
MSG_UPDATE_DATA
);
BufferIO
::
WriteInt8
(
qbuf
,
player
);
BufferIO
::
WriteInt8
(
qbuf
,
LOCATION_SZONE
);
...
...
@@ -1602,8 +1603,8 @@ void TagDuel::RefreshSzone(int player, int flag, int use_cache) {
NetServer
::
ReSendToPlayer
(
*
pit
);
}
void
TagDuel
::
RefreshHand
(
int
player
,
int
flag
,
int
use_cache
)
{
char
query_buffer
[
0x4000
];
char
*
qbuf
=
query_buffer
;
unsigned
char
query_buffer
[
0x4000
];
auto
qbuf
=
query_buffer
;
BufferIO
::
WriteInt8
(
qbuf
,
MSG_UPDATE_DATA
);
BufferIO
::
WriteInt8
(
qbuf
,
player
);
BufferIO
::
WriteInt8
(
qbuf
,
LOCATION_HAND
);
...
...
@@ -1629,8 +1630,8 @@ void TagDuel::RefreshHand(int player, int flag, int use_cache) {
NetServer
::
ReSendToPlayer
(
*
pit
);
}
void
TagDuel
::
RefreshGrave
(
int
player
,
int
flag
,
int
use_cache
)
{
char
query_buffer
[
0x4000
];
char
*
qbuf
=
query_buffer
;
unsigned
char
query_buffer
[
0x4000
];
auto
qbuf
=
query_buffer
;
BufferIO
::
WriteInt8
(
qbuf
,
MSG_UPDATE_DATA
);
BufferIO
::
WriteInt8
(
qbuf
,
player
);
BufferIO
::
WriteInt8
(
qbuf
,
LOCATION_GRAVE
);
...
...
@@ -1643,8 +1644,8 @@ void TagDuel::RefreshGrave(int player, int flag, int use_cache) {
NetServer
::
ReSendToPlayer
(
*
pit
);
}
void
TagDuel
::
RefreshExtra
(
int
player
,
int
flag
,
int
use_cache
)
{
char
query_buffer
[
0x4000
];
char
*
qbuf
=
query_buffer
;
unsigned
char
query_buffer
[
0x4000
];
auto
qbuf
=
query_buffer
;
BufferIO
::
WriteInt8
(
qbuf
,
MSG_UPDATE_DATA
);
BufferIO
::
WriteInt8
(
qbuf
,
player
);
BufferIO
::
WriteInt8
(
qbuf
,
LOCATION_EXTRA
);
...
...
@@ -1652,8 +1653,8 @@ void TagDuel::RefreshExtra(int player, int flag, int use_cache) {
NetServer
::
SendBufferToPlayer
(
cur_player
[
player
],
STOC_GAME_MSG
,
query_buffer
,
len
+
3
);
}
void
TagDuel
::
RefreshSingle
(
int
player
,
int
location
,
int
sequence
,
int
flag
)
{
char
query_buffer
[
0x4000
];
char
*
qbuf
=
query_buffer
;
unsigned
char
query_buffer
[
0x4000
];
auto
qbuf
=
query_buffer
;
BufferIO
::
WriteInt8
(
qbuf
,
MSG_UPDATE_CARD
);
BufferIO
::
WriteInt8
(
qbuf
,
player
);
BufferIO
::
WriteInt8
(
qbuf
,
location
);
...
...
gframe/tag_duel.h
View file @
32389dda
...
...
@@ -24,7 +24,7 @@ public:
virtual
void
TPResult
(
DuelPlayer
*
dp
,
unsigned
char
tp
);
virtual
void
Process
();
virtual
void
Surrender
(
DuelPlayer
*
dp
);
virtual
int
Analyze
(
char
*
msgbuffer
,
unsigned
int
len
);
virtual
int
Analyze
(
unsigned
char
*
msgbuffer
,
unsigned
int
len
);
virtual
void
GetResponse
(
DuelPlayer
*
dp
,
void
*
pdata
,
unsigned
int
len
);
virtual
void
TimeConfirm
(
DuelPlayer
*
dp
);
virtual
void
EndDuel
();
...
...
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