Merge branch 'main' into feature/diva

# Conflicts:
#	server/channelserver/handlers_quest.go
This commit is contained in:
wish
2022-11-01 12:54:25 +11:00
69 changed files with 536 additions and 1034 deletions

View File

@@ -6,7 +6,6 @@ import (
"erupe-ce/common/stringsupport"
"fmt"
"io"
"math"
"net"
"strings"
"time"
@@ -74,26 +73,16 @@ func doAckSimpleFail(s *Session, ackHandle uint32, data []byte) {
}
func updateRights(s *Session) {
s.rights = uint32(0x0E)
s.server.db.QueryRow("SELECT rights FROM users u INNER JOIN characters c ON u.id = c.user_id WHERE c.id = $1", s.charID).Scan(&s.rights)
rights := make([]mhfpacket.ClientRight, 0)
tempRights := s.rights
for i := 30; i > 0; i-- {
right := uint32(math.Pow(2, float64(i)))
if tempRights-right < 0x80000000 {
if i == 1 {
continue
}
rights = append(rights, mhfpacket.ClientRight{ID: uint16(i), Timestamp: 0x70DB59F0})
tempRights -= right
}
rightsInt := uint32(0x0E)
s.server.db.QueryRow("SELECT rights FROM users u INNER JOIN characters c ON u.id = c.user_id WHERE c.id = $1", s.charID).Scan(&rightsInt)
s.courses = mhfpacket.GetCourseStruct(rightsInt)
rights := []mhfpacket.ClientRight{{1, 0, 0}}
for _, course := range s.courses {
rights = append(rights, mhfpacket.ClientRight{ID: course.ID, Timestamp: 0x70DB59F0})
}
rights = append(rights, mhfpacket.ClientRight{ID: 1, Timestamp: 0})
update := &mhfpacket.MsgSysUpdateRight{
ClientRespAckHandle: 0,
Bitfield: s.rights,
Bitfield: rightsInt,
Rights: rights,
UnkSize: 0,
}
@@ -190,6 +179,16 @@ func logoutPlayer(s *Session) {
s.server.Unlock()
for _, stage := range s.server.stages {
// Tell sessions registered to disconnecting players quest to unregister
if stage.host != nil && stage.host.charID == s.charID {
for _, sess := range s.server.sessions {
for rSlot := range stage.reservedClientSlots {
if sess.charID == rSlot && sess.stage != nil && sess.stage.id[3:5] != "Qs" {
sess.QueueSendMHF(&mhfpacket.MsgSysStageDestruct{})
}
}
}
}
for session := range stage.clients {
if session.charID == s.charID {
delete(stage.clients, session)
@@ -214,7 +213,7 @@ func logoutPlayer(s *Session) {
timePlayed += sessionTime
var rpGained int
if s.rights >= 0x40000000 { // N Course
if s.FindCourse("Netcafe").ID != 0 {
rpGained = timePlayed / 900
timePlayed = timePlayed % 900
} else {

View File

@@ -4,6 +4,7 @@ import (
"erupe-ce/common/byteframe"
ps "erupe-ce/common/pascalstring"
"erupe-ce/network/mhfpacket"
"fmt"
"go.uber.org/zap"
"io"
"time"
@@ -71,15 +72,22 @@ func handleMsgMhfGetCafeDuration(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfGetCafeDuration)
bf := byteframe.NewByteFrame()
var cafeReset time.Time
err := s.server.db.QueryRow(`SELECT cafe_reset FROM characters WHERE id=$1`, s.charID).Scan(&cafeReset)
if Time_Current_Adjusted().After(cafeReset) {
cafeReset = TimeWeekNext()
s.server.db.Exec(`UPDATE characters SET cafe_time=0, cafe_reset=$1 WHERE id=$2; DELETE FROM cafe_accepted WHERE character_id=$2`, cafeReset, s.charID)
}
var cafeTime uint32
err := s.server.db.QueryRow("SELECT cafe_time FROM characters WHERE id = $1", s.charID).Scan(&cafeTime)
err = s.server.db.QueryRow("SELECT cafe_time FROM characters WHERE id = $1", s.charID).Scan(&cafeTime)
if err != nil {
panic(err)
}
cafeTime = uint32(Time_Current_Adjusted().Unix()) - uint32(s.sessionStart) + cafeTime
bf.WriteUint32(cafeTime) // Total cafe time
bf.WriteUint16(0)
ps.Uint16(bf, "Resets at next maintenance", true)
ps.Uint16(bf, fmt.Sprintf("Resets on %s %d", cafeReset.Month().String(), cafeReset.Day()), true)
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
}

View File

@@ -7,6 +7,7 @@ import (
"erupe-ce/network/binpacket"
"erupe-ce/network/mhfpacket"
"fmt"
"golang.org/x/exp/slices"
"math"
"math/rand"
"strings"
@@ -19,6 +20,7 @@ import (
const (
BinaryMessageTypeState = 0
BinaryMessageTypeChat = 1
BinaryMessageTypeQuest = 2
BinaryMessageTypeData = 3
BinaryMessageTypeMailNotify = 4
BinaryMessageTypeEmote = 6
@@ -89,6 +91,18 @@ func handleMsgSysCastBinary(s *Session, p mhfpacket.MHFPacket) {
}
}
if s.server.erupeConfig.DevModeOptions.QuestDebugTools == true && s.server.erupeConfig.DevMode {
if pkt.BroadcastType == 0x03 && pkt.MessageType == 0x02 && len(pkt.RawDataPayload) > 32 {
// This is only correct most of the time
tmp.ReadBytes(20)
tmp.SetLE()
x := tmp.ReadFloat32()
y := tmp.ReadFloat32()
z := tmp.ReadFloat32()
s.logger.Debug("Coord", zap.Float32s("XYZ", []float32{x, y, z}))
}
}
// Parse out the real casted binary payload
var msgBinTargeted *binpacket.MsgBinTargeted
var authorLen, msgLen uint16
@@ -298,6 +312,53 @@ func handleMsgSysCastBinary(s *Session, p mhfpacket.MHFPacket) {
}
}
if strings.HasPrefix(chatMessage.Message, commands["Course"].Prefix) {
if commands["Course"].Enabled {
var name string
n, err := fmt.Sscanf(chatMessage.Message, "!course %s", &name)
if err != nil || n != 1 {
sendServerChatMessage(s, "Error in command. Format: !course <name>")
} else {
name = strings.ToLower(name)
for _, course := range mhfpacket.Courses() {
for _, alias := range course.Aliases {
if strings.ToLower(name) == strings.ToLower(alias) {
if slices.Contains(s.server.erupeConfig.Courses, config.Course{Name: course.Aliases[0], Enabled: true}) {
if s.FindCourse(name).Value != 0 {
ei := slices.IndexFunc(s.courses, func(c mhfpacket.Course) bool {
for _, alias := range c.Aliases {
if strings.ToLower(name) == strings.ToLower(alias) {
return true
}
}
return false
})
if ei != -1 {
s.courses = append(s.courses[:ei], s.courses[ei+1:]...)
sendServerChatMessage(s, fmt.Sprintf(`%s Course disabled.`, course.Aliases[0]))
}
} else {
s.courses = append(s.courses, course)
sendServerChatMessage(s, fmt.Sprintf(`%s Course enabled.`, course.Aliases[0]))
}
var newInt uint32
for _, course := range s.courses {
newInt += course.Value
}
s.server.db.Exec("UPDATE users u SET rights=$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)", newInt, s.charID)
updateRights(s)
} else {
sendServerChatMessage(s, fmt.Sprintf(`%s Course is locked.`, course.Aliases[0]))
}
}
}
}
}
} else {
sendDisabledCommandMessage(s, commands["Course"])
}
}
if strings.HasPrefix(chatMessage.Message, commands["Raviente"].Prefix) {
if commands["Raviente"].Enabled {
if getRaviSemaphore(s) != "" {

View File

@@ -2,6 +2,7 @@ package channelserver
import (
"encoding/hex"
"erupe-ce/common/bfutil"
"erupe-ce/common/stringsupport"
"fmt"
"io"
@@ -9,7 +10,6 @@ import (
"os"
"path/filepath"
"erupe-ce/common/bfutil"
"erupe-ce/common/byteframe"
"erupe-ce/network/mhfpacket"
"erupe-ce/server/channelserver/compression/deltacomp"
@@ -49,7 +49,7 @@ func handleMsgMhfSavedata(s *Session, p mhfpacket.MHFPacket) {
characterSaveData.Save(s)
s.logger.Info("Wrote recompressed savedata back to DB.")
characterSaveData.Name = s.clientContext.StrConv.MustDecode(bfutil.UpToNull(characterSaveData.decompSave[88:100]))
characterSaveData.Name = stringsupport.SJISToUTF8(bfutil.UpToNull(characterSaveData.decompSave[88:100]))
_, err = s.server.db.Exec("UPDATE characters SET name=$1 WHERE id=$2", characterSaveData.Name, s.charID)
if err != nil {
s.logger.Fatal("Failed to update character name in db", zap.Error(err))

View File

@@ -53,38 +53,46 @@ func handleMsgMhfEnumerateEvent(s *Session, p mhfpacket.MHFPacket) {
}
type activeFeature struct {
StartTime time.Time
ActiveFeatures uint32
Unk1 uint16
StartTime time.Time `db:"start_time"`
ActiveFeatures uint32 `db:"featured"`
}
func handleMsgMhfGetWeeklySchedule(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfGetWeeklySchedule)
persistentEventSchedule := make([]activeFeature, 8) // generate day after weekly restart
for x := -1; x < 7; x++ {
feat := generateActiveWeapons(14) // number of active weapons
// TODO: only generate this once per restart (server should be restarted weekly)
// then load data from db instead of regenerating
persistentEventSchedule[x+1] = activeFeature{
StartTime: Time_Current_Midnight().Add(time.Duration(24*x) * time.Hour),
ActiveFeatures: uint32(feat),
Unk1: 0,
var features []activeFeature
rows, _ := s.server.db.Queryx(`SELECT start_time, featured FROM feature_weapon WHERE start_time=$1 OR start_time=$2`, Time_Current_Midnight().Add(-24*time.Hour), Time_Current_Midnight())
for rows.Next() {
var feature activeFeature
rows.StructScan(&feature)
features = append(features, feature)
}
if len(features) < 2 {
if len(features) == 0 {
feature := generateFeatureWeapons(s.server.erupeConfig.FeaturedWeapons)
feature.StartTime = Time_Current_Midnight().Add(-24 * time.Hour)
features = append(features, feature)
s.server.db.Exec(`INSERT INTO feature_weapon VALUES ($1, $2)`, feature.StartTime, feature.ActiveFeatures)
}
feature := generateFeatureWeapons(s.server.erupeConfig.FeaturedWeapons)
feature.StartTime = Time_Current_Midnight()
features = append(features, feature)
s.server.db.Exec(`INSERT INTO feature_weapon VALUES ($1, $2)`, feature.StartTime, feature.ActiveFeatures)
}
resp := byteframe.NewByteFrame()
resp.WriteUint8(uint8(len(persistentEventSchedule))) // Entry count, client only parses the first 7 or 8.
resp.WriteUint32(uint32(Time_Current_Adjusted().Add(-5 * time.Minute).Unix())) // 5 minutes ago server time
for _, es := range persistentEventSchedule {
resp.WriteUint32(uint32(es.StartTime.Unix()))
resp.WriteUint32(es.ActiveFeatures)
resp.WriteUint16(es.Unk1)
bf := byteframe.NewByteFrame()
bf.WriteUint8(2)
bf.WriteUint32(uint32(Time_Current_Adjusted().Add(-5 * time.Minute).Unix()))
for _, feature := range features {
bf.WriteUint32(uint32(feature.StartTime.Unix()))
bf.WriteUint32(feature.ActiveFeatures)
bf.WriteUint16(0)
}
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
}
func generateActiveWeapons(count int) int {
func generateFeatureWeapons(count int) activeFeature {
nums := make([]int, 0)
var result int
r := rand.New(rand.NewSource(time.Now().UnixNano()))
@@ -104,7 +112,7 @@ func generateActiveWeapons(count int) int {
for _, num := range nums {
result += int(math.Pow(2, float64(num)))
}
return result
return activeFeature{ActiveFeatures: uint32(result)}
}
type loginBoost struct {

View File

@@ -6,6 +6,7 @@ import (
ps "erupe-ce/common/pascalstring"
"erupe-ce/network/mhfpacket"
"math/rand"
"sort"
"time"
)
@@ -253,11 +254,19 @@ func handleMsgMhfStateFestaU(s *Session, p mhfpacket.MHFPacket) {
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
return
}
var souls uint32
var souls, exists uint32
s.server.db.QueryRow("SELECT souls FROM guild_characters WHERE character_id=$1", s.charID).Scan(&souls)
err = s.server.db.QueryRow("SELECT prize_id FROM festa_prizes_accepted WHERE prize_id=0 AND character_id=$1", s.charID).Scan(&exists)
bf := byteframe.NewByteFrame()
bf.WriteUint32(souls)
bf.WriteUint32(0) // unk
if err != nil {
bf.WriteBool(true)
bf.WriteBool(false)
} else {
bf.WriteBool(false)
bf.WriteBool(true)
}
bf.WriteUint16(0) // Unk
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
}
@@ -280,10 +289,10 @@ func handleMsgMhfStateFestaG(s *Session, p mhfpacket.MHFPacket) {
return
}
resp.WriteUint32(guild.Souls)
resp.WriteUint32(0) // unk
resp.WriteUint32(0) // unk, rank?
resp.WriteUint32(0) // unk
resp.WriteUint32(0) // unk
resp.WriteUint32(1) // unk
resp.WriteUint32(1) // unk
resp.WriteUint32(1) // unk, rank?
resp.WriteUint32(1) // unk
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
}
@@ -302,6 +311,9 @@ func handleMsgMhfEnumerateFestaMember(s *Session, p mhfpacket.MHFPacket) {
bf := byteframe.NewByteFrame()
bf.WriteUint16(uint16(len(members)))
bf.WriteUint16(0) // Unk
sort.Slice(members, func(i, j int) bool {
return members[i].Souls > members[j].Souls
})
for _, member := range members {
bf.WriteUint32(member.CharID)
bf.WriteUint32(member.Souls)
@@ -342,6 +354,7 @@ func handleMsgMhfChargeFesta(s *Session, p mhfpacket.MHFPacket) {
func handleMsgMhfAcquireFesta(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfAcquireFesta)
s.server.db.Exec("INSERT INTO public.festa_prizes_accepted VALUES (0, $1)", s.charID)
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
}
@@ -368,7 +381,7 @@ type Prize struct {
func handleMsgMhfEnumerateFestaPersonalPrize(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfEnumerateFestaPersonalPrize)
rows, _ := s.server.db.Queryx("SELECT id, tier, souls_req, item_id, num_item, (SELECT count(*) FROM festa_prizes_accepted fpa WHERE fp.id = fpa.prize_id AND fpa.character_id = 4) AS claimed FROM festa_prizes fp WHERE type='personal'")
rows, _ := s.server.db.Queryx(`SELECT id, tier, souls_req, item_id, num_item, (SELECT count(*) FROM festa_prizes_accepted fpa WHERE fp.id = fpa.prize_id AND fpa.character_id = $1) AS claimed FROM festa_prizes fp WHERE type='personal'`, s.charID)
var count uint32
prizeData := byteframe.NewByteFrame()
for rows.Next() {
@@ -394,7 +407,7 @@ func handleMsgMhfEnumerateFestaPersonalPrize(s *Session, p mhfpacket.MHFPacket)
func handleMsgMhfEnumerateFestaIntermediatePrize(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfEnumerateFestaIntermediatePrize)
rows, _ := s.server.db.Queryx("SELECT id, tier, souls_req, item_id, num_item, (SELECT count(*) FROM festa_prizes_accepted fpa WHERE fp.id = fpa.prize_id AND fpa.character_id = 4) AS claimed FROM festa_prizes fp WHERE type='guild'")
rows, _ := s.server.db.Queryx(`SELECT id, tier, souls_req, item_id, num_item, (SELECT count(*) FROM festa_prizes_accepted fpa WHERE fp.id = fpa.prize_id AND fpa.character_id = $1) AS claimed FROM festa_prizes fp WHERE type='guild'`, s.charID)
var count uint32
prizeData := byteframe.NewByteFrame()
for rows.Next() {

View File

@@ -1034,7 +1034,7 @@ func handleMsgMhfInfoGuild(s *Session, p mhfpacket.MHFPacket) {
}
applicants, err := GetGuildMembers(s, guild.ID, true)
if err != nil {
if err != nil || (characterGuildData != nil && !characterGuildData.CanRecruit()) {
bf.WriteUint16(0)
} else {
bf.WriteUint16(uint16(len(applicants)))
@@ -1101,9 +1101,9 @@ func handleMsgMhfEnumerateGuild(s *Session, p mhfpacket.MHFPacket) {
switch pkt.Type {
case mhfpacket.ENUMERATE_GUILD_TYPE_GUILD_NAME:
bf.ReadBytes(10)
bf.ReadBytes(8)
searchTerm := fmt.Sprintf(`%%%s%%`, stringsupport.SJISToUTF8(bf.ReadNullTerminatedBytes()))
rows, err = s.server.db.Queryx(fmt.Sprintf(`%s WHERE g.name ILIKE $1 OFFSET $2`, guildInfoSelectQuery), searchTerm, pkt.Page*10)
rows, err = s.server.db.Queryx(fmt.Sprintf(`%s WHERE g.name ILIKE $1 OFFSET $2 LIMIT 11`, guildInfoSelectQuery), searchTerm, pkt.Page*10)
if err == nil {
for rows.Next() {
guild, _ := buildGuildObjectFromDbResult(rows, err, s)
@@ -1111,9 +1111,9 @@ func handleMsgMhfEnumerateGuild(s *Session, p mhfpacket.MHFPacket) {
}
}
case mhfpacket.ENUMERATE_GUILD_TYPE_LEADER_NAME:
bf.ReadBytes(10)
bf.ReadBytes(8)
searchTerm := fmt.Sprintf(`%%%s%%`, stringsupport.SJISToUTF8(bf.ReadNullTerminatedBytes()))
rows, err = s.server.db.Queryx(fmt.Sprintf(`%s WHERE lc.name ILIKE $1 OFFSET $2`, guildInfoSelectQuery), searchTerm, pkt.Page*10)
rows, err = s.server.db.Queryx(fmt.Sprintf(`%s WHERE lc.name ILIKE $1 OFFSET $2 LIMIT 11`, guildInfoSelectQuery), searchTerm, pkt.Page*10)
if err == nil {
for rows.Next() {
guild, _ := buildGuildObjectFromDbResult(rows, err, s)
@@ -1121,7 +1121,6 @@ func handleMsgMhfEnumerateGuild(s *Session, p mhfpacket.MHFPacket) {
}
}
case mhfpacket.ENUMERATE_GUILD_TYPE_LEADER_ID:
bf.ReadBytes(2)
ID := bf.ReadUint32()
rows, err = s.server.db.Queryx(fmt.Sprintf(`%s WHERE leader_id = $1`, guildInfoSelectQuery), ID)
if err == nil {
@@ -1131,11 +1130,10 @@ func handleMsgMhfEnumerateGuild(s *Session, p mhfpacket.MHFPacket) {
}
}
case mhfpacket.ENUMERATE_GUILD_TYPE_ORDER_MEMBERS:
sorting := bf.ReadUint8()
if sorting == 1 {
rows, err = s.server.db.Queryx(fmt.Sprintf(`%s ORDER BY member_count DESC OFFSET $1`, guildInfoSelectQuery), pkt.Page*10)
if pkt.Sorting {
rows, err = s.server.db.Queryx(fmt.Sprintf(`%s ORDER BY member_count DESC OFFSET $1 LIMIT 11`, guildInfoSelectQuery), pkt.Page*10)
} else {
rows, err = s.server.db.Queryx(fmt.Sprintf(`%s ORDER BY member_count ASC OFFSET $1`, guildInfoSelectQuery), pkt.Page*10)
rows, err = s.server.db.Queryx(fmt.Sprintf(`%s ORDER BY member_count ASC OFFSET $1 LIMIT 11`, guildInfoSelectQuery), pkt.Page*10)
}
if err == nil {
for rows.Next() {
@@ -1144,11 +1142,10 @@ func handleMsgMhfEnumerateGuild(s *Session, p mhfpacket.MHFPacket) {
}
}
case mhfpacket.ENUMERATE_GUILD_TYPE_ORDER_REGISTRATION:
sorting := bf.ReadUint8()
if sorting == 1 {
rows, err = s.server.db.Queryx(fmt.Sprintf(`%s ORDER BY id ASC OFFSET $1`, guildInfoSelectQuery), pkt.Page*10)
if pkt.Sorting {
rows, err = s.server.db.Queryx(fmt.Sprintf(`%s ORDER BY id ASC OFFSET $1 LIMIT 11`, guildInfoSelectQuery), pkt.Page*10)
} else {
rows, err = s.server.db.Queryx(fmt.Sprintf(`%s ORDER BY id DESC OFFSET $1`, guildInfoSelectQuery), pkt.Page*10)
rows, err = s.server.db.Queryx(fmt.Sprintf(`%s ORDER BY id DESC OFFSET $1 LIMIT 11`, guildInfoSelectQuery), pkt.Page*10)
}
if err == nil {
for rows.Next() {
@@ -1157,11 +1154,10 @@ func handleMsgMhfEnumerateGuild(s *Session, p mhfpacket.MHFPacket) {
}
}
case mhfpacket.ENUMERATE_GUILD_TYPE_ORDER_RANK:
sorting := bf.ReadUint8()
if sorting == 1 {
rows, err = s.server.db.Queryx(fmt.Sprintf(`%s ORDER BY rank_rp DESC OFFSET $1`, guildInfoSelectQuery), pkt.Page*10)
if pkt.Sorting {
rows, err = s.server.db.Queryx(fmt.Sprintf(`%s ORDER BY rank_rp DESC OFFSET $1 LIMIT 11`, guildInfoSelectQuery), pkt.Page*10)
} else {
rows, err = s.server.db.Queryx(fmt.Sprintf(`%s ORDER BY rank_rp ASC OFFSET $1`, guildInfoSelectQuery), pkt.Page*10)
rows, err = s.server.db.Queryx(fmt.Sprintf(`%s ORDER BY rank_rp ASC OFFSET $1 LIMIT 11`, guildInfoSelectQuery), pkt.Page*10)
}
if err == nil {
for rows.Next() {
@@ -1170,10 +1166,9 @@ func handleMsgMhfEnumerateGuild(s *Session, p mhfpacket.MHFPacket) {
}
}
case mhfpacket.ENUMERATE_GUILD_TYPE_MOTTO:
bf.ReadBytes(2)
mainMotto := bf.ReadUint16()
subMotto := bf.ReadUint16()
rows, err = s.server.db.Queryx(fmt.Sprintf(`%s WHERE main_motto = $1 AND sub_motto = $2 OFFSET $3`, guildInfoSelectQuery), mainMotto, subMotto, pkt.Page*10)
rows, err = s.server.db.Queryx(fmt.Sprintf(`%s WHERE main_motto = $1 AND sub_motto = $2 OFFSET $3 LIMIT 11`, guildInfoSelectQuery), mainMotto, subMotto, pkt.Page*10)
if err == nil {
for rows.Next() {
guild, _ := buildGuildObjectFromDbResult(rows, err, s)
@@ -1182,7 +1177,7 @@ func handleMsgMhfEnumerateGuild(s *Session, p mhfpacket.MHFPacket) {
}
case mhfpacket.ENUMERATE_GUILD_TYPE_RECRUITING:
// Assume the player wants the newest guilds with open recruitment
rows, err = s.server.db.Queryx(fmt.Sprintf(`%s WHERE recruiting=true ORDER BY id DESC OFFSET $1`, guildInfoSelectQuery), pkt.Page*10)
rows, err = s.server.db.Queryx(fmt.Sprintf(`%s WHERE recruiting=true ORDER BY id DESC OFFSET $1 LIMIT 11`, guildInfoSelectQuery), pkt.Page*10)
if err == nil {
for rows.Next() {
guild, _ := buildGuildObjectFromDbResult(rows, err, s)
@@ -1202,7 +1197,7 @@ func handleMsgMhfEnumerateGuild(s *Session, p mhfpacket.MHFPacket) {
}
switch pkt.Type {
case mhfpacket.ENUMERATE_ALLIANCE_TYPE_ALLIANCE_NAME:
bf.ReadBytes(10)
bf.ReadBytes(8)
searchTerm := stringsupport.SJISToUTF8(bf.ReadNullTerminatedBytes())
for _, alliance := range tempAlliances {
if strings.Contains(alliance.Name, searchTerm) {
@@ -1210,7 +1205,7 @@ func handleMsgMhfEnumerateGuild(s *Session, p mhfpacket.MHFPacket) {
}
}
case mhfpacket.ENUMERATE_ALLIANCE_TYPE_LEADER_NAME:
bf.ReadBytes(10)
bf.ReadBytes(8)
searchTerm := stringsupport.SJISToUTF8(bf.ReadNullTerminatedBytes())
for _, alliance := range tempAlliances {
if strings.Contains(alliance.ParentGuild.LeaderName, searchTerm) {
@@ -1218,7 +1213,6 @@ func handleMsgMhfEnumerateGuild(s *Session, p mhfpacket.MHFPacket) {
}
}
case mhfpacket.ENUMERATE_ALLIANCE_TYPE_LEADER_ID:
bf.ReadBytes(2)
ID := bf.ReadUint32()
for _, alliance := range tempAlliances {
if alliance.ParentGuild.LeaderCharID == ID {
@@ -1226,8 +1220,7 @@ func handleMsgMhfEnumerateGuild(s *Session, p mhfpacket.MHFPacket) {
}
}
case mhfpacket.ENUMERATE_ALLIANCE_TYPE_ORDER_MEMBERS:
sorting := bf.ReadBool()
if sorting {
if pkt.Sorting {
sort.Slice(tempAlliances, func(i, j int) bool {
return tempAlliances[i].TotalMembers > tempAlliances[j].TotalMembers
})
@@ -1238,8 +1231,7 @@ func handleMsgMhfEnumerateGuild(s *Session, p mhfpacket.MHFPacket) {
}
alliances = tempAlliances
case mhfpacket.ENUMERATE_ALLIANCE_TYPE_ORDER_REGISTRATION:
sorting := bf.ReadBool()
if sorting {
if pkt.Sorting {
sort.Slice(tempAlliances, func(i, j int) bool {
return tempAlliances[i].CreatedAt.Unix() > tempAlliances[j].CreatedAt.Unix()
})
@@ -1260,16 +1252,14 @@ func handleMsgMhfEnumerateGuild(s *Session, p mhfpacket.MHFPacket) {
bf = byteframe.NewByteFrame()
if pkt.Type > 8 {
if len(guilds) > 10 {
bf.WriteUint16(10)
} else {
bf.WriteUint16(uint16(len(alliances)))
hasNextPage := false
if len(alliances) > 10 {
hasNextPage = true
alliances = alliances[:10]
}
bf.WriteUint8(0x00) // Unk
for i, alliance := range alliances {
if i == 10 {
break
}
bf.WriteUint16(uint16(len(alliances)))
bf.WriteBool(hasNextPage)
for _, alliance := range alliances {
bf.WriteUint32(alliance.ID)
bf.WriteUint32(alliance.ParentGuild.LeaderCharID)
bf.WriteUint16(alliance.TotalMembers)
@@ -1288,16 +1278,14 @@ func handleMsgMhfEnumerateGuild(s *Session, p mhfpacket.MHFPacket) {
bf.WriteBool(true) // TODO: Enable GuildAlliance applications
}
} else {
hasNextPage := false
if len(guilds) > 10 {
bf.WriteUint16(10)
} else {
bf.WriteUint16(uint16(len(guilds)))
hasNextPage = true
guilds = guilds[:10]
}
bf.WriteUint8(0x01) // Unk
for i, guild := range guilds {
if i == 10 {
break
}
bf.WriteUint16(uint16(len(guilds)))
bf.WriteBool(hasNextPage)
for _, guild := range guilds {
bf.WriteUint32(guild.ID)
bf.WriteUint32(guild.LeaderCharID)
bf.WriteUint16(guild.MemberCount)

View File

@@ -2,7 +2,7 @@ package channelserver
import (
"fmt"
"io"
"go.uber.org/zap"
"io/ioutil"
"os"
"path/filepath"
@@ -14,14 +14,24 @@ import (
func handleMsgSysGetFile(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgSysGetFile)
// Debug print the request.
if pkt.IsScenario {
fmt.Printf("%+v\n", pkt.ScenarioIdentifer)
if s.server.erupeConfig.DevModeOptions.QuestDebugTools && s.server.erupeConfig.DevMode {
s.logger.Debug(
"Scenario",
zap.Uint8("CategoryID", pkt.ScenarioIdentifer.CategoryID),
zap.Uint32("MainID", pkt.ScenarioIdentifer.MainID),
zap.Uint8("ChapterID", pkt.ScenarioIdentifer.ChapterID),
zap.Uint8("Flags", pkt.ScenarioIdentifer.Flags),
)
}
filename := fmt.Sprintf("%d_0_0_0_S%d_T%d_C%d", pkt.ScenarioIdentifer.CategoryID, pkt.ScenarioIdentifer.MainID, pkt.ScenarioIdentifer.Flags, pkt.ScenarioIdentifer.ChapterID)
// Read the scenario file.
data, err := ioutil.ReadFile(filepath.Join(s.server.erupeConfig.BinPath, fmt.Sprintf("scenarios/%s.bin", filename)))
if err != nil {
panic(err)
s.logger.Error(fmt.Sprintf("Failed to open file: %s/scenarios/%s.bin", s.server.erupeConfig.BinPath, filename))
// This will crash the game.
doAckBufSucceed(s, pkt.AckHandle, data)
return
}
doAckBufSucceed(s, pkt.AckHandle, data)
} else {
@@ -32,10 +42,19 @@ func handleMsgSysGetFile(s *Session, p mhfpacket.MHFPacket) {
}
doAckBufSucceed(s, pkt.AckHandle, data)
} else {
if s.server.erupeConfig.DevModeOptions.QuestDebugTools && s.server.erupeConfig.DevMode {
s.logger.Debug(
"Quest",
zap.String("Filename", pkt.Filename),
)
}
// Get quest file.
data, err := ioutil.ReadFile(filepath.Join(s.server.erupeConfig.BinPath, fmt.Sprintf("quests/%s.bin", pkt.Filename)))
if err != nil {
s.logger.Fatal(fmt.Sprintf("Failed to open quest file: quests/%s.bin", pkt.Filename))
s.logger.Error(fmt.Sprintf("Failed to open file: %s/quests/%s.bin", s.server.erupeConfig.BinPath, pkt.Filename))
// This will crash the game.
doAckBufSucceed(s, pkt.AckHandle, data)
return
}
doAckBufSucceed(s, pkt.AckHandle, data)
}

View File

@@ -3,6 +3,7 @@ package channelserver
import (
ps "erupe-ce/common/pascalstring"
"fmt"
"github.com/jmoiron/sqlx"
"io/ioutil"
"path/filepath"
@@ -96,20 +97,13 @@ func handleMsgMhfGetRengokuBinary(s *Session, p mhfpacket.MHFPacket) {
doAckBufSucceed(s, pkt.AckHandle, data)
}
const rengokuScoreQuery = `
SELECT max_stages_mp, max_points_mp, max_stages_sp, max_points_sp, c.name, gc.guild_id
FROM rengoku_score rs
const rengokuScoreQuery = `, c.name FROM rengoku_score rs
LEFT JOIN characters c ON c.id = rs.character_id
LEFT JOIN guild_characters gc ON gc.character_id = rs.character_id
`
LEFT JOIN guild_characters gc ON gc.character_id = rs.character_id `
type RengokuScore struct {
Name string `db:"name"`
GuildID int `db:"guild_id"`
MaxStagesMP uint32 `db:"max_stages_mp"`
MaxPointsMP uint32 `db:"max_points_mp"`
MaxStagesSP uint32 `db:"max_stages_sp"`
MaxPointsSP uint32 `db:"max_points_sp"`
Name string `db:"name"`
Score uint32 `db:"score"`
}
func handleMsgMhfEnumerateRengokuRanking(s *Session, p mhfpacket.MHFPacket) {
@@ -121,170 +115,64 @@ func handleMsgMhfEnumerateRengokuRanking(s *Session, p mhfpacket.MHFPacket) {
guild = nil
}
if pkt.Leaderboard == 2 || pkt.Leaderboard == 3 || pkt.Leaderboard == 6 || pkt.Leaderboard == 7 {
if guild == nil {
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 11))
return
}
}
var score RengokuScore
var selfExist bool
i := uint32(1)
bf := byteframe.NewByteFrame()
scoreData := byteframe.NewByteFrame()
var rows *sqlx.Rows
switch pkt.Leaderboard {
case 0: // Max stage overall MP
rows, _ := s.server.db.Queryx(fmt.Sprintf("%s ORDER BY max_stages_mp DESC", rengokuScoreQuery))
for rows.Next() {
rows.StructScan(&score)
if score.Name == s.Name {
bf.WriteUint32(i)
bf.WriteUint32(score.MaxStagesMP)
ps.Uint8(bf, s.Name, true)
ps.Uint8(bf, "", false)
}
scoreData.WriteUint32(i)
scoreData.WriteUint32(score.MaxStagesMP)
ps.Uint8(scoreData, score.Name, true)
ps.Uint8(scoreData, "", false)
i++
}
case 1: // Max RdP overall MP
rows, _ := s.server.db.Queryx(fmt.Sprintf("%s ORDER BY max_points_mp DESC", rengokuScoreQuery))
for rows.Next() {
rows.StructScan(&score)
if score.Name == s.Name {
bf.WriteUint32(i)
bf.WriteUint32(score.MaxPointsMP)
ps.Uint8(bf, s.Name, true)
ps.Uint8(bf, "", false)
}
scoreData.WriteUint32(i)
scoreData.WriteUint32(score.MaxPointsMP)
ps.Uint8(scoreData, score.Name, true)
ps.Uint8(scoreData, "", false)
i++
}
case 2: // Max stage guild MP
if guild != nil {
rows, _ := s.server.db.Queryx(fmt.Sprintf("%s WHERE guild_id=$1 ORDER BY max_stages_mp DESC", rengokuScoreQuery), guild.ID)
for rows.Next() {
rows.StructScan(&score)
if score.Name == s.Name {
bf.WriteUint32(i)
bf.WriteUint32(score.MaxStagesMP)
ps.Uint8(bf, s.Name, true)
ps.Uint8(bf, "", false)
}
scoreData.WriteUint32(i)
scoreData.WriteUint32(score.MaxStagesMP)
ps.Uint8(scoreData, score.Name, true)
ps.Uint8(scoreData, "", false)
i++
}
} else {
bf.WriteBytes(make([]byte, 11))
}
case 3: // Max RdP guild MP
if guild != nil {
rows, _ := s.server.db.Queryx(fmt.Sprintf("%s WHERE guild_id=$1 ORDER BY max_points_mp DESC", rengokuScoreQuery), guild.ID)
for rows.Next() {
rows.StructScan(&score)
if score.Name == s.Name {
bf.WriteUint32(i)
bf.WriteUint32(score.MaxPointsMP)
ps.Uint8(bf, s.Name, true)
ps.Uint8(bf, "", false)
}
scoreData.WriteUint32(i)
scoreData.WriteUint32(score.MaxPointsMP)
ps.Uint8(scoreData, score.Name, true)
ps.Uint8(scoreData, "", false)
i++
}
} else {
bf.WriteBytes(make([]byte, 11))
}
case 4: // Max stage overall SP
rows, _ := s.server.db.Queryx(fmt.Sprintf("%s ORDER BY max_stages_sp DESC", rengokuScoreQuery))
for rows.Next() {
rows.StructScan(&score)
if score.Name == s.Name {
bf.WriteUint32(i)
bf.WriteUint32(score.MaxStagesSP)
ps.Uint8(bf, s.Name, true)
ps.Uint8(bf, "", false)
}
scoreData.WriteUint32(i)
scoreData.WriteUint32(score.MaxStagesSP)
ps.Uint8(scoreData, score.Name, true)
ps.Uint8(scoreData, "", false)
i++
}
case 5: // Max RdP overall SP
rows, _ := s.server.db.Queryx(fmt.Sprintf("%s ORDER BY max_points_sp DESC", rengokuScoreQuery))
for rows.Next() {
rows.StructScan(&score)
if score.Name == s.Name {
bf.WriteUint32(i)
bf.WriteUint32(score.MaxPointsSP)
ps.Uint8(bf, s.Name, true)
ps.Uint8(bf, "", false)
}
scoreData.WriteUint32(i)
scoreData.WriteUint32(score.MaxPointsSP)
ps.Uint8(scoreData, score.Name, true)
ps.Uint8(scoreData, "", false)
i++
}
case 6: // Max stage guild SP
if guild != nil {
rows, _ := s.server.db.Queryx(fmt.Sprintf("%s WHERE guild_id=$1 ORDER BY max_stages_sp DESC", rengokuScoreQuery), guild.ID)
for rows.Next() {
rows.StructScan(&score)
if score.Name == s.Name {
bf.WriteUint32(i)
bf.WriteUint32(score.MaxStagesSP)
ps.Uint8(bf, s.Name, true)
ps.Uint8(bf, "", false)
}
scoreData.WriteUint32(i)
scoreData.WriteUint32(score.MaxStagesSP)
ps.Uint8(scoreData, score.Name, true)
ps.Uint8(scoreData, "", false)
i++
}
} else {
bf.WriteBytes(make([]byte, 11))
}
case 7: // Max RdP guild SP
if guild != nil {
rows, _ := s.server.db.Queryx(fmt.Sprintf("%s WHERE guild_id=$1 ORDER BY max_points_sp DESC", rengokuScoreQuery), guild.ID)
for rows.Next() {
rows.StructScan(&score)
if score.Name == s.Name {
bf.WriteUint32(i)
bf.WriteUint32(score.MaxPointsSP)
ps.Uint8(bf, s.Name, true)
ps.Uint8(bf, "", false)
}
scoreData.WriteUint32(i)
scoreData.WriteUint32(score.MaxPointsSP)
ps.Uint8(scoreData, score.Name, true)
ps.Uint8(scoreData, "", false)
i++
}
} else {
bf.WriteBytes(make([]byte, 11))
}
case 0:
rows, _ = s.server.db.Queryx(fmt.Sprintf("SELECT max_stages_mp AS score %s ORDER BY max_stages_mp DESC", rengokuScoreQuery))
case 1:
rows, _ = s.server.db.Queryx(fmt.Sprintf("SELECT max_points_mp AS score %s ORDER BY max_points_mp DESC", rengokuScoreQuery))
case 2:
rows, _ = s.server.db.Queryx(fmt.Sprintf("SELECT max_stages_mp AS score %s WHERE guild_id=$1 ORDER BY max_stages_mp DESC", rengokuScoreQuery), guild.ID)
case 3:
rows, _ = s.server.db.Queryx(fmt.Sprintf("SELECT max_points_mp AS score %s WHERE guild_id=$1 ORDER BY max_points_mp DESC", rengokuScoreQuery), guild.ID)
case 4:
rows, _ = s.server.db.Queryx(fmt.Sprintf("SELECT max_stages_sp AS score %s ORDER BY max_stages_sp DESC", rengokuScoreQuery))
case 5:
rows, _ = s.server.db.Queryx(fmt.Sprintf("SELECT max_points_sp AS score %s ORDER BY max_points_sp DESC", rengokuScoreQuery))
case 6:
rows, _ = s.server.db.Queryx(fmt.Sprintf("SELECT max_stages_sp AS score %s WHERE guild_id=$1 ORDER BY max_stages_sp DESC", rengokuScoreQuery), guild.ID)
case 7:
rows, _ = s.server.db.Queryx(fmt.Sprintf("SELECT max_points_sp AS score %s WHERE guild_id=$1 ORDER BY max_points_sp DESC", rengokuScoreQuery), guild.ID)
}
if i == 1 {
bf.WriteUint32(1)
bf.WriteUint32(0)
ps.Uint8(bf, s.Name, true)
ps.Uint8(bf, "", false)
bf.WriteUint8(1)
bf.WriteUint32(1)
bf.WriteUint32(0)
ps.Uint8(bf, s.Name, true)
ps.Uint8(bf, "", false)
} else {
bf.WriteUint8(uint8(i) - 1)
bf.WriteBytes(scoreData.Data())
for rows.Next() {
rows.StructScan(&score)
if score.Name == s.Name {
bf.WriteUint32(i)
bf.WriteUint32(score.Score)
ps.Uint8(bf, s.Name, true)
ps.Uint8(bf, "", false)
selfExist = true
}
if i > 100 {
i++
continue
}
scoreData.WriteUint32(i)
scoreData.WriteUint32(score.Score)
ps.Uint8(scoreData, score.Name, true)
ps.Uint8(scoreData, "", false)
i++
}
if !selfExist {
bf.WriteBytes(make([]byte, 10))
}
bf.WriteUint8(uint8(i) - 1)
bf.WriteBytes(scoreData.Data())
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
}

View File

@@ -19,6 +19,7 @@ func handleMsgSysCreateStage(s *Session, p mhfpacket.MHFPacket) {
doAckSimpleFail(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
} else {
stage := NewStage(pkt.StageID)
stage.host = s
stage.maxPlayers = uint16(pkt.PlayerCount)
s.server.stages[stage.id] = stage
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
@@ -42,6 +43,7 @@ func doStageTransfer(s *Session, ackHandle uint32, stageID string) {
stage = s.server.stages[stageID]
s.server.Unlock()
stage.Lock()
stage.host = s
stage.clients[s] = s.charID
stage.Unlock()
}

View File

@@ -6,17 +6,16 @@ import (
"fmt"
"io"
"net"
"strings"
"sync"
"time"
"erupe-ce/common/byteframe"
"erupe-ce/common/stringstack"
"erupe-ce/common/stringsupport"
"erupe-ce/network"
"erupe-ce/network/clientctx"
"erupe-ce/network/mhfpacket"
"go.uber.org/zap"
"golang.org/x/text/encoding/japanese"
)
type packet struct {
@@ -43,7 +42,7 @@ type Session struct {
charID uint32
logKey []byte
sessionStart int64
rights uint32
courses []mhfpacket.Course
token string
kqf []byte
kqfOverride bool
@@ -68,16 +67,12 @@ type Session struct {
// NewSession creates a new Session type.
func NewSession(server *Server, conn net.Conn) *Session {
s := &Session{
logger: server.logger.Named(conn.RemoteAddr().String()),
server: server,
rawConn: conn,
cryptConn: network.NewCryptConn(conn),
sendPackets: make(chan packet, 20),
clientContext: &clientctx.ClientContext{
StrConv: &stringsupport.StringConverter{
Encoding: japanese.ShiftJIS,
},
},
logger: server.logger.Named(conn.RemoteAddr().String()),
server: server,
rawConn: conn,
cryptConn: network.NewCryptConn(conn),
sendPackets: make(chan packet, 20),
clientContext: &clientctx.ClientContext{}, // Unused
sessionStart: Time_Current_Adjusted().Unix(),
stageMoveStack: stringstack.New(),
}
@@ -268,3 +263,14 @@ func (s *Session) logMessage(opcode uint16, data []byte, sender string, recipien
fmt.Printf("Data [%d bytes]:\n(Too long!)\n\n", len(data))
}
}
func (s *Session) FindCourse(name string) mhfpacket.Course {
for _, course := range s.courses {
for _, alias := range course.Aliases {
if strings.ToLower(name) == strings.ToLower(alias) {
return course
}
}
}
return mhfpacket.Course{}
}

View File

@@ -46,6 +46,7 @@ type Stage struct {
// other clients expect the server to echo them back in the exact same format.
rawBinaryData map[stageBinaryKey][]byte
host *Session
maxPlayers uint16
password string
createdAt string

View File

@@ -90,6 +90,7 @@ func (s *Server) acceptClients() {
}
func (s *Server) handleEntranceServerConnection(conn net.Conn) {
defer conn.Close()
// Client initalizes the connection with a one-time buffer of 8 NULL bytes.
nullInit := make([]byte, 8)
n, err := io.ReadFull(conn, nullInit)
@@ -118,5 +119,4 @@ func (s *Server) handleEntranceServerConnection(conn net.Conn) {
cc.SendPacket(data)
// Close because we only need to send the response once.
// Any further requests from the client will come from a new connection.
conn.Close()
}

View File

@@ -148,7 +148,7 @@ func (s *Server) getFriendsForCharacters(chars []character) []members {
if err != nil {
continue
}
for i, _ := range charFriends {
for i := range charFriends {
charFriends[i].CID = char.ID
}
friends = append(friends, charFriends...)

View File

@@ -42,13 +42,23 @@ func (s *Session) makeSignInResp(uid int) []byte {
bf := byteframe.NewByteFrame()
bf.WriteUint8(1) // resp_code
bf.WriteUint8(0) // file/patch server count
bf.WriteUint8(1) // resp_code
if s.server.erupeConfig.DevMode && s.server.erupeConfig.DevModeOptions.PatchServerManifest != "" && s.server.erupeConfig.DevModeOptions.PatchServerFile != "" {
bf.WriteUint8(2)
} else {
bf.WriteUint8(0)
}
bf.WriteUint8(1) // entrance server count
bf.WriteUint8(uint8(len(chars))) // character count
bf.WriteUint32(0xFFFFFFFF) // login_token_number
bf.WriteBytes([]byte(token)) // login_token
bf.WriteUint32(uint32(time.Now().Unix())) // current time
if s.server.erupeConfig.DevMode {
if s.server.erupeConfig.DevModeOptions.PatchServerManifest != "" && s.server.erupeConfig.DevModeOptions.PatchServerFile != "" {
ps.Uint8(bf, s.server.erupeConfig.DevModeOptions.PatchServerManifest, false)
ps.Uint8(bf, s.server.erupeConfig.DevModeOptions.PatchServerFile, false)
}
}
ps.Uint8(bf, fmt.Sprintf("%s:%d", s.server.erupeConfig.Host, s.server.erupeConfig.Entrance.Port), false)
lastPlayed := uint32(0)

View File

@@ -16,32 +16,19 @@ import (
type Session struct {
sync.Mutex
logger *zap.Logger
sid int
server *Server
rawConn *net.Conn
rawConn net.Conn
cryptConn *network.CryptConn
}
func (s *Session) fail() {
s.server.Lock()
delete(s.server.sessions, s.sid)
s.server.Unlock()
}
func (s *Session) work() {
for {
pkt, err := s.cryptConn.ReadPacket()
if err != nil {
s.fail()
return
}
err = s.handlePacket(pkt)
if err != nil {
s.fail()
return
}
pkt, err := s.cryptConn.ReadPacket()
if err != nil {
return
}
err = s.handlePacket(pkt)
if err != nil {
return
}
}
@@ -61,6 +48,7 @@ func (s *Session) handlePacket(pkt []byte) error {
case "DELETE:100":
loginTokenString := string(bf.ReadNullTerminatedBytes())
characterID := int(bf.ReadUint32())
_ = int(bf.ReadUint32()) // login_token_number
s.server.deleteCharacter(characterID, loginTokenString)
sugar.Infof("Deleted character ID: %v\n", characterID)
err := s.cryptConn.SendPacket([]byte{0x01}) // DEL_SUCCESS
@@ -78,13 +66,13 @@ func (s *Session) handleDSGNRequest(bf *byteframe.ByteFrame) error {
reqUsername := string(bf.ReadNullTerminatedBytes())
reqPassword := string(bf.ReadNullTerminatedBytes())
reqUnk := string(bf.ReadNullTerminatedBytes())
reqSkey := string(bf.ReadNullTerminatedBytes())
s.server.logger.Info(
"Got sign in request",
zap.String("reqUsername", reqUsername),
zap.String("reqPassword", reqPassword),
zap.String("reqUnk", reqUnk),
zap.String("reqSkey", reqSkey),
)
newCharaReq := false
@@ -105,12 +93,15 @@ func (s *Session) handleDSGNRequest(bf *byteframe.ByteFrame) error {
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)
if s.server.erupeConfig.DevMode && s.server.erupeConfig.DevModeOptions.AutoCreateAccount {
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
}
} else {
break
}

View File

@@ -24,7 +24,6 @@ type Server struct {
sync.Mutex
logger *zap.Logger
erupeConfig *config.Config
sid int
sessions map[int]*Session
db *sqlx.DB
listener net.Listener
@@ -36,8 +35,6 @@ func NewServer(config *Config) *Server {
s := &Server{
logger: config.Logger,
erupeConfig: config.ErupeConfig,
sid: 0,
sessions: make(map[int]*Session),
db: config.DB,
}
return s
@@ -84,20 +81,19 @@ func (s *Server) acceptClients() {
}
}
go s.handleConnection(s.sid, conn)
s.sid++
go s.handleConnection(conn)
}
}
func (s *Server) handleConnection(sid int, conn net.Conn) {
func (s *Server) handleConnection(conn net.Conn) {
s.logger.Info("Got connection to sign server", zap.String("remoteaddr", conn.RemoteAddr().String()))
defer conn.Close()
// Client initalizes the connection with a one-time buffer of 8 NULL bytes.
nullInit := make([]byte, 8)
_, err := io.ReadFull(conn, nullInit)
if err != nil {
fmt.Println(err)
conn.Close()
s.logger.Error("Error initialising sign server connection", zap.Error(err))
return
}
@@ -105,15 +101,10 @@ func (s *Server) handleConnection(sid int, conn net.Conn) {
session := &Session{
logger: s.logger,
server: s,
rawConn: &conn,
rawConn: conn,
cryptConn: network.NewCryptConn(conn),
}
// Add the session to the server's sessions map.
s.Lock()
s.sessions[sid] = session
s.Unlock()
// Do the session's work.
session.work()
}