Initial chat prototype

This commit is contained in:
Andrew Gutekanst
2020-01-19 12:52:57 -05:00
parent e6d7b7b9c2
commit fa608fa555
73 changed files with 1646 additions and 714 deletions

2
.gitignore vendored
View File

@@ -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
test.py

View File

@@ -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
}
]
}
]
}

4
go.mod
View File

@@ -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
)

7
go.sum
View File

@@ -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=

19
main.go
View File

@@ -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)
}

View File

@@ -0,0 +1,8 @@
BEGIN;
ALTER TABLE characters
DROP COLUMN exp,
DROP COLUMN weapon,
DROP COLUMN last_login;
END;

View File

@@ -0,0 +1,8 @@
BEGIN;
ALTER TABLE characters
ADD COLUMN exp uint16,
ADD COLUMN weapon uint16,
ADD COLUMN last_login integer;
END;

View File

@@ -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,7 +19,10 @@ 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.

View File

@@ -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,7 +19,10 @@ 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.

View File

@@ -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,7 +23,14 @@ 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.

View File

@@ -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,7 +17,8 @@ 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.

View File

@@ -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,7 +17,8 @@ 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.

View File

@@ -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,7 +17,8 @@ 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.

View File

@@ -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,7 +19,10 @@ 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.

View File

@@ -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,7 +24,15 @@ 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.

View File

@@ -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,7 +18,9 @@ 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.

View File

@@ -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,7 +17,8 @@ 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.

View File

@@ -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,7 +17,8 @@ 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.

View File

@@ -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,7 +20,11 @@ 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.

View File

@@ -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,7 +30,11 @@ 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.

View File

@@ -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,7 +17,8 @@ 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.

View File

@@ -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,7 +17,8 @@ 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.

View File

@@ -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,7 +17,8 @@ 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.

View File

@@ -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,7 +17,8 @@ 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.

View File

@@ -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,7 +19,10 @@ 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.

View File

@@ -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,7 +17,8 @@ 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.

View File

@@ -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,7 +17,8 @@ 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.

View File

@@ -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,7 +17,8 @@ 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.

View File

@@ -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,7 +17,8 @@ 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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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,7 +17,8 @@ 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.

View File

@@ -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,7 +17,8 @@ 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.

View File

@@ -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,7 +17,8 @@ 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.

View File

@@ -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,7 +17,8 @@ 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.

View File

@@ -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,7 +17,8 @@ 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.

View File

@@ -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,7 +20,16 @@ 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.

View File

@@ -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.

View File

@@ -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,7 +20,11 @@ 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.

View File

@@ -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,7 +19,10 @@ 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.

View File

@@ -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,7 +19,10 @@ 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.

View File

@@ -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,7 +19,10 @@ 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.

View File

@@ -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,7 +22,13 @@ 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.

View File

@@ -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,7 +19,10 @@ 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.

View File

@@ -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
}

View File

@@ -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,7 +21,13 @@ 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.

View File

@@ -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")
bf.WriteUint32(m.CharID)
bf.WriteUint8(m.Type0)
bf.WriteUint8(m.Type0)
bf.WriteUint16(uint16(len(m.RawDataPayload)))
bf.WriteBytes(m.RawDataPayload)
return nil
}

View File

@@ -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,7 +19,12 @@ 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.

View File

@@ -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
}

View File

@@ -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,7 +20,11 @@ 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.

View File

@@ -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
}

View File

@@ -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.

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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.

View File

@@ -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,7 +17,8 @@ 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.

View File

@@ -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,7 +17,8 @@ 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.

View File

@@ -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,7 +19,10 @@ 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.

View File

@@ -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,7 +19,10 @@ 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.

View File

@@ -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,7 +27,26 @@ 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.

View File

@@ -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
}

View File

@@ -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")
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
}

View File

@@ -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())
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -3,7 +3,6 @@ package channelserver
import (
"encoding/hex"
"fmt"
"io/ioutil"
"net"
"sync"
@@ -20,6 +19,10 @@ type Session struct {
server *Server
rawConn net.Conn
cryptConn *network.CryptConn
sendPackets chan []byte
stageID string
charID uint32
}
// NewSession creates a new Session type.
@@ -29,35 +32,87 @@ func NewSession(server *Server, conn net.Conn) *Session {
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.
go s.sendLoop()
s.recvLoop()
}()
}
// 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 channel server readpacket", zap.Error(err))
s.logger.Warn("Error on ReadPacket, exiting recv loop", zap.Error(err))
return
}
s.handlePacketGroup(pkt)
}
}()
}
var loadDataCount int
var getPaperDataCount int
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,145 +122,16 @@ 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 {
@@ -216,221 +142,10 @@ func (s *Session) handlePacketGroup(pktGroup []byte) {
// Parse and handle the packet
mhfPkt.Parse(bf)
handlerTable[opcode](s, mhfPkt)
break
}
// 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)
}
}
*/

View File

@@ -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
}

View File

@@ -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()
}

View File

@@ -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

View File

@@ -13,7 +13,7 @@ func serverList(s *Server, w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w,
`<?xml version="1.0"?><server_groups><group idx='0' nam='Erupe' ip='%s' port="%d"/></server_groups>`,
s.erupeConfig.HostIP,
s.erupeConfig.Entrance.Port,
s.erupeConfig.Sign.Port,
)
}

View File

@@ -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
}

View File

@@ -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,90 +32,44 @@ 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

View File

@@ -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)

View File

@@ -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
}