From fa608fa5552130c9108c6b65c6021cab265a7eec Mon Sep 17 00:00:00 2001 From: Andrew Gutekanst Date: Sun, 19 Jan 2020 12:52:57 -0500 Subject: [PATCH] Initial chat prototype --- .gitignore | 4 +- config.json | 34 +- go.mod | 4 +- go.sum | 7 + main.go | 19 +- migrations/000002_alter_characters.down.sql | 8 + migrations/000002_alter_characters.up.sql | 8 + network/mhfpacket/msg_mhf_enumerate_order.go | 13 +- network/mhfpacket/msg_mhf_enumerate_price.go | 13 +- network/mhfpacket/msg_mhf_enumerate_shop.go | 21 +- network/mhfpacket/msg_mhf_get_boost_right.go | 9 +- network/mhfpacket/msg_mhf_get_boost_time.go | 9 +- .../mhfpacket/msg_mhf_get_boost_time_limit.go | 9 +- network/mhfpacket/msg_mhf_get_earth_status.go | 13 +- network/mhfpacket/msg_mhf_get_earth_value.go | 23 +- .../msg_mhf_get_enhanced_minidata.go | 11 +- .../msg_mhf_get_keep_login_boost_status.go | 9 +- .../mhfpacket/msg_mhf_get_kouryou_point.go | 9 +- network/mhfpacket/msg_mhf_get_paper_data.go | 15 +- network/mhfpacket/msg_mhf_get_tower_info.go | 25 +- network/mhfpacket/msg_mhf_get_ud_info.go | 9 +- .../mhfpacket/msg_mhf_get_ud_monster_point.go | 9 +- network/mhfpacket/msg_mhf_get_ud_schedule.go | 9 +- .../mhfpacket/msg_mhf_get_weekly_schedule.go | 9 +- network/mhfpacket/msg_mhf_info_festa.go | 13 +- network/mhfpacket/msg_mhf_load_deco_myset.go | 9 +- .../mhfpacket/msg_mhf_load_favorite_quest.go | 9 +- network/mhfpacket/msg_mhf_load_hunter_navi.go | 9 +- network/mhfpacket/msg_mhf_load_mezfes_data.go | 9 +- network/mhfpacket/msg_mhf_load_otomo_airou.go | 7 +- network/mhfpacket/msg_mhf_load_partner.go | 7 +- network/mhfpacket/msg_mhf_load_plate_box.go | 9 +- network/mhfpacket/msg_mhf_load_plate_data.go | 9 +- network/mhfpacket/msg_mhf_load_plate_myset.go | 9 +- .../mhfpacket/msg_mhf_load_rengoku_data.go | 9 +- .../mhfpacket/msg_mhf_load_scenario_data.go | 9 +- network/mhfpacket/msg_mhf_read_beat_level.go | 20 +- network/mhfpacket/msg_mhf_read_mercenary_w.go | 2 +- network/mhfpacket/msg_mhf_save_hunter_navi.go | 15 +- network/mhfpacket/msg_mhf_save_mezfes_data.go | 13 +- network/mhfpacket/msg_mhf_save_partner.go | 13 +- .../mhfpacket/msg_mhf_save_scenario_data.go | 13 +- network/mhfpacket/msg_mhf_savedata.go | 19 +- .../msg_mhf_set_enhanced_minidata.go | 13 +- network/mhfpacket/msg_sys_ack.go | 11 +- network/mhfpacket/msg_sys_cast_binary.go | 18 +- network/mhfpacket/msg_sys_casted_binary.go | 16 +- network/mhfpacket/msg_sys_create_object.go | 15 +- network/mhfpacket/msg_sys_end.go | 2 + network/mhfpacket/msg_sys_enter_stage.go | 15 +- network/mhfpacket/msg_sys_extend_threshold.go | 2 + network/mhfpacket/msg_sys_hide_client.go | 11 +- network/mhfpacket/msg_sys_nop.go | 2 + network/mhfpacket/msg_sys_ping.go | 3 - network/mhfpacket/msg_sys_position_object.go | 11 +- network/mhfpacket/msg_sys_reserve188.go | 9 +- network/mhfpacket/msg_sys_reserve18b.go | 9 +- .../mhfpacket/msg_sys_set_object_binary.go | 13 +- network/mhfpacket/msg_sys_set_user_binary.go | 13 +- network/mhfpacket/msg_sys_terminal_log.go | 37 +- network/mhfpacket/msg_sys_time.go | 8 +- network/mhfpacket/msg_sys_update_right.go | 49 +- server/channelserver/channel_server.go | 30 +- server/channelserver/handlers.go | 886 ++++++++++++++++-- server/channelserver/session.go | 475 ++-------- server/entranceserver/entrance_server.go | 6 +- server/entranceserver/make_resp.go | 10 + server/launcherserver/launcher_server.go | 6 +- server/launcherserver/routes.go | 2 +- server/signserver/dbutils.go | 56 ++ server/signserver/dsgn_resp.go | 103 +- server/signserver/session.go | 21 +- server/signserver/sign_server.go | 6 +- 73 files changed, 1646 insertions(+), 714 deletions(-) create mode 100644 migrations/000002_alter_characters.down.sql create mode 100644 migrations/000002_alter_characters.up.sql create mode 100644 server/signserver/dbutils.go diff --git a/.gitignore b/.gitignore index 8d6aeaab4..be42fbcb3 100644 --- a/.gitignore +++ b/.gitignore @@ -2,8 +2,10 @@ www/tw/ www/jp/ bin_resp/ +savedata/ custom_entrance_server_resp.bin dec_bin8_data_dump.bin entrance_resp_bin8_encrypted.bin tw_server_list_resp.bin -Erupe.exe \ No newline at end of file +Erupe.exe +test.py \ No newline at end of file diff --git a/config.json b/config.json index cfb58cd45..6dafbae4c 100644 --- a/config.json +++ b/config.json @@ -21,17 +21,17 @@ "port": 53310, "entries": [ { - "name": "AErupe server 1", + "name": "AErupe server noob", "ip": "127.0.0.1", "unk2": 0, - "type": 1, + "type": 3, "season": 0, - "unk6": 3, + "unk6": 0, "allowedclientflags": "4096", "channels": [ { "port": 54001, - "MaxPlayers": 100, + "MaxPlayers": 10, "CurrentPlayers": 0, "Unk4": 0, "Unk5": 0, @@ -45,6 +45,32 @@ "Unk13": 12345 } ] + }, + { + "name": "AErupe server open", + "ip": "127.0.0.1", + "unk2": 0, + "type": 1, + "season": 0, + "unk6": 0, + "allowedclientflags": 0, + "channels": [ + { + "port": 54001, + "MaxPlayers": 10, + "CurrentPlayers": 0, + "Unk4": 0, + "Unk5": 0, + "Unk6": 0, + "Unk7": 0, + "Unk8": 0, + "Unk9": 0, + "Unk10": 318, + "Unk11": 251, + "Unk12": 155, + "Unk13": 12345 + } + ] } ] } diff --git a/go.mod b/go.mod index 7f512f3a0..a2635d524 100644 --- a/go.mod +++ b/go.mod @@ -3,15 +3,17 @@ module github.com/Andoryuuta/Erupe go 1.13 require ( - github.com/Andoryuuta/byteframe v0.0.0-20191219124302-41f4085eb4c0 + github.com/Andoryuuta/byteframe v0.0.0-20200114030334-8979c5cc4c4a github.com/BurntSushi/toml v0.3.1 github.com/gorilla/handlers v1.4.2 github.com/gorilla/mux v1.7.3 + github.com/jmoiron/sqlx v1.2.0 github.com/lib/pq v1.3.0 github.com/spf13/viper v1.6.1 go.uber.org/atomic v1.5.1 // indirect go.uber.org/multierr v1.4.0 // indirect go.uber.org/zap v1.13.0 golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f // indirect + golang.org/x/text v0.3.0 golang.org/x/tools v0.0.0-20200110213125-a7a6caa82ab2 // indirect ) diff --git a/go.sum b/go.sum index b236b54e0..575a8db8b 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/Andoryuuta/byteframe v0.0.0-20191219124302-41f4085eb4c0 h1:2pVgen9rh18IxSWxOa80bObcpyfrS6d5bJtZeCUN7rY= github.com/Andoryuuta/byteframe v0.0.0-20191219124302-41f4085eb4c0/go.mod h1:koVyx+gN3TfE70rpOidywETVODk87304YpwW69Y27J4= +github.com/Andoryuuta/byteframe v0.0.0-20200114030334-8979c5cc4c4a h1:41dzqxDfdVhYjpkr8lxwrBdJe0RE/AXsGV1AGpP6wig= +github.com/Andoryuuta/byteframe v0.0.0-20200114030334-8979c5cc4c4a/go.mod h1:koVyx+gN3TfE70rpOidywETVODk87304YpwW69Y27J4= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= @@ -26,6 +28,7 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= @@ -48,6 +51,8 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/jmoiron/sqlx v1.2.0 h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA= +github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= @@ -58,10 +63,12 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.3.0 h1:/qkRGz8zljWiDcFvgpwUpwIAPu3r07TDvs3Rws+o/pU= github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= diff --git a/main.go b/main.go index 3490f8ea4..296dd248e 100644 --- a/main.go +++ b/main.go @@ -1,7 +1,6 @@ package main import ( - "database/sql" "fmt" "os" "os/signal" @@ -13,10 +12,18 @@ import ( "github.com/Andoryuuta/Erupe/server/entranceserver" "github.com/Andoryuuta/Erupe/server/launcherserver" "github.com/Andoryuuta/Erupe/server/signserver" + "github.com/jmoiron/sqlx" _ "github.com/lib/pq" "go.uber.org/zap" ) +// Temporary DB auto clean on startup for quick development & testing. +func cleanDB(db *sqlx.DB) { + _ = db.MustExec("DELETE FROM characters") + _ = db.MustExec("DELETE FROM sign_sessions") + _ = db.MustExec("DELETE FROM users") +} + func main() { zapLogger, _ := zap.NewDevelopment() defer zapLogger.Sync() @@ -40,7 +47,7 @@ func main() { erupeConfig.Database.Database, ) - db, err := sql.Open("postgres", connectString) + db, err := sqlx.Open("postgres", connectString) if err != nil { logger.Fatal("Failed to open sql database", zap.Error(err)) } @@ -50,7 +57,11 @@ func main() { if err != nil { logger.Fatal("Failed to ping database", zap.Error(err)) } - logger.Info("Connected to database.") + logger.Info("Connected to database") + + logger.Info("Cleaning DB") + cleanDB(db) + logger.Info("Done cleaning DB") // Now start our server(s). @@ -119,5 +130,5 @@ func main() { entranceServer.Shutdown() launcherServer.Shutdown() - time.Sleep(5 * time.Second) + time.Sleep(1 * time.Second) } diff --git a/migrations/000002_alter_characters.down.sql b/migrations/000002_alter_characters.down.sql new file mode 100644 index 000000000..c5eeb425b --- /dev/null +++ b/migrations/000002_alter_characters.down.sql @@ -0,0 +1,8 @@ +BEGIN; + +ALTER TABLE characters + DROP COLUMN exp, + DROP COLUMN weapon, + DROP COLUMN last_login; + +END; \ No newline at end of file diff --git a/migrations/000002_alter_characters.up.sql b/migrations/000002_alter_characters.up.sql new file mode 100644 index 000000000..8e92154dc --- /dev/null +++ b/migrations/000002_alter_characters.up.sql @@ -0,0 +1,8 @@ +BEGIN; + +ALTER TABLE characters + ADD COLUMN exp uint16, + ADD COLUMN weapon uint16, + ADD COLUMN last_login integer; + +END; \ No newline at end of file diff --git a/network/mhfpacket/msg_mhf_enumerate_order.go b/network/mhfpacket/msg_mhf_enumerate_order.go index 5c3dc0a93..a5c26eb9a 100644 --- a/network/mhfpacket/msg_mhf_enumerate_order.go +++ b/network/mhfpacket/msg_mhf_enumerate_order.go @@ -6,7 +6,11 @@ import ( ) // MsgMhfEnumerateOrder represents the MSG_MHF_ENUMERATE_ORDER -type MsgMhfEnumerateOrder struct{} +type MsgMhfEnumerateOrder struct { + AckHandle uint32 + Unk0 uint32 + Unk1 uint32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfEnumerateOrder) Opcode() network.PacketID { @@ -15,10 +19,13 @@ func (m *MsgMhfEnumerateOrder) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfEnumerateOrder) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint32() + m.Unk1 = bf.ReadUint32() + return nil } // Build builds a binary packet from the current data. func (m *MsgMhfEnumerateOrder) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/network/mhfpacket/msg_mhf_enumerate_price.go b/network/mhfpacket/msg_mhf_enumerate_price.go index ade7862c8..1e5b5fa6d 100644 --- a/network/mhfpacket/msg_mhf_enumerate_price.go +++ b/network/mhfpacket/msg_mhf_enumerate_price.go @@ -6,7 +6,11 @@ import ( ) // MsgMhfEnumeratePrice represents the MSG_MHF_ENUMERATE_PRICE -type MsgMhfEnumeratePrice struct{} +type MsgMhfEnumeratePrice struct { + AckHandle uint32 + Unk0 uint16 // Hardcoded 0 in the binary + Unk1 uint16 // Hardcoded 0 in the binary +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfEnumeratePrice) Opcode() network.PacketID { @@ -15,10 +19,13 @@ func (m *MsgMhfEnumeratePrice) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfEnumeratePrice) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint16() + m.Unk1 = bf.ReadUint16() + return nil } // Build builds a binary packet from the current data. func (m *MsgMhfEnumeratePrice) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/network/mhfpacket/msg_mhf_enumerate_shop.go b/network/mhfpacket/msg_mhf_enumerate_shop.go index 938393c44..da3ad308f 100644 --- a/network/mhfpacket/msg_mhf_enumerate_shop.go +++ b/network/mhfpacket/msg_mhf_enumerate_shop.go @@ -6,7 +6,15 @@ import ( ) // MsgMhfEnumerateShop represents the MSG_MHF_ENUMERATE_SHOP -type MsgMhfEnumerateShop struct{} +type MsgMhfEnumerateShop struct { + AckHandle uint32 + Unk0 uint8 // Shop ID maybe? I seen 0 -> 10. + Unk1 uint32 + Unk2 uint16 + Unk3 uint8 + Unk4 uint8 + Unk5 uint32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfEnumerateShop) Opcode() network.PacketID { @@ -15,10 +23,17 @@ func (m *MsgMhfEnumerateShop) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfEnumerateShop) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint8() + m.Unk1 = bf.ReadUint32() + m.Unk2 = bf.ReadUint16() + m.Unk3 = bf.ReadUint8() + m.Unk4 = bf.ReadUint8() + m.Unk5 = bf.ReadUint32() + return nil } // Build builds a binary packet from the current data. func (m *MsgMhfEnumerateShop) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/network/mhfpacket/msg_mhf_get_boost_right.go b/network/mhfpacket/msg_mhf_get_boost_right.go index d520aab3d..4b48c2203 100644 --- a/network/mhfpacket/msg_mhf_get_boost_right.go +++ b/network/mhfpacket/msg_mhf_get_boost_right.go @@ -6,7 +6,9 @@ import ( ) // MsgMhfGetBoostRight represents the MSG_MHF_GET_BOOST_RIGHT -type MsgMhfGetBoostRight struct{} +type MsgMhfGetBoostRight struct { + AckHandle uint32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfGetBoostRight) Opcode() network.PacketID { @@ -15,10 +17,11 @@ func (m *MsgMhfGetBoostRight) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfGetBoostRight) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.AckHandle = bf.ReadUint32() + return nil } // Build builds a binary packet from the current data. func (m *MsgMhfGetBoostRight) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/network/mhfpacket/msg_mhf_get_boost_time.go b/network/mhfpacket/msg_mhf_get_boost_time.go index e0bea7a18..12da72f23 100644 --- a/network/mhfpacket/msg_mhf_get_boost_time.go +++ b/network/mhfpacket/msg_mhf_get_boost_time.go @@ -6,7 +6,9 @@ import ( ) // MsgMhfGetBoostTime represents the MSG_MHF_GET_BOOST_TIME -type MsgMhfGetBoostTime struct{} +type MsgMhfGetBoostTime struct { + AckHandle uint32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfGetBoostTime) Opcode() network.PacketID { @@ -15,10 +17,11 @@ func (m *MsgMhfGetBoostTime) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfGetBoostTime) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.AckHandle = bf.ReadUint32() + return nil } // Build builds a binary packet from the current data. func (m *MsgMhfGetBoostTime) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/network/mhfpacket/msg_mhf_get_boost_time_limit.go b/network/mhfpacket/msg_mhf_get_boost_time_limit.go index d2ad3a758..0c234e12f 100644 --- a/network/mhfpacket/msg_mhf_get_boost_time_limit.go +++ b/network/mhfpacket/msg_mhf_get_boost_time_limit.go @@ -6,7 +6,9 @@ import ( ) // MsgMhfGetBoostTimeLimit represents the MSG_MHF_GET_BOOST_TIME_LIMIT -type MsgMhfGetBoostTimeLimit struct{} +type MsgMhfGetBoostTimeLimit struct { + AckHandle uint32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfGetBoostTimeLimit) Opcode() network.PacketID { @@ -15,10 +17,11 @@ func (m *MsgMhfGetBoostTimeLimit) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfGetBoostTimeLimit) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.AckHandle = bf.ReadUint32() + return nil } // Build builds a binary packet from the current data. func (m *MsgMhfGetBoostTimeLimit) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/network/mhfpacket/msg_mhf_get_earth_status.go b/network/mhfpacket/msg_mhf_get_earth_status.go index f1e699d25..0ba575040 100644 --- a/network/mhfpacket/msg_mhf_get_earth_status.go +++ b/network/mhfpacket/msg_mhf_get_earth_status.go @@ -6,7 +6,11 @@ import ( ) // MsgMhfGetEarthStatus represents the MSG_MHF_GET_EARTH_STATUS -type MsgMhfGetEarthStatus struct{} +type MsgMhfGetEarthStatus struct { + AckHandle uint32 + Unk0 uint32 + Unk1 uint32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfGetEarthStatus) Opcode() network.PacketID { @@ -15,10 +19,13 @@ func (m *MsgMhfGetEarthStatus) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfGetEarthStatus) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint32() + m.Unk1 = bf.ReadUint32() + return nil } // Build builds a binary packet from the current data. func (m *MsgMhfGetEarthStatus) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/network/mhfpacket/msg_mhf_get_earth_value.go b/network/mhfpacket/msg_mhf_get_earth_value.go index da435d462..de83c0a61 100644 --- a/network/mhfpacket/msg_mhf_get_earth_value.go +++ b/network/mhfpacket/msg_mhf_get_earth_value.go @@ -6,7 +6,16 @@ import ( ) // MsgMhfGetEarthValue represents the MSG_MHF_GET_EARTH_VALUE -type MsgMhfGetEarthValue struct{} +type MsgMhfGetEarthValue struct { + AckHandle uint32 + Unk0 uint32 + Unk1 uint32 + Unk2 uint32 + Unk3 uint32 + Unk4 uint32 + Unk5 uint32 + Unk6 uint32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfGetEarthValue) Opcode() network.PacketID { @@ -15,10 +24,18 @@ func (m *MsgMhfGetEarthValue) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfGetEarthValue) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint32() + m.Unk1 = bf.ReadUint32() + m.Unk2 = bf.ReadUint32() + m.Unk3 = bf.ReadUint32() + m.Unk4 = bf.ReadUint32() + m.Unk5 = bf.ReadUint32() + m.Unk6 = bf.ReadUint32() + return nil } // Build builds a binary packet from the current data. func (m *MsgMhfGetEarthValue) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/network/mhfpacket/msg_mhf_get_enhanced_minidata.go b/network/mhfpacket/msg_mhf_get_enhanced_minidata.go index cf2d56592..ff03df97a 100644 --- a/network/mhfpacket/msg_mhf_get_enhanced_minidata.go +++ b/network/mhfpacket/msg_mhf_get_enhanced_minidata.go @@ -6,7 +6,10 @@ import ( ) // MsgMhfGetEnhancedMinidata represents the MSG_MHF_GET_ENHANCED_MINIDATA -type MsgMhfGetEnhancedMinidata struct{} +type MsgMhfGetEnhancedMinidata struct { + AckHandle uint32 + CharID uint32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfGetEnhancedMinidata) Opcode() network.PacketID { @@ -15,10 +18,12 @@ func (m *MsgMhfGetEnhancedMinidata) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfGetEnhancedMinidata) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.AckHandle = bf.ReadUint32() + m.CharID = bf.ReadUint32() + return nil } // Build builds a binary packet from the current data. func (m *MsgMhfGetEnhancedMinidata) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/network/mhfpacket/msg_mhf_get_keep_login_boost_status.go b/network/mhfpacket/msg_mhf_get_keep_login_boost_status.go index 9ca1ed5a1..43022755a 100644 --- a/network/mhfpacket/msg_mhf_get_keep_login_boost_status.go +++ b/network/mhfpacket/msg_mhf_get_keep_login_boost_status.go @@ -6,7 +6,9 @@ import ( ) // MsgMhfGetKeepLoginBoostStatus represents the MSG_MHF_GET_KEEP_LOGIN_BOOST_STATUS -type MsgMhfGetKeepLoginBoostStatus struct{} +type MsgMhfGetKeepLoginBoostStatus struct { + AckHandle uint32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfGetKeepLoginBoostStatus) Opcode() network.PacketID { @@ -15,10 +17,11 @@ func (m *MsgMhfGetKeepLoginBoostStatus) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfGetKeepLoginBoostStatus) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.AckHandle = bf.ReadUint32() + return nil } // Build builds a binary packet from the current data. func (m *MsgMhfGetKeepLoginBoostStatus) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/network/mhfpacket/msg_mhf_get_kouryou_point.go b/network/mhfpacket/msg_mhf_get_kouryou_point.go index 434c07876..e279509da 100644 --- a/network/mhfpacket/msg_mhf_get_kouryou_point.go +++ b/network/mhfpacket/msg_mhf_get_kouryou_point.go @@ -6,7 +6,9 @@ import ( ) // MsgMhfGetKouryouPoint represents the MSG_MHF_GET_KOURYOU_POINT -type MsgMhfGetKouryouPoint struct{} +type MsgMhfGetKouryouPoint struct { + AckHandle uint32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfGetKouryouPoint) Opcode() network.PacketID { @@ -15,10 +17,11 @@ func (m *MsgMhfGetKouryouPoint) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfGetKouryouPoint) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.AckHandle = bf.ReadUint32() + return nil } // Build builds a binary packet from the current data. func (m *MsgMhfGetKouryouPoint) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/network/mhfpacket/msg_mhf_get_paper_data.go b/network/mhfpacket/msg_mhf_get_paper_data.go index 7782f6f0f..19d5207f6 100644 --- a/network/mhfpacket/msg_mhf_get_paper_data.go +++ b/network/mhfpacket/msg_mhf_get_paper_data.go @@ -6,7 +6,12 @@ import ( ) // MsgMhfGetPaperData represents the MSG_MHF_GET_PAPER_DATA -type MsgMhfGetPaperData struct{} +type MsgMhfGetPaperData struct { + AckHandle uint32 + Unk0 uint32 + Unk1 uint32 + Unk2 uint32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfGetPaperData) Opcode() network.PacketID { @@ -15,10 +20,14 @@ func (m *MsgMhfGetPaperData) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfGetPaperData) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint32() + m.Unk1 = bf.ReadUint32() + m.Unk2 = bf.ReadUint32() + return nil } // Build builds a binary packet from the current data. func (m *MsgMhfGetPaperData) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/network/mhfpacket/msg_mhf_get_tower_info.go b/network/mhfpacket/msg_mhf_get_tower_info.go index c2bbcdf62..5cb86cbc7 100644 --- a/network/mhfpacket/msg_mhf_get_tower_info.go +++ b/network/mhfpacket/msg_mhf_get_tower_info.go @@ -5,8 +5,23 @@ import ( "github.com/Andoryuuta/byteframe" ) +// The server sends different responses based on these values. +const ( + TowerInfoTypeUnk0 = iota + TowerInfoTypeTowerRankPoint + TowerInfoTypeGetOwnTowerSkill + TowerInfoTypeUnk3 + TowerInfoTypeTowerTouhaHistory + TowerInfoTypeUnk5 +) + // MsgMhfGetTowerInfo represents the MSG_MHF_GET_TOWER_INFO -type MsgMhfGetTowerInfo struct{} +type MsgMhfGetTowerInfo struct { + AckHandle uint32 + InfoType uint32 // Requested response type + Unk0 uint32 + Unk1 uint32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfGetTowerInfo) Opcode() network.PacketID { @@ -15,10 +30,14 @@ func (m *MsgMhfGetTowerInfo) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfGetTowerInfo) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.AckHandle = bf.ReadUint32() + m.InfoType = bf.ReadUint32() + m.Unk0 = bf.ReadUint32() + m.Unk1 = bf.ReadUint32() + return nil } // Build builds a binary packet from the current data. func (m *MsgMhfGetTowerInfo) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/network/mhfpacket/msg_mhf_get_ud_info.go b/network/mhfpacket/msg_mhf_get_ud_info.go index d73402c97..0647fb198 100644 --- a/network/mhfpacket/msg_mhf_get_ud_info.go +++ b/network/mhfpacket/msg_mhf_get_ud_info.go @@ -6,7 +6,9 @@ import ( ) // MsgMhfGetUdInfo represents the MSG_MHF_GET_UD_INFO -type MsgMhfGetUdInfo struct{} +type MsgMhfGetUdInfo struct { + AckHandle uint32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfGetUdInfo) Opcode() network.PacketID { @@ -15,10 +17,11 @@ func (m *MsgMhfGetUdInfo) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfGetUdInfo) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.AckHandle = bf.ReadUint32() + return nil } // Build builds a binary packet from the current data. func (m *MsgMhfGetUdInfo) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/network/mhfpacket/msg_mhf_get_ud_monster_point.go b/network/mhfpacket/msg_mhf_get_ud_monster_point.go index 01de9256b..1311541ed 100644 --- a/network/mhfpacket/msg_mhf_get_ud_monster_point.go +++ b/network/mhfpacket/msg_mhf_get_ud_monster_point.go @@ -6,7 +6,9 @@ import ( ) // MsgMhfGetUdMonsterPoint represents the MSG_MHF_GET_UD_MONSTER_POINT -type MsgMhfGetUdMonsterPoint struct{} +type MsgMhfGetUdMonsterPoint struct { + AckHandle uint32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfGetUdMonsterPoint) Opcode() network.PacketID { @@ -15,10 +17,11 @@ func (m *MsgMhfGetUdMonsterPoint) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfGetUdMonsterPoint) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.AckHandle = bf.ReadUint32() + return nil } // Build builds a binary packet from the current data. func (m *MsgMhfGetUdMonsterPoint) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/network/mhfpacket/msg_mhf_get_ud_schedule.go b/network/mhfpacket/msg_mhf_get_ud_schedule.go index bbe23ea56..f543cce0c 100644 --- a/network/mhfpacket/msg_mhf_get_ud_schedule.go +++ b/network/mhfpacket/msg_mhf_get_ud_schedule.go @@ -6,7 +6,9 @@ import ( ) // MsgMhfGetUdSchedule represents the MSG_MHF_GET_UD_SCHEDULE -type MsgMhfGetUdSchedule struct{} +type MsgMhfGetUdSchedule struct { + AckHandle uint32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfGetUdSchedule) Opcode() network.PacketID { @@ -15,10 +17,11 @@ func (m *MsgMhfGetUdSchedule) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfGetUdSchedule) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.AckHandle = bf.ReadUint32() + return nil } // Build builds a binary packet from the current data. func (m *MsgMhfGetUdSchedule) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/network/mhfpacket/msg_mhf_get_weekly_schedule.go b/network/mhfpacket/msg_mhf_get_weekly_schedule.go index b6458028b..c8a01cb7b 100644 --- a/network/mhfpacket/msg_mhf_get_weekly_schedule.go +++ b/network/mhfpacket/msg_mhf_get_weekly_schedule.go @@ -6,7 +6,9 @@ import ( ) // MsgMhfGetWeeklySchedule represents the MSG_MHF_GET_WEEKLY_SCHEDULE -type MsgMhfGetWeeklySchedule struct{} +type MsgMhfGetWeeklySchedule struct { + AckHandle uint32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfGetWeeklySchedule) Opcode() network.PacketID { @@ -15,10 +17,11 @@ func (m *MsgMhfGetWeeklySchedule) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfGetWeeklySchedule) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.AckHandle = bf.ReadUint32() + return nil } // Build builds a binary packet from the current data. func (m *MsgMhfGetWeeklySchedule) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/network/mhfpacket/msg_mhf_info_festa.go b/network/mhfpacket/msg_mhf_info_festa.go index 0e65fac3d..f376f77ff 100644 --- a/network/mhfpacket/msg_mhf_info_festa.go +++ b/network/mhfpacket/msg_mhf_info_festa.go @@ -6,7 +6,11 @@ import ( ) // MsgMhfInfoFesta represents the MSG_MHF_INFO_FESTA -type MsgMhfInfoFesta struct{} +type MsgMhfInfoFesta struct { + AckHandle uint32 + Unk0 uint16 // Hardcoded 0 in the binary + Unk1 uint16 // Hardcoded 0 in the binary +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfInfoFesta) Opcode() network.PacketID { @@ -15,10 +19,13 @@ func (m *MsgMhfInfoFesta) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfInfoFesta) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint16() + m.Unk1 = bf.ReadUint16() + return nil } // Build builds a binary packet from the current data. func (m *MsgMhfInfoFesta) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/network/mhfpacket/msg_mhf_load_deco_myset.go b/network/mhfpacket/msg_mhf_load_deco_myset.go index 9b0040f9d..e2f97f326 100644 --- a/network/mhfpacket/msg_mhf_load_deco_myset.go +++ b/network/mhfpacket/msg_mhf_load_deco_myset.go @@ -6,7 +6,9 @@ import ( ) // MsgMhfLoadDecoMyset represents the MSG_MHF_LOAD_DECO_MYSET -type MsgMhfLoadDecoMyset struct{} +type MsgMhfLoadDecoMyset struct { + AckHandle uint32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfLoadDecoMyset) Opcode() network.PacketID { @@ -15,10 +17,11 @@ func (m *MsgMhfLoadDecoMyset) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfLoadDecoMyset) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.AckHandle = bf.ReadUint32() + return nil } // Build builds a binary packet from the current data. func (m *MsgMhfLoadDecoMyset) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/network/mhfpacket/msg_mhf_load_favorite_quest.go b/network/mhfpacket/msg_mhf_load_favorite_quest.go index b1da3c9f5..f3224962a 100644 --- a/network/mhfpacket/msg_mhf_load_favorite_quest.go +++ b/network/mhfpacket/msg_mhf_load_favorite_quest.go @@ -6,7 +6,9 @@ import ( ) // MsgMhfLoadFavoriteQuest represents the MSG_MHF_LOAD_FAVORITE_QUEST -type MsgMhfLoadFavoriteQuest struct{} +type MsgMhfLoadFavoriteQuest struct { + AckHandle uint32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfLoadFavoriteQuest) Opcode() network.PacketID { @@ -15,10 +17,11 @@ func (m *MsgMhfLoadFavoriteQuest) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfLoadFavoriteQuest) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.AckHandle = bf.ReadUint32() + return nil } // Build builds a binary packet from the current data. func (m *MsgMhfLoadFavoriteQuest) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/network/mhfpacket/msg_mhf_load_hunter_navi.go b/network/mhfpacket/msg_mhf_load_hunter_navi.go index fb30a0562..777e983a7 100644 --- a/network/mhfpacket/msg_mhf_load_hunter_navi.go +++ b/network/mhfpacket/msg_mhf_load_hunter_navi.go @@ -6,7 +6,9 @@ import ( ) // MsgMhfLoadHunterNavi represents the MSG_MHF_LOAD_HUNTER_NAVI -type MsgMhfLoadHunterNavi struct{} +type MsgMhfLoadHunterNavi struct { + AckHandle uint32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfLoadHunterNavi) Opcode() network.PacketID { @@ -15,10 +17,11 @@ func (m *MsgMhfLoadHunterNavi) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfLoadHunterNavi) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.AckHandle = bf.ReadUint32() + return nil } // Build builds a binary packet from the current data. func (m *MsgMhfLoadHunterNavi) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/network/mhfpacket/msg_mhf_load_mezfes_data.go b/network/mhfpacket/msg_mhf_load_mezfes_data.go index 1e265f3a6..4f31a61e9 100644 --- a/network/mhfpacket/msg_mhf_load_mezfes_data.go +++ b/network/mhfpacket/msg_mhf_load_mezfes_data.go @@ -6,7 +6,9 @@ import ( ) // MsgMhfLoadMezfesData represents the MSG_MHF_LOAD_MEZFES_DATA -type MsgMhfLoadMezfesData struct{} +type MsgMhfLoadMezfesData struct { + AckHandle uint32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfLoadMezfesData) Opcode() network.PacketID { @@ -15,10 +17,11 @@ func (m *MsgMhfLoadMezfesData) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfLoadMezfesData) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.AckHandle = bf.ReadUint32() + return nil } // Build builds a binary packet from the current data. func (m *MsgMhfLoadMezfesData) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/network/mhfpacket/msg_mhf_load_otomo_airou.go b/network/mhfpacket/msg_mhf_load_otomo_airou.go index bf3bbdbe8..33b7dc92c 100644 --- a/network/mhfpacket/msg_mhf_load_otomo_airou.go +++ b/network/mhfpacket/msg_mhf_load_otomo_airou.go @@ -6,7 +6,9 @@ import ( ) // MsgMhfLoadOtomoAirou represents the MSG_MHF_LOAD_OTOMO_AIROU -type MsgMhfLoadOtomoAirou struct{} +type MsgMhfLoadOtomoAirou struct{ + AckHandle uint32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfLoadOtomoAirou) Opcode() network.PacketID { @@ -15,7 +17,8 @@ func (m *MsgMhfLoadOtomoAirou) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfLoadOtomoAirou) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.AckHandle = bf.ReadUint32() + return nil } // Build builds a binary packet from the current data. diff --git a/network/mhfpacket/msg_mhf_load_partner.go b/network/mhfpacket/msg_mhf_load_partner.go index 63b0e9a53..703308a2e 100644 --- a/network/mhfpacket/msg_mhf_load_partner.go +++ b/network/mhfpacket/msg_mhf_load_partner.go @@ -6,7 +6,9 @@ import ( ) // MsgMhfLoadPartner represents the MSG_MHF_LOAD_PARTNER -type MsgMhfLoadPartner struct{} +type MsgMhfLoadPartner struct{ + AckHandle uint32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfLoadPartner) Opcode() network.PacketID { @@ -15,7 +17,8 @@ func (m *MsgMhfLoadPartner) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfLoadPartner) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.AckHandle = bf.ReadUint32() + return nil } // Build builds a binary packet from the current data. diff --git a/network/mhfpacket/msg_mhf_load_plate_box.go b/network/mhfpacket/msg_mhf_load_plate_box.go index 8625e2038..b6d2e2ca2 100644 --- a/network/mhfpacket/msg_mhf_load_plate_box.go +++ b/network/mhfpacket/msg_mhf_load_plate_box.go @@ -6,7 +6,9 @@ import ( ) // MsgMhfLoadPlateBox represents the MSG_MHF_LOAD_PLATE_BOX -type MsgMhfLoadPlateBox struct{} +type MsgMhfLoadPlateBox struct { + AckHandle uint32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfLoadPlateBox) Opcode() network.PacketID { @@ -15,10 +17,11 @@ func (m *MsgMhfLoadPlateBox) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfLoadPlateBox) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.AckHandle = bf.ReadUint32() + return nil } // Build builds a binary packet from the current data. func (m *MsgMhfLoadPlateBox) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/network/mhfpacket/msg_mhf_load_plate_data.go b/network/mhfpacket/msg_mhf_load_plate_data.go index 5fc835c06..f7b16339c 100644 --- a/network/mhfpacket/msg_mhf_load_plate_data.go +++ b/network/mhfpacket/msg_mhf_load_plate_data.go @@ -6,7 +6,9 @@ import ( ) // MsgMhfLoadPlateData represents the MSG_MHF_LOAD_PLATE_DATA -type MsgMhfLoadPlateData struct{} +type MsgMhfLoadPlateData struct { + AckHandle uint32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfLoadPlateData) Opcode() network.PacketID { @@ -15,10 +17,11 @@ func (m *MsgMhfLoadPlateData) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfLoadPlateData) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.AckHandle = bf.ReadUint32() + return nil } // Build builds a binary packet from the current data. func (m *MsgMhfLoadPlateData) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/network/mhfpacket/msg_mhf_load_plate_myset.go b/network/mhfpacket/msg_mhf_load_plate_myset.go index 831d807ce..429f62c37 100644 --- a/network/mhfpacket/msg_mhf_load_plate_myset.go +++ b/network/mhfpacket/msg_mhf_load_plate_myset.go @@ -6,7 +6,9 @@ import ( ) // MsgMhfLoadPlateMyset represents the MSG_MHF_LOAD_PLATE_MYSET -type MsgMhfLoadPlateMyset struct{} +type MsgMhfLoadPlateMyset struct { + AckHandle uint32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfLoadPlateMyset) Opcode() network.PacketID { @@ -15,10 +17,11 @@ func (m *MsgMhfLoadPlateMyset) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfLoadPlateMyset) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.AckHandle = bf.ReadUint32() + return nil } // Build builds a binary packet from the current data. func (m *MsgMhfLoadPlateMyset) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/network/mhfpacket/msg_mhf_load_rengoku_data.go b/network/mhfpacket/msg_mhf_load_rengoku_data.go index 9005716a8..98c9396cf 100644 --- a/network/mhfpacket/msg_mhf_load_rengoku_data.go +++ b/network/mhfpacket/msg_mhf_load_rengoku_data.go @@ -6,7 +6,9 @@ import ( ) // MsgMhfLoadRengokuData represents the MSG_MHF_LOAD_RENGOKU_DATA -type MsgMhfLoadRengokuData struct{} +type MsgMhfLoadRengokuData struct { + AckHandle uint32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfLoadRengokuData) Opcode() network.PacketID { @@ -15,10 +17,11 @@ func (m *MsgMhfLoadRengokuData) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfLoadRengokuData) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.AckHandle = bf.ReadUint32() + return nil } // Build builds a binary packet from the current data. func (m *MsgMhfLoadRengokuData) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/network/mhfpacket/msg_mhf_load_scenario_data.go b/network/mhfpacket/msg_mhf_load_scenario_data.go index b115c0712..911a555c0 100644 --- a/network/mhfpacket/msg_mhf_load_scenario_data.go +++ b/network/mhfpacket/msg_mhf_load_scenario_data.go @@ -6,7 +6,9 @@ import ( ) // MsgMhfLoadScenarioData represents the MSG_MHF_LOAD_SCENARIO_DATA -type MsgMhfLoadScenarioData struct{} +type MsgMhfLoadScenarioData struct { + AckHandle uint32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfLoadScenarioData) Opcode() network.PacketID { @@ -15,10 +17,11 @@ func (m *MsgMhfLoadScenarioData) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfLoadScenarioData) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.AckHandle = bf.ReadUint32() + return nil } // Build builds a binary packet from the current data. func (m *MsgMhfLoadScenarioData) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/network/mhfpacket/msg_mhf_read_beat_level.go b/network/mhfpacket/msg_mhf_read_beat_level.go index 85a6cd334..2110c580c 100644 --- a/network/mhfpacket/msg_mhf_read_beat_level.go +++ b/network/mhfpacket/msg_mhf_read_beat_level.go @@ -6,7 +6,12 @@ import ( ) // MsgMhfReadBeatLevel represents the MSG_MHF_READ_BEAT_LEVEL -type MsgMhfReadBeatLevel struct{} +type MsgMhfReadBeatLevel struct { + AckHandle uint32 + Unk0 uint32 + ValidIDCount uint32 // Valid entries in the array + IDs [16]uint32 +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfReadBeatLevel) Opcode() network.PacketID { @@ -15,10 +20,19 @@ func (m *MsgMhfReadBeatLevel) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfReadBeatLevel) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + // I assume this used to be dynamic, but as of the last JP client version, all of this data is hard-coded literals. + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint32() // Always 1 + m.ValidIDCount = bf.ReadUint32() // Always 4 + + // Always 0x74, 0x6B, 0x02, 0x24 followed by 12 zero values. + for i := 0; i < len(m.IDs); i++ { + m.IDs[i] = bf.ReadUint32() + } + return nil } // Build builds a binary packet from the current data. func (m *MsgMhfReadBeatLevel) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/network/mhfpacket/msg_mhf_read_mercenary_w.go b/network/mhfpacket/msg_mhf_read_mercenary_w.go index 89aa4a530..cfd4c6719 100644 --- a/network/mhfpacket/msg_mhf_read_mercenary_w.go +++ b/network/mhfpacket/msg_mhf_read_mercenary_w.go @@ -10,7 +10,7 @@ type MsgMhfReadMercenaryW struct { AckHandle uint32 Unk0 uint8 Unk1 uint8 - Unk2 uint16 + Unk2 uint16 // Hardcoded 0 in the binary } // Opcode returns the ID associated with this packet type. diff --git a/network/mhfpacket/msg_mhf_save_hunter_navi.go b/network/mhfpacket/msg_mhf_save_hunter_navi.go index d62f39254..36b1bdbc1 100644 --- a/network/mhfpacket/msg_mhf_save_hunter_navi.go +++ b/network/mhfpacket/msg_mhf_save_hunter_navi.go @@ -6,7 +6,12 @@ import ( ) // MsgMhfSaveHunterNavi represents the MSG_MHF_SAVE_HUNTER_NAVI -type MsgMhfSaveHunterNavi struct{} +type MsgMhfSaveHunterNavi struct { + AckHandle uint32 + DataSize uint32 + Unk0 bool + RawDataPayload []byte +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfSaveHunterNavi) Opcode() network.PacketID { @@ -15,10 +20,14 @@ func (m *MsgMhfSaveHunterNavi) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfSaveHunterNavi) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.AckHandle = bf.ReadUint32() + m.DataSize = bf.ReadUint32() + m.Unk0 = bf.ReadBool() + m.RawDataPayload = bf.ReadBytes(uint(m.DataSize)) + return nil } // Build builds a binary packet from the current data. func (m *MsgMhfSaveHunterNavi) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/network/mhfpacket/msg_mhf_save_mezfes_data.go b/network/mhfpacket/msg_mhf_save_mezfes_data.go index 0c7daa000..96746627f 100644 --- a/network/mhfpacket/msg_mhf_save_mezfes_data.go +++ b/network/mhfpacket/msg_mhf_save_mezfes_data.go @@ -6,7 +6,11 @@ import ( ) // MsgMhfSaveMezfesData represents the MSG_MHF_SAVE_MEZFES_DATA -type MsgMhfSaveMezfesData struct{} +type MsgMhfSaveMezfesData struct { + AckHandle uint32 + DataSize uint32 + RawDataPayload []byte +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfSaveMezfesData) Opcode() network.PacketID { @@ -15,10 +19,13 @@ func (m *MsgMhfSaveMezfesData) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfSaveMezfesData) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.AckHandle = bf.ReadUint32() + m.DataSize = bf.ReadUint32() + m.RawDataPayload = bf.ReadBytes(uint(m.DataSize)) + return nil } // Build builds a binary packet from the current data. func (m *MsgMhfSaveMezfesData) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/network/mhfpacket/msg_mhf_save_partner.go b/network/mhfpacket/msg_mhf_save_partner.go index 0bdb84b8c..ee341ab55 100644 --- a/network/mhfpacket/msg_mhf_save_partner.go +++ b/network/mhfpacket/msg_mhf_save_partner.go @@ -6,7 +6,11 @@ import ( ) // MsgMhfSavePartner represents the MSG_MHF_SAVE_PARTNER -type MsgMhfSavePartner struct{} +type MsgMhfSavePartner struct { + AckHandle uint32 + DataSize uint16 + RawDataPayload []byte +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfSavePartner) Opcode() network.PacketID { @@ -15,10 +19,13 @@ func (m *MsgMhfSavePartner) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfSavePartner) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.AckHandle = bf.ReadUint32() + m.DataSize = bf.ReadUint16() + m.RawDataPayload = bf.ReadBytes(uint(m.DataSize)) + return nil } // Build builds a binary packet from the current data. func (m *MsgMhfSavePartner) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/network/mhfpacket/msg_mhf_save_scenario_data.go b/network/mhfpacket/msg_mhf_save_scenario_data.go index 6b4ce46a9..7b2d880e0 100644 --- a/network/mhfpacket/msg_mhf_save_scenario_data.go +++ b/network/mhfpacket/msg_mhf_save_scenario_data.go @@ -6,7 +6,11 @@ import ( ) // MsgMhfSaveScenarioData represents the MSG_MHF_SAVE_SCENARIO_DATA -type MsgMhfSaveScenarioData struct{} +type MsgMhfSaveScenarioData struct { + AckHandle uint32 + DataSize uint32 + RawDataPayload []byte +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfSaveScenarioData) Opcode() network.PacketID { @@ -15,10 +19,13 @@ func (m *MsgMhfSaveScenarioData) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfSaveScenarioData) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.AckHandle = bf.ReadUint32() + m.DataSize = bf.ReadUint32() + m.RawDataPayload = bf.ReadBytes(uint(m.DataSize)) + return nil } // Build builds a binary packet from the current data. func (m *MsgMhfSaveScenarioData) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/network/mhfpacket/msg_mhf_savedata.go b/network/mhfpacket/msg_mhf_savedata.go index 76ca02722..556d4f3ab 100644 --- a/network/mhfpacket/msg_mhf_savedata.go +++ b/network/mhfpacket/msg_mhf_savedata.go @@ -6,7 +6,14 @@ import ( ) // MsgMhfSavedata represents the MSG_MHF_SAVEDATA -type MsgMhfSavedata struct{} +type MsgMhfSavedata struct { + AckHandle uint32 + AllocMemSize uint32 + Unk0 uint8 // Either 1 or 2, representing a true or false value for some reason. + Unk1 uint32 + DataSize uint32 + RawDataPayload []byte +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfSavedata) Opcode() network.PacketID { @@ -15,10 +22,16 @@ func (m *MsgMhfSavedata) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfSavedata) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.AckHandle = bf.ReadUint32() + m.AllocMemSize = bf.ReadUint32() + m.Unk0 = bf.ReadUint8() + m.Unk1 = bf.ReadUint32() + m.DataSize = bf.ReadUint32() + m.RawDataPayload = bf.ReadBytes(uint(m.DataSize)) + return nil } // Build builds a binary packet from the current data. func (m *MsgMhfSavedata) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/network/mhfpacket/msg_mhf_set_enhanced_minidata.go b/network/mhfpacket/msg_mhf_set_enhanced_minidata.go index cae548e7c..3ab5ac480 100644 --- a/network/mhfpacket/msg_mhf_set_enhanced_minidata.go +++ b/network/mhfpacket/msg_mhf_set_enhanced_minidata.go @@ -6,7 +6,11 @@ import ( ) // MsgMhfSetEnhancedMinidata represents the MSG_MHF_SET_ENHANCED_MINIDATA -type MsgMhfSetEnhancedMinidata struct{} +type MsgMhfSetEnhancedMinidata struct { + AckHandle uint32 + Unk0 uint16 // Hardcoded 4 in the binary. + RawDataPayload []byte +} // Opcode returns the ID associated with this packet type. func (m *MsgMhfSetEnhancedMinidata) Opcode() network.PacketID { @@ -15,10 +19,13 @@ func (m *MsgMhfSetEnhancedMinidata) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgMhfSetEnhancedMinidata) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint16() + m.RawDataPayload = bf.ReadBytes(0x400) + return nil } // Build builds a binary packet from the current data. func (m *MsgMhfSetEnhancedMinidata) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/network/mhfpacket/msg_sys_ack.go b/network/mhfpacket/msg_sys_ack.go index 978e0f5d6..0b8dccad5 100644 --- a/network/mhfpacket/msg_sys_ack.go +++ b/network/mhfpacket/msg_sys_ack.go @@ -8,8 +8,7 @@ import ( // MsgSysAck represents the MSG_SYS_ACK type MsgSysAck struct { AckHandle uint32 - Unk0 uint32 - Unk1 uint32 + AckData []byte } // Opcode returns the ID associated with this packet type. @@ -20,16 +19,12 @@ func (m *MsgSysAck) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgSysAck) Parse(bf *byteframe.ByteFrame) error { m.AckHandle = bf.ReadUint32() - m.Unk0 = bf.ReadUint32() - m.Unk1 = bf.ReadUint32() - - return nil + panic("No way to parse without prior context as the packet doesn't include it's own length.") } // Build builds a binary packet from the current data. func (m *MsgSysAck) Build(bf *byteframe.ByteFrame) error { bf.WriteUint32(m.AckHandle) - bf.WriteUint32(m.Unk0) - bf.WriteUint32(m.Unk1) + bf.WriteBytes(m.AckData) return nil } diff --git a/network/mhfpacket/msg_sys_cast_binary.go b/network/mhfpacket/msg_sys_cast_binary.go index 69c9a727b..90667fd36 100644 --- a/network/mhfpacket/msg_sys_cast_binary.go +++ b/network/mhfpacket/msg_sys_cast_binary.go @@ -6,7 +6,13 @@ import ( ) // MsgSysCastBinary represents the MSG_SYS_CAST_BINARY -type MsgSysCastBinary struct{} +type MsgSysCastBinary struct { + Unk0 uint16 + Unk1 uint16 + Type0 uint8 + Type1 uint8 + RawDataPayload []byte +} // Opcode returns the ID associated with this packet type. func (m *MsgSysCastBinary) Opcode() network.PacketID { @@ -15,10 +21,16 @@ func (m *MsgSysCastBinary) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgSysCastBinary) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.Unk0 = bf.ReadUint16() + m.Unk1 = bf.ReadUint16() + m.Type0 = bf.ReadUint8() + m.Type1 = bf.ReadUint8() + dataSize := bf.ReadUint16() + m.RawDataPayload = bf.ReadBytes(uint(dataSize)) + return nil } // Build builds a binary packet from the current data. func (m *MsgSysCastBinary) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/network/mhfpacket/msg_sys_casted_binary.go b/network/mhfpacket/msg_sys_casted_binary.go index aeddac73c..d2c0145d4 100644 --- a/network/mhfpacket/msg_sys_casted_binary.go +++ b/network/mhfpacket/msg_sys_casted_binary.go @@ -6,7 +6,12 @@ import ( ) // MsgSysCastedBinary represents the MSG_SYS_CASTED_BINARY -type MsgSysCastedBinary struct{} +type MsgSysCastedBinary struct { + CharID uint32 + Type0 uint8 + Type1 uint8 + RawDataPayload []byte +} // Opcode returns the ID associated with this packet type. func (m *MsgSysCastedBinary) Opcode() network.PacketID { @@ -20,5 +25,10 @@ func (m *MsgSysCastedBinary) Parse(bf *byteframe.ByteFrame) error { // Build builds a binary packet from the current data. func (m *MsgSysCastedBinary) Build(bf *byteframe.ByteFrame) error { - panic("Not implemented") -} \ No newline at end of file + bf.WriteUint32(m.CharID) + bf.WriteUint8(m.Type0) + bf.WriteUint8(m.Type0) + bf.WriteUint16(uint16(len(m.RawDataPayload))) + bf.WriteBytes(m.RawDataPayload) + return nil +} diff --git a/network/mhfpacket/msg_sys_create_object.go b/network/mhfpacket/msg_sys_create_object.go index 42c23b337..107e982be 100644 --- a/network/mhfpacket/msg_sys_create_object.go +++ b/network/mhfpacket/msg_sys_create_object.go @@ -6,7 +6,11 @@ import ( ) // MsgSysCreateObject represents the MSG_SYS_CREATE_OBJECT -type MsgSysCreateObject struct{} +type MsgSysCreateObject struct { + AckHandle uint32 + X, Y, Z float32 + Unk0 uint32 +} // Opcode returns the ID associated with this packet type. func (m *MsgSysCreateObject) Opcode() network.PacketID { @@ -15,10 +19,15 @@ func (m *MsgSysCreateObject) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgSysCreateObject) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.AckHandle = bf.ReadUint32() + m.X = bf.ReadFloat32() + m.Y = bf.ReadFloat32() + m.Z = bf.ReadFloat32() + m.Unk0 = bf.ReadUint32() + return nil } // Build builds a binary packet from the current data. func (m *MsgSysCreateObject) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/network/mhfpacket/msg_sys_end.go b/network/mhfpacket/msg_sys_end.go index f6c874657..07da6c0ce 100644 --- a/network/mhfpacket/msg_sys_end.go +++ b/network/mhfpacket/msg_sys_end.go @@ -15,10 +15,12 @@ func (m *MsgSysEnd) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgSysEnd) Parse(bf *byteframe.ByteFrame) error { + // No data aside from opcode. return nil } // Build builds a binary packet from the current data. func (m *MsgSysEnd) Build(bf *byteframe.ByteFrame) error { + // No data aside from opcode. return nil } diff --git a/network/mhfpacket/msg_sys_enter_stage.go b/network/mhfpacket/msg_sys_enter_stage.go index 8dd614b92..ee8391988 100644 --- a/network/mhfpacket/msg_sys_enter_stage.go +++ b/network/mhfpacket/msg_sys_enter_stage.go @@ -6,7 +6,12 @@ import ( ) // MsgSysEnterStage represents the MSG_SYS_ENTER_STAGE -type MsgSysEnterStage struct{} +type MsgSysEnterStage struct { + AckHandle uint32 + UnkBool uint8 + StageIDLength uint8 + StageID []byte +} // Opcode returns the ID associated with this packet type. func (m *MsgSysEnterStage) Opcode() network.PacketID { @@ -15,10 +20,14 @@ func (m *MsgSysEnterStage) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgSysEnterStage) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.AckHandle = bf.ReadUint32() + m.UnkBool = bf.ReadUint8() + m.StageIDLength = bf.ReadUint8() + m.StageID = bf.ReadBytes(uint(m.StageIDLength)) + return nil } // Build builds a binary packet from the current data. func (m *MsgSysEnterStage) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/network/mhfpacket/msg_sys_extend_threshold.go b/network/mhfpacket/msg_sys_extend_threshold.go index f07dc384d..7058b42f8 100644 --- a/network/mhfpacket/msg_sys_extend_threshold.go +++ b/network/mhfpacket/msg_sys_extend_threshold.go @@ -15,10 +15,12 @@ func (m *MsgSysExtendThreshold) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgSysExtendThreshold) Parse(bf *byteframe.ByteFrame) error { + // No data aside from opcode. return nil } // Build builds a binary packet from the current data. func (m *MsgSysExtendThreshold) Build(bf *byteframe.ByteFrame) error { + // No data aside from opcode. return nil } diff --git a/network/mhfpacket/msg_sys_hide_client.go b/network/mhfpacket/msg_sys_hide_client.go index 95ff37edc..181305088 100644 --- a/network/mhfpacket/msg_sys_hide_client.go +++ b/network/mhfpacket/msg_sys_hide_client.go @@ -6,7 +6,11 @@ import ( ) // MsgSysHideClient represents the MSG_SYS_HIDE_CLIENT -type MsgSysHideClient struct{} +type MsgSysHideClient struct{ + Hide bool + Unk0 uint16 // Hardcoded 0 in binary + Unk1 uint8 // Hardcoded 0 in binary +} // Opcode returns the ID associated with this packet type. func (m *MsgSysHideClient) Opcode() network.PacketID { @@ -15,7 +19,10 @@ func (m *MsgSysHideClient) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgSysHideClient) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.Hide = bf.ReadBool() + m.Unk0 = bf.ReadUint16() + m.Unk1 = bf.ReadUint8() + return nil } // Build builds a binary packet from the current data. diff --git a/network/mhfpacket/msg_sys_nop.go b/network/mhfpacket/msg_sys_nop.go index e769142cd..6b56434a7 100644 --- a/network/mhfpacket/msg_sys_nop.go +++ b/network/mhfpacket/msg_sys_nop.go @@ -15,10 +15,12 @@ func (m *MsgSysNop) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgSysNop) Parse(bf *byteframe.ByteFrame) error { + // No data aside from opcode. return nil } // Build builds a binary packet from the current data. func (m *MsgSysNop) Build(bf *byteframe.ByteFrame) error { + // No data aside from opcode. return nil } diff --git a/network/mhfpacket/msg_sys_ping.go b/network/mhfpacket/msg_sys_ping.go index ebbfe27ad..90d7343b6 100644 --- a/network/mhfpacket/msg_sys_ping.go +++ b/network/mhfpacket/msg_sys_ping.go @@ -8,7 +8,6 @@ import ( // MsgSysPing represents the MSG_SYS_PING type MsgSysPing struct { AckHandle uint32 - Unk0 uint16 } // Opcode returns the ID associated with this packet type. @@ -19,13 +18,11 @@ func (m *MsgSysPing) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgSysPing) Parse(bf *byteframe.ByteFrame) error { m.AckHandle = bf.ReadUint32() - m.Unk0 = bf.ReadUint16() return nil } // Build builds a binary packet from the current data. func (m *MsgSysPing) Build(bf *byteframe.ByteFrame) error { bf.WriteUint32(m.AckHandle) - bf.WriteUint16(m.Unk0) return nil } diff --git a/network/mhfpacket/msg_sys_position_object.go b/network/mhfpacket/msg_sys_position_object.go index 335a526d3..7bb70157c 100644 --- a/network/mhfpacket/msg_sys_position_object.go +++ b/network/mhfpacket/msg_sys_position_object.go @@ -6,7 +6,10 @@ import ( ) // MsgSysPositionObject represents the MSG_SYS_POSITION_OBJECT -type MsgSysPositionObject struct{} +type MsgSysPositionObject struct{ + ObjID uint32 + X, Y, Z float32 +} // Opcode returns the ID associated with this packet type. func (m *MsgSysPositionObject) Opcode() network.PacketID { @@ -15,7 +18,11 @@ func (m *MsgSysPositionObject) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgSysPositionObject) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.ObjID = bf.ReadUint32() + m.X = bf.ReadFloat32() + m.Y = bf.ReadFloat32() + m.Z = bf.ReadFloat32() + return nil } // Build builds a binary packet from the current data. diff --git a/network/mhfpacket/msg_sys_reserve188.go b/network/mhfpacket/msg_sys_reserve188.go index 530ad4e9f..1f6f27860 100644 --- a/network/mhfpacket/msg_sys_reserve188.go +++ b/network/mhfpacket/msg_sys_reserve188.go @@ -6,7 +6,9 @@ import ( ) // MsgSysReserve188 represents the MSG_SYS_reserve188 -type MsgSysReserve188 struct{} +type MsgSysReserve188 struct { + AckHandle uint32 +} // Opcode returns the ID associated with this packet type. func (m *MsgSysReserve188) Opcode() network.PacketID { @@ -15,10 +17,11 @@ func (m *MsgSysReserve188) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgSysReserve188) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.AckHandle = bf.ReadUint32() + return nil } // Build builds a binary packet from the current data. func (m *MsgSysReserve188) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/network/mhfpacket/msg_sys_reserve18b.go b/network/mhfpacket/msg_sys_reserve18b.go index fd9492a13..3874772f8 100644 --- a/network/mhfpacket/msg_sys_reserve18b.go +++ b/network/mhfpacket/msg_sys_reserve18b.go @@ -6,7 +6,9 @@ import ( ) // MsgSysReserve18B represents the MSG_SYS_reserve18B -type MsgSysReserve18B struct{} +type MsgSysReserve18B struct { + AckHandle uint32 +} // Opcode returns the ID associated with this packet type. func (m *MsgSysReserve18B) Opcode() network.PacketID { @@ -15,10 +17,11 @@ func (m *MsgSysReserve18B) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgSysReserve18B) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.AckHandle = bf.ReadUint32() + return nil } // Build builds a binary packet from the current data. func (m *MsgSysReserve18B) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/network/mhfpacket/msg_sys_set_object_binary.go b/network/mhfpacket/msg_sys_set_object_binary.go index 324a7db9d..5c37505fd 100644 --- a/network/mhfpacket/msg_sys_set_object_binary.go +++ b/network/mhfpacket/msg_sys_set_object_binary.go @@ -6,7 +6,11 @@ import ( ) // MsgSysSetObjectBinary represents the MSG_SYS_SET_OBJECT_BINARY -type MsgSysSetObjectBinary struct{} +type MsgSysSetObjectBinary struct { + ObjID uint32 + DataSize uint16 + RawDataPayload []byte +} // Opcode returns the ID associated with this packet type. func (m *MsgSysSetObjectBinary) Opcode() network.PacketID { @@ -15,10 +19,13 @@ func (m *MsgSysSetObjectBinary) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgSysSetObjectBinary) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.ObjID = bf.ReadUint32() + m.DataSize = bf.ReadUint16() + m.RawDataPayload = bf.ReadBytes(uint(m.DataSize)) + return nil } // Build builds a binary packet from the current data. func (m *MsgSysSetObjectBinary) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/network/mhfpacket/msg_sys_set_user_binary.go b/network/mhfpacket/msg_sys_set_user_binary.go index 8a75b0409..ef6f05fcd 100644 --- a/network/mhfpacket/msg_sys_set_user_binary.go +++ b/network/mhfpacket/msg_sys_set_user_binary.go @@ -6,7 +6,11 @@ import ( ) // MsgSysSetUserBinary represents the MSG_SYS_SET_USER_BINARY -type MsgSysSetUserBinary struct{} +type MsgSysSetUserBinary struct { + BinaryType uint8 + DataSize uint16 + RawDataPayload []byte +} // Opcode returns the ID associated with this packet type. func (m *MsgSysSetUserBinary) Opcode() network.PacketID { @@ -15,10 +19,13 @@ func (m *MsgSysSetUserBinary) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgSysSetUserBinary) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.BinaryType = bf.ReadUint8() + m.DataSize = bf.ReadUint16() + m.RawDataPayload = bf.ReadBytes(uint(m.DataSize)) + return nil } // Build builds a binary packet from the current data. func (m *MsgSysSetUserBinary) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/network/mhfpacket/msg_sys_terminal_log.go b/network/mhfpacket/msg_sys_terminal_log.go index c34a03a08..e786962ad 100644 --- a/network/mhfpacket/msg_sys_terminal_log.go +++ b/network/mhfpacket/msg_sys_terminal_log.go @@ -5,8 +5,20 @@ import ( "github.com/Andoryuuta/byteframe" ) +// TerminalLogEntry represents an entry in the MSG_SYS_TERMINAL_LOG packet. +type TerminalLogEntry struct { + // Unknown fields + U0, U1, U2, U3, U4, U5, U6, U7, U8 uint32 +} + // MsgSysTerminalLog represents the MSG_SYS_TERMINAL_LOG -type MsgSysTerminalLog struct{} +type MsgSysTerminalLog struct { + AckHandle uint32 + LogID uint32 // 0 on the first packet, and the server sends back a value to use for subsequent requests. + EntryCount uint16 + Unk0 uint16 // Hardcoded 0 in the binary + Entries []*TerminalLogEntry +} // Opcode returns the ID associated with this packet type. func (m *MsgSysTerminalLog) Opcode() network.PacketID { @@ -15,10 +27,29 @@ func (m *MsgSysTerminalLog) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgSysTerminalLog) Parse(bf *byteframe.ByteFrame) error { - panic("Not implemented") + m.AckHandle = bf.ReadUint32() + m.LogID = bf.ReadUint32() + m.EntryCount = bf.ReadUint16() + m.Unk0 = bf.ReadUint16() + + for i := 0; i < int(m.EntryCount); i++ { + e := &TerminalLogEntry{} + e.U0 = bf.ReadUint32() + e.U1 = bf.ReadUint32() + e.U2 = bf.ReadUint32() + e.U3 = bf.ReadUint32() + e.U4 = bf.ReadUint32() + e.U5 = bf.ReadUint32() + e.U6 = bf.ReadUint32() + e.U7 = bf.ReadUint32() + e.U8 = bf.ReadUint32() + m.Entries = append(m.Entries, e) + } + + return nil } // Build builds a binary packet from the current data. func (m *MsgSysTerminalLog) Build(bf *byteframe.ByteFrame) error { panic("Not implemented") -} \ No newline at end of file +} diff --git a/network/mhfpacket/msg_sys_time.go b/network/mhfpacket/msg_sys_time.go index 715a97161..0029395db 100644 --- a/network/mhfpacket/msg_sys_time.go +++ b/network/mhfpacket/msg_sys_time.go @@ -7,8 +7,8 @@ import ( // MsgSysTime represents the MSG_SYS_TIME type MsgSysTime struct { - Unk0 uint8 - Timestamp uint32 // unix timestamp, e.g. 1577105879 + GetRemoteTime bool // Ask the other end to send it's time as well. + Timestamp uint32 // Unix timestamp, e.g. 1577105879 } // Opcode returns the ID associated with this packet type. @@ -18,14 +18,14 @@ func (m *MsgSysTime) Opcode() network.PacketID { // Parse parses the packet from binary func (m *MsgSysTime) Parse(bf *byteframe.ByteFrame) error { - m.Unk0 = bf.ReadUint8() + m.GetRemoteTime = bf.ReadBool() m.Timestamp = bf.ReadUint32() return nil } // Build builds a binary packet from the current data. func (m *MsgSysTime) Build(bf *byteframe.ByteFrame) error { - bf.WriteUint8(m.Unk0) + bf.WriteBool(m.GetRemoteTime) bf.WriteUint32(m.Timestamp) return nil } diff --git a/network/mhfpacket/msg_sys_update_right.go b/network/mhfpacket/msg_sys_update_right.go index b3d7d33e2..628bd834f 100644 --- a/network/mhfpacket/msg_sys_update_right.go +++ b/network/mhfpacket/msg_sys_update_right.go @@ -5,8 +5,41 @@ import ( "github.com/Andoryuuta/byteframe" ) +/* +00 58 // Opcode + +00 00 00 00 +00 00 00 4e + +00 04 // Count +00 00 // Skipped(padding?) + +00 01 00 00 00 00 00 00 +00 02 00 00 5d fa 14 c0 +00 03 00 00 5d fa 14 c0 +00 06 00 00 5d e7 05 10 + +00 00 // Count of some buf up to 0x800 bytes following it. + +00 10 // Trailer +*/ + +// ClientRight represents a right that the client has. +type ClientRight struct { + ID uint16 + Unk0 uint16 + Timestamp uint32 +} + // MsgSysUpdateRight represents the MSG_SYS_UPDATE_RIGHT -type MsgSysUpdateRight struct{} +type MsgSysUpdateRight struct { + Unk0 uint32 + Unk1 uint32 + //RightCount uint16 + //Unk3 uint16 // Likely struct padding + Rights []ClientRight + UnkSize uint16 // Count of some buf up to 0x800 bytes following it. +} // Opcode returns the ID associated with this packet type. func (m *MsgSysUpdateRight) Opcode() network.PacketID { @@ -20,5 +53,15 @@ func (m *MsgSysUpdateRight) Parse(bf *byteframe.ByteFrame) error { // Build builds a binary packet from the current data. func (m *MsgSysUpdateRight) Build(bf *byteframe.ByteFrame) error { - panic("Not implemented") -} \ No newline at end of file + bf.WriteUint32(m.Unk0) + bf.WriteUint32(m.Unk1) + bf.WriteUint16(uint16(len(m.Rights))) + bf.WriteUint16(0) // m.Unk3, struct padding. + for _, v := range m.Rights { + bf.WriteUint16(v.ID) + bf.WriteUint16(v.Unk0) + bf.WriteUint32(v.Timestamp) + } + bf.WriteUint16(m.UnkSize) + return nil +} diff --git a/server/channelserver/channel_server.go b/server/channelserver/channel_server.go index 5c43e7e55..0d11080c8 100644 --- a/server/channelserver/channel_server.go +++ b/server/channelserver/channel_server.go @@ -1,19 +1,21 @@ package channelserver import ( - "database/sql" "fmt" "net" "sync" "github.com/Andoryuuta/Erupe/config" + "github.com/Andoryuuta/Erupe/network/mhfpacket" + "github.com/Andoryuuta/byteframe" + "github.com/jmoiron/sqlx" "go.uber.org/zap" ) // Config struct allows configuring the server. type Config struct { Logger *zap.Logger - DB *sql.DB + DB *sqlx.DB ErupeConfig *config.Config } @@ -21,7 +23,7 @@ type Config struct { type Server struct { sync.Mutex logger *zap.Logger - db *sql.DB + db *sqlx.DB erupeConfig *config.Config acceptConns chan net.Conn deleteConns chan net.Conn @@ -29,6 +31,9 @@ type Server struct { listener net.Listener // Listener that is created when Server.Start is called. isShuttingDown bool + + gameObjectLock sync.Mutex + gameObjectCount uint32 } // NewServer creates a new Server type. @@ -117,3 +122,22 @@ func (s *Server) manageSessions() { } } } + +// BroadcastMHF queues a MHFPacket to be sent to all sessions. +func (s *Server) BroadcastMHF(pkt mhfpacket.MHFPacket, ignoredSession *Session) { + // Make the header + bf := byteframe.NewByteFrame() + bf.WriteUint16(uint16(pkt.Opcode())) + + // Build the packet onto the byteframe. + pkt.Build(bf) + + // Broadcast the data. + for _, session := range s.sessions { + if session == ignoredSession { + continue + } + // Enqueue in a non-blocking way that drops the packet if the connections send buffer channel is full. + session.QueueSendNonBlocking(bf.Data()) + } +} diff --git a/server/channelserver/handlers.go b/server/channelserver/handlers.go index de185f0f1..8cb2f427f 100644 --- a/server/channelserver/handlers.go +++ b/server/channelserver/handlers.go @@ -1,11 +1,66 @@ package channelserver import ( - "github.com/Andoryuuta/Erupe/network" + "bytes" + "fmt" + "io/ioutil" + "log" + "time" + "github.com/Andoryuuta/Erupe/network/mhfpacket" "github.com/Andoryuuta/byteframe" + "golang.org/x/text/encoding/japanese" + "golang.org/x/text/transform" ) +// Temporary function to just return no results for a MSG_MHF_ENUMERATE* packet +func stubEnumerateNoResults(s *Session, ackHandle uint32) { + enumBf := byteframe.NewByteFrame() + enumBf.WriteUint16(0) // Entry count (count for quests, rankings, events, etc.) + + doSizedAckResp(s, ackHandle, enumBf.Data()) +} + +// Temporary function to just return no results for many MSG_MHF_GET* packets. +func stubGetNoResults(s *Session, ackHandle uint32) { + resp := byteframe.NewByteFrame() + resp.WriteUint32(0x0A218EAD) // Unk shared ID. Sent in response of MSG_MHF_GET_TOWER_INFO, MSG_MHF_GET_PAPER_DATA etc. (World ID?) + resp.WriteUint32(0) // Unk + resp.WriteUint32(0) // Unk + resp.WriteUint32(0) // Entry count + + doSizedAckResp(s, ackHandle, resp.Data()) +} + +// Some common ACK response header that a lot (but not all) of the packet responses use. +func doSizedAckResp(s *Session, ackHandle uint32, data []byte) { + // Wrap the data into another container with the data size. + bfw := byteframe.NewByteFrame() + bfw.WriteUint8(1) // Unk + bfw.WriteUint8(0) // Unk + bfw.WriteUint16(uint16(len(data))) // Data size + if len(data) > 0 { + bfw.WriteBytes(data) + } + + s.QueueAck(ackHandle, bfw.Data()) +} + +func fixedSizeShiftJIS(text string, size int) []byte { + r := bytes.NewBuffer([]byte(text)) + encoded, err := ioutil.ReadAll(transform.NewReader(r, japanese.ShiftJIS.NewEncoder())) + if err != nil { + panic(err) + } + + out := make([]byte, size) + copy(out, encoded) + + // Null terminate it. + out[len(out)-1] = 0 + return out +} + func handleMsgHead(s *Session, p mhfpacket.MHFPacket) {} func handleMsgSysReserve01(s *Session, p mhfpacket.MHFPacket) {} @@ -36,24 +91,45 @@ func handleMsgSysReserve0D(s *Session, p mhfpacket.MHFPacket) {} func handleMsgSysReserve0E(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgSysExtendThreshold(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgSysExtendThreshold(s *Session, p mhfpacket.MHFPacket) { + // No data aside from header, no resp required. +} -func handleMsgSysEnd(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgSysEnd(s *Session, p mhfpacket.MHFPacket) { + // No data aside from header, no resp required. +} -func handleMsgSysNop(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgSysNop(s *Session, p mhfpacket.MHFPacket) { + // No data aside from header, no resp required. +} func handleMsgSysAck(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgSysTerminalLog(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgSysTerminalLog(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysTerminalLog) + + resp := byteframe.NewByteFrame() + /* + if pkt.LogID == 0{ + fmt.Println("New log session") + } + */ + resp.WriteUint32(0) // UNK + resp.WriteUint32(0x98bd51a9) // LogID to use for requests after this. + s.QueueAck(pkt.AckHandle, resp.Data()) +} func handleMsgSysLogin(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysLogin) + s.Lock() + s.charID = pkt.CharID0 + s.Unlock() + bf := byteframe.NewByteFrame() - bf.WriteUint16(uint16(network.MSG_SYS_ACK)) - bf.WriteUint32(pkt.AckHandle) - bf.WriteUint64(0x000000005E00B9C2) // Timestamp? - s.cryptConn.SendPacket(bf.Data()) + bf.WriteUint32(0) // Unk + bf.WriteUint32(uint32(time.Now().Unix())) // Unix timestamp + s.QueueAck(pkt.AckHandle, bf.Data()) } func handleMsgSysLogout(s *Session, p mhfpacket.MHFPacket) {} @@ -64,31 +140,72 @@ func handleMsgSysPing(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysPing) bf := byteframe.NewByteFrame() - bf.WriteUint16(uint16(network.MSG_SYS_ACK)) - ack := mhfpacket.MsgSysAck{ - AckHandle: pkt.AckHandle, - Unk0: 0, - Unk1: 0, - } - ack.Build(bf) - s.cryptConn.SendPacket(bf.Data()) + bf.WriteUint32(0) // Unk + bf.WriteUint32(0) // Unk + s.QueueAck(pkt.AckHandle, bf.Data()) } -func handleMsgSysCastBinary(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgSysCastBinary(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysCastBinary) -func handleMsgSysHideClient(s *Session, p mhfpacket.MHFPacket) {} + if pkt.Type0 == 3 && pkt.Type1 == 1 { + fmt.Println("Got chat message!") + + resp := &mhfpacket.MsgSysCastedBinary{ + CharID: s.charID, + Type0: 1, + Type1: 1, + RawDataPayload: pkt.RawDataPayload, + } + s.server.BroadcastMHF(resp, s) + + /* + // Made the inside of the casted binary + payload := byteframe.NewByteFrame() + payload.WriteUint16(uint16(i)) // Chat type + + //Chat type 0 = World + //Chat type 1 = Local + //Chat type 2 = Guild + //Chat type 3 = Alliance + //Chat type 4 = Party + //Chat type 5 = Whisper + //Thanks to @Alice on discord for identifying these. + + payload.WriteUint8(0) // Unknown + msg := fmt.Sprintf("Chat type %d", i) + playername := fmt.Sprintf("Ando") + payload.WriteUint16(uint16(len(playername) + 1)) + payload.WriteUint16(uint16(len(msg) + 1)) + payload.WriteUint8(0) // Is this correct, or do I have the endianess of the prev 2 fields wrong? + payload.WriteNullTerminatedBytes([]byte(msg)) + payload.WriteNullTerminatedBytes([]byte(playername)) + payloadBytes := payload.Data() + + //Wrap it in a CASTED_BINARY packet to broadcast + bfw := byteframe.NewByteFrame() + bfw.WriteUint16(uint16(network.MSG_SYS_CASTED_BINARY)) + bfw.WriteUint32(0x23325A29) // Character ID + bfw.WriteUint8(1) // type + bfw.WriteUint8(1) // type2 + bfw.WriteUint16(uint16(len(payloadBytes))) + bfw.WriteBytes(payloadBytes) + */ + } +} + +func handleMsgSysHideClient(s *Session, p mhfpacket.MHFPacket) { + //pkt := p.(*mhfpacket.MsgSysHideClient) +} func handleMsgSysTime(s *Session, p mhfpacket.MHFPacket) { - pkt := p.(*mhfpacket.MsgSysTime) + //pkt := p.(*mhfpacket.MsgSysTime) - bf := byteframe.NewByteFrame() - bf.WriteUint16(uint16(network.MSG_SYS_TIME)) - resp := mhfpacket.MsgSysTime{ - Unk0: pkt.Unk0, - Timestamp: pkt.Timestamp, + resp := &mhfpacket.MsgSysTime{ + GetRemoteTime: false, + Timestamp: uint32(time.Now().Unix()), } - resp.Build(bf) - s.cryptConn.SendPacket(bf.Data()) + s.QueueSendMHF(resp) } func handleMsgSysCastedBinary(s *Session, p mhfpacket.MHFPacket) {} @@ -105,7 +222,17 @@ func handleMsgSysCreateStage(s *Session, p mhfpacket.MHFPacket) {} func handleMsgSysStageDestruct(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgSysEnterStage(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgSysEnterStage(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysEnterStage) + + s.Lock() + s.stageID = string(pkt.StageID) + s.Unlock() + + //TODO: Send MSG_SYS_CLEANUP_OBJECT here before the client changes stages. + + s.QueueAck(pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) +} func handleMsgSysBackStage(s *Session, p mhfpacket.MHFPacket) {} @@ -165,17 +292,37 @@ func handleMsgSysLoadRegister(s *Session, p mhfpacket.MHFPacket) {} func handleMsgSysNotifyRegister(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgSysCreateObject(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgSysCreateObject(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysCreateObject) + + // Make a new object ID. + s.server.gameObjectLock.Lock() + objID := s.server.gameObjectCount + s.server.gameObjectCount++ + s.server.gameObjectLock.Unlock() + + resp := byteframe.NewByteFrame() + resp.WriteUint32(0) // Unk, is this echoed back from pkt.Unk0? + resp.WriteUint32(objID) // New local obj handle. + + s.QueueAck(pkt.AckHandle, resp.Data()) +} func handleMsgSysDeleteObject(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgSysPositionObject(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgSysPositionObject(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysPositionObject) + fmt.Printf("Moved object %v to (%f,%f,%f)\n", pkt.ObjID, pkt.X, pkt.Y, pkt.Z) + +} func handleMsgSysRotateObject(s *Session, p mhfpacket.MHFPacket) {} func handleMsgSysDuplicateObject(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgSysSetObjectBinary(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgSysSetObjectBinary(s *Session, p mhfpacket.MHFPacket) { + +} func handleMsgSysGetObjectBinary(s *Session, p mhfpacket.MHFPacket) {} @@ -201,7 +348,9 @@ func handleMsgSysInsertUser(s *Session, p mhfpacket.MHFPacket) {} func handleMsgSysDeleteUser(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgSysSetUserBinary(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgSysSetUserBinary(s *Session, p mhfpacket.MHFPacket) { + //pkt := p.(*mhfpacket.MsgSysSetUserBinary) +} func handleMsgSysGetUserBinary(s *Session, p mhfpacket.MHFPacket) {} @@ -229,7 +378,14 @@ func handleMsgSysReserve5E(s *Session, p mhfpacket.MHFPacket) {} func handleMsgSysReserve5F(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgMhfSavedata(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfSavedata(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfSavedata) + err := ioutil.WriteFile(fmt.Sprintf("savedata\\%d.bin", time.Now().Unix()), pkt.RawDataPayload, 0644) + if err != nil { + log.Fatal(err) + } + s.QueueAck(pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) +} func handleMsgMhfLoaddata(s *Session, p mhfpacket.MHFPacket) {} @@ -253,7 +409,11 @@ func handleMsgMhfListMail(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfOprtMail(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgMhfLoadFavoriteQuest(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfLoadFavoriteQuest(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfLoadFavoriteQuest) + // TODO(Andoryuuta): Save data from MsgMhfSaveFavoriteQuest and resend it here. + doSizedAckResp(s, pkt.AckHandle, []byte{}) +} func handleMsgMhfSaveFavoriteQuest(s *Session, p mhfpacket.MHFPacket) {} @@ -357,17 +517,35 @@ func handleMsgMhfMercenaryHuntdata(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfEntryRookieGuild(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfEnumerateQuest) + stubEnumerateNoResults(s, pkt.AckHandle) +} -func handleMsgMhfEnumerateEvent(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfEnumerateEvent(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfEnumerateEvent) + stubEnumerateNoResults(s, pkt.AckHandle) +} -func handleMsgMhfEnumeratePrice(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfEnumeratePrice(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfEnumeratePrice) + stubEnumerateNoResults(s, pkt.AckHandle) +} -func handleMsgMhfEnumerateRanking(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfEnumerateRanking(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfEnumerateRanking) + stubEnumerateNoResults(s, pkt.AckHandle) +} -func handleMsgMhfEnumerateOrder(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfEnumerateOrder(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfEnumerateOrder) + stubEnumerateNoResults(s, pkt.AckHandle) +} -func handleMsgMhfEnumerateShop(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfEnumerateShop(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfEnumerateShop) + stubEnumerateNoResults(s, pkt.AckHandle) +} func handleMsgMhfGetExtraInfo(s *Session, p mhfpacket.MHFPacket) {} @@ -405,7 +583,12 @@ func handleMsgMhfInfoJoint(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfUpdateGuildIcon(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfInfoFesta) + + // REALLY large/complex format... stubbing it out here for simplicity. + doSizedAckResp(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} func handleMsgMhfEntryFesta(s *Session, p mhfpacket.MHFPacket) {} @@ -441,7 +624,12 @@ func handleMsgMhfCreateMercenary(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfSaveMercenary(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgMhfReadMercenaryW(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfReadMercenaryW(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfReadMercenaryW) + + // Unk format: + doSizedAckResp(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) +} func handleMsgMhfReadMercenaryM(s *Session, p mhfpacket.MHFPacket) {} @@ -473,15 +661,31 @@ func handleMsgMhfDisplayedAchievement(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfInfoScenarioCounter(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgMhfSaveScenarioData(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfSaveScenarioData(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfSaveScenarioData) + s.QueueAck(pkt.AckHandle, []byte{0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40}) +} -func handleMsgMhfLoadScenarioData(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfLoadScenarioData(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfLoadScenarioData) + doSizedAckResp(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) +} func handleMsgMhfGetBbsSnsStatus(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfApplyBbsArticle(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgMhfGetEtcPoints(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfGetEtcPoints(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetEtcPoints) + + resp := byteframe.NewByteFrame() + resp.WriteUint8(0x3) // Maybe a count of uint32(s)? + resp.WriteUint32(0) + resp.WriteUint32(0) + resp.WriteUint32(0) + + doSizedAckResp(s, pkt.AckHandle, resp.Data()) +} func handleMsgMhfUpdateEtcPoint(s *Session, p mhfpacket.MHFPacket) {} @@ -489,7 +693,32 @@ func handleMsgMhfGetMyhouseInfo(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfUpdateMyhouseInfo(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgMhfGetWeeklySchedule(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfGetWeeklySchedule(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetWeeklySchedule) + + eventSchedules := []struct { + StartTime time.Time + Unk0 uint32 // Event ID? + Unk1 uint16 + }{ + { + StartTime: time.Now().Add(time.Duration(-5) * time.Minute), // Event started 5 minutes ago. + Unk0: 4, + Unk1: 0, + }, + } + + resp := byteframe.NewByteFrame() + resp.WriteUint8(uint8(len(eventSchedules))) // Entry count, client only parses the first 7 or 8. + resp.WriteUint32(uint32(time.Now().Unix())) // Current server time + for _, es := range eventSchedules { + resp.WriteUint32(uint32(es.StartTime.Unix())) + resp.WriteUint32(es.Unk0) + resp.WriteUint16(es.Unk1) + } + + doSizedAckResp(s, pkt.AckHandle, resp.Data()) +} func handleMsgMhfEnumerateInvGuild(s *Session, p mhfpacket.MHFPacket) {} @@ -501,19 +730,56 @@ func handleMsgMhfStampcardPrize(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfUnreserveSrg(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgMhfLoadPlateData(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfLoadPlateData(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfLoadPlateData) + + // TODO(Andoryuuta): Save data from MsgMhfSavePlateData and resend it here. + doSizedAckResp(s, pkt.AckHandle, []byte{}) +} func handleMsgMhfSavePlateData(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgMhfLoadPlateBox(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfLoadPlateBox(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfLoadPlateBox) + // TODO(Andoryuuta): Save data from MsgMhfSavePlateBox and resend it here. + doSizedAckResp(s, pkt.AckHandle, []byte{}) +} func handleMsgMhfSavePlateBox(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgMhfReadGuildcard(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfReadGuildcard(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfReadGuildcard) + + resp := byteframe.NewByteFrame() + resp.WriteUint32(0) + resp.WriteUint32(0) + resp.WriteUint32(0) + resp.WriteUint32(0) + resp.WriteUint32(0) + resp.WriteUint32(0) + resp.WriteUint32(0) + resp.WriteUint32(0) + + doSizedAckResp(s, pkt.AckHandle, resp.Data()) +} func handleMsgMhfUpdateGuildcard(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgMhfReadBeatLevel(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfReadBeatLevel(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfReadBeatLevel) + + // This response is fixed and will never change on JP, + // but I've left it dynamic for possible other client differences. + resp := byteframe.NewByteFrame() + for i := 0; i < int(pkt.ValidIDCount); i++ { + resp.WriteUint32(pkt.IDs[i]) + resp.WriteUint32(1) + resp.WriteUint32(1) + resp.WriteUint32(1) + } + + doSizedAckResp(s, pkt.AckHandle, resp.Data()) +} func handleMsgMhfUpdateBeatLevel(s *Session, p mhfpacket.MHFPacket) {} @@ -537,11 +803,32 @@ func handleMsgMhfGetBreakSeibatuLevelReward(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfGetWeeklySeibatuRankingReward(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgMhfGetEarthStatus(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfGetEarthStatus(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetEarthStatus) -func handleMsgMhfLoadPartner(s *Session, p mhfpacket.MHFPacket) {} + // TODO(Andoryuuta): Track down format for this data, + // it can somehow be parsed as 8*uint32 chunks if the header is right. + resp := byteframe.NewByteFrame() + resp.WriteUint32(0) + resp.WriteUint32(0) -func handleMsgMhfSavePartner(s *Session, p mhfpacket.MHFPacket) {} + s.QueueAck(pkt.AckHandle, resp.Data()) +} + +func handleMsgMhfLoadPartner(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfLoadPartner) + + // TODO(Andoryuuta): Figure out unusual double ack. One sized, one not. + + // TODO(Andoryuuta): Save data from MsgMhfSavePartner and resend it here. + doSizedAckResp(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) + s.QueueAck(pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfSavePartner(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfSavePartner) + s.QueueAck(pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) +} func handleMsgMhfGetGuildMissionList(s *Session, p mhfpacket.MHFPacket) {} @@ -553,7 +840,12 @@ func handleMsgMhfSetGuildMissionTarget(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfCancelGuildMissionTarget(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgMhfLoadOtomoAirou(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfLoadOtomoAirou(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfLoadOtomoAirou) + + // TODO(Andoryuuta): Save data from MsgMhfSaveOtomoAirou and resend it here. + doSizedAckResp(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) +} func handleMsgMhfSaveOtomoAirou(s *Session, p mhfpacket.MHFPacket) {} @@ -575,7 +867,12 @@ func handleMsgMhfEnumerateFestaIntermediatePrize(s *Session, p mhfpacket.MHFPack func handleMsgMhfAcquireFestaIntermediatePrize(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgMhfLoadDecoMyset(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfLoadDecoMyset(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfLoadDecoMyset) + + // TODO(Andoryuuta): Save data from MsgMhfSaveDecoMyset and resend it here. + doSizedAckResp(s, pkt.AckHandle, []byte{0x01, 0x00}) +} func handleMsgMhfSaveDecoMyset(s *Session, p mhfpacket.MHFPacket) {} @@ -595,7 +892,12 @@ func handleMsgMhfChargeGuildAdventure(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfLoadLegendDispatch(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgMhfLoadHunterNavi(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfLoadHunterNavi(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfLoadHunterNavi) + // TODO(Andoryuuta): Save data from MsgMhfSaveHunterNavi and resend it here. + blankData := make([]byte, 0x228) + doSizedAckResp(s, pkt.AckHandle, blankData) +} func handleMsgMhfSaveHunterNavi(s *Session, p mhfpacket.MHFPacket) {} @@ -607,7 +909,46 @@ func handleMsgMhfGetGuildWeeklyBonusActiveCount(s *Session, p mhfpacket.MHFPacke func handleMsgMhfAddGuildWeeklyBonusExceptionalUser(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgMhfGetTowerInfo(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfGetTowerInfo(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetTowerInfo) + + /* + type: + 1 == TOWER_RANK_POINT, + 2 == GET_OWN_TOWER_SKILL + 3 == ? + 4 == TOWER_TOUHA_HISTORY + 5 = ? + + [] = type + req + resp + + 01 1d 01 fc 00 09 [00 00 00 01] 00 00 00 02 00 00 00 00 + 00 12 01 fc 00 09 01 00 00 18 0a 21 8e ad 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 + + 01 1d 01 fc 00 0a [00 00 00 02] 00 00 00 00 00 00 00 00 + 00 12 01 fc 00 0a 01 00 00 94 0a 21 8e ad 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + 01 1d 01 ff 00 0f [00 00 00 04] 00 00 00 00 00 00 00 00 + 00 12 01 ff 00 0f 01 00 00 24 0a 21 8e ad 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + 01 1d 01 fc 00 0b [00 00 00 05] 00 00 00 00 00 00 00 00 + 00 12 01 fc 00 0b 01 00 00 10 0a 21 8e ad 00 00 00 00 00 00 00 00 00 00 00 00 + */ + /* + switch pkt.InfoType { + case mhfpacket.TowerInfoTypeTowerRankPoint: + case mhfpacket.TowerInfoTypeGetOwnTowerSkill: + case mhfpacket.TowerInfoTypeUnk3: + panic("No known response values for TowerInfoTypeUnk3") + case mhfpacket.TowerInfoTypeTowerTouhaHistory: + case mhfpacket.TowerInfoTypeUnk5: + } + */ + + stubGetNoResults(s, pkt.AckHandle) +} func handleMsgMhfPostTowerInfo(s *Session, p mhfpacket.MHFPacket) {} @@ -615,21 +956,92 @@ func handleMsgMhfGetGemInfo(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfPostGemInfo(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgMhfGetEarthValue(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfGetEarthValue(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetEarthValue) + + earthValues := []struct { + Unk0, Unk1, Unk2, Unk3, Unk4, Unk5 uint32 + }{ + { + Unk0: 0x03E9, + Unk1: 0x5B, + }, + { + Unk0: 0x2329, + Unk1: 0x03, + }, + { + Unk0: 0x232A, + Unk1: 0x0A, + Unk2: 0x012C, + }, + } + + resp := byteframe.NewByteFrame() + resp.WriteUint32(0x0A218EAD) // Unk shared ID. Sent in response of MSG_MHF_GET_TOWER_INFO, MSG_MHF_GET_PAPER_DATA etc. + resp.WriteUint32(0) // Unk + resp.WriteUint32(0) // Unk + resp.WriteUint32(uint32(len(earthValues))) // value count + for _, v := range earthValues { + resp.WriteUint32(v.Unk0) + resp.WriteUint32(v.Unk1) + resp.WriteUint32(v.Unk2) + resp.WriteUint32(v.Unk3) + resp.WriteUint32(v.Unk4) + resp.WriteUint32(v.Unk5) + } + + doSizedAckResp(s, pkt.AckHandle, resp.Data()) +} func handleMsgMhfDebugPostValue(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgMhfGetPaperData(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfGetPaperData(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetPaperData) + stubGetNoResults(s, pkt.AckHandle) +} func handleMsgMhfGetNotice(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfPostNotice(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgMhfGetBoostTime(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfGetBoostTime(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetBoostTime) + doSizedAckResp(s, pkt.AckHandle, []byte{}) + + // Update the client's rights as well: + update := &mhfpacket.MsgSysUpdateRight{ + Unk0: 0, + Unk1: 0x4E, + Rights: []mhfpacket.ClientRight{ + { + ID: 1, + Timestamp: 0, + }, + { + ID: 2, + Timestamp: 0x5dfa14c0, + }, + { + ID: 3, + Timestamp: 0x5dfa14c0, + }, + { + ID: 6, + Timestamp: 0x5de70510, + }, + }, + UnkSize: 0, + } + s.QueueSendMHF(update) +} func handleMsgMhfPostBoostTime(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgMhfGetBoostTimeLimit(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfGetBoostTimeLimit(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetBoostTimeLimit) + doSizedAckResp(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} func handleMsgMhfPostBoostTimeLimit(s *Session, p mhfpacket.MHFPacket) {} @@ -647,7 +1059,10 @@ func handleMsgMhfReceiveCafeDurationBonus(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfPostCafeDurationBonusReceived(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgMhfGetGachaPoint(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfGetGachaPoint(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetGachaPoint) + doSizedAckResp(s, pkt.AckHandle, []byte{}) +} func handleMsgMhfUseGachaPoint(s *Session, p mhfpacket.MHFPacket) {} @@ -673,7 +1088,10 @@ func handleMsgMhfGetSenyuDailyCount(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfGetGuildTargetMemberNum(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgMhfGetBoostRight(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfGetBoostRight(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetBoostRight) + doSizedAckResp(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} func handleMsgMhfStartBoostTime(s *Session, p mhfpacket.MHFPacket) {} @@ -727,13 +1145,101 @@ func handleMsgMhfGetCaAchievementHist(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfSetCaAchievementHist(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgMhfGetKeepLoginBoostStatus(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfGetKeepLoginBoostStatus(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetKeepLoginBoostStatus) + + unkRespFields := [5]struct { + U0, U1, U2 uint8 + U3 uint32 + }{ + { + U0: 1, + U1: 1, + U2: 1, + U3: 0, + }, + { + U0: 2, + U1: 0, + U2: 1, + U3: 0, + }, + { + U0: 3, + U1: 0, + U2: 1, + U3: 0, + }, + { + U0: 4, + U1: 0, + U2: 1, + U3: 0, + }, + { + U0: 5, + U1: 0, + U2: 1, + U3: 0, + }, + } + + resp := byteframe.NewByteFrame() + for _, v := range unkRespFields { + resp.WriteUint8(v.U0) + resp.WriteUint8(v.U1) + resp.WriteUint8(v.U2) + resp.WriteUint32(v.U3) + } + doSizedAckResp(s, pkt.AckHandle, resp.Data()) +} func handleMsgMhfUseKeepLoginBoost(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgMhfGetUdSchedule(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfGetUdSchedule(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetUdSchedule) -func handleMsgMhfGetUdInfo(s *Session, p mhfpacket.MHFPacket) {} + resp := byteframe.NewByteFrame() + resp.WriteUint32(0x0b5397df) // Unk + resp.WriteUint32(0x5ddde6b0) // Timestamp + resp.WriteUint32(0x5de71320) // Timestamp + resp.WriteUint32(0x5de7225c) // Timestamp + resp.WriteUint32(0x5df04da0) // Timestamp + resp.WriteUint32(0x5df05cdc) // Timestamp + resp.WriteUint32(0x5dfa30e0) // Timestamp + resp.WriteUint16(0x19) // Unk + resp.WriteUint16(0x2d) // Unk + resp.WriteUint16(0x02) // Unk + resp.WriteUint16(0x02) // Unk + + doSizedAckResp(s, pkt.AckHandle, resp.Data()) +} + +func handleMsgMhfGetUdInfo(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetUdInfo) + + udInfos := []struct { + Text string + StartTime time.Time + EndTime time.Time + }{ + { + Text: " ~C17【Erupe】 launch event!\n\n■Features\n~C18 Walk around!\n~C17 Crash your connection by doing nearly anything!", + StartTime: time.Now().Add(time.Duration(-5) * time.Minute), // Event started 5 minutes ago, + EndTime: time.Now().Add(time.Duration(5) * time.Minute), // Event ends in 5 minutes, + }, + } + + resp := byteframe.NewByteFrame() + resp.WriteUint8(uint8(len(udInfos))) + for _, udInfo := range udInfos { + resp.WriteBytes(fixedSizeShiftJIS(udInfo.Text, 1024)) + resp.WriteUint32(uint32(udInfo.StartTime.Unix())) + resp.WriteUint32(uint32(udInfo.EndTime.Unix())) + } + + doSizedAckResp(s, pkt.AckHandle, resp.Data()) +} func handleMsgMhfGetKijuInfo(s *Session, p mhfpacket.MHFPacket) {} @@ -749,7 +1255,137 @@ func handleMsgMhfGetUdBonusQuestInfo(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfGetUdSelectedColorInfo(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgMhfGetUdMonsterPoint(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfGetUdMonsterPoint(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetUdMonsterPoint) + + monsterPoints := []struct { + MID uint8 // Monster ID ? + Points uint16 + }{ + {MID: 0x01, Points: 0x3C}, + {MID: 0x02, Points: 0x5A}, + {MID: 0x06, Points: 0x14}, + {MID: 0x07, Points: 0x50}, + {MID: 0x08, Points: 0x28}, + {MID: 0x0B, Points: 0x3C}, + {MID: 0x0E, Points: 0x3C}, + {MID: 0x0F, Points: 0x46}, + {MID: 0x11, Points: 0x46}, + {MID: 0x14, Points: 0x28}, + {MID: 0x15, Points: 0x3C}, + {MID: 0x16, Points: 0x32}, + {MID: 0x1A, Points: 0x32}, + {MID: 0x1B, Points: 0x0A}, + {MID: 0x1C, Points: 0x0A}, + {MID: 0x1F, Points: 0x0A}, + {MID: 0x21, Points: 0x50}, + {MID: 0x24, Points: 0x64}, + {MID: 0x25, Points: 0x3C}, + {MID: 0x26, Points: 0x1E}, + {MID: 0x27, Points: 0x28}, + {MID: 0x28, Points: 0x50}, + {MID: 0x29, Points: 0x5A}, + {MID: 0x2A, Points: 0x50}, + {MID: 0x2B, Points: 0x3C}, + {MID: 0x2C, Points: 0x3C}, + {MID: 0x2D, Points: 0x46}, + {MID: 0x2E, Points: 0x3C}, + {MID: 0x2F, Points: 0x50}, + {MID: 0x30, Points: 0x1E}, + {MID: 0x31, Points: 0x3C}, + {MID: 0x32, Points: 0x50}, + {MID: 0x33, Points: 0x3C}, + {MID: 0x34, Points: 0x28}, + {MID: 0x35, Points: 0x50}, + {MID: 0x36, Points: 0x6E}, + {MID: 0x37, Points: 0x50}, + {MID: 0x3A, Points: 0x50}, + {MID: 0x3B, Points: 0x6E}, + {MID: 0x40, Points: 0x64}, + {MID: 0x41, Points: 0x6E}, + {MID: 0x43, Points: 0x28}, + {MID: 0x44, Points: 0x0A}, + {MID: 0x47, Points: 0x6E}, + {MID: 0x4A, Points: 0xFA}, + {MID: 0x4B, Points: 0xFA}, + {MID: 0x4C, Points: 0x46}, + {MID: 0x4D, Points: 0x64}, + {MID: 0x4E, Points: 0xFA}, + {MID: 0x4F, Points: 0xFA}, + {MID: 0x50, Points: 0xFA}, + {MID: 0x51, Points: 0xFA}, + {MID: 0x52, Points: 0xFA}, + {MID: 0x53, Points: 0xFA}, + {MID: 0x54, Points: 0xFA}, + {MID: 0x55, Points: 0xFA}, + {MID: 0x59, Points: 0xFA}, + {MID: 0x5A, Points: 0xFA}, + {MID: 0x5B, Points: 0xFA}, + {MID: 0x5C, Points: 0xFA}, + {MID: 0x5E, Points: 0xFA}, + {MID: 0x5F, Points: 0xFA}, + {MID: 0x60, Points: 0xFA}, + {MID: 0x63, Points: 0xFA}, + {MID: 0x65, Points: 0xFA}, + {MID: 0x67, Points: 0xFA}, + {MID: 0x68, Points: 0xFA}, + {MID: 0x69, Points: 0xFA}, + {MID: 0x6A, Points: 0xFA}, + {MID: 0x6B, Points: 0xFA}, + {MID: 0x6C, Points: 0xFA}, + {MID: 0x6D, Points: 0xFA}, + {MID: 0x6E, Points: 0xFA}, + {MID: 0x6F, Points: 0xFA}, + {MID: 0x70, Points: 0xFA}, + {MID: 0x72, Points: 0xFA}, + {MID: 0x73, Points: 0xFA}, + {MID: 0x74, Points: 0xFA}, + {MID: 0x77, Points: 0xFA}, + {MID: 0x78, Points: 0xFA}, + {MID: 0x79, Points: 0xFA}, + {MID: 0x7A, Points: 0xFA}, + {MID: 0x7B, Points: 0xFA}, + {MID: 0x7D, Points: 0xFA}, + {MID: 0x7E, Points: 0xFA}, + {MID: 0x7F, Points: 0xFA}, + {MID: 0x80, Points: 0xFA}, + {MID: 0x81, Points: 0xFA}, + {MID: 0x82, Points: 0xFA}, + {MID: 0x83, Points: 0xFA}, + {MID: 0x8B, Points: 0xFA}, + {MID: 0x8C, Points: 0xFA}, + {MID: 0x8D, Points: 0xFA}, + {MID: 0x8E, Points: 0xFA}, + {MID: 0x90, Points: 0xFA}, + {MID: 0x92, Points: 0x78}, + {MID: 0x93, Points: 0x78}, + {MID: 0x94, Points: 0x78}, + {MID: 0x96, Points: 0xFA}, + {MID: 0x97, Points: 0x78}, + {MID: 0x98, Points: 0x78}, + {MID: 0x99, Points: 0x78}, + {MID: 0x9A, Points: 0xFA}, + {MID: 0x9E, Points: 0xFA}, + {MID: 0x9F, Points: 0x78}, + {MID: 0xA0, Points: 0xFA}, + {MID: 0xA1, Points: 0xFA}, + {MID: 0xA2, Points: 0x78}, + {MID: 0xA4, Points: 0x78}, + {MID: 0xA5, Points: 0x78}, + {MID: 0xA6, Points: 0xFA}, + {MID: 0xA9, Points: 0x78}, + {MID: 0xAA, Points: 0xFA}, + } + + resp := byteframe.NewByteFrame() + resp.WriteUint8(uint8(len(monsterPoints))) + for _, mp := range monsterPoints { + resp.WriteUint8(mp.MID) + resp.WriteUint16(mp.Points) + } + + doSizedAckResp(s, pkt.AckHandle, resp.Data()) +} func handleMsgMhfGetUdDailyPresentList(s *Session, p mhfpacket.MHFPacket) {} @@ -769,7 +1405,14 @@ func handleMsgMhfGetUdRanking(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfGetUdMyRanking(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgMhfAcquireMonthlyReward(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfAcquireMonthlyReward(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfAcquireMonthlyReward) + + resp := byteframe.NewByteFrame() + resp.WriteUint32(0) + + doSizedAckResp(s, pkt.AckHandle, resp.Data()) +} func handleMsgMhfGetUdGuildMapInfo(s *Session, p mhfpacket.MHFPacket) {} @@ -797,9 +1440,14 @@ func handleMsgMhfGetUdShopCoin(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfUseUdShopCoin(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgMhfGetEnhancedMinidata(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfGetEnhancedMinidata(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetEnhancedMinidata) + doSizedAckResp(s, pkt.AckHandle, []byte{0x00}) +} -func handleMsgMhfSetEnhancedMinidata(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfSetEnhancedMinidata(s *Session, p mhfpacket.MHFPacket) { + +} func handleMsgMhfSexChanger(s *Session, p mhfpacket.MHFPacket) {} @@ -811,7 +1459,10 @@ func handleMsgMhfGuildHuntdata(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfAddKouryouPoint(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgMhfGetKouryouPoint(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfGetKouryouPoint(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetKouryouPoint) + doSizedAckResp(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} func handleMsgMhfExchangeKouryouPoint(s *Session, p mhfpacket.MHFPacket) {} @@ -821,13 +1472,29 @@ func handleMsgMhfGetUdTacticsFirstQuestBonus(s *Session, p mhfpacket.MHFPacket) func handleMsgMhfGetUdTacticsRemainingPoint(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgSysReserve188(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgSysReserve188(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysReserve188) -func handleMsgMhfLoadPlateMyset(s *Session, p mhfpacket.MHFPacket) {} + // Left as raw bytes because I couldn't easily find the request or resp parser function in the binary. + doSizedAckResp(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfLoadPlateMyset(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfLoadPlateMyset) + // TODO(Andoryuuta): Save data from MsgMhfSavePlateMyset and resend it here. + blankData := make([]byte, 0x780) + doSizedAckResp(s, pkt.AckHandle, blankData) +} func handleMsgMhfSavePlateMyset(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgSysReserve18B(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgSysReserve18B(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysReserve18B) + + // Left as raw bytes because I couldn't easily find the request or resp parser function in the binary. + doSizedAckResp(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x3C}) + +} func handleMsgMhfGetRestrictionEvent(s *Session, p mhfpacket.MHFPacket) {} @@ -849,7 +1516,47 @@ func handleMsgSysReserve194(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfSaveRengokuData(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgMhfLoadRengokuData(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfLoadRengokuData(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfLoadRengokuData) + + resp := byteframe.NewByteFrame() + resp.WriteUint32(0) + resp.WriteUint32(0) + resp.WriteUint16(0) + resp.WriteUint32(0) + resp.WriteUint16(0) + resp.WriteUint16(0) + resp.WriteUint32(0) + + resp.WriteUint8(3) // Count of next 3 + resp.WriteUint16(0) + resp.WriteUint16(0) + resp.WriteUint16(0) + + resp.WriteUint32(0) + resp.WriteUint32(0) + resp.WriteUint32(0) + + resp.WriteUint8(3) // Count of next 3 + resp.WriteUint32(0) + resp.WriteUint32(0) + resp.WriteUint32(0) + + resp.WriteUint8(3) // Count of next 3 + resp.WriteUint32(0) + resp.WriteUint32(0) + resp.WriteUint32(0) + + resp.WriteUint32(0) + resp.WriteUint32(0) + resp.WriteUint32(0) + resp.WriteUint32(0) + resp.WriteUint32(0) + resp.WriteUint32(0) + + doSizedAckResp(s, pkt.AckHandle, resp.Data()) + +} func handleMsgMhfGetRengokuBinary(s *Session, p mhfpacket.MHFPacket) {} @@ -858,20 +1565,35 @@ func handleMsgMhfEnumerateRengokuRanking(s *Session, p mhfpacket.MHFPacket) {} func handleMsgMhfGetRengokuRankingRank(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgMhfGetRengokuRankingRank) - bf := byteframe.NewByteFrame() - bf.WriteUint16(uint16(network.MSG_SYS_ACK)) - bf.WriteUint32(pkt.AckHandle) - bf.WriteBytes([]byte{0x01, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) - s.cryptConn.SendPacket(bf.Data()) + resp := byteframe.NewByteFrame() + resp.WriteBytes([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) + + doSizedAckResp(s, pkt.AckHandle, resp.Data()) } func handleMsgMhfAcquireExchangeShop(s *Session, p mhfpacket.MHFPacket) {} func handleMsgSysReserve19B(s *Session, p mhfpacket.MHFPacket) {} -func handleMsgMhfSaveMezfesData(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfSaveMezfesData(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfSaveMezfesData) + s.QueueAck(pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) +} -func handleMsgMhfLoadMezfesData(s *Session, p mhfpacket.MHFPacket) {} +func handleMsgMhfLoadMezfesData(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfLoadMezfesData) + + resp := byteframe.NewByteFrame() + resp.WriteUint32(0) // Unk + + resp.WriteUint8(2) // Count of the next 2 uint32s + resp.WriteUint32(0) + resp.WriteUint32(0) + + resp.WriteUint32(0) // Unk + + doSizedAckResp(s, pkt.AckHandle, resp.Data()) +} func handleMsgSysReserve19E(s *Session, p mhfpacket.MHFPacket) {} diff --git a/server/channelserver/session.go b/server/channelserver/session.go index 0e0a0e079..1024df74b 100644 --- a/server/channelserver/session.go +++ b/server/channelserver/session.go @@ -3,7 +3,6 @@ package channelserver import ( "encoding/hex" "fmt" - "io/ioutil" "net" "sync" @@ -16,48 +15,104 @@ import ( // Session holds state for the channel server connection. type Session struct { sync.Mutex - logger *zap.Logger - server *Server - rawConn net.Conn - cryptConn *network.CryptConn + logger *zap.Logger + server *Server + rawConn net.Conn + cryptConn *network.CryptConn + sendPackets chan []byte + + stageID string + charID uint32 } // NewSession creates a new Session type. func NewSession(server *Server, conn net.Conn) *Session { s := &Session{ - logger: server.logger, - server: server, - rawConn: conn, - cryptConn: network.NewCryptConn(conn), + logger: server.logger, + server: server, + rawConn: conn, + cryptConn: network.NewCryptConn(conn), + sendPackets: make(chan []byte, 20), } return s } -// Start starts the session packet read&handle loop. +// Start starts the session packet send and recv loop(s). func (s *Session) Start() { go func() { - s.logger.Info("Channel server got connection!") + s.logger.Info("Channel server got connection!", zap.String("remoteaddr", s.rawConn.RemoteAddr().String())) // Unlike the sign and entrance server, // the client DOES NOT initalize the channel connection with 8 NULL bytes. - - for { - pkt, err := s.cryptConn.ReadPacket() - if err != nil { - s.logger.Warn("Error on channel server readpacket", zap.Error(err)) - return - } - - s.handlePacketGroup(pkt) - - } + go s.sendLoop() + s.recvLoop() }() } -var loadDataCount int -var getPaperDataCount int +// QueueSend queues a packet (raw []byte) to be sent. +func (s *Session) QueueSend(data []byte) { + s.sendPackets <- data +} + +// QueueSendNonBlocking queues a packet (raw []byte) to be sent, dropping the packet entirely if the queue is full. +func (s *Session) QueueSendNonBlocking(data []byte) { + select { + case s.sendPackets <- data: + // Enqueued properly. + default: + // Couldn't enqueue, likely something wrong with the connection. + s.logger.Warn("Dropped packet for session because of full send buffer, something is probably wrong") + } +} + +// QueueSendMHF queues a MHFPacket to be sent. +func (s *Session) QueueSendMHF(pkt mhfpacket.MHFPacket) { + // Make the header + bf := byteframe.NewByteFrame() + bf.WriteUint16(uint16(pkt.Opcode())) + + // Build the packet onto the byteframe. + pkt.Build(bf) + + // Queue it. + s.QueueSend(bf.Data()) +} + +// QueueAck is a helper function to queue an MSG_SYS_ACK with the given ack handle and data. +func (s *Session) QueueAck(ackHandle uint32, data []byte) { + bf := byteframe.NewByteFrame() + bf.WriteUint16(uint16(network.MSG_SYS_ACK)) + bf.WriteUint32(ackHandle) + bf.WriteBytes(data) + s.QueueSend(bf.Data()) +} + +func (s *Session) sendLoop() { + for { + // TODO(Andoryuuta): Test making this into a buffered channel and grouping the packet together before sending. + rawPacket := <-s.sendPackets + if rawPacket == nil { + s.logger.Debug("Got nil from s.SendPackets, exiting send loop") + return + } + s.cryptConn.SendPacket(rawPacket) + } +} + +func (s *Session) recvLoop() { + for { + pkt, err := s.cryptConn.ReadPacket() + if err != nil { + s.logger.Warn("Error on ReadPacket, exiting recv loop", zap.Error(err)) + return + } + + s.handlePacketGroup(pkt) + } +} func (s *Session) handlePacketGroup(pktGroup []byte) { + // This shouldn't be needed, but it's better to recover and let the connection die than to panic the server. defer func() { if r := recover(); r != nil { fmt.Println("Recovered from panic.") @@ -67,370 +122,30 @@ func (s *Session) handlePacketGroup(pktGroup []byte) { bf := byteframe.NewByteFrameFromBytes(pktGroup) opcode := network.PacketID(bf.ReadUint16()) - if opcode != network.MSG_SYS_END { + // Print any (non-common spam) packet opcodes and data. + if opcode != network.MSG_SYS_END && + opcode != network.MSG_SYS_PING && + opcode != network.MSG_SYS_NOP && + opcode != network.MSG_SYS_TIME && + opcode != network.MSG_SYS_EXTEND_THRESHOLD { fmt.Printf("Opcode: %s\n", opcode) fmt.Printf("Data:\n%s\n", hex.Dump(pktGroup)) } - switch opcode { - case network.MSG_MHF_ENUMERATE_EVENT: - fallthrough - case network.MSG_MHF_ENUMERATE_QUEST: - fallthrough - case network.MSG_MHF_ENUMERATE_RANKING: - fallthrough - case network.MSG_MHF_READ_MERCENARY_W: - fallthrough - case network.MSG_MHF_GET_ETC_POINTS: - fallthrough - case network.MSG_MHF_READ_GUILDCARD: - fallthrough - case network.MSG_MHF_READ_BEAT_LEVEL: - fallthrough - case network.MSG_MHF_GET_EARTH_STATUS: - fallthrough - case network.MSG_MHF_GET_EARTH_VALUE: - fallthrough - case network.MSG_MHF_GET_WEEKLY_SCHEDULE: - fallthrough - case network.MSG_MHF_LIST_MEMBER: - fallthrough - case network.MSG_MHF_LOAD_PLATE_DATA: - fallthrough - case network.MSG_MHF_LOAD_PLATE_BOX: - fallthrough - case network.MSG_MHF_LOAD_FAVORITE_QUEST: - fallthrough - case network.MSG_MHF_LOAD_PARTNER: - fallthrough - case network.MSG_MHF_GET_TOWER_INFO: - fallthrough - case network.MSG_MHF_LOAD_OTOMO_AIROU: - fallthrough - case network.MSG_MHF_LOAD_DECO_MYSET: - fallthrough - case network.MSG_MHF_LOAD_HUNTER_NAVI: - fallthrough - case network.MSG_MHF_GET_UD_SCHEDULE: - fallthrough - case network.MSG_MHF_GET_UD_INFO: - fallthrough - case network.MSG_MHF_GET_UD_MONSTER_POINT: - fallthrough - case network.MSG_MHF_GET_RAND_FROM_TABLE: - fallthrough - case network.MSG_MHF_ACQUIRE_MONTHLY_REWARD: - fallthrough - case network.MSG_MHF_LOAD_PLATE_MYSET: - fallthrough - case network.MSG_MHF_LOAD_RENGOKU_DATA: - fallthrough - case network.MSG_MHF_ENUMERATE_SHOP: - fallthrough - case network.MSG_MHF_LOAD_SCENARIO_DATA: - fallthrough - case network.MSG_MHF_GET_BOOST_TIME_LIMIT: - fallthrough - case network.MSG_MHF_GET_BOOST_RIGHT: - fallthrough - case network.MSG_MHF_GET_REWARD_SONG: - fallthrough - case network.MSG_MHF_GET_GACHA_POINT: - fallthrough - case network.MSG_MHF_GET_KOURYOU_POINT: - fallthrough - case network.MSG_MHF_GET_ENHANCED_MINIDATA: - - ackHandle := bf.ReadUint32() - - data, err := ioutil.ReadFile(fmt.Sprintf("bin_resp/%s_resp.bin", opcode.String())) - if err != nil { - panic(err) - } - - bfw := byteframe.NewByteFrame() - bfw.WriteUint16(uint16(network.MSG_SYS_ACK)) - bfw.WriteUint32(ackHandle) - bfw.WriteBytes(data) - s.cryptConn.SendPacket(bfw.Data()) - - case network.MSG_MHF_INFO_FESTA: - ackHandle := bf.ReadUint32() - _ = bf.ReadUint32() - - data, err := ioutil.ReadFile(fmt.Sprintf("bin_resp/%s_resp.bin", opcode.String())) - if err != nil { - panic(err) - } - - bfw := byteframe.NewByteFrame() - bfw.WriteUint16(uint16(network.MSG_SYS_ACK)) - bfw.WriteUint32(ackHandle) - bfw.WriteBytes(data) - s.cryptConn.SendPacket(bfw.Data()) - - case network.MSG_MHF_LOADDATA: - ackHandle := bf.ReadUint32() - - data, err := ioutil.ReadFile(fmt.Sprintf("bin_resp/%s_resp%d.bin", opcode.String(), loadDataCount)) - if err != nil { - panic(err) - } - - bfw := byteframe.NewByteFrame() - bfw.WriteUint16(uint16(network.MSG_SYS_ACK)) - bfw.WriteUint32(ackHandle) - bfw.WriteBytes(data) - s.cryptConn.SendPacket(bfw.Data()) - - loadDataCount++ - if loadDataCount > 1 { - loadDataCount = 0 - } - case network.MSG_MHF_GET_PAPER_DATA: - ackHandle := bf.ReadUint32() - - data, err := ioutil.ReadFile(fmt.Sprintf("bin_resp/%s_resp%d.bin", opcode.String(), getPaperDataCount)) - if err != nil { - panic(err) - } - - bfw := byteframe.NewByteFrame() - bfw.WriteUint16(uint16(network.MSG_SYS_ACK)) - bfw.WriteUint32(ackHandle) - bfw.WriteBytes(data) - s.cryptConn.SendPacket(bfw.Data()) - - getPaperDataCount++ - if getPaperDataCount > 7 { - getPaperDataCount = 0 - } - default: - // Get the packet parser and handler for this opcode. - mhfPkt := mhfpacket.FromOpcode(opcode) - if mhfPkt == nil { - fmt.Println("Got opcode which we don't know how to parse, can't parse anymore for this group") - return - } - - // Parse and handle the packet - mhfPkt.Parse(bf) - handlerTable[opcode](s, mhfPkt) - break + // Get the packet parser and handler for this opcode. + mhfPkt := mhfpacket.FromOpcode(opcode) + if mhfPkt == nil { + fmt.Println("Got opcode which we don't know how to parse, can't parse anymore for this group") + return } + // Parse and handle the packet + mhfPkt.Parse(bf) + handlerTable[opcode](s, mhfPkt) + // If there is more data on the stream that the .Parse method didn't read, then read another packet off it. remainingData := bf.DataFromCurrent() - if len(remainingData) >= 2 && (opcode == network.MSG_SYS_TIME || opcode == network.MSG_MHF_INFO_FESTA || opcode == network.MSG_SYS_EXTEND_THRESHOLD) { + if len(remainingData) >= 2 { s.handlePacketGroup(remainingData) } } - -/* -func handlePacket(cc *network.CryptConn, pkt []byte) { - defer func() { - if r := recover(); r != nil { - fmt.Println("Recovered from panic.") - } - }() - - bf := byteframe.NewByteFrameFromBytes(pkt) - opcode := network.PacketID(bf.ReadUint16()) - - if opcode == network.MSG_SYS_EXTEND_THRESHOLD { - opcode = network.PacketID(bf.ReadUint16()) - } - - fmt.Printf("Opcode: %s\n", opcode) - switch opcode { - case network.MSG_SYS_PING: - ackHandle := bf.ReadUint32() - _ = bf.ReadUint16() - - bfw := byteframe.NewByteFrame() - bfw.WriteUint16(uint16(network.MSG_SYS_ACK)) - bfw.WriteUint32(ackHandle) - bfw.WriteUint32(0) - bfw.WriteUint32(0) - cc.SendPacket(bfw.Data()) - case network.MSG_SYS_TIME: - _ = bf.ReadUint8() - timestamp := bf.ReadUint32() // unix timestamp, e.g. 1577105879 - - bfw := byteframe.NewByteFrame() - bfw.WriteUint16(uint16(network.MSG_SYS_TIME)) - bfw.WriteUint8(0) - bfw.WriteUint32(timestamp) - cc.SendPacket(bfw.Data()) - case network.MSG_SYS_LOGIN: - ackHandle := bf.ReadUint32() - charID0 := bf.ReadUint32() - loginTokenNumber := bf.ReadUint32() - hardcodedZero0 := bf.ReadUint16() - requestVersion := bf.ReadUint16() - charID1 := bf.ReadUint32() - hardcodedZero1 := bf.ReadUint16() - loginTokenLength := bf.ReadUint16() // hardcoded to 0x11 - loginTokenString := bf.ReadBytes(17) - - _ = ackHandle - _ = charID0 - _ = loginTokenNumber - _ = hardcodedZero0 - _ = requestVersion - _ = charID1 - _ = hardcodedZero1 - _ = loginTokenLength - _ = loginTokenString - - bfw := byteframe.NewByteFrame() - bfw.WriteUint16(uint16(network.MSG_SYS_ACK)) - bfw.WriteUint32(ackHandle) - bfw.WriteUint64(0x000000005E00B9C2) // Timestamp? - cc.SendPacket(bfw.Data()) - - case network.MSG_MHF_ENUMERATE_EVENT: - fallthrough - case network.MSG_MHF_ENUMERATE_QUEST: - fallthrough - case network.MSG_MHF_ENUMERATE_RANKING: - fallthrough - case network.MSG_MHF_READ_MERCENARY_W: - fallthrough - case network.MSG_MHF_GET_ETC_POINTS: - fallthrough - case network.MSG_MHF_READ_GUILDCARD: - fallthrough - case network.MSG_MHF_READ_BEAT_LEVEL: - fallthrough - case network.MSG_MHF_GET_EARTH_STATUS: - fallthrough - case network.MSG_MHF_GET_EARTH_VALUE: - fallthrough - case network.MSG_MHF_GET_WEEKLY_SCHEDULE: - fallthrough - case network.MSG_MHF_LIST_MEMBER: - fallthrough - case network.MSG_MHF_LOAD_PLATE_DATA: - fallthrough - case network.MSG_MHF_LOAD_PLATE_BOX: - fallthrough - case network.MSG_MHF_LOAD_FAVORITE_QUEST: - fallthrough - case network.MSG_MHF_LOAD_PARTNER: - fallthrough - case network.MSG_MHF_GET_TOWER_INFO: - fallthrough - case network.MSG_MHF_LOAD_OTOMO_AIROU: - fallthrough - case network.MSG_MHF_LOAD_DECO_MYSET: - fallthrough - case network.MSG_MHF_LOAD_HUNTER_NAVI: - fallthrough - case network.MSG_MHF_GET_UD_SCHEDULE: - fallthrough - case network.MSG_MHF_GET_UD_INFO: - fallthrough - case network.MSG_MHF_GET_UD_MONSTER_POINT: - fallthrough - case network.MSG_MHF_GET_RAND_FROM_TABLE: - fallthrough - case network.MSG_MHF_ACQUIRE_MONTHLY_REWARD: - fallthrough - case network.MSG_MHF_GET_RENGOKU_RANKING_RANK: - fallthrough - case network.MSG_MHF_LOAD_PLATE_MYSET: - fallthrough - case network.MSG_MHF_LOAD_RENGOKU_DATA: - fallthrough - case network.MSG_MHF_ENUMERATE_SHOP: - fallthrough - case network.MSG_MHF_LOAD_SCENARIO_DATA: - fallthrough - case network.MSG_MHF_GET_BOOST_TIME_LIMIT: - fallthrough - case network.MSG_MHF_GET_BOOST_RIGHT: - fallthrough - case network.MSG_MHF_GET_REWARD_SONG: - fallthrough - case network.MSG_MHF_GET_GACHA_POINT: - fallthrough - case network.MSG_MHF_GET_KOURYOU_POINT: - fallthrough - case network.MSG_MHF_GET_ENHANCED_MINIDATA: - - ackHandle := bf.ReadUint32() - - data, err := ioutil.ReadFile(fmt.Sprintf("bin_resp/%s_resp.bin", opcode.String())) - if err != nil { - panic(err) - } - - bfw := byteframe.NewByteFrame() - bfw.WriteUint16(uint16(network.MSG_SYS_ACK)) - bfw.WriteUint32(ackHandle) - bfw.WriteBytes(data) - cc.SendPacket(bfw.Data()) - - case network.MSG_MHF_INFO_FESTA: - ackHandle := bf.ReadUint32() - _ = bf.ReadUint32() - - data, err := ioutil.ReadFile(fmt.Sprintf("bin_resp/%s_resp.bin", opcode.String())) - if err != nil { - panic(err) - } - - bfw := byteframe.NewByteFrame() - bfw.WriteUint16(uint16(network.MSG_SYS_ACK)) - bfw.WriteUint32(ackHandle) - bfw.WriteBytes(data) - cc.SendPacket(bfw.Data()) - - case network.MSG_MHF_LOADDATA: - ackHandle := bf.ReadUint32() - - data, err := ioutil.ReadFile(fmt.Sprintf("bin_resp/%s_resp%d.bin", opcode.String(), loadDataCount)) - if err != nil { - panic(err) - } - - bfw := byteframe.NewByteFrame() - bfw.WriteUint16(uint16(network.MSG_SYS_ACK)) - bfw.WriteUint32(ackHandle) - bfw.WriteBytes(data) - cc.SendPacket(bfw.Data()) - - loadDataCount++ - if loadDataCount > 1 { - loadDataCount = 0 - } - case network.MSG_MHF_GET_PAPER_DATA: - ackHandle := bf.ReadUint32() - - data, err := ioutil.ReadFile(fmt.Sprintf("bin_resp/%s_resp%d.bin", opcode.String(), getPaperDataCount)) - if err != nil { - panic(err) - } - - bfw := byteframe.NewByteFrame() - bfw.WriteUint16(uint16(network.MSG_SYS_ACK)) - bfw.WriteUint32(ackHandle) - bfw.WriteBytes(data) - cc.SendPacket(bfw.Data()) - - getPaperDataCount++ - if getPaperDataCount > 7 { - getPaperDataCount = 0 - } - default: - fmt.Printf("Data:\n%s\n", hex.Dump(pkt)) - break - } - - remainingData := bf.DataFromCurrent() - if len(remainingData) >= 2 && (opcode == network.MSG_SYS_TIME || opcode == network.MSG_MHF_INFO_FESTA) { - handlePacket(cc, remainingData) - } -} -*/ diff --git a/server/entranceserver/entrance_server.go b/server/entranceserver/entrance_server.go index 8ac3a9846..3760def97 100644 --- a/server/entranceserver/entrance_server.go +++ b/server/entranceserver/entrance_server.go @@ -1,7 +1,6 @@ package entranceserver import ( - "database/sql" "encoding/hex" "fmt" "io" @@ -10,6 +9,7 @@ import ( "github.com/Andoryuuta/Erupe/config" "github.com/Andoryuuta/Erupe/network" + "github.com/jmoiron/sqlx" "go.uber.org/zap" ) @@ -18,7 +18,7 @@ type Server struct { sync.Mutex logger *zap.Logger erupeConfig *config.Config - db *sql.DB + db *sqlx.DB listener net.Listener isShuttingDown bool } @@ -26,7 +26,7 @@ type Server struct { // Config struct allows configuring the server. type Config struct { Logger *zap.Logger - DB *sql.DB + DB *sqlx.DB ErupeConfig *config.Config } diff --git a/server/entranceserver/make_resp.go b/server/entranceserver/make_resp.go index 73ac12ea6..0a2ab71c2 100644 --- a/server/entranceserver/make_resp.go +++ b/server/entranceserver/make_resp.go @@ -2,6 +2,9 @@ package entranceserver import ( "encoding/binary" + "fmt" + "io/ioutil" + "log" "net" "github.com/Andoryuuta/Erupe/config" @@ -32,6 +35,7 @@ func encodeServerInfo(serverInfos []config.EntranceServerInfo) []byte { bf.WriteUint32(si.AllowedClientFlags) for channelIdx, ci := range si.Channels { + fmt.Println("Channel idx", channelIdx) bf.WriteUint16(ci.Port) bf.WriteUint16(16 + uint16(channelIdx)) bf.WriteUint16(ci.MaxPlayers) @@ -71,6 +75,7 @@ func makeHeader(data []byte, respType string, entryCount uint16, key byte) []byt } func makeResp(servers []config.EntranceServerInfo) []byte { + fmt.Printf("%+v\n", servers) rawServerData := encodeServerInfo(servers) bf := byteframe.NewByteFrame() @@ -81,6 +86,11 @@ func makeResp(servers []config.EntranceServerInfo) []byte { // If so, how does it work without the entrance server connection being authenticated? bf.WriteBytes(makeHeader([]byte{}, "USR", 0, 0x00)) + err := ioutil.WriteFile("go_entrance_resp.bin", bf.Data(), 0644) + if err != nil { + log.Fatal(err) + } + return bf.Data() } diff --git a/server/launcherserver/launcher_server.go b/server/launcherserver/launcher_server.go index 8d2e39adb..a3297ebe9 100644 --- a/server/launcherserver/launcher_server.go +++ b/server/launcherserver/launcher_server.go @@ -2,7 +2,6 @@ package launcherserver import ( "context" - "database/sql" "fmt" "net/http" "os" @@ -12,13 +11,14 @@ import ( "github.com/Andoryuuta/Erupe/config" "github.com/gorilla/handlers" "github.com/gorilla/mux" + "github.com/jmoiron/sqlx" "go.uber.org/zap" ) // Config struct allows configuring the server. type Config struct { Logger *zap.Logger - DB *sql.DB + DB *sqlx.DB ErupeConfig *config.Config UseOriginalLauncherFiles bool } @@ -28,7 +28,7 @@ type Server struct { sync.Mutex logger *zap.Logger erupeConfig *config.Config - db *sql.DB + db *sqlx.DB httpServer *http.Server useOriginalLauncherFiles bool isShuttingDown bool diff --git a/server/launcherserver/routes.go b/server/launcherserver/routes.go index bcdce830b..c951bf08a 100644 --- a/server/launcherserver/routes.go +++ b/server/launcherserver/routes.go @@ -13,7 +13,7 @@ func serverList(s *Server, w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, ``, s.erupeConfig.HostIP, - s.erupeConfig.Entrance.Port, + s.erupeConfig.Sign.Port, ) } diff --git a/server/signserver/dbutils.go b/server/signserver/dbutils.go new file mode 100644 index 000000000..bb5d4812d --- /dev/null +++ b/server/signserver/dbutils.go @@ -0,0 +1,56 @@ +package signserver + +import "time" + +func (s *Server) registerDBAccount(username string, password string) error { + _, err := s.db.Exec("INSERT INTO users (username, password) VALUES ($1, $2)", username, password) + if err != nil { + return err + } + + var id int + err = s.db.QueryRow("SELECT id FROM users WHERE username = $1", username).Scan(&id) + if err != nil { + return err + } + + // Create a base new character. + _, err = s.db.Exec(` + INSERT INTO characters ( + user_id, is_female, is_new_character, small_gr_level, gr_override_mode, name, unk_desc_string, + gr_override_level, gr_override_unk0, gr_override_unk1, exp, weapon, last_login) + VALUES($1, False, True, 0, True, '', '', 0, 0, 0, 0, 0, $2)`, + id, + uint32(time.Now().Unix()), + ) + if err != nil { + return err + } + + return nil +} + +type character struct { + ID uint32 `db:"id"` + IsFemale bool `db:"is_female"` + IsNewCharacter bool `db:"is_new_character"` + SmallGRLevel uint8 `db:"small_gr_level"` + GROverrideMode bool `db:"gr_override_mode"` + Name string `db:"name"` + UnkDescString string `db:"unk_desc_string"` + GROverrideLevel uint16 `db:"gr_override_level"` + GROverrideUnk0 uint8 `db:"gr_override_unk0"` + GROverrideUnk1 uint8 `db:"gr_override_unk1"` + Exp uint16 `db:"exp"` + Weapon uint16 `db:"weapon"` + LastLogin uint32 `db:"last_login"` +} + +func (s *Server) getCharactersForUser(uid int) ([]character, error) { + characters := []character{} + err := s.db.Select(&characters, "SELECT id, is_female, is_new_character, small_gr_level, gr_override_mode, name, unk_desc_string, gr_override_level, gr_override_unk0, gr_override_unk1, exp, weapon, last_login FROM characters WHERE user_id = $1", uid) + if err != nil { + return nil, err + } + return characters, nil +} diff --git a/server/signserver/dsgn_resp.go b/server/signserver/dsgn_resp.go index 593368eca..c05737ab5 100644 --- a/server/signserver/dsgn_resp.go +++ b/server/signserver/dsgn_resp.go @@ -1,6 +1,11 @@ package signserver -import "github.com/Andoryuuta/byteframe" +import ( + "fmt" + + "github.com/Andoryuuta/byteframe" + "go.uber.org/zap" +) func paddedString(x string, size uint) []byte { out := make([]byte, size) @@ -27,91 +32,45 @@ func makeSignInFailureResp(respID RespID) []byte { return bf.Data() } -func (session *Session) makeSignInResp(username string) []byte { - bf := byteframe.NewByteFrame() +func (s *Session) makeSignInResp(uid int) []byte { + // Get the characters from the DB. + chars, err := s.server.getCharactersForUser(uid) + if err != nil { + s.logger.Warn("Error getting characters from DB", zap.Error(err)) + } - // delete me: - //bf.WriteUint8(8) - //return bf.Data() + bf := byteframe.NewByteFrame() bf.WriteUint8(1) // resp_code bf.WriteUint8(0) // file/patch server count bf.WriteUint8(4) // entrance server count - bf.WriteUint8(1) // character count + bf.WriteUint8(uint8(len(chars))) // character count bf.WriteUint32(0xFFFFFFFF) // login_token_number bf.WriteBytes(paddedString("logintokenstrng", 16)) // login_token (16 byte padded string) bf.WriteUint32(1576761190) - - // file patch server PascalStrings here - - // Array(this.entrance_server_count, PascalString(Byte, "utf8")), - uint8PascalString(bf, "localhost:53310") + uint8PascalString(bf, fmt.Sprintf("%s:%d", s.server.erupeConfig.HostIP, s.server.erupeConfig.Entrance.Port)) uint8PascalString(bf, "") uint8PascalString(bf, "") uint8PascalString(bf, "mhf-n.capcom.com.tw") - /////////////////////////// - // Characters: - - /* - tab = '123456789ABCDEFGHJKLMNPQRTUVWXYZ' - def make_uid_str(cid): - out = '' - for i in range(6): - v = (cid>>5*i) - out += tab[v&0x1f] - return out - - def make_cid_int(uid): - v = 0 - for c in uid[::-1]: - idx = tab.find(c) - if idx == -1: - raise Exception("not in tab") - v |= idx - v = v<<5 - return v>>5 - */ - bf.WriteUint32(469153291) // character ID 469153291 - bf.WriteUint16(999) // Exp, HR[x] is split by 0, 1, 30, 50, 99, 299, 998, 999 - - //44.204 - - /* - 0=大劍/Big sword - 1=重弩/Heavy crossbow - 2=大錘/Sledgehammer - 3=長槍/Spear - 4=單手劍/One-handed sword - 5=輕弩/Light crossbow - 6=雙劍/Double sword - 7=太刀/Tadao - 8=狩獵笛/Hunting flute - 9=銃槍/Shotgun - 10=弓/bow - 11=穿龍棍/Wear a dragon stick - 12=斬擊斧F/Chopping Axe F - 13=--- - default=不明/unknown - */ - bf.WriteUint16(7) // Weapon, 0-13. - - bf.WriteUint32(1576761172) // Last login date, unix timestamp in seconds. - bf.WriteUint8(1) // Sex, 0=male, 1=female. - bf.WriteUint8(0) // Is new character, 1 replaces character name with ?????. - grMode := uint8(0) - bf.WriteUint8(1) // GR level if grMode == 0 - bf.WriteUint8(grMode) // GR mode. - bf.WriteBytes(paddedString(username, 16)) // Character name - bf.WriteBytes(paddedString("0", 32)) // unk str - if grMode == 1 { - bf.WriteUint16(55) // GR level override. - bf.WriteUint8(0) // unk - bf.WriteUint8(0) // unk + for _, char := range chars { + bf.WriteUint32(char.ID) // character ID 469153291 + bf.WriteUint16(char.Exp) // Exp, HR[x] is split by 0, 1, 30, 50, 99, 299, 998, 999 + bf.WriteUint16(char.Weapon) // Weapon, 0-13. + bf.WriteUint32(char.LastLogin) // Last login date, unix timestamp in seconds. + bf.WriteBool(char.IsFemale) // Sex, 0=male, 1=female. + bf.WriteBool(char.IsNewCharacter) // Is new character, 1 replaces character name with ?????. + bf.WriteUint8(char.SmallGRLevel) // GR level if grMode == 0 + bf.WriteBool(char.GROverrideMode) // GR mode. + bf.WriteBytes(paddedString(char.Name, 16)) // Character name + bf.WriteBytes(paddedString(char.UnkDescString, 32)) // unk str + if char.GROverrideMode { + bf.WriteUint16(char.GROverrideLevel) // GR level override. + bf.WriteUint8(char.GROverrideUnk0) // unk + bf.WriteUint8(char.GROverrideUnk1) // unk + } } - ////////////////////////// - bf.WriteUint8(0) // friends_list_count bf.WriteUint8(0) // guild_members_count bf.WriteUint8(0) // notice_count diff --git a/server/signserver/session.go b/server/signserver/session.go index c749a79d1..7c2051a4e 100644 --- a/server/signserver/session.go +++ b/server/signserver/session.go @@ -95,6 +95,25 @@ func (s *Session) handleDSGNRequest(bf *byteframe.ByteFrame) error { case err == sql.ErrNoRows: s.logger.Info("Account not found", zap.String("reqUsername", reqUsername)) serverRespBytes = makeSignInFailureResp(SIGN_EAUTH) + + // HACK(Andoryuuta): Create a new account if it doesn't exit. + s.logger.Info("Creating account", zap.String("reqUsername", reqUsername), zap.String("reqPassword", reqPassword)) + err = s.server.registerDBAccount(reqUsername, reqPassword) + if err != nil { + s.logger.Info("Error on creating new account", zap.Error(err)) + serverRespBytes = makeSignInFailureResp(SIGN_EABORT) + break + } + + var id int + err = s.server.db.QueryRow("SELECT id FROM users WHERE username = $1", reqUsername).Scan(&id) + if err != nil { + s.logger.Info("Error on querying account id", zap.Error(err)) + serverRespBytes = makeSignInFailureResp(SIGN_EABORT) + break + } + + serverRespBytes = s.makeSignInResp(id) break case err != nil: serverRespBytes = makeSignInFailureResp(SIGN_EABORT) @@ -103,7 +122,7 @@ func (s *Session) handleDSGNRequest(bf *byteframe.ByteFrame) error { default: if reqPassword == password { s.logger.Info("Passwords match!") - serverRespBytes = s.makeSignInResp(reqUsername) + serverRespBytes = s.makeSignInResp(id) } else { s.logger.Info("Passwords don't match!") serverRespBytes = makeSignInFailureResp(SIGN_EPASS) diff --git a/server/signserver/sign_server.go b/server/signserver/sign_server.go index de6b60d5d..7a37189c0 100644 --- a/server/signserver/sign_server.go +++ b/server/signserver/sign_server.go @@ -1,7 +1,6 @@ package signserver import ( - "database/sql" "fmt" "io" "net" @@ -9,13 +8,14 @@ import ( "github.com/Andoryuuta/Erupe/config" "github.com/Andoryuuta/Erupe/network" + "github.com/jmoiron/sqlx" "go.uber.org/zap" ) // Config struct allows configuring the server. type Config struct { Logger *zap.Logger - DB *sql.DB + DB *sqlx.DB ErupeConfig *config.Config } @@ -26,7 +26,7 @@ type Server struct { erupeConfig *config.Config sid int sessions map[int]*Session - db *sql.DB + db *sqlx.DB listener net.Listener isShuttingDown bool }