Compare commits

...

3 Commits

6 changed files with 50 additions and 53 deletions

View File

@ -17,33 +17,24 @@ type Inventory struct {
// start && end are both inclusive // start && end are both inclusive
func (db *DBHandler) GetPlayerInventorySlots(PlayerID int, start int, end int) ([]protocol.SItemBase, error) { func (db *DBHandler) GetPlayerInventorySlots(PlayerID int, start int, end int) ([]protocol.SItemBase, error) {
rows, err := db.Query("SELECT PlayerID, Slot, ID, Type, Opt, TimeLimit FROM Inventory WHERE Slot BETWEEN ? AND ? AND PlayerID = ?", start, end, PlayerID) rows, err := db.Query("SELECT Slot, Type, ID, Opt, TimeLimit FROM Inventory WHERE Slot BETWEEN ? AND ? AND PlayerID = ?", start, end, PlayerID)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var inven []Inventory items := make([]protocol.SItemBase, end-start)
for rows.Next() { for rows.Next() {
item := Inventory{} var slot int
item := protocol.SItemBase{}
if err := rows.Scan( if err := rows.Scan(
&item.PlayerID, &item.Slot, &item.ID, &item.Type, &item.Opt, &item.TimeLimit); err != nil { &slot, &item.IType, &item.IID, &item.IOpt, &item.ITimeLimit); err != nil {
return nil, err return nil, err
} }
inven = append(inven, item) items[slot-start] = item
} }
// populate an SItemBase array
items := make([]protocol.SItemBase, end-start)
for _, item := range inven {
items[item.Slot-start] = protocol.SItemBase{
IID: int16(item.ID),
IType: int16(item.Type),
IOpt: int32(item.Opt),
ITimeLimit: int32(item.TimeLimit),
}
}
return items, nil return items, nil
} }
@ -51,7 +42,7 @@ func (db *DBHandler) GetPlayerInventorySlots(PlayerID int, start int, end int) (
func (db *DBHandler) SetPlayerInventorySlots(PlayerID int, start int, items []protocol.SItemBase) error { func (db *DBHandler) SetPlayerInventorySlots(PlayerID int, start int, items []protocol.SItemBase) error {
return db.Transaction(func(tx *sql.Tx) error { return db.Transaction(func(tx *sql.Tx) error {
// delete inventory slots // delete inventory slots
_, err := db.Query("DELETE FROM Inventory WHERE Slot BETWEEN ? AND ? AND PlayerID = ?", start, start+len(items)-1, PlayerID) _, err := db.Exec("DELETE FROM Inventory WHERE Slot BETWEEN ? AND ? AND PlayerID = ?", start, start+len(items)-1, PlayerID)
if err != nil { if err != nil {
return err return err
} }
@ -59,7 +50,7 @@ func (db *DBHandler) SetPlayerInventorySlots(PlayerID int, start int, items []pr
// insert inventory // insert inventory
for i, item := range items { for i, item := range items {
if item.IID != 0 { if item.IID != 0 {
_, err := db.Query("INSERT INTO Inventory (PlayerID, Slot, ID, Type, Opt, TimeLimit) VALUES (?, ?, ?, ?, ?, ?)", PlayerID, start+i, item.IID, item.IType, item.IOpt, item.ITimeLimit) _, err := db.Exec("INSERT INTO Inventory (PlayerID, Slot, ID, Type, Opt, TimeLimit) VALUES (?, ?, ?, ?, ?, ?)", PlayerID, start+i, item.IID, item.IType, item.IOpt, item.ITimeLimit)
if err != nil { if err != nil {
return err return err
} }

View File

@ -17,11 +17,6 @@ type DBHandler struct {
db *sql.DB db *sql.DB
} }
type DBQuery interface {
Query(query string, args ...any) (*sql.Rows, error)
Exec(query string, args ...any) (sql.Result, error)
}
//go:embed migrations/new.sql //go:embed migrations/new.sql
var createDBQuery string var createDBQuery string

View File

@ -5,7 +5,7 @@ import (
"sync" "sync"
) )
var allocator = sync.Pool{ var allocator = &sync.Pool{
New: func() any { return new(bytes.Buffer) }, New: func() any { return new(bytes.Buffer) },
} }

View File

@ -105,9 +105,14 @@ func (server *LoginServer) Login(peer *Peer, pkt protocol.Packet) error {
return err return err
} }
// truncate plrs
if len(plrs) > 3 {
plrs = plrs[:4]
}
// build character list // build character list
charInfo := make([]protocol.SP_LS2CL_REP_CHAR_INFO, 0, 4) charInfo := [4]protocol.SP_LS2CL_REP_CHAR_INFO{}
for _, plr := range plrs { for i, plr := range plrs {
PCStyle, PCStyle2 := util.Player2PCStyle(&plr) PCStyle, PCStyle2 := util.Player2PCStyle(&plr)
info := protocol.SP_LS2CL_REP_CHAR_INFO{ info := protocol.SP_LS2CL_REP_CHAR_INFO{
ISlot: int8(plr.Slot), ISlot: int8(plr.Slot),
@ -126,10 +131,10 @@ func (server *LoginServer) Login(peer *Peer, pkt protocol.Packet) error {
} }
copy(info.AEquip[:], AEquip) copy(info.AEquip[:], AEquip)
charInfo = append(charInfo, info) charInfo[i] = info
} }
return server.AcceptLogin(peer, loginPkt.SzID, loginPkt.IClientVerC, 1, charInfo) return server.AcceptLogin(peer, loginPkt.SzID, loginPkt.IClientVerC, 1, charInfo[:len(plrs)])
} }
func (server *LoginServer) CheckCharacterName(peer *Peer, pkt protocol.Packet) error { func (server *LoginServer) CheckCharacterName(peer *Peer, pkt protocol.Packet) error {
@ -191,6 +196,7 @@ func validateCharacterCreation(character *protocol.SP_CL2LS_REQ_CHAR_CREATE) boo
return false return false
} }
// TODO: sanity check items in SOn_Item; see db.FinishPlayer()
return true return true
} }

View File

@ -17,6 +17,8 @@ type LoginServer struct {
peersLock sync.Mutex peersLock sync.Mutex
} }
func stubbedPacket(_ *Peer, _ protocol.Packet) error { /* stubbed */ return nil }
func NewLoginServer() *LoginServer { func NewLoginServer() *LoginServer {
listener, err := net.Listen("tcp", ":23000") listener, err := net.Listen("tcp", ":23000")
if err != nil { if err != nil {
@ -24,25 +26,26 @@ func NewLoginServer() *LoginServer {
} }
loginServer := &LoginServer{ loginServer := &LoginServer{
listener: listener, listener: listener,
packetHandlers: make(map[uint32]PacketHandler), peers: make(map[*Peer]bool),
peers: make(map[*Peer]bool),
} }
loginServer.RegisterPacketHandler(protocol.P_CL2LS_REQ_LOGIN, loginServer.Login) loginServer.packetHandlers = map[uint32]PacketHandler{
loginServer.RegisterPacketHandler(protocol.P_CL2LS_REQ_CHECK_CHAR_NAME, loginServer.CheckCharacterName) protocol.P_CL2LS_REQ_LOGIN: loginServer.Login,
loginServer.RegisterPacketHandler(protocol.P_CL2LS_REQ_SAVE_CHAR_NAME, loginServer.SaveCharacterName) protocol.P_CL2LS_REQ_CHECK_CHAR_NAME: loginServer.CheckCharacterName,
loginServer.RegisterPacketHandler(protocol.P_CL2LS_REQ_CHAR_CREATE, loginServer.CharacterCreate) protocol.P_CL2LS_REQ_SAVE_CHAR_NAME: loginServer.SaveCharacterName,
// loginServer.RegisterPacketHandler(protocol.P_CL2LS_REQ_CHAR_SELECT, func(_ *Peer, _ protocol.Packet) error { /* stubbed */ return nil }) protocol.P_CL2LS_REQ_CHAR_CREATE: loginServer.CharacterCreate,
loginServer.RegisterPacketHandler(protocol.P_CL2LS_REQ_CHAR_DELETE, loginServer.CharacterDelete) protocol.P_CL2LS_REQ_CHAR_SELECT: stubbedPacket,
// loginServer.RegisterPacketHandler(protocol.P_CL2LS_REQ_SHARD_SELECT, func(_ *Peer, _ protocol.Packet) error { /* stubbed */ return nil }) protocol.P_CL2LS_REQ_CHAR_DELETE: loginServer.CharacterDelete,
// loginServer.RegisterPacketHandler(protocol.P_CL2LS_REQ_SHARD_LIST_INFO, func(_ *Peer, _ protocol.Packet) error { /* stubbed */ return nil }) protocol.P_CL2LS_REQ_SHARD_SELECT: stubbedPacket,
// loginServer.RegisterPacketHandler(protocol.P_CL2LS_CHECK_NAME_LIST, func(_ *Peer, _ protocol.Packet) error { /* stubbed */ return nil }) protocol.P_CL2LS_REQ_SHARD_LIST_INFO: stubbedPacket,
loginServer.RegisterPacketHandler(protocol.P_CL2LS_REQ_SAVE_CHAR_TUTOR, loginServer.FinishTutorial) protocol.P_CL2LS_CHECK_NAME_LIST: stubbedPacket,
// loginServer.RegisterPacketHandler(protocol.P_CL2LS_REQ_PC_EXIT_DUPLICATE, func(_ *Peer, _ protocol.Packet) error { /* stubbed */ return nil }) protocol.P_CL2LS_REQ_SAVE_CHAR_TUTOR: loginServer.FinishTutorial,
// loginServer.RegisterPacketHandler(protocol.P_CL2LS_REP_LIVE_CHECK, func(_ *Peer, _ protocol.Packet) error { /* stubbed */ return nil }) protocol.P_CL2LS_REQ_PC_EXIT_DUPLICATE: stubbedPacket,
// loginServer.RegisterPacketHandler(protocol.P_CL2LS_REQ_CHANGE_CHAR_NAME, func(_ *Peer, _ protocol.Packet) error { /* stubbed */ return nil }) protocol.P_CL2LS_REP_LIVE_CHECK: stubbedPacket,
// loginServer.RegisterPacketHandler(protocol.P_CL2LS_REQ_SERVER_SELECT, func(_ *Peer, _ protocol.Packet) error { /* stubbed */ return nil }) protocol.P_CL2LS_REQ_CHANGE_CHAR_NAME: stubbedPacket,
protocol.P_CL2LS_REQ_SERVER_SELECT: stubbedPacket,
}
return loginServer return loginServer
} }
@ -73,7 +76,7 @@ func (server *LoginServer) HandlePacket(peer *Peer, typeID uint32, pkt protocol.
return err return err
} }
} else { } else {
log.Printf("[WARN] unsupported packet ID: %x\n", typeID) log.Printf("[WARN] invalid packet ID: %x\n", typeID)
} }
return nil return nil

View File

@ -24,15 +24,15 @@ type PeerHandler interface {
} }
type Peer struct { type Peer struct {
Player *db.Player
conn net.Conn
handler PeerHandler
SzID string
E_key []byte E_key []byte
FE_key []byte FE_key []byte
SzID string
AccountID int AccountID int
Player *db.Player
handler PeerHandler
conn net.Conn
alive bool
whichKey int whichKey int
alive bool
} }
func NewPeer(handler PeerHandler, conn net.Conn) *Peer { func NewPeer(handler PeerHandler, conn net.Conn) *Peer {
@ -50,14 +50,15 @@ func NewPeer(handler PeerHandler, conn net.Conn) *Peer {
} }
func (peer *Peer) Send(typeID uint32, data ...interface{}) error { func (peer *Peer) Send(typeID uint32, data ...interface{}) error {
// grab buffer from pool
buf := pool.Get() buf := pool.Get()
defer pool.Put(buf) // always return the buffer to the pool defer pool.Put(buf)
// body start // body start
pkt := protocol.NewPacket(buf) pkt := protocol.NewPacket(buf)
// encode type id // encode type id
if err := pkt.Encode(uint32(typeID)); err != nil { if err := pkt.Encode(typeID); err != nil {
return err return err
} }
@ -117,8 +118,9 @@ func (peer *Peer) Handler() {
return return
} }
// read packet body // grab buffer && read packet body
buf := pool.Get() buf := pool.Get()
defer pool.Put(buf)
if _, err := buf.ReadFrom(io.LimitReader(peer.conn, int64(sz))); err != nil { if _, err := buf.ReadFrom(io.LimitReader(peer.conn, int64(sz))); err != nil {
log.Printf("[FATAL] failed to read packet body! %v", err) log.Printf("[FATAL] failed to read packet body! %v", err)
return return