mirror of
https://github.com/Mezeporta/Erupe.git
synced 2025-12-18 18:04:52 +01:00
129 lines
3.6 KiB
Go
129 lines
3.6 KiB
Go
package entranceserver
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"net"
|
|
|
|
"erupe-ce/common/stringsupport"
|
|
|
|
"github.com/Andoryuuta/byteframe"
|
|
"erupe-ce/config"
|
|
"erupe-ce/server/channelserver"
|
|
)
|
|
|
|
func paddedString(x string, size uint) []byte {
|
|
out := make([]byte, size)
|
|
copy(out, x)
|
|
|
|
// Null terminate it.
|
|
out[len(out)-1] = 0
|
|
return out
|
|
}
|
|
|
|
// Server Entries
|
|
var name string
|
|
var season uint8
|
|
|
|
// Server Channels
|
|
var currentplayers uint16
|
|
|
|
func encodeServerInfo(serverInfos []config.EntranceServerInfo, s *Server) []byte {
|
|
bf := byteframe.NewByteFrame()
|
|
|
|
for serverIdx, si := range serverInfos {
|
|
err := s.db.QueryRow("SELECT server_name FROM servers WHERE server_name=$1", si.Name).Scan(&name)
|
|
if err != nil {
|
|
_, err := s.db.Exec("INSERT INTO servers (server_name, season, current_players, event_id, event_expiration) VALUES ($1, $2, 0, 0, 0)", si.Name, si.Season)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
} else {
|
|
err := s.db.QueryRow("SELECT season FROM servers WHERE server_name=$1", si.Name).Scan(&season)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
bf.WriteUint32(binary.LittleEndian.Uint32(net.ParseIP(si.IP).To4()))
|
|
bf.WriteUint16(16 + uint16(serverIdx))
|
|
bf.WriteUint16(0x0000)
|
|
bf.WriteUint16(uint16(len(si.Channels)))
|
|
bf.WriteUint8(si.Type)
|
|
bf.WriteUint8(season)
|
|
bf.WriteUint8(si.Recommended)
|
|
shiftjisName, err := stringsupport.ConvertUTF8ToShiftJIS(si.Name)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
bf.WriteBytes(paddedString(string(shiftjisName), 66))
|
|
bf.WriteUint32(si.AllowedClientFlags)
|
|
|
|
for channelIdx, ci := range si.Channels {
|
|
bf.WriteUint16(ci.Port)
|
|
bf.WriteUint16(16 + uint16(channelIdx))
|
|
bf.WriteUint16(ci.MaxPlayers)
|
|
err := s.db.QueryRow("SELECT current_players FROM servers WHERE server_name=$1", si.Name).Scan(¤tplayers)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
bf.WriteUint16(currentplayers)
|
|
bf.WriteUint32(0)
|
|
bf.WriteUint32(0)
|
|
bf.WriteUint32(0)
|
|
bf.WriteUint16(ci.Unk0)
|
|
bf.WriteUint16(ci.Unk1)
|
|
bf.WriteUint16(ci.Unk2)
|
|
bf.WriteUint16(0x3039)
|
|
}
|
|
}
|
|
bf.WriteUint32(uint32(channelserver.Time_Current_Adjusted().Unix()))
|
|
bf.WriteUint32(0x0000003C)
|
|
return bf.Data()
|
|
}
|
|
|
|
func makeHeader(data []byte, respType string, entryCount uint16, key byte) []byte {
|
|
bf := byteframe.NewByteFrame()
|
|
bf.WriteBytes([]byte(respType))
|
|
bf.WriteUint16(entryCount)
|
|
bf.WriteUint16(uint16(len(data)))
|
|
if len(data) > 0 {
|
|
bf.WriteUint32(CalcSum32(data))
|
|
bf.WriteBytes(data)
|
|
}
|
|
|
|
dataToEncrypt := bf.Data()
|
|
|
|
bf = byteframe.NewByteFrame()
|
|
bf.WriteUint8(key)
|
|
bf.WriteBytes(EncryptBin8(dataToEncrypt, key))
|
|
return bf.Data()
|
|
}
|
|
|
|
func makeSv2Resp(servers []config.EntranceServerInfo, s *Server) []byte {
|
|
rawServerData := encodeServerInfo(servers, s)
|
|
bf := byteframe.NewByteFrame()
|
|
bf.WriteBytes(makeHeader(rawServerData, "SV2", uint16(len(servers)), 0x00))
|
|
return bf.Data()
|
|
}
|
|
|
|
func makeUsrResp(pkt []byte) []byte {
|
|
// TODO(Andoryuuta): Figure out what this user data is.
|
|
// Is it for the friends list at the world selection screen?
|
|
// If so, how does it work without the entrance server connection being authenticated?
|
|
|
|
// uint16 for number of requested ids
|
|
// uint32 for each id
|
|
// response seems to be server number starting from 10 10 00 00 for server 1 channel 1?
|
|
bf := byteframe.NewByteFrameFromBytes(pkt)
|
|
_ = bf.ReadUint32() // ALL+
|
|
_ = bf.ReadUint8() // 0x00
|
|
|
|
userEntries := bf.ReadUint16()
|
|
// actual process will be reading all ids and returning real server, just returning all in server 1 for now
|
|
bf = byteframe.NewByteFrame()
|
|
for i := 0; i < int(userEntries); i++ {
|
|
bf.WriteBytes([]byte{0x10, 0x10, 0x00, 0x00})
|
|
}
|
|
return makeHeader(bf.Data(), "USR", userEntries, 0x00)
|
|
|
|
}
|