mirror of
https://github.com/Mezeporta/Erupe.git
synced 2026-02-06 01:57:38 +01:00
Config / DB now its own package
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
package _config
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
@@ -299,15 +300,10 @@ type EntranceChannelInfo struct {
|
||||
CurrentPlayers uint16
|
||||
}
|
||||
|
||||
var ErupeConfig *Config
|
||||
|
||||
func init() {
|
||||
var err error
|
||||
ErupeConfig, err = LoadConfig()
|
||||
if err != nil {
|
||||
preventClose(fmt.Sprintf("Failed to load config: %s", err.Error()))
|
||||
}
|
||||
}
|
||||
var (
|
||||
once sync.Once
|
||||
ErupeConfig *Config
|
||||
)
|
||||
|
||||
// getOutboundIP4 gets the preferred outbound ip4 of this machine
|
||||
// From https://stackoverflow.com/a/37382208
|
||||
@@ -368,7 +364,16 @@ func LoadConfig() (*Config, error) {
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func GetConfig() *Config {
|
||||
once.Do(func() {
|
||||
var err error
|
||||
ErupeConfig, err = LoadConfig()
|
||||
if err != nil {
|
||||
preventClose(fmt.Sprintf("Failed to load config: %s", err.Error()))
|
||||
}
|
||||
})
|
||||
return ErupeConfig
|
||||
}
|
||||
func preventClose(text string) {
|
||||
if ErupeConfig.DisableSoftCrash {
|
||||
os.Exit(0)
|
||||
|
||||
180
main.go
180
main.go
@@ -1,7 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
_config "erupe-ce/config"
|
||||
"erupe-ce/config"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
@@ -13,27 +13,19 @@ import (
|
||||
"erupe-ce/server/api"
|
||||
"erupe-ce/server/channelserver"
|
||||
"erupe-ce/server/discordbot"
|
||||
"erupe-ce/server/entranceserver"
|
||||
"erupe-ce/server/entrance"
|
||||
"erupe-ce/server/sign"
|
||||
"erupe-ce/utils/db"
|
||||
"erupe-ce/utils/logger"
|
||||
|
||||
"erupe-ce/server/signserver"
|
||||
"erupe-ce/utils/gametime"
|
||||
|
||||
"github.com/jmoiron/sqlx"
|
||||
_ "github.com/lib/pq"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
var mainLogger logger.Logger
|
||||
|
||||
// Temporary DB auto clean on startup for quick development & testing.
|
||||
func cleanDB(db *sqlx.DB) {
|
||||
_ = db.MustExec("DELETE FROM guild_characters")
|
||||
_ = db.MustExec("DELETE FROM guilds")
|
||||
_ = db.MustExec("DELETE FROM characters")
|
||||
_ = db.MustExec("DELETE FROM users")
|
||||
}
|
||||
|
||||
var Commit = func() string {
|
||||
if info, ok := debug.ReadBuildInfo(); ok {
|
||||
for _, setting := range info.Settings {
|
||||
@@ -54,96 +46,24 @@ func initLogger() {
|
||||
mainLogger = logger.Get().Named("main")
|
||||
|
||||
}
|
||||
|
||||
func main() {
|
||||
var err error
|
||||
|
||||
config := _config.ErupeConfig
|
||||
config := config.GetConfig()
|
||||
initLogger()
|
||||
mainLogger.Info(fmt.Sprintf("Starting Erupe (9.3b-%s)", Commit()))
|
||||
mainLogger.Info(fmt.Sprintf("Client Mode: %s (%d)", config.ClientMode, config.ClientID))
|
||||
|
||||
if config.Database.Password == "" {
|
||||
preventClose("Database password is blank")
|
||||
}
|
||||
checkAndExitIf(config.Database.Password == "", "Database password is blank")
|
||||
|
||||
if net.ParseIP(config.Host) == nil {
|
||||
ips, _ := net.LookupIP(config.Host)
|
||||
for _, ip := range ips {
|
||||
if ip != nil {
|
||||
config.Host = ip.String()
|
||||
break
|
||||
}
|
||||
}
|
||||
if net.ParseIP(config.Host) == nil {
|
||||
preventClose("Invalid host address")
|
||||
}
|
||||
}
|
||||
resolveHostIP()
|
||||
|
||||
// Discord bot
|
||||
var discordBot *discordbot.DiscordBot = nil
|
||||
discordBot := initializeDiscordBot()
|
||||
|
||||
if config.Discord.Enabled {
|
||||
bot, err := discordbot.NewDiscordBot(discordbot.Options{
|
||||
Config: _config.ErupeConfig,
|
||||
})
|
||||
DiscordFailMsg := "Discord: Failed to start, %s"
|
||||
if err != nil {
|
||||
preventClose(fmt.Sprintf(DiscordFailMsg, err.Error()))
|
||||
}
|
||||
|
||||
// Discord bot
|
||||
err = bot.Start()
|
||||
|
||||
if err != nil {
|
||||
preventClose(fmt.Sprintf(DiscordFailMsg, err.Error()))
|
||||
}
|
||||
|
||||
discordBot = bot
|
||||
|
||||
_, err = discordBot.Session.ApplicationCommandBulkOverwrite(discordBot.Session.State.User.ID, "", discordbot.Commands)
|
||||
if err != nil {
|
||||
preventClose(fmt.Sprintf(DiscordFailMsg, err.Error()))
|
||||
}
|
||||
|
||||
mainLogger.Info("Discord: Started successfully")
|
||||
} else {
|
||||
mainLogger.Info("Discord: Disabled")
|
||||
}
|
||||
|
||||
// Create the postgres DB pool.
|
||||
connectString := fmt.Sprintf(
|
||||
"host='%s' port='%d' user='%s' password='%s' dbname='%s' sslmode=disable",
|
||||
config.Database.Host,
|
||||
config.Database.Port,
|
||||
config.Database.User,
|
||||
config.Database.Password,
|
||||
config.Database.Database,
|
||||
)
|
||||
|
||||
db, err := sqlx.Open("postgres", connectString)
|
||||
database, err := db.InitDB(config)
|
||||
if err != nil {
|
||||
preventClose(fmt.Sprintf("Database: Failed to open, %s", err.Error()))
|
||||
}
|
||||
|
||||
// Test the DB connection.
|
||||
err = db.Ping()
|
||||
if err != nil {
|
||||
preventClose(fmt.Sprintf("Database: Failed to ping, %s", err.Error()))
|
||||
}
|
||||
mainLogger.Info("Database: Started successfully")
|
||||
|
||||
// Clear stale data
|
||||
if config.DebugOptions.ProxyPort == 0 {
|
||||
_ = db.MustExec("DELETE FROM sign_sessions")
|
||||
}
|
||||
_ = db.MustExec("DELETE FROM servers")
|
||||
_ = db.MustExec(`UPDATE guild_characters SET treasure_hunt=NULL`)
|
||||
|
||||
// Clean the DB if the option is on.
|
||||
if config.DebugOptions.CleanDB {
|
||||
mainLogger.Info("Database: Started clearing...")
|
||||
cleanDB(db)
|
||||
mainLogger.Info("Database: Finished clearing")
|
||||
mainLogger.Fatal(fmt.Sprintf("Database initialization failed: %s", err))
|
||||
}
|
||||
|
||||
mainLogger.Info(fmt.Sprintf("Server Time: %s", gametime.TimeAdjusted().String()))
|
||||
@@ -151,16 +71,10 @@ func main() {
|
||||
// Now start our server(s).
|
||||
|
||||
// Entrance server.
|
||||
entranceLogger := logger.Get().Named("entrance")
|
||||
|
||||
var entranceServer *entranceserver.Server
|
||||
var entranceServer *entrance.EntranceServer
|
||||
if config.Entrance.Enabled {
|
||||
entranceServer = entranceserver.NewServer(
|
||||
&entranceserver.Config{
|
||||
Logger: entranceLogger,
|
||||
ErupeConfig: _config.ErupeConfig,
|
||||
DB: db,
|
||||
})
|
||||
entranceServer = entrance.NewServer()
|
||||
err = entranceServer.Start()
|
||||
if err != nil {
|
||||
preventClose(fmt.Sprintf("Entrance: Failed to start, %s", err.Error()))
|
||||
@@ -171,13 +85,9 @@ func main() {
|
||||
}
|
||||
|
||||
// Sign server.
|
||||
var signServer *signserver.Server
|
||||
var signServer *sign.SignServer
|
||||
if config.Sign.Enabled {
|
||||
signServer = signserver.NewServer(
|
||||
&signserver.Config{
|
||||
ErupeConfig: _config.ErupeConfig,
|
||||
DB: db,
|
||||
})
|
||||
signServer = sign.NewServer()
|
||||
err = signServer.Start()
|
||||
if err != nil {
|
||||
preventClose(fmt.Sprintf("Sign: Failed to start, %s", err.Error()))
|
||||
@@ -188,14 +98,10 @@ func main() {
|
||||
}
|
||||
|
||||
// Api server
|
||||
var ApiServer *api.APIServer
|
||||
var apiServer *api.APIServer
|
||||
if config.API.Enabled {
|
||||
ApiServer = api.NewAPIServer(
|
||||
&api.Config{
|
||||
ErupeConfig: _config.ErupeConfig,
|
||||
DB: db,
|
||||
})
|
||||
err = ApiServer.Start()
|
||||
apiServer = api.NewAPIServer()
|
||||
err = apiServer.Start()
|
||||
if err != nil {
|
||||
preventClose(fmt.Sprintf("API: Failed to start, %s", err.Error()))
|
||||
}
|
||||
@@ -203,8 +109,7 @@ func main() {
|
||||
} else {
|
||||
mainLogger.Info("API: Disabled")
|
||||
}
|
||||
|
||||
var channelServers []*channelserver.Server
|
||||
var channelServers []*channelserver.ChannelServer
|
||||
if config.Channel.Enabled {
|
||||
channelQuery := ""
|
||||
si := 0
|
||||
@@ -214,10 +119,8 @@ func main() {
|
||||
for i, ce := range ee.Channels {
|
||||
sid := (4096 + si*256) + (16 + ci)
|
||||
c := *channelserver.NewServer(&channelserver.Config{
|
||||
ID: uint16(sid),
|
||||
ErupeConfig: _config.ErupeConfig,
|
||||
DB: db,
|
||||
DiscordBot: discordBot,
|
||||
ID: uint16(sid),
|
||||
DiscordBot: discordBot,
|
||||
})
|
||||
if ee.IP == "" {
|
||||
c.IP = config.Host
|
||||
@@ -242,7 +145,7 @@ func main() {
|
||||
}
|
||||
|
||||
// Register all servers in DB
|
||||
_ = db.MustExec(channelQuery)
|
||||
_ = database.MustExec(channelQuery)
|
||||
|
||||
for _, c := range channelServers {
|
||||
c.Channels = channelServers
|
||||
@@ -278,7 +181,7 @@ func main() {
|
||||
}
|
||||
|
||||
if config.API.Enabled {
|
||||
ApiServer.Shutdown()
|
||||
apiServer.Shutdown()
|
||||
}
|
||||
|
||||
if config.Entrance.Enabled {
|
||||
@@ -295,7 +198,7 @@ func wait() {
|
||||
}
|
||||
|
||||
func preventClose(text string) {
|
||||
if _config.ErupeConfig.DisableSoftCrash {
|
||||
if config.GetConfig().DisableSoftCrash {
|
||||
os.Exit(0)
|
||||
}
|
||||
mainLogger.Error(fmt.Sprintf(("\nFailed to start Erupe:\n" + text)))
|
||||
@@ -303,3 +206,38 @@ func preventClose(text string) {
|
||||
mainLogger.Error(fmt.Sprintf(("\nPress Enter/Return to exit...")))
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
func checkAndExitIf(condition bool, message string) {
|
||||
if condition {
|
||||
preventClose(message)
|
||||
}
|
||||
}
|
||||
|
||||
func resolveHostIP() {
|
||||
if net.ParseIP(config.GetConfig().Host) == nil {
|
||||
ips, err := net.LookupIP(config.GetConfig().Host)
|
||||
if err == nil && len(ips) > 0 {
|
||||
config.GetConfig().Host = ips[0].String()
|
||||
}
|
||||
checkAndExitIf(net.ParseIP(config.GetConfig().Host) == nil, "Invalid host address")
|
||||
}
|
||||
}
|
||||
|
||||
func initializeDiscordBot() *discordbot.DiscordBot {
|
||||
if !config.GetConfig().Discord.Enabled {
|
||||
mainLogger.Info("Discord: Disabled")
|
||||
return nil
|
||||
}
|
||||
|
||||
bot, err := discordbot.NewDiscordBot()
|
||||
checkAndExitIf(err != nil, fmt.Sprintf("Discord: Failed to start, %s", err))
|
||||
|
||||
err = bot.Start()
|
||||
checkAndExitIf(err != nil, fmt.Sprintf("Discord: Failed to start, %s", err))
|
||||
|
||||
_, err = bot.Session.ApplicationCommandBulkOverwrite(bot.Session.State.User.ID, "", discordbot.Commands)
|
||||
checkAndExitIf(err != nil, fmt.Sprintf("Discord: Failed to register commands, %s", err))
|
||||
|
||||
mainLogger.Info("Discord: Started successfully")
|
||||
return bot
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package network
|
||||
import (
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
_config "erupe-ce/config"
|
||||
"erupe-ce/config"
|
||||
"erupe-ce/network/crypto"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -51,7 +51,7 @@ func (cc *CryptConn) ReadPacket() ([]byte, error) {
|
||||
var encryptedPacketBody []byte
|
||||
|
||||
// Don't know when support for this was added, works in Forward.4, doesn't work in Season 6.0
|
||||
if _config.ErupeConfig.ClientID < _config.F1 {
|
||||
if config.GetConfig().ClientID < config.F1 {
|
||||
encryptedPacketBody = make([]byte, cph.DataSize)
|
||||
} else {
|
||||
encryptedPacketBody = make([]byte, uint32(cph.DataSize)+(uint32(cph.Pf0-0x03)*0x1000))
|
||||
|
||||
@@ -2,7 +2,7 @@ package mhfpacket
|
||||
|
||||
import (
|
||||
"errors"
|
||||
_config "erupe-ce/config"
|
||||
"erupe-ce/config"
|
||||
|
||||
"erupe-ce/network"
|
||||
"erupe-ce/utils/byteframe"
|
||||
@@ -30,7 +30,7 @@ func (m *MsgMhfAcquireCafeItem) Parse(bf *byteframe.ByteFrame) error {
|
||||
m.ItemType = bf.ReadUint16()
|
||||
m.ItemID = bf.ReadUint16()
|
||||
m.Quant = bf.ReadUint16()
|
||||
if _config.ErupeConfig.ClientID >= _config.G1 {
|
||||
if config.GetConfig().ClientID >= config.G1 {
|
||||
m.PointCost = bf.ReadUint32()
|
||||
} else {
|
||||
m.PointCost = uint32(bf.ReadUint16())
|
||||
|
||||
@@ -2,7 +2,7 @@ package mhfpacket
|
||||
|
||||
import (
|
||||
"errors"
|
||||
_config "erupe-ce/config"
|
||||
"erupe-ce/config"
|
||||
"erupe-ce/network"
|
||||
"erupe-ce/utils/byteframe"
|
||||
)
|
||||
@@ -26,10 +26,10 @@ func (m *MsgMhfApplyDistItem) Parse(bf *byteframe.ByteFrame) error {
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
m.DistributionType = bf.ReadUint8()
|
||||
m.DistributionID = bf.ReadUint32()
|
||||
if _config.ErupeConfig.ClientID >= _config.G8 {
|
||||
if config.GetConfig().ClientID >= config.G8 {
|
||||
m.Unk2 = bf.ReadUint32()
|
||||
}
|
||||
if _config.ErupeConfig.ClientID >= _config.G10 {
|
||||
if config.GetConfig().ClientID >= config.G10 {
|
||||
m.Unk3 = bf.ReadUint32()
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -2,7 +2,7 @@ package mhfpacket
|
||||
|
||||
import (
|
||||
"errors"
|
||||
_config "erupe-ce/config"
|
||||
"erupe-ce/config"
|
||||
"erupe-ce/network"
|
||||
"erupe-ce/utils/byteframe"
|
||||
)
|
||||
@@ -27,7 +27,7 @@ func (m *MsgMhfEnumerateDistItem) Parse(bf *byteframe.ByteFrame) error {
|
||||
m.DistType = bf.ReadUint8()
|
||||
m.Unk1 = bf.ReadUint8()
|
||||
m.Unk2 = bf.ReadUint16() // Maximum? Hardcoded to 256
|
||||
if _config.ErupeConfig.ClientID >= _config.Z1 {
|
||||
if config.GetConfig().ClientID >= config.Z1 {
|
||||
m.Unk3 = bf.ReadBytes(uint(bf.ReadUint8()))
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -2,7 +2,7 @@ package mhfpacket
|
||||
|
||||
import (
|
||||
"errors"
|
||||
_config "erupe-ce/config"
|
||||
"erupe-ce/config"
|
||||
|
||||
"erupe-ce/network"
|
||||
"erupe-ce/utils/byteframe"
|
||||
@@ -29,7 +29,7 @@ func (m *MsgMhfEnumerateQuest) Parse(bf *byteframe.ByteFrame) error {
|
||||
m.Unk0 = bf.ReadUint8()
|
||||
m.World = bf.ReadUint8()
|
||||
m.Counter = bf.ReadUint16()
|
||||
if _config.ErupeConfig.ClientID <= _config.Z1 {
|
||||
if config.GetConfig().ClientID <= config.Z1 {
|
||||
m.Offset = uint16(bf.ReadUint8())
|
||||
} else {
|
||||
m.Offset = bf.ReadUint16()
|
||||
|
||||
@@ -2,7 +2,7 @@ package mhfpacket
|
||||
|
||||
import (
|
||||
"errors"
|
||||
_config "erupe-ce/config"
|
||||
"erupe-ce/config"
|
||||
|
||||
"erupe-ce/network"
|
||||
"erupe-ce/utils/byteframe"
|
||||
@@ -31,7 +31,7 @@ func (m *MsgMhfEnumerateShop) Parse(bf *byteframe.ByteFrame) error {
|
||||
m.ShopID = bf.ReadUint32()
|
||||
m.Limit = bf.ReadUint16()
|
||||
m.Unk3 = bf.ReadUint8()
|
||||
if _config.ErupeConfig.ClientID >= _config.G2 {
|
||||
if config.GetConfig().ClientID >= config.G2 {
|
||||
m.Unk4 = bf.ReadUint8()
|
||||
m.Unk5 = bf.ReadUint32()
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package mhfpacket
|
||||
|
||||
import (
|
||||
"errors"
|
||||
_config "erupe-ce/config"
|
||||
"erupe-ce/config"
|
||||
|
||||
"erupe-ce/network"
|
||||
"erupe-ce/utils/byteframe"
|
||||
@@ -29,7 +29,7 @@ func (m *MsgMhfSavedata) Parse(bf *byteframe.ByteFrame) error {
|
||||
m.AllocMemSize = bf.ReadUint32()
|
||||
m.SaveType = bf.ReadUint8()
|
||||
m.Unk1 = bf.ReadUint32()
|
||||
if _config.ErupeConfig.ClientID >= _config.G1 {
|
||||
if config.GetConfig().ClientID >= config.G1 {
|
||||
m.DataSize = bf.ReadUint32()
|
||||
}
|
||||
if m.DataSize == 0 { // seems to be used when DataSize = 0 rather than on savetype?
|
||||
|
||||
@@ -2,7 +2,7 @@ package mhfpacket
|
||||
|
||||
import (
|
||||
"errors"
|
||||
_config "erupe-ce/config"
|
||||
"erupe-ce/config"
|
||||
|
||||
"erupe-ce/network"
|
||||
"erupe-ce/utils/byteframe"
|
||||
@@ -31,12 +31,12 @@ func (m *MsgMhfStampcardStamp) Opcode() network.PacketID {
|
||||
func (m *MsgMhfStampcardStamp) Parse(bf *byteframe.ByteFrame) error {
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
m.HR = bf.ReadUint16()
|
||||
if _config.ErupeConfig.ClientID >= _config.G1 {
|
||||
if config.GetConfig().ClientID >= config.G1 {
|
||||
m.GR = bf.ReadUint16()
|
||||
}
|
||||
m.Stamps = bf.ReadUint16()
|
||||
bf.ReadUint16() // Zeroed
|
||||
if _config.ErupeConfig.ClientID >= _config.Z2 {
|
||||
if config.GetConfig().ClientID >= config.Z2 {
|
||||
m.Reward1 = uint16(bf.ReadUint32())
|
||||
m.Reward2 = uint16(bf.ReadUint32())
|
||||
m.Item1 = uint16(bf.ReadUint32())
|
||||
|
||||
@@ -3,7 +3,7 @@ package mhfpacket
|
||||
import (
|
||||
"errors"
|
||||
|
||||
_config "erupe-ce/config"
|
||||
"erupe-ce/config"
|
||||
"erupe-ce/network"
|
||||
"erupe-ce/utils/byteframe"
|
||||
)
|
||||
@@ -22,11 +22,11 @@ func (m *MsgMhfUpdateMyhouseInfo) Opcode() network.PacketID {
|
||||
// Parse parses the packet from binary
|
||||
func (m *MsgMhfUpdateMyhouseInfo) Parse(bf *byteframe.ByteFrame) error {
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
if _config.ErupeConfig.ClientID >= _config.G10 {
|
||||
if config.GetConfig().ClientID >= config.G10 {
|
||||
m.Data = bf.ReadBytes(362)
|
||||
} else if _config.ErupeConfig.ClientID >= _config.GG {
|
||||
} else if config.GetConfig().ClientID >= config.GG {
|
||||
m.Data = bf.ReadBytes(338)
|
||||
} else if _config.ErupeConfig.ClientID >= _config.F5 {
|
||||
} else if config.GetConfig().ClientID >= config.F5 {
|
||||
// G1 is a guess
|
||||
m.Data = bf.ReadBytes(314)
|
||||
} else {
|
||||
|
||||
@@ -2,7 +2,7 @@ package mhfpacket
|
||||
|
||||
import (
|
||||
"errors"
|
||||
_config "erupe-ce/config"
|
||||
"erupe-ce/config"
|
||||
"erupe-ce/network"
|
||||
"erupe-ce/utils/byteframe"
|
||||
)
|
||||
@@ -24,7 +24,7 @@ func (m *MsgSysCreateAcquireSemaphore) Opcode() network.PacketID {
|
||||
func (m *MsgSysCreateAcquireSemaphore) Parse(bf *byteframe.ByteFrame) error {
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
m.Unk0 = bf.ReadUint16()
|
||||
if _config.ErupeConfig.ClientID >= _config.S7 { // Assuming this was added with Ravi?
|
||||
if config.GetConfig().ClientID >= config.S7 { // Assuming this was added with Ravi?
|
||||
m.PlayerCount = bf.ReadUint8()
|
||||
}
|
||||
bf.ReadUint8() // SemaphoreID length
|
||||
|
||||
@@ -2,7 +2,7 @@ package mhfpacket
|
||||
|
||||
import (
|
||||
"errors"
|
||||
_config "erupe-ce/config"
|
||||
"erupe-ce/config"
|
||||
|
||||
"erupe-ce/network"
|
||||
"erupe-ce/utils/byteframe"
|
||||
@@ -25,7 +25,7 @@ func (m *MsgSysCreateSemaphore) Opcode() network.PacketID {
|
||||
func (m *MsgSysCreateSemaphore) Parse(bf *byteframe.ByteFrame) error {
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
m.Unk0 = bf.ReadUint16()
|
||||
if _config.ErupeConfig.ClientID >= _config.S7 { // Assuming this was added with Ravi?
|
||||
if config.GetConfig().ClientID >= config.S7 { // Assuming this was added with Ravi?
|
||||
m.PlayerCount = bf.ReadUint8()
|
||||
}
|
||||
bf.ReadUint8() // SemaphoreID length
|
||||
|
||||
@@ -2,7 +2,7 @@ package mhfpacket
|
||||
|
||||
import (
|
||||
"errors"
|
||||
_config "erupe-ce/config"
|
||||
"erupe-ce/config"
|
||||
|
||||
"erupe-ce/network"
|
||||
"erupe-ce/utils/byteframe"
|
||||
@@ -48,7 +48,7 @@ func (m *MsgSysTerminalLog) Parse(bf *byteframe.ByteFrame) error {
|
||||
e.Unk1 = bf.ReadInt32()
|
||||
e.Unk2 = bf.ReadInt32()
|
||||
e.Unk3 = bf.ReadInt32()
|
||||
if _config.ErupeConfig.ClientID >= _config.G1 {
|
||||
if config.GetConfig().ClientID >= config.G1 {
|
||||
for j := 0; j < 4; j++ {
|
||||
e.Unk4 = append(e.Unk4, bf.ReadInt32())
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
_config "erupe-ce/config"
|
||||
"erupe-ce/config"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
@@ -13,33 +13,24 @@ import (
|
||||
|
||||
"github.com/gorilla/handlers"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/jmoiron/sqlx"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
DB *sqlx.DB
|
||||
ErupeConfig *_config.Config
|
||||
}
|
||||
|
||||
// APIServer is Erupes Standard API interface
|
||||
type APIServer struct {
|
||||
sync.Mutex
|
||||
logger logger.Logger
|
||||
erupeConfig *_config.Config
|
||||
db *sqlx.DB
|
||||
erupeConfig *config.Config
|
||||
httpServer *http.Server
|
||||
isShuttingDown bool
|
||||
}
|
||||
|
||||
// NewAPIServer creates a new Server type.
|
||||
func NewAPIServer(config *Config) *APIServer {
|
||||
func NewAPIServer() *APIServer {
|
||||
|
||||
s := &APIServer{
|
||||
logger: logger.Get().Named("API"),
|
||||
erupeConfig: config.ErupeConfig,
|
||||
db: config.DB,
|
||||
httpServer: &http.Server{},
|
||||
logger: logger.Get().Named("API"),
|
||||
httpServer: &http.Server{},
|
||||
}
|
||||
return s
|
||||
}
|
||||
@@ -58,7 +49,7 @@ func (s *APIServer) Start() error {
|
||||
r.HandleFunc("/api/ss/bbs/{id}", s.ScreenShotGet)
|
||||
handler := handlers.CORS(handlers.AllowedHeaders([]string{"Content-Type"}))(r)
|
||||
s.httpServer.Handler = handlers.LoggingHandler(os.Stdout, handler)
|
||||
s.httpServer.Addr = fmt.Sprintf(":%d", s.erupeConfig.API.Port)
|
||||
s.httpServer.Addr = fmt.Sprintf(":%d", config.GetConfig().API.Port)
|
||||
|
||||
serveError := make(chan error, 1)
|
||||
go func() {
|
||||
|
||||
@@ -3,6 +3,7 @@ package api
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"erupe-ce/utils/db"
|
||||
"erupe-ce/utils/token"
|
||||
"fmt"
|
||||
"time"
|
||||
@@ -21,7 +22,11 @@ func (s *APIServer) createNewUser(ctx context.Context, username string, password
|
||||
id uint32
|
||||
rights uint32
|
||||
)
|
||||
err = s.db.QueryRowContext(
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
err = database.QueryRowContext(
|
||||
ctx, `
|
||||
INSERT INTO users (username, password, return_expires)
|
||||
VALUES ($1, $2, $3)
|
||||
@@ -35,7 +40,11 @@ func (s *APIServer) createNewUser(ctx context.Context, username string, password
|
||||
func (s *APIServer) createLoginToken(ctx context.Context, uid uint32) (uint32, string, error) {
|
||||
loginToken := token.Generate(16)
|
||||
var tid uint32
|
||||
err := s.db.QueryRowContext(ctx, "INSERT INTO sign_sessions (user_id, token) VALUES ($1, $2) RETURNING id", uid, loginToken).Scan(&tid)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
err = database.QueryRowContext(ctx, "INSERT INTO sign_sessions (user_id, token) VALUES ($1, $2) RETURNING id", uid, loginToken).Scan(&tid)
|
||||
if err != nil {
|
||||
return 0, "", err
|
||||
}
|
||||
@@ -44,7 +53,11 @@ func (s *APIServer) createLoginToken(ctx context.Context, uid uint32) (uint32, s
|
||||
|
||||
func (s *APIServer) userIDFromToken(ctx context.Context, token string) (uint32, error) {
|
||||
var userID uint32
|
||||
err := s.db.QueryRowContext(ctx, "SELECT user_id FROM sign_sessions WHERE token = $1", token).Scan(&userID)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
err = database.QueryRowContext(ctx, "SELECT user_id FROM sign_sessions WHERE token = $1", token).Scan(&userID)
|
||||
if err == sql.ErrNoRows {
|
||||
return 0, fmt.Errorf("invalid login token")
|
||||
} else if err != nil {
|
||||
@@ -55,17 +68,21 @@ func (s *APIServer) userIDFromToken(ctx context.Context, token string) (uint32,
|
||||
|
||||
func (s *APIServer) createCharacter(ctx context.Context, userID uint32) (Character, error) {
|
||||
var character Character
|
||||
err := s.db.GetContext(ctx, &character,
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
err = database.GetContext(ctx, &character,
|
||||
"SELECT id, name, is_female, weapon_type, hr, gr, last_login FROM characters WHERE is_new_character = true AND user_id = $1 LIMIT 1",
|
||||
userID,
|
||||
)
|
||||
if err == sql.ErrNoRows {
|
||||
var count int
|
||||
s.db.QueryRowContext(ctx, "SELECT COUNT(*) FROM characters WHERE user_id = $1", userID).Scan(&count)
|
||||
database.QueryRowContext(ctx, "SELECT COUNT(*) FROM characters WHERE user_id = $1", userID).Scan(&count)
|
||||
if count >= 16 {
|
||||
return character, fmt.Errorf("cannot have more than 16 characters")
|
||||
}
|
||||
err = s.db.GetContext(ctx, &character, `
|
||||
err = database.GetContext(ctx, &character, `
|
||||
INSERT INTO characters (
|
||||
user_id, is_female, is_new_character, name, unk_desc_string,
|
||||
hr, gr, weapon_type, last_login
|
||||
@@ -80,21 +97,29 @@ func (s *APIServer) createCharacter(ctx context.Context, userID uint32) (Charact
|
||||
|
||||
func (s *APIServer) deleteCharacter(ctx context.Context, userID uint32, charID uint32) error {
|
||||
var isNew bool
|
||||
err := s.db.QueryRow("SELECT is_new_character FROM characters WHERE id = $1", charID).Scan(&isNew)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
err = database.QueryRow("SELECT is_new_character FROM characters WHERE id = $1", charID).Scan(&isNew)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if isNew {
|
||||
_, err = s.db.Exec("DELETE FROM characters WHERE id = $1", charID)
|
||||
_, err = database.Exec("DELETE FROM characters WHERE id = $1", charID)
|
||||
} else {
|
||||
_, err = s.db.Exec("UPDATE characters SET deleted = true WHERE id = $1", charID)
|
||||
_, err = database.Exec("UPDATE characters SET deleted = true WHERE id = $1", charID)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *APIServer) getCharactersForUser(ctx context.Context, uid uint32) ([]Character, error) {
|
||||
var characters []Character
|
||||
err := s.db.SelectContext(
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
err = database.SelectContext(
|
||||
ctx, &characters, `
|
||||
SELECT id, name, is_female, weapon_type, hr, gr, last_login
|
||||
FROM characters
|
||||
@@ -109,25 +134,33 @@ func (s *APIServer) getCharactersForUser(ctx context.Context, uid uint32) ([]Cha
|
||||
|
||||
func (s *APIServer) getReturnExpiry(uid uint32) time.Time {
|
||||
var returnExpiry, lastLogin time.Time
|
||||
s.db.Get(&lastLogin, "SELECT COALESCE(last_login, now()) FROM users WHERE id=$1", uid)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
err = database.Get(&lastLogin, "SELECT COALESCE(last_login, now()) FROM users WHERE id=$1", uid)
|
||||
if time.Now().Add((time.Hour * 24) * -90).After(lastLogin) {
|
||||
returnExpiry = time.Now().Add(time.Hour * 24 * 30)
|
||||
s.db.Exec("UPDATE users SET return_expires=$1 WHERE id=$2", returnExpiry, uid)
|
||||
database.Exec("UPDATE users SET return_expires=$1 WHERE id=$2", returnExpiry, uid)
|
||||
} else {
|
||||
err := s.db.Get(&returnExpiry, "SELECT return_expires FROM users WHERE id=$1", uid)
|
||||
err := database.Get(&returnExpiry, "SELECT return_expires FROM users WHERE id=$1", uid)
|
||||
if err != nil {
|
||||
returnExpiry = time.Now()
|
||||
s.db.Exec("UPDATE users SET return_expires=$1 WHERE id=$2", returnExpiry, uid)
|
||||
database.Exec("UPDATE users SET return_expires=$1 WHERE id=$2", returnExpiry, uid)
|
||||
}
|
||||
}
|
||||
s.db.Exec("UPDATE users SET last_login=$1 WHERE id=$2", time.Now(), uid)
|
||||
database.Exec("UPDATE users SET last_login=$1 WHERE id=$2", time.Now(), uid)
|
||||
return returnExpiry
|
||||
}
|
||||
|
||||
func (s *APIServer) exportSave(ctx context.Context, uid uint32, cid uint32) (map[string]interface{}, error) {
|
||||
row := s.db.QueryRowxContext(ctx, "SELECT * FROM characters WHERE id=$1 AND user_id=$2", cid, uid)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
row := database.QueryRowxContext(ctx, "SELECT * FROM characters WHERE id=$1 AND user_id=$2", cid, uid)
|
||||
result := make(map[string]interface{})
|
||||
err := row.MapScan(result)
|
||||
err = row.MapScan(result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -5,7 +5,8 @@ import (
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
_config "erupe-ce/config"
|
||||
"erupe-ce/config"
|
||||
"erupe-ce/utils/db"
|
||||
"erupe-ce/utils/gametime"
|
||||
"fmt"
|
||||
"image"
|
||||
@@ -30,9 +31,9 @@ const (
|
||||
)
|
||||
|
||||
type LauncherResponse struct {
|
||||
Banners []_config.APISignBanner `json:"banners"`
|
||||
Messages []_config.APISignMessage `json:"messages"`
|
||||
Links []_config.APISignLink `json:"links"`
|
||||
Banners []config.APISignBanner `json:"banners"`
|
||||
Messages []config.APISignMessage `json:"messages"`
|
||||
Links []config.APISignLink `json:"links"`
|
||||
}
|
||||
|
||||
type User struct {
|
||||
@@ -137,7 +138,11 @@ func (s *APIServer) Login(w http.ResponseWriter, r *http.Request) {
|
||||
userRights uint32
|
||||
password string
|
||||
)
|
||||
err := s.db.QueryRow("SELECT id, password, rights FROM users WHERE username = $1", reqData.Username).Scan(&userID, &password, &userRights)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
err = database.QueryRow("SELECT id, password, rights FROM users WHERE username = $1", reqData.Username).Scan(&userID, &password, &userRights)
|
||||
if err == sql.ErrNoRows {
|
||||
w.WriteHeader(400)
|
||||
w.Write([]byte("username-error"))
|
||||
|
||||
@@ -1,23 +1,24 @@
|
||||
package channelserver
|
||||
|
||||
import (
|
||||
"erupe-ce/config"
|
||||
"erupe-ce/network/mhfpacket"
|
||||
"erupe-ce/utils/byteframe"
|
||||
)
|
||||
|
||||
func doAckEarthSucceed(s *Session, ackHandle uint32, data []*byteframe.ByteFrame) {
|
||||
func DoAckEarthSucceed(s *Session, ackHandle uint32, data []*byteframe.ByteFrame) {
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint32(uint32(s.server.erupeConfig.EarthID))
|
||||
bf.WriteUint32(uint32(config.GetConfig().EarthID))
|
||||
bf.WriteUint32(0)
|
||||
bf.WriteUint32(0)
|
||||
bf.WriteUint32(uint32(len(data)))
|
||||
for i := range data {
|
||||
bf.WriteBytes(data[i].Data())
|
||||
}
|
||||
doAckBufSucceed(s, ackHandle, bf.Data())
|
||||
DoAckBufSucceed(s, ackHandle, bf.Data())
|
||||
}
|
||||
|
||||
func doAckBufSucceed(s *Session, ackHandle uint32, data []byte) {
|
||||
func DoAckBufSucceed(s *Session, ackHandle uint32, data []byte) {
|
||||
s.QueueSendMHF(&mhfpacket.MsgSysAck{
|
||||
AckHandle: ackHandle,
|
||||
IsBufferResponse: true,
|
||||
@@ -26,7 +27,7 @@ func doAckBufSucceed(s *Session, ackHandle uint32, data []byte) {
|
||||
})
|
||||
}
|
||||
|
||||
func doAckBufFail(s *Session, ackHandle uint32, data []byte) {
|
||||
func DoAckBufFail(s *Session, ackHandle uint32, data []byte) {
|
||||
s.QueueSendMHF(&mhfpacket.MsgSysAck{
|
||||
AckHandle: ackHandle,
|
||||
IsBufferResponse: true,
|
||||
@@ -35,7 +36,7 @@ func doAckBufFail(s *Session, ackHandle uint32, data []byte) {
|
||||
})
|
||||
}
|
||||
|
||||
func doAckSimpleSucceed(s *Session, ackHandle uint32, data []byte) {
|
||||
func DoAckSimpleSucceed(s *Session, ackHandle uint32, data []byte) {
|
||||
s.QueueSendMHF(&mhfpacket.MsgSysAck{
|
||||
AckHandle: ackHandle,
|
||||
IsBufferResponse: false,
|
||||
@@ -44,7 +45,7 @@ func doAckSimpleSucceed(s *Session, ackHandle uint32, data []byte) {
|
||||
})
|
||||
}
|
||||
|
||||
func doAckSimpleFail(s *Session, ackHandle uint32, data []byte) {
|
||||
func DoAckSimpleFail(s *Session, ackHandle uint32, data []byte) {
|
||||
s.QueueSendMHF(&mhfpacket.MsgSysAck{
|
||||
AckHandle: ackHandle,
|
||||
IsBufferResponse: false,
|
||||
|
||||
@@ -2,7 +2,8 @@ package channelserver
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
_config "erupe-ce/config"
|
||||
"erupe-ce/config"
|
||||
"erupe-ce/utils/db"
|
||||
"erupe-ce/utils/gametime"
|
||||
"erupe-ce/utils/mhfcourse"
|
||||
"erupe-ce/utils/mhfitem"
|
||||
@@ -28,12 +29,16 @@ func stubEnumerateNoResults(s *Session, ackHandle uint32) {
|
||||
enumBf := byteframe.NewByteFrame()
|
||||
enumBf.WriteUint32(0) // Entry count (count for quests, rankings, events, etc.)
|
||||
|
||||
doAckBufSucceed(s, ackHandle, enumBf.Data())
|
||||
DoAckBufSucceed(s, ackHandle, enumBf.Data())
|
||||
}
|
||||
|
||||
func updateRights(s *Session) {
|
||||
rightsInt := uint32(2)
|
||||
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)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
database.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, rightsInt = mhfcourse.GetCourseStruct(rightsInt)
|
||||
update := &mhfpacket.MsgSysUpdateRight{
|
||||
ClientRespAckHandle: 0,
|
||||
@@ -63,7 +68,7 @@ func handleMsgSysAck(s *Session, p mhfpacket.MHFPacket) {}
|
||||
func handleMsgSysTerminalLog(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgSysTerminalLog)
|
||||
for i := range pkt.Entries {
|
||||
s.server.logger.Info("SysTerminalLog",
|
||||
s.Server.logger.Info("SysTerminalLog",
|
||||
zap.Uint8("Type1", pkt.Entries[i].Type1),
|
||||
zap.Uint8("Type2", pkt.Entries[i].Type2),
|
||||
zap.Int16("Unk0", pkt.Entries[i].Unk0),
|
||||
@@ -75,55 +80,58 @@ func handleMsgSysTerminalLog(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
resp := byteframe.NewByteFrame()
|
||||
resp.WriteUint32(pkt.LogID + 1) // LogID to use for requests after this.
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, resp.Data())
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, resp.Data())
|
||||
}
|
||||
|
||||
func handleMsgSysLogin(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgSysLogin)
|
||||
|
||||
if !s.server.erupeConfig.DebugOptions.DisableTokenCheck {
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
if !config.GetConfig().DebugOptions.DisableTokenCheck {
|
||||
var token string
|
||||
err := s.server.db.QueryRow("SELECT token FROM sign_sessions ss INNER JOIN public.users u on ss.user_id = u.id WHERE token=$1 AND ss.id=$2 AND u.id=(SELECT c.user_id FROM characters c WHERE c.id=$3)", pkt.LoginTokenString, pkt.LoginTokenNumber, pkt.CharID0).Scan(&token)
|
||||
err := database.QueryRow("SELECT token FROM sign_sessions ss INNER JOIN public.users u on ss.user_id = u.id WHERE token=$1 AND ss.id=$2 AND u.id=(SELECT c.user_id FROM characters c WHERE c.id=$3)", pkt.LoginTokenString, pkt.LoginTokenNumber, pkt.CharID0).Scan(&token)
|
||||
if err != nil {
|
||||
s.rawConn.Close()
|
||||
s.logger.Warn(fmt.Sprintf("Invalid login token, offending CID: (%d)", pkt.CharID0))
|
||||
s.Logger.Warn(fmt.Sprintf("Invalid login token, offending CID: (%d)", pkt.CharID0))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
s.Lock()
|
||||
s.charID = pkt.CharID0
|
||||
s.CharID = pkt.CharID0
|
||||
s.token = pkt.LoginTokenString
|
||||
s.Unlock()
|
||||
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint32(uint32(gametime.TimeAdjusted().Unix())) // Unix timestamp
|
||||
|
||||
_, err := s.server.db.Exec("UPDATE servers SET current_players=$1 WHERE server_id=$2", len(s.server.sessions), s.server.ID)
|
||||
_, err = database.Exec("UPDATE servers SET current_players=$1 WHERE server_id=$2", len(s.Server.sessions), s.Server.ID)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
_, err = s.server.db.Exec("UPDATE sign_sessions SET server_id=$1, char_id=$2 WHERE token=$3", s.server.ID, s.charID, s.token)
|
||||
_, err = database.Exec("UPDATE sign_sessions SET server_id=$1, char_id=$2 WHERE token=$3", s.Server.ID, s.CharID, s.token)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
_, err = s.server.db.Exec("UPDATE characters SET last_login=$1 WHERE id=$2", gametime.TimeAdjusted().Unix(), s.charID)
|
||||
_, err = database.Exec("UPDATE characters SET last_login=$1 WHERE id=$2", gametime.TimeAdjusted().Unix(), s.CharID)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
_, err = s.server.db.Exec("UPDATE users u SET last_character=$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)", s.charID)
|
||||
_, err = database.Exec("UPDATE users u SET last_character=$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)", s.CharID)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
|
||||
|
||||
updateRights(s)
|
||||
|
||||
s.server.BroadcastMHF(&mhfpacket.MsgSysInsertUser{CharID: s.charID}, s)
|
||||
s.Server.BroadcastMHF(&mhfpacket.MsgSysInsertUser{CharID: s.CharID}, s)
|
||||
}
|
||||
|
||||
func handleMsgSysLogout(s *Session, p mhfpacket.MHFPacket) {
|
||||
@@ -131,45 +139,49 @@ func handleMsgSysLogout(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
|
||||
func logoutPlayer(s *Session) {
|
||||
s.server.Lock()
|
||||
if _, exists := s.server.sessions[s.rawConn]; exists {
|
||||
delete(s.server.sessions, s.rawConn)
|
||||
|
||||
s.Server.Lock()
|
||||
if _, exists := s.Server.sessions[s.rawConn]; exists {
|
||||
delete(s.Server.sessions, s.rawConn)
|
||||
}
|
||||
s.rawConn.Close()
|
||||
delete(s.server.objectIDs, s)
|
||||
s.server.Unlock()
|
||||
delete(s.Server.objectIDs, s)
|
||||
s.Server.Unlock()
|
||||
|
||||
for _, stage := range s.server.stages {
|
||||
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 {
|
||||
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" {
|
||||
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 {
|
||||
if session.CharID == s.CharID {
|
||||
delete(stage.clients, session)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_, err := s.server.db.Exec("UPDATE sign_sessions SET server_id=NULL, char_id=NULL WHERE token=$1", s.token)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
_, err = database.Exec("UPDATE sign_sessions SET server_id=NULL, char_id=NULL WHERE token=$1", s.token)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
_, err = s.server.db.Exec("UPDATE servers SET current_players=$1 WHERE server_id=$2", len(s.server.sessions), s.server.ID)
|
||||
_, err = database.Exec("UPDATE servers SET current_players=$1 WHERE server_id=$2", len(s.Server.sessions), s.Server.ID)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
var timePlayed int
|
||||
var sessionTime int
|
||||
_ = s.server.db.QueryRow("SELECT time_played FROM characters WHERE id = $1", s.charID).Scan(&timePlayed)
|
||||
_ = database.QueryRow("SELECT time_played FROM characters WHERE id = $1", s.CharID).Scan(&timePlayed)
|
||||
sessionTime = int(gametime.TimeAdjusted().Unix()) - int(s.sessionStart)
|
||||
timePlayed += sessionTime
|
||||
|
||||
@@ -177,43 +189,43 @@ func logoutPlayer(s *Session) {
|
||||
if mhfcourse.CourseExists(30, s.courses) {
|
||||
rpGained = timePlayed / 900
|
||||
timePlayed = timePlayed % 900
|
||||
s.server.db.Exec("UPDATE characters SET cafe_time=cafe_time+$1 WHERE id=$2", sessionTime, s.charID)
|
||||
database.Exec("UPDATE characters SET cafe_time=cafe_time+$1 WHERE id=$2", sessionTime, s.CharID)
|
||||
} else {
|
||||
rpGained = timePlayed / 1800
|
||||
timePlayed = timePlayed % 1800
|
||||
}
|
||||
|
||||
s.server.db.Exec("UPDATE characters SET time_played = $1 WHERE id = $2", timePlayed, s.charID)
|
||||
database.Exec("UPDATE characters SET time_played = $1 WHERE id = $2", timePlayed, s.CharID)
|
||||
|
||||
s.server.db.Exec(`UPDATE guild_characters SET treasure_hunt=NULL WHERE character_id=$1`, s.charID)
|
||||
database.Exec(`UPDATE guild_characters SET treasure_hunt=NULL WHERE character_id=$1`, s.CharID)
|
||||
|
||||
if s.stage == nil {
|
||||
return
|
||||
}
|
||||
|
||||
s.server.BroadcastMHF(&mhfpacket.MsgSysDeleteUser{
|
||||
CharID: s.charID,
|
||||
s.Server.BroadcastMHF(&mhfpacket.MsgSysDeleteUser{
|
||||
CharID: s.CharID,
|
||||
}, s)
|
||||
|
||||
s.server.Lock()
|
||||
for _, stage := range s.server.stages {
|
||||
if _, exists := stage.reservedClientSlots[s.charID]; exists {
|
||||
delete(stage.reservedClientSlots, s.charID)
|
||||
s.Server.Lock()
|
||||
for _, stage := range s.Server.stages {
|
||||
if _, exists := stage.reservedClientSlots[s.CharID]; exists {
|
||||
delete(stage.reservedClientSlots, s.CharID)
|
||||
}
|
||||
}
|
||||
s.server.Unlock()
|
||||
s.Server.Unlock()
|
||||
|
||||
removeSessionFromSemaphore(s)
|
||||
removeSessionFromStage(s)
|
||||
|
||||
saveData, err := GetCharacterSaveData(s, s.charID)
|
||||
saveData, err := GetCharacterSaveData(s, s.CharID)
|
||||
if err != nil || saveData == nil {
|
||||
s.logger.Error("Failed to get savedata")
|
||||
s.Logger.Error("Failed to get savedata")
|
||||
return
|
||||
}
|
||||
saveData.RP += uint16(rpGained)
|
||||
if saveData.RP >= s.server.erupeConfig.GameplayOptions.MaximumRP {
|
||||
saveData.RP = s.server.erupeConfig.GameplayOptions.MaximumRP
|
||||
if saveData.RP >= config.GetConfig().GameplayOptions.MaximumRP {
|
||||
saveData.RP = config.GetConfig().GameplayOptions.MaximumRP
|
||||
}
|
||||
saveData.Save(s)
|
||||
}
|
||||
@@ -222,7 +234,7 @@ func handleMsgSysSetStatus(s *Session, p mhfpacket.MHFPacket) {}
|
||||
|
||||
func handleMsgSysPing(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgSysPing)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
}
|
||||
|
||||
func handleMsgSysTime(s *Session, p mhfpacket.MHFPacket) {
|
||||
@@ -253,25 +265,29 @@ func handleMsgSysIssueLogkey(s *Session, p mhfpacket.MHFPacket) {
|
||||
// Issue it.
|
||||
resp := byteframe.NewByteFrame()
|
||||
resp.WriteBytes(logKey)
|
||||
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
}
|
||||
|
||||
func handleMsgSysRecordLog(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgSysRecordLog)
|
||||
if _config.ErupeConfig.ClientID == _config.ZZ {
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
if config.GetConfig().ClientID == config.ZZ {
|
||||
bf := byteframe.NewByteFrameFromBytes(pkt.Data)
|
||||
bf.Seek(32, 0)
|
||||
var val uint8
|
||||
for i := 0; i < 176; i++ {
|
||||
val = bf.ReadUint8()
|
||||
if val > 0 && mhfmon.Monsters[i].Large {
|
||||
s.server.db.Exec(`INSERT INTO kill_logs (character_id, monster, quantity, timestamp) VALUES ($1, $2, $3, $4)`, s.charID, i, val, gametime.TimeAdjusted())
|
||||
database.Exec(`INSERT INTO kill_logs (character_id, monster, quantity, timestamp) VALUES ($1, $2, $3, $4)`, s.CharID, i, val, gametime.TimeAdjusted())
|
||||
}
|
||||
}
|
||||
}
|
||||
// remove a client returning to town from reserved slots to make sure the stage is hidden from board
|
||||
delete(s.stage.reservedClientSlots, s.charID)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
delete(s.stage.reservedClientSlots, s.CharID)
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func handleMsgSysEcho(s *Session, p mhfpacket.MHFPacket) {}
|
||||
@@ -279,7 +295,7 @@ func handleMsgSysEcho(s *Session, p mhfpacket.MHFPacket) {}
|
||||
func handleMsgSysLockGlobalSema(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgSysLockGlobalSema)
|
||||
var sgid string
|
||||
for _, channel := range s.server.Channels {
|
||||
for _, channel := range s.Server.Channels {
|
||||
for id := range channel.stages {
|
||||
if strings.HasSuffix(id, pkt.UserIDString) {
|
||||
sgid = channel.GlobalID
|
||||
@@ -287,7 +303,7 @@ func handleMsgSysLockGlobalSema(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
}
|
||||
bf := byteframe.NewByteFrame()
|
||||
if len(sgid) > 0 && sgid != s.server.GlobalID {
|
||||
if len(sgid) > 0 && sgid != s.Server.GlobalID {
|
||||
bf.WriteUint8(0)
|
||||
bf.WriteUint8(0)
|
||||
ps.Uint16(bf, sgid, false)
|
||||
@@ -296,12 +312,12 @@ func handleMsgSysLockGlobalSema(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint8(0)
|
||||
ps.Uint16(bf, pkt.ServerChannelIDString, false)
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgSysUnlockGlobalSema(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgSysUnlockGlobalSema)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func handleMsgSysUpdateRight(s *Session, p mhfpacket.MHFPacket) {}
|
||||
@@ -313,7 +329,7 @@ func handleMsgSysAuthTerminal(s *Session, p mhfpacket.MHFPacket) {}
|
||||
func handleMsgSysRightsReload(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgSysRightsReload)
|
||||
updateRights(s)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
}
|
||||
|
||||
func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) {
|
||||
@@ -351,18 +367,18 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) {
|
||||
resp.WriteUint16(0)
|
||||
switch pkt.SearchType {
|
||||
case 1, 2, 3: // usersearchidx, usersearchname, lobbysearchname
|
||||
for _, c := range s.server.Channels {
|
||||
for _, c := range s.Server.Channels {
|
||||
for _, session := range c.sessions {
|
||||
if count == maxResults {
|
||||
break
|
||||
}
|
||||
if pkt.SearchType == 1 && session.charID != cid {
|
||||
if pkt.SearchType == 1 && session.CharID != cid {
|
||||
continue
|
||||
}
|
||||
if pkt.SearchType == 2 && !strings.Contains(session.Name, term) {
|
||||
continue
|
||||
}
|
||||
if pkt.SearchType == 3 && session.server.IP != ip && session.server.Port != port && session.stage.id != term {
|
||||
if pkt.SearchType == 3 && session.Server.IP != ip && session.Server.Port != port && session.stage.id != term {
|
||||
continue
|
||||
}
|
||||
count++
|
||||
@@ -374,13 +390,13 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) {
|
||||
resp.WriteUint32(0x0100007F)
|
||||
}
|
||||
resp.WriteUint16(c.Port)
|
||||
resp.WriteUint32(session.charID)
|
||||
resp.WriteUint32(session.CharID)
|
||||
resp.WriteUint8(uint8(len(sessionStage) + 1))
|
||||
resp.WriteUint8(uint8(len(sessionName) + 1))
|
||||
resp.WriteUint16(uint16(len(c.userBinaryParts[userBinaryPartID{charID: session.charID, index: 3}])))
|
||||
resp.WriteUint16(uint16(len(c.userBinaryParts[userBinaryPartID{charID: session.CharID, index: 3}])))
|
||||
|
||||
// TODO: This case might be <=G2
|
||||
if _config.ErupeConfig.ClientID <= _config.G1 {
|
||||
if config.GetConfig().ClientID <= config.G1 {
|
||||
resp.WriteBytes(make([]byte, 8))
|
||||
} else {
|
||||
resp.WriteBytes(make([]byte, 40))
|
||||
@@ -389,7 +405,7 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) {
|
||||
|
||||
resp.WriteNullTerminatedBytes(sessionStage)
|
||||
resp.WriteNullTerminatedBytes(sessionName)
|
||||
resp.WriteBytes(c.userBinaryParts[userBinaryPartID{session.charID, 3}])
|
||||
resp.WriteBytes(c.userBinaryParts[userBinaryPartID{session.CharID, 3}])
|
||||
}
|
||||
}
|
||||
case 4: // lobbysearch
|
||||
@@ -411,7 +427,7 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) {
|
||||
case 0:
|
||||
values := bf.ReadUint8()
|
||||
for i := uint8(0); i < values; i++ {
|
||||
if _config.ErupeConfig.ClientID >= _config.Z1 {
|
||||
if config.GetConfig().ClientID >= config.Z1 {
|
||||
findPartyParams.RankRestriction = bf.ReadInt16()
|
||||
} else {
|
||||
findPartyParams.RankRestriction = int16(bf.ReadInt8())
|
||||
@@ -420,7 +436,7 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) {
|
||||
case 1:
|
||||
values := bf.ReadUint8()
|
||||
for i := uint8(0); i < values; i++ {
|
||||
if _config.ErupeConfig.ClientID >= _config.Z1 {
|
||||
if config.GetConfig().ClientID >= config.Z1 {
|
||||
findPartyParams.Targets = append(findPartyParams.Targets, bf.ReadInt16())
|
||||
} else {
|
||||
findPartyParams.Targets = append(findPartyParams.Targets, int16(bf.ReadInt8()))
|
||||
@@ -430,7 +446,7 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) {
|
||||
values := bf.ReadUint8()
|
||||
for i := uint8(0); i < values; i++ {
|
||||
var value int16
|
||||
if _config.ErupeConfig.ClientID >= _config.Z1 {
|
||||
if config.GetConfig().ClientID >= config.Z1 {
|
||||
value = bf.ReadInt16()
|
||||
} else {
|
||||
value = int16(bf.ReadInt8())
|
||||
@@ -451,7 +467,7 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) {
|
||||
case 3: // Unknown
|
||||
values := bf.ReadUint8()
|
||||
for i := uint8(0); i < values; i++ {
|
||||
if _config.ErupeConfig.ClientID >= _config.Z1 {
|
||||
if config.GetConfig().ClientID >= config.Z1 {
|
||||
findPartyParams.Unk0 = append(findPartyParams.Unk0, bf.ReadInt16())
|
||||
} else {
|
||||
findPartyParams.Unk0 = append(findPartyParams.Unk0, int16(bf.ReadInt8()))
|
||||
@@ -460,7 +476,7 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) {
|
||||
case 4: // Looking for n or already have n
|
||||
values := bf.ReadUint8()
|
||||
for i := uint8(0); i < values; i++ {
|
||||
if _config.ErupeConfig.ClientID >= _config.Z1 {
|
||||
if config.GetConfig().ClientID >= config.Z1 {
|
||||
findPartyParams.Unk1 = append(findPartyParams.Unk1, bf.ReadInt16())
|
||||
} else {
|
||||
findPartyParams.Unk1 = append(findPartyParams.Unk1, int16(bf.ReadInt8()))
|
||||
@@ -469,7 +485,7 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) {
|
||||
case 5:
|
||||
values := bf.ReadUint8()
|
||||
for i := uint8(0); i < values; i++ {
|
||||
if _config.ErupeConfig.ClientID >= _config.Z1 {
|
||||
if config.GetConfig().ClientID >= config.Z1 {
|
||||
findPartyParams.QuestID = append(findPartyParams.QuestID, bf.ReadInt16())
|
||||
} else {
|
||||
findPartyParams.QuestID = append(findPartyParams.QuestID, int16(bf.ReadInt8()))
|
||||
@@ -477,7 +493,7 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, c := range s.server.Channels {
|
||||
for _, c := range s.Server.Channels {
|
||||
for _, stage := range c.stages {
|
||||
if count == maxResults {
|
||||
break
|
||||
@@ -487,15 +503,15 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) {
|
||||
sb3.Seek(4, 0)
|
||||
|
||||
stageDataParams := 7
|
||||
if _config.ErupeConfig.ClientID <= _config.G10 {
|
||||
if config.GetConfig().ClientID <= config.G10 {
|
||||
stageDataParams = 4
|
||||
} else if _config.ErupeConfig.ClientID <= _config.Z1 {
|
||||
} else if config.GetConfig().ClientID <= config.Z1 {
|
||||
stageDataParams = 6
|
||||
}
|
||||
|
||||
var stageData []int16
|
||||
for i := 0; i < stageDataParams; i++ {
|
||||
if _config.ErupeConfig.ClientID >= _config.Z1 {
|
||||
if config.GetConfig().ClientID >= config.Z1 {
|
||||
stageData = append(stageData, sb3.ReadInt16())
|
||||
} else {
|
||||
stageData = append(stageData, int16(sb3.ReadInt8()))
|
||||
@@ -544,7 +560,7 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) {
|
||||
resp.WriteUint8(uint8(len(stage.rawBinaryData[stageBinaryKey{1, 1}])))
|
||||
|
||||
for i := range stageData {
|
||||
if _config.ErupeConfig.ClientID >= _config.Z1 {
|
||||
if config.GetConfig().ClientID >= config.Z1 {
|
||||
resp.WriteInt16(stageData[i])
|
||||
} else {
|
||||
resp.WriteInt8(int8(stageData[i]))
|
||||
@@ -562,7 +578,7 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
resp.Seek(0, io.SeekStart)
|
||||
resp.WriteUint16(count)
|
||||
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
}
|
||||
|
||||
func handleMsgCaExchangeItem(s *Session, p mhfpacket.MHFPacket) {}
|
||||
@@ -571,8 +587,8 @@ func handleMsgMhfServerCommand(s *Session, p mhfpacket.MHFPacket) {}
|
||||
|
||||
func handleMsgMhfAnnounce(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfAnnounce)
|
||||
s.server.BroadcastRaviente(pkt.IPAddress, pkt.Port, pkt.StageID, pkt.Data.ReadUint8())
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
s.Server.BroadcastRaviente(pkt.IPAddress, pkt.Port, pkt.StageID, pkt.Data.ReadUint8())
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func handleMsgMhfSetLoginwindow(s *Session, p mhfpacket.MHFPacket) {}
|
||||
@@ -595,7 +611,7 @@ func handleMsgMhfGetCaUniqueID(s *Session, p mhfpacket.MHFPacket) {}
|
||||
|
||||
func handleMsgMhfTransferItem(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfTransferItem)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
}
|
||||
|
||||
func handleMsgMhfEnumeratePrice(s *Session, p mhfpacket.MHFPacket) {
|
||||
@@ -760,7 +776,7 @@ func handleMsgMhfEnumeratePrice(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint16(gz.Unk3)
|
||||
bf.WriteUint8(gz.Unk4)
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfEnumerateOrder(s *Session, p mhfpacket.MHFPacket) {
|
||||
@@ -773,7 +789,11 @@ func handleMsgMhfGetExtraInfo(s *Session, p mhfpacket.MHFPacket) {}
|
||||
func userGetItems(s *Session) []mhfitem.MHFItemStack {
|
||||
var data []byte
|
||||
var items []mhfitem.MHFItemStack
|
||||
s.server.db.QueryRow(`SELECT item_box FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)`, s.charID).Scan(&data)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
database.QueryRow(`SELECT item_box FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)`, s.CharID).Scan(&data)
|
||||
if len(data) > 0 {
|
||||
box := byteframe.NewByteFrameFromBytes(data)
|
||||
numStacks := box.ReadUint16()
|
||||
@@ -790,14 +810,18 @@ func handleMsgMhfEnumerateUnionItem(s *Session, p mhfpacket.MHFPacket) {
|
||||
items := userGetItems(s)
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteBytes(mhfitem.SerializeWarehouseItems(items))
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfUpdateUnionItem(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfUpdateUnionItem)
|
||||
newStacks := mhfitem.DiffItemStacks(userGetItems(s), pkt.UpdatedItems)
|
||||
s.server.db.Exec(`UPDATE users u SET item_box=$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, mhfitem.SerializeWarehouseItems(newStacks), s.charID)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
database.Exec(`UPDATE users u SET item_box=$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, mhfitem.SerializeWarehouseItems(newStacks), s.CharID)
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func handleMsgMhfGetCogInfo(s *Session, p mhfpacket.MHFPacket) {}
|
||||
@@ -806,20 +830,24 @@ func handleMsgMhfCheckWeeklyStamp(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfCheckWeeklyStamp)
|
||||
var total, redeemed, updated uint16
|
||||
var lastCheck time.Time
|
||||
err := s.server.db.QueryRow(fmt.Sprintf("SELECT %s_checked FROM stamps WHERE character_id=$1", pkt.StampType), s.charID).Scan(&lastCheck)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
err = database.QueryRow(fmt.Sprintf("SELECT %s_checked FROM stamps WHERE character_id=$1", pkt.StampType), s.CharID).Scan(&lastCheck)
|
||||
if err != nil {
|
||||
lastCheck = gametime.TimeAdjusted()
|
||||
s.server.db.Exec("INSERT INTO stamps (character_id, hl_checked, ex_checked) VALUES ($1, $2, $2)", s.charID, gametime.TimeAdjusted())
|
||||
database.Exec("INSERT INTO stamps (character_id, hl_checked, ex_checked) VALUES ($1, $2, $2)", s.CharID, gametime.TimeAdjusted())
|
||||
} else {
|
||||
s.server.db.Exec(fmt.Sprintf(`UPDATE stamps SET %s_checked=$1 WHERE character_id=$2`, pkt.StampType), gametime.TimeAdjusted(), s.charID)
|
||||
database.Exec(fmt.Sprintf(`UPDATE stamps SET %s_checked=$1 WHERE character_id=$2`, pkt.StampType), gametime.TimeAdjusted(), s.CharID)
|
||||
}
|
||||
|
||||
if lastCheck.Before(gametime.TimeWeekStart()) {
|
||||
s.server.db.Exec(fmt.Sprintf("UPDATE stamps SET %s_total=%s_total+1 WHERE character_id=$1", pkt.StampType, pkt.StampType), s.charID)
|
||||
database.Exec(fmt.Sprintf("UPDATE stamps SET %s_total=%s_total+1 WHERE character_id=$1", pkt.StampType, pkt.StampType), s.CharID)
|
||||
updated = 1
|
||||
}
|
||||
|
||||
s.server.db.QueryRow(fmt.Sprintf("SELECT %s_total, %s_redeemed FROM stamps WHERE character_id=$1", pkt.StampType, pkt.StampType), s.charID).Scan(&total, &redeemed)
|
||||
database.QueryRow(fmt.Sprintf("SELECT %s_total, %s_redeemed FROM stamps WHERE character_id=$1", pkt.StampType, pkt.StampType), s.CharID).Scan(&total, &redeemed)
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint16(total)
|
||||
bf.WriteUint16(redeemed)
|
||||
@@ -827,18 +855,22 @@ func handleMsgMhfCheckWeeklyStamp(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint16(0)
|
||||
bf.WriteUint16(0)
|
||||
bf.WriteUint32(uint32(gametime.TimeWeekStart().Unix()))
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfExchangeWeeklyStamp(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfExchangeWeeklyStamp)
|
||||
var total, redeemed uint16
|
||||
var tktStack mhfitem.MHFItemStack
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
if pkt.Unk1 == 10 { // Yearly Sub Ex
|
||||
s.server.db.QueryRow("UPDATE stamps SET hl_total=hl_total-48, hl_redeemed=hl_redeemed-48 WHERE character_id=$1 RETURNING hl_total, hl_redeemed", s.charID).Scan(&total, &redeemed)
|
||||
database.QueryRow("UPDATE stamps SET hl_total=hl_total-48, hl_redeemed=hl_redeemed-48 WHERE character_id=$1 RETURNING hl_total, hl_redeemed", s.CharID).Scan(&total, &redeemed)
|
||||
tktStack = mhfitem.MHFItemStack{Item: mhfitem.MHFItem{ItemID: 2210}, Quantity: 1}
|
||||
} else {
|
||||
s.server.db.QueryRow(fmt.Sprintf("UPDATE stamps SET %s_redeemed=%s_redeemed+8 WHERE character_id=$1 RETURNING %s_total, %s_redeemed", pkt.StampType, pkt.StampType, pkt.StampType, pkt.StampType), s.charID).Scan(&total, &redeemed)
|
||||
database.QueryRow(fmt.Sprintf("UPDATE stamps SET %s_redeemed=%s_redeemed+8 WHERE character_id=$1 RETURNING %s_total, %s_redeemed", pkt.StampType, pkt.StampType, pkt.StampType, pkt.StampType), s.CharID).Scan(&total, &redeemed)
|
||||
if pkt.StampType == "hl" {
|
||||
tktStack = mhfitem.MHFItemStack{Item: mhfitem.MHFItem{ItemID: 1630}, Quantity: 5}
|
||||
} else {
|
||||
@@ -853,16 +885,20 @@ func handleMsgMhfExchangeWeeklyStamp(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint16(tktStack.Item.ItemID)
|
||||
bf.WriteUint16(tktStack.Quantity)
|
||||
bf.WriteUint32(uint32(gametime.TimeWeekStart().Unix()))
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func getGoocooData(s *Session, cid uint32) [][]byte {
|
||||
var goocoo []byte
|
||||
var goocoos [][]byte
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
for i := 0; i < 5; i++ {
|
||||
err := s.server.db.QueryRow(fmt.Sprintf("SELECT goocoo%d FROM goocoo WHERE id=$1", i), cid).Scan(&goocoo)
|
||||
err := database.QueryRow(fmt.Sprintf("SELECT goocoo%d FROM goocoo WHERE id=$1", i), cid).Scan(&goocoo)
|
||||
if err != nil {
|
||||
s.server.db.Exec("INSERT INTO goocoo (id) VALUES ($1)", s.charID)
|
||||
database.Exec("INSERT INTO goocoo (id) VALUES ($1)", s.CharID)
|
||||
return goocoos
|
||||
}
|
||||
if err == nil && goocoo != nil {
|
||||
@@ -875,20 +911,24 @@ func getGoocooData(s *Session, cid uint32) [][]byte {
|
||||
func handleMsgMhfEnumerateGuacot(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfEnumerateGuacot)
|
||||
bf := byteframe.NewByteFrame()
|
||||
goocoos := getGoocooData(s, s.charID)
|
||||
goocoos := getGoocooData(s, s.CharID)
|
||||
bf.WriteUint16(uint16(len(goocoos)))
|
||||
bf.WriteUint16(0)
|
||||
for _, goocoo := range goocoos {
|
||||
bf.WriteBytes(goocoo)
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfUpdateGuacot(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfUpdateGuacot)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
for _, goocoo := range pkt.Goocoos {
|
||||
if goocoo.Data1[0] == 0 {
|
||||
s.server.db.Exec(fmt.Sprintf("UPDATE goocoo SET goocoo%d=NULL WHERE id=$1", goocoo.Index), s.charID)
|
||||
database.Exec(fmt.Sprintf("UPDATE goocoo SET goocoo%d=NULL WHERE id=$1", goocoo.Index), s.CharID)
|
||||
} else {
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint32(goocoo.Index)
|
||||
@@ -900,11 +940,11 @@ func handleMsgMhfUpdateGuacot(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
bf.WriteUint8(uint8(len(goocoo.Name)))
|
||||
bf.WriteBytes(goocoo.Name)
|
||||
s.server.db.Exec(fmt.Sprintf("UPDATE goocoo SET goocoo%d=$1 WHERE id=$2", goocoo.Index), bf.Data(), s.charID)
|
||||
database.Exec(fmt.Sprintf("UPDATE goocoo SET goocoo%d=$1 WHERE id=$2", goocoo.Index), bf.Data(), s.CharID)
|
||||
dumpSaveData(s, bf.Data(), fmt.Sprintf("goocoo-%d", goocoo.Index))
|
||||
}
|
||||
}
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
type Scenario struct {
|
||||
@@ -921,11 +961,15 @@ func handleMsgMhfInfoScenarioCounter(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfInfoScenarioCounter)
|
||||
var scenarios []Scenario
|
||||
var scenario Scenario
|
||||
scenarioData, err := s.server.db.Queryx("SELECT scenario_id, category_id FROM scenario_counter")
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
scenarioData, err := database.Queryx("SELECT scenario_id, category_id FROM scenario_counter")
|
||||
if err != nil {
|
||||
scenarioData.Close()
|
||||
s.logger.Error("Failed to get scenario counter info from db", zap.Error(err))
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 1))
|
||||
s.Logger.Error("Failed to get scenario counter info from db", zap.Error(err))
|
||||
DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 1))
|
||||
return
|
||||
}
|
||||
for scenarioData.Next() {
|
||||
@@ -954,26 +998,29 @@ func handleMsgMhfInfoScenarioCounter(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
bf.WriteUint8(scenario.CategoryID)
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfGetEtcPoints(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetEtcPoints)
|
||||
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
var dailyTime time.Time
|
||||
_ = s.server.db.QueryRow("SELECT COALESCE(daily_time, $2) FROM characters WHERE id = $1", s.charID, time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)).Scan(&dailyTime)
|
||||
_ = database.QueryRow("SELECT COALESCE(daily_time, $2) FROM characters WHERE id = $1", s.CharID, time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)).Scan(&dailyTime)
|
||||
if gametime.TimeAdjusted().After(dailyTime) {
|
||||
s.server.db.Exec("UPDATE characters SET bonus_quests = 0, daily_quests = 0 WHERE id=$1", s.charID)
|
||||
database.Exec("UPDATE characters SET bonus_quests = 0, daily_quests = 0 WHERE id=$1", s.CharID)
|
||||
}
|
||||
|
||||
var bonusQuests, dailyQuests, promoPoints uint32
|
||||
_ = s.server.db.QueryRow(`SELECT bonus_quests, daily_quests, promo_points FROM characters WHERE id = $1`, s.charID).Scan(&bonusQuests, &dailyQuests, &promoPoints)
|
||||
_ = database.QueryRow(`SELECT bonus_quests, daily_quests, promo_points FROM characters WHERE id = $1`, s.CharID).Scan(&bonusQuests, &dailyQuests, &promoPoints)
|
||||
resp := byteframe.NewByteFrame()
|
||||
resp.WriteUint8(3) // Maybe a count of uint32(s)?
|
||||
resp.WriteUint32(bonusQuests)
|
||||
resp.WriteUint32(dailyQuests)
|
||||
resp.WriteUint32(promoPoints)
|
||||
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfUpdateEtcPoint(s *Session, p mhfpacket.MHFPacket) {
|
||||
@@ -988,17 +1035,20 @@ func handleMsgMhfUpdateEtcPoint(s *Session, p mhfpacket.MHFPacket) {
|
||||
case 2:
|
||||
column = "promo_points"
|
||||
}
|
||||
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
var value int16
|
||||
err := s.server.db.QueryRow(fmt.Sprintf(`SELECT %s FROM characters WHERE id = $1`, column), s.charID).Scan(&value)
|
||||
err = database.QueryRow(fmt.Sprintf(`SELECT %s FROM characters WHERE id = $1`, column), s.CharID).Scan(&value)
|
||||
if err == nil {
|
||||
if value+pkt.Delta < 0 {
|
||||
s.server.db.Exec(fmt.Sprintf(`UPDATE characters SET %s = 0 WHERE id = $1`, column), s.charID)
|
||||
database.Exec(fmt.Sprintf(`UPDATE characters SET %s = 0 WHERE id = $1`, column), s.CharID)
|
||||
} else {
|
||||
s.server.db.Exec(fmt.Sprintf(`UPDATE characters SET %s = %s + $1 WHERE id = $2`, column, column), pkt.Delta, s.charID)
|
||||
database.Exec(fmt.Sprintf(`UPDATE characters SET %s = %s + $1 WHERE id = $2`, column, column), pkt.Delta, s.CharID)
|
||||
}
|
||||
}
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func handleMsgMhfStampcardStamp(s *Session, p mhfpacket.MHFPacket) {
|
||||
@@ -1017,7 +1067,7 @@ func handleMsgMhfStampcardStamp(s *Session, p mhfpacket.MHFPacket) {
|
||||
{300, 5392, 1, 5392, 3},
|
||||
{999, 5392, 1, 5392, 4},
|
||||
}
|
||||
if _config.ErupeConfig.ClientID <= _config.Z1 {
|
||||
if config.GetConfig().ClientID <= config.Z1 {
|
||||
for _, reward := range rewards {
|
||||
if pkt.HR >= reward.HR {
|
||||
pkt.Item1 = reward.Item1
|
||||
@@ -1030,12 +1080,16 @@ func handleMsgMhfStampcardStamp(s *Session, p mhfpacket.MHFPacket) {
|
||||
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint16(pkt.HR)
|
||||
if _config.ErupeConfig.ClientID >= _config.G1 {
|
||||
if config.GetConfig().ClientID >= config.G1 {
|
||||
bf.WriteUint16(pkt.GR)
|
||||
}
|
||||
var stamps, rewardTier, rewardUnk uint16
|
||||
reward := mhfitem.MHFItemStack{Item: mhfitem.MHFItem{}}
|
||||
s.server.db.QueryRow(`UPDATE characters SET stampcard = stampcard + $1 WHERE id = $2 RETURNING stampcard`, pkt.Stamps, s.charID).Scan(&stamps)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
database.QueryRow(`UPDATE characters SET stampcard = stampcard + $1 WHERE id = $2 RETURNING stampcard`, pkt.Stamps, s.CharID).Scan(&stamps)
|
||||
bf.WriteUint16(stamps - pkt.Stamps)
|
||||
bf.WriteUint16(stamps)
|
||||
|
||||
@@ -1055,14 +1109,14 @@ func handleMsgMhfStampcardStamp(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint16(rewardUnk)
|
||||
bf.WriteUint16(reward.Item.ItemID)
|
||||
bf.WriteUint16(reward.Quantity)
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfStampcardPrize(s *Session, p mhfpacket.MHFPacket) {}
|
||||
|
||||
func handleMsgMhfUnreserveSrg(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfUnreserveSrg)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func handleMsgMhfKickExportForce(s *Session, p mhfpacket.MHFPacket) {}
|
||||
@@ -1072,10 +1126,10 @@ func handleMsgMhfGetEarthStatus(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint32(uint32(gametime.TimeWeekStart().Unix())) // Start
|
||||
bf.WriteUint32(uint32(gametime.TimeWeekNext().Unix())) // End
|
||||
bf.WriteInt32(s.server.erupeConfig.EarthStatus)
|
||||
bf.WriteInt32(s.server.erupeConfig.EarthID)
|
||||
for i, m := range s.server.erupeConfig.EarthMonsters {
|
||||
if _config.ErupeConfig.ClientID <= _config.G9 {
|
||||
bf.WriteInt32(config.GetConfig().EarthStatus)
|
||||
bf.WriteInt32(config.GetConfig().EarthID)
|
||||
for i, m := range config.GetConfig().EarthMonsters {
|
||||
if config.GetConfig().ClientID <= config.G9 {
|
||||
if i == 3 {
|
||||
break
|
||||
}
|
||||
@@ -1085,7 +1139,7 @@ func handleMsgMhfGetEarthStatus(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
bf.WriteInt32(m)
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfRegistSpabiTime(s *Session, p mhfpacket.MHFPacket) {}
|
||||
@@ -1124,7 +1178,7 @@ func handleMsgMhfGetEarthValue(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
data = append(data, bf)
|
||||
}
|
||||
doAckEarthSucceed(s, pkt.AckHandle, data)
|
||||
DoAckEarthSucceed(s, pkt.AckHandle, data)
|
||||
}
|
||||
|
||||
func handleMsgMhfDebugPostValue(s *Session, p mhfpacket.MHFPacket) {}
|
||||
@@ -1135,7 +1189,7 @@ func handleMsgMhfGetRandFromTable(s *Session, p mhfpacket.MHFPacket) {
|
||||
for i := uint16(0); i < pkt.Results; i++ {
|
||||
bf.WriteUint32(0)
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfGetSenyuDailyCount(s *Session, p mhfpacket.MHFPacket) {
|
||||
@@ -1143,7 +1197,7 @@ func handleMsgMhfGetSenyuDailyCount(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint16(0)
|
||||
bf.WriteUint16(0)
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
type SeibattleTimetable struct {
|
||||
@@ -1281,12 +1335,12 @@ func handleMsgMhfGetSeibattle(s *Session, p mhfpacket.MHFPacket) {
|
||||
data = append(data, bf)
|
||||
}
|
||||
}
|
||||
doAckEarthSucceed(s, pkt.AckHandle, data)
|
||||
DoAckEarthSucceed(s, pkt.AckHandle, data)
|
||||
}
|
||||
|
||||
func handleMsgMhfPostSeibattle(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfPostSeibattle)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func handleMsgMhfGetDailyMissionMaster(s *Session, p mhfpacket.MHFPacket) {}
|
||||
@@ -1297,10 +1351,10 @@ func handleMsgMhfSetDailyMissionPersonal(s *Session, p mhfpacket.MHFPacket) {}
|
||||
|
||||
func equipSkinHistSize() int {
|
||||
size := 3200
|
||||
if _config.ErupeConfig.ClientID <= _config.Z2 {
|
||||
if config.GetConfig().ClientID <= config.Z2 {
|
||||
size = 2560
|
||||
}
|
||||
if _config.ErupeConfig.ClientID <= _config.Z1 {
|
||||
if config.GetConfig().ClientID <= config.Z1 {
|
||||
size = 1280
|
||||
}
|
||||
return size
|
||||
@@ -1310,22 +1364,30 @@ func handleMsgMhfGetEquipSkinHist(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetEquipSkinHist)
|
||||
size := equipSkinHistSize()
|
||||
var data []byte
|
||||
err := s.server.db.QueryRow("SELECT COALESCE(skin_hist::bytea, $2::bytea) FROM characters WHERE id = $1", s.charID, make([]byte, size)).Scan(&data)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to load skin_hist", zap.Error(err))
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
err = database.QueryRow("SELECT COALESCE(skin_hist::bytea, $2::bytea) FROM characters WHERE id = $1", s.CharID, make([]byte, size)).Scan(&data)
|
||||
if err != nil {
|
||||
s.Logger.Error("Failed to load skin_hist", zap.Error(err))
|
||||
data = make([]byte, size)
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, data)
|
||||
DoAckBufSucceed(s, pkt.AckHandle, data)
|
||||
}
|
||||
|
||||
func handleMsgMhfUpdateEquipSkinHist(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfUpdateEquipSkinHist)
|
||||
size := equipSkinHistSize()
|
||||
var data []byte
|
||||
err := s.server.db.QueryRow("SELECT COALESCE(skin_hist, $2) FROM characters WHERE id = $1", s.charID, make([]byte, size)).Scan(&data)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get skin_hist", zap.Error(err))
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
err = database.QueryRow("SELECT COALESCE(skin_hist, $2) FROM characters WHERE id = $1", s.CharID, make([]byte, size)).Scan(&data)
|
||||
if err != nil {
|
||||
s.Logger.Error("Failed to get skin_hist", zap.Error(err))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1336,15 +1398,15 @@ func handleMsgMhfUpdateEquipSkinHist(s *Session, p mhfpacket.MHFPacket) {
|
||||
bitInByte := bit % 8
|
||||
data[startByte+byteInd] |= bits.Reverse8(1 << uint(bitInByte))
|
||||
dumpSaveData(s, data, "skinhist")
|
||||
s.server.db.Exec("UPDATE characters SET skin_hist=$1 WHERE id=$2", data, s.charID)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
database.Exec("UPDATE characters SET skin_hist=$1 WHERE id=$2", data, s.CharID)
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func handleMsgMhfGetUdShopCoin(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetUdShopCoin)
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint32(0)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfUseUdShopCoin(s *Session, p mhfpacket.MHFPacket) {}
|
||||
@@ -1353,22 +1415,30 @@ func handleMsgMhfGetEnhancedMinidata(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetEnhancedMinidata)
|
||||
// this looks to be the detailed chunk of information you can pull up on players in town
|
||||
var data []byte
|
||||
err := s.server.db.QueryRow("SELECT minidata FROM characters WHERE id = $1", pkt.CharID).Scan(&data)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to load minidata")
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
err = database.QueryRow("SELECT minidata FROM characters WHERE id = $1", pkt.CharID).Scan(&data)
|
||||
if err != nil {
|
||||
s.Logger.Error("Failed to load minidata")
|
||||
data = make([]byte, 1)
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, data)
|
||||
DoAckBufSucceed(s, pkt.AckHandle, data)
|
||||
}
|
||||
|
||||
func handleMsgMhfSetEnhancedMinidata(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfSetEnhancedMinidata)
|
||||
dumpSaveData(s, pkt.RawDataPayload, "minidata")
|
||||
_, err := s.server.db.Exec("UPDATE characters SET minidata=$1 WHERE id=$2", pkt.RawDataPayload, s.charID)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to save minidata", zap.Error(err))
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
_, err = database.Exec("UPDATE characters SET minidata=$1 WHERE id=$2", pkt.RawDataPayload, s.CharID)
|
||||
if err != nil {
|
||||
s.Logger.Error("Failed to save minidata", zap.Error(err))
|
||||
}
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
}
|
||||
|
||||
func handleMsgMhfGetLobbyCrowd(s *Session, p mhfpacket.MHFPacket) {
|
||||
@@ -1378,7 +1448,7 @@ func handleMsgMhfGetLobbyCrowd(s *Session, p mhfpacket.MHFPacket) {
|
||||
// It can be worried about later if we ever get to the point where there are
|
||||
// full servers to actually need to migrate people from and empty ones to
|
||||
pkt := p.(*mhfpacket.MsgMhfGetLobbyCrowd)
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 0x320))
|
||||
DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 0x320))
|
||||
}
|
||||
|
||||
type TrendWeapon struct {
|
||||
@@ -1389,8 +1459,12 @@ type TrendWeapon struct {
|
||||
func handleMsgMhfGetTrendWeapon(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetTrendWeapon)
|
||||
trendWeapons := [14][3]TrendWeapon{}
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
for i := uint8(0); i < 14; i++ {
|
||||
rows, err := s.server.db.Query(`SELECT weapon_id FROM trend_weapons WHERE weapon_type=$1 ORDER BY count DESC LIMIT 3`, i)
|
||||
rows, err := database.Query(`SELECT weapon_id FROM trend_weapons WHERE weapon_type=$1 ORDER BY count DESC LIMIT 3`, i)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
@@ -1414,12 +1488,16 @@ func handleMsgMhfGetTrendWeapon(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
bf.Seek(0, 0)
|
||||
bf.WriteUint8(x)
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfUpdateUseTrendWeaponLog(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfUpdateUseTrendWeaponLog)
|
||||
s.server.db.Exec(`INSERT INTO trend_weapons (weapon_id, weapon_type, count) VALUES ($1, $2, 1) ON CONFLICT (weapon_id) DO
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
database.Exec(`INSERT INTO trend_weapons (weapon_id, weapon_type, count) VALUES ($1, $2, 1) ON CONFLICT (weapon_id) DO
|
||||
UPDATE SET count = trend_weapons.count+1`, pkt.WeaponID, pkt.WeaponType)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package channelserver
|
||||
import (
|
||||
"erupe-ce/network/mhfpacket"
|
||||
"erupe-ce/utils/byteframe"
|
||||
"erupe-ce/utils/db"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
@@ -88,19 +89,23 @@ func handleMsgMhfGetAchievement(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetAchievement)
|
||||
|
||||
var exists int
|
||||
err := s.server.db.QueryRow("SELECT id FROM achievements WHERE id=$1", pkt.CharID).Scan(&exists)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.server.db.Exec("INSERT INTO achievements (id) VALUES ($1)", pkt.CharID)
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
err = database.QueryRow("SELECT id FROM achievements WHERE id=$1", pkt.CharID).Scan(&exists)
|
||||
if err != nil {
|
||||
database.Exec("INSERT INTO achievements (id) VALUES ($1)", pkt.CharID)
|
||||
}
|
||||
|
||||
var scores [33]int32
|
||||
err = s.server.db.QueryRow("SELECT * FROM achievements WHERE id=$1", pkt.CharID).Scan(&scores[0],
|
||||
err = database.QueryRow("SELECT * FROM achievements WHERE id=$1", pkt.CharID).Scan(&scores[0],
|
||||
&scores[0], &scores[1], &scores[2], &scores[3], &scores[4], &scores[5], &scores[6], &scores[7], &scores[8],
|
||||
&scores[9], &scores[10], &scores[11], &scores[12], &scores[13], &scores[14], &scores[15], &scores[16],
|
||||
&scores[17], &scores[18], &scores[19], &scores[20], &scores[21], &scores[22], &scores[23], &scores[24],
|
||||
&scores[25], &scores[26], &scores[27], &scores[28], &scores[29], &scores[30], &scores[31], &scores[32])
|
||||
if err != nil {
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 20))
|
||||
DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 20))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -136,26 +141,29 @@ func handleMsgMhfGetAchievement(s *Session, p mhfpacket.MHFPacket) {
|
||||
resp.WriteUint32(points)
|
||||
resp.WriteUint32(points)
|
||||
resp.WriteUint32(points)
|
||||
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfSetCaAchievementHist(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfSetCaAchievementHist)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
}
|
||||
|
||||
func handleMsgMhfResetAchievement(s *Session, p mhfpacket.MHFPacket) {}
|
||||
|
||||
func handleMsgMhfAddAchievement(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfAddAchievement)
|
||||
|
||||
var exists int
|
||||
err := s.server.db.QueryRow("SELECT id FROM achievements WHERE id=$1", s.charID).Scan(&exists)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.server.db.Exec("INSERT INTO achievements (id) VALUES ($1)", s.charID)
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
var exists int
|
||||
err = database.QueryRow("SELECT id FROM achievements WHERE id=$1", s.CharID).Scan(&exists)
|
||||
if err != nil {
|
||||
database.Exec("INSERT INTO achievements (id) VALUES ($1)", s.CharID)
|
||||
}
|
||||
|
||||
s.server.db.Exec(fmt.Sprintf("UPDATE achievements SET ach%d=ach%d+1 WHERE id=$1", pkt.AchievementID, pkt.AchievementID), s.charID)
|
||||
database.Exec(fmt.Sprintf("UPDATE achievements SET ach%d=ach%d+1 WHERE id=$1", pkt.AchievementID, pkt.AchievementID), s.CharID)
|
||||
}
|
||||
|
||||
func handleMsgMhfPaymentAchievement(s *Session, p mhfpacket.MHFPacket) {}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package channelserver
|
||||
|
||||
import (
|
||||
"erupe-ce/config"
|
||||
"erupe-ce/network/mhfpacket"
|
||||
"erupe-ce/utils/byteframe"
|
||||
"erupe-ce/utils/stringsupport"
|
||||
@@ -18,7 +19,7 @@ func handleMsgMhfGetBbsUserStatus(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint32(0)
|
||||
bf.WriteUint32(0)
|
||||
bf.WriteUint32(0)
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
// Checks the status of Bultin Board Server to see if authenticated
|
||||
@@ -29,7 +30,7 @@ func handleMsgMhfGetBbsSnsStatus(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint32(401) //unk http status?
|
||||
bf.WriteUint32(401) //unk http status?
|
||||
bf.WriteUint32(0)
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
// Tells the game client what host port and gives the bultin board article a token
|
||||
@@ -39,15 +40,15 @@ func handleMsgMhfApplyBbsArticle(s *Session, p mhfpacket.MHFPacket) {
|
||||
articleToken := token.Generate(40)
|
||||
|
||||
bf.WriteUint32(200) //http status //200 success //4XX An error occured server side
|
||||
bf.WriteUint32(s.server.erupeConfig.Screenshots.Port)
|
||||
bf.WriteUint32(config.GetConfig().Screenshots.Port)
|
||||
bf.WriteUint32(0)
|
||||
bf.WriteUint32(0)
|
||||
bf.WriteBytes(stringsupport.PaddedString(articleToken, 64, false))
|
||||
bf.WriteBytes(stringsupport.PaddedString(s.server.erupeConfig.Screenshots.Host, 64, false))
|
||||
bf.WriteBytes(stringsupport.PaddedString(config.GetConfig().Screenshots.Host, 64, false))
|
||||
//pkt.unk1[3] == Changes sometimes?
|
||||
if s.server.erupeConfig.Screenshots.Enabled && s.server.erupeConfig.Discord.Enabled {
|
||||
s.server.DiscordScreenShotSend(pkt.Name, pkt.Title, pkt.Description, articleToken)
|
||||
if config.GetConfig().Screenshots.Enabled && config.GetConfig().Discord.Enabled {
|
||||
s.Server.DiscordScreenShotSend(pkt.Name, pkt.Title, pkt.Description, articleToken)
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
|
||||
}
|
||||
|
||||
@@ -2,10 +2,11 @@ package channelserver
|
||||
|
||||
import (
|
||||
"erupe-ce/utils/byteframe"
|
||||
"erupe-ce/utils/db"
|
||||
"erupe-ce/utils/gametime"
|
||||
"erupe-ce/utils/mhfcourse"
|
||||
|
||||
_config "erupe-ce/config"
|
||||
"erupe-ce/config"
|
||||
"erupe-ce/network/mhfpacket"
|
||||
ps "erupe-ce/utils/pascalstring"
|
||||
"fmt"
|
||||
@@ -18,25 +19,33 @@ import (
|
||||
func handleMsgMhfAcquireCafeItem(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfAcquireCafeItem)
|
||||
var netcafePoints uint32
|
||||
err := s.server.db.QueryRow("UPDATE characters SET netcafe_points = netcafe_points - $1 WHERE id = $2 RETURNING netcafe_points", pkt.PointCost, s.charID).Scan(&netcafePoints)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get netcafe points from db", zap.Error(err))
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
err = database.QueryRow("UPDATE characters SET netcafe_points = netcafe_points - $1 WHERE id = $2 RETURNING netcafe_points", pkt.PointCost, s.CharID).Scan(&netcafePoints)
|
||||
if err != nil {
|
||||
s.Logger.Error("Failed to get netcafe points from db", zap.Error(err))
|
||||
}
|
||||
resp := byteframe.NewByteFrame()
|
||||
resp.WriteUint32(netcafePoints)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, resp.Data())
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, resp.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfUpdateCafepoint(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfUpdateCafepoint)
|
||||
var netcafePoints uint32
|
||||
err := s.server.db.QueryRow("SELECT COALESCE(netcafe_points, 0) FROM characters WHERE id = $1", s.charID).Scan(&netcafePoints)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get netcate points from db", zap.Error(err))
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
err = database.QueryRow("SELECT COALESCE(netcafe_points, 0) FROM characters WHERE id = $1", s.CharID).Scan(&netcafePoints)
|
||||
if err != nil {
|
||||
s.Logger.Error("Failed to get netcate points from db", zap.Error(err))
|
||||
}
|
||||
resp := byteframe.NewByteFrame()
|
||||
resp.WriteUint32(netcafePoints)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, resp.Data())
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, resp.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfCheckDailyCafepoint(s *Session, p mhfpacket.MHFPacket) {
|
||||
@@ -49,9 +58,13 @@ func handleMsgMhfCheckDailyCafepoint(s *Session, p mhfpacket.MHFPacket) {
|
||||
|
||||
// get time after which daily claiming would be valid from db
|
||||
var dailyTime time.Time
|
||||
err := s.server.db.QueryRow("SELECT COALESCE(daily_time, $2) FROM characters WHERE id = $1", s.charID, time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)).Scan(&dailyTime)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get daily_time savedata from db", zap.Error(err))
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
err = database.QueryRow("SELECT COALESCE(daily_time, $2) FROM characters WHERE id = $1", s.CharID, time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)).Scan(&dailyTime)
|
||||
if err != nil {
|
||||
s.Logger.Error("Failed to get daily_time savedata from db", zap.Error(err))
|
||||
}
|
||||
|
||||
var bondBonus, bonusQuests, dailyQuests uint32
|
||||
@@ -59,9 +72,9 @@ func handleMsgMhfCheckDailyCafepoint(s *Session, p mhfpacket.MHFPacket) {
|
||||
if midday.After(dailyTime) {
|
||||
addPointNetcafe(s, 5)
|
||||
bondBonus = 5 // Bond point bonus quests
|
||||
bonusQuests = s.server.erupeConfig.GameplayOptions.BonusQuestAllowance
|
||||
dailyQuests = s.server.erupeConfig.GameplayOptions.DailyQuestAllowance
|
||||
s.server.db.Exec("UPDATE characters SET daily_time=$1, bonus_quests = $2, daily_quests = $3 WHERE id=$4", midday, bonusQuests, dailyQuests, s.charID)
|
||||
bonusQuests = config.GetConfig().GameplayOptions.BonusQuestAllowance
|
||||
dailyQuests = config.GetConfig().GameplayOptions.DailyQuestAllowance
|
||||
database.Exec("UPDATE characters SET daily_time=$1, bonus_quests = $2, daily_quests = $3 WHERE id=$4", midday, bonusQuests, dailyQuests, s.CharID)
|
||||
bf.WriteBool(true) // Success?
|
||||
} else {
|
||||
bf.WriteBool(false)
|
||||
@@ -69,27 +82,30 @@ func handleMsgMhfCheckDailyCafepoint(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint32(bondBonus)
|
||||
bf.WriteUint32(bonusQuests)
|
||||
bf.WriteUint32(dailyQuests)
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfGetCafeDuration(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetCafeDuration)
|
||||
bf := byteframe.NewByteFrame()
|
||||
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
var cafeReset time.Time
|
||||
err := s.server.db.QueryRow(`SELECT cafe_reset FROM characters WHERE id=$1`, s.charID).Scan(&cafeReset)
|
||||
err = database.QueryRow(`SELECT cafe_reset FROM characters WHERE id=$1`, s.CharID).Scan(&cafeReset)
|
||||
if err != nil {
|
||||
cafeReset = gametime.TimeWeekNext()
|
||||
s.server.db.Exec(`UPDATE characters SET cafe_reset=$1 WHERE id=$2`, cafeReset, s.charID)
|
||||
database.Exec(`UPDATE characters SET cafe_reset=$1 WHERE id=$2`, cafeReset, s.CharID)
|
||||
}
|
||||
if gametime.TimeAdjusted().After(cafeReset) {
|
||||
cafeReset = gametime.TimeWeekNext()
|
||||
s.server.db.Exec(`UPDATE characters SET cafe_time=0, cafe_reset=$1 WHERE id=$2`, cafeReset, s.charID)
|
||||
s.server.db.Exec(`DELETE FROM cafe_accepted WHERE character_id=$1`, s.charID)
|
||||
database.Exec(`UPDATE characters SET cafe_time=0, cafe_reset=$1 WHERE id=$2`, cafeReset, s.CharID)
|
||||
database.Exec(`DELETE FROM cafe_accepted WHERE character_id=$1`, s.CharID)
|
||||
}
|
||||
|
||||
var cafeTime uint32
|
||||
err = s.server.db.QueryRow("SELECT cafe_time FROM characters WHERE id = $1", s.charID).Scan(&cafeTime)
|
||||
err = database.QueryRow("SELECT cafe_time FROM characters WHERE id = $1", s.CharID).Scan(&cafeTime)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -97,11 +113,11 @@ func handleMsgMhfGetCafeDuration(s *Session, p mhfpacket.MHFPacket) {
|
||||
cafeTime = uint32(gametime.TimeAdjusted().Unix()) - uint32(s.sessionStart) + cafeTime
|
||||
}
|
||||
bf.WriteUint32(cafeTime)
|
||||
if _config.ErupeConfig.ClientID >= _config.ZZ {
|
||||
if config.GetConfig().ClientID >= config.ZZ {
|
||||
bf.WriteUint16(0)
|
||||
ps.Uint16(bf, fmt.Sprintf(s.server.i18n.cafe.reset, int(cafeReset.Month()), cafeReset.Day()), true)
|
||||
ps.Uint16(bf, fmt.Sprintf(s.Server.i18n.cafe.reset, int(cafeReset.Month()), cafeReset.Day()), true)
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
type CafeBonus struct {
|
||||
@@ -116,26 +132,29 @@ type CafeBonus struct {
|
||||
func handleMsgMhfGetCafeDurationBonusInfo(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetCafeDurationBonusInfo)
|
||||
bf := byteframe.NewByteFrame()
|
||||
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
var count uint32
|
||||
rows, err := s.server.db.Queryx(`
|
||||
rows, err := database.Queryx(`
|
||||
SELECT cb.id, time_req, item_type, item_id, quantity,
|
||||
(
|
||||
SELECT count(*)
|
||||
FROM cafe_accepted ca
|
||||
WHERE cb.id = ca.cafe_id AND ca.character_id = $1
|
||||
)::int::bool AS claimed
|
||||
FROM cafebonus cb ORDER BY id ASC;`, s.charID)
|
||||
FROM cafebonus cb ORDER BY id ASC;`, s.CharID)
|
||||
if err != nil {
|
||||
s.logger.Error("Error getting cafebonus", zap.Error(err))
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
s.Logger.Error("Error getting cafebonus", zap.Error(err))
|
||||
DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
} else {
|
||||
for rows.Next() {
|
||||
count++
|
||||
cafeBonus := &CafeBonus{}
|
||||
err = rows.StructScan(&cafeBonus)
|
||||
if err != nil {
|
||||
s.logger.Error("Error scanning cafebonus", zap.Error(err))
|
||||
s.Logger.Error("Error scanning cafebonus", zap.Error(err))
|
||||
}
|
||||
bf.WriteUint32(cafeBonus.TimeReq)
|
||||
bf.WriteUint32(cafeBonus.ItemType)
|
||||
@@ -148,7 +167,7 @@ func handleMsgMhfGetCafeDurationBonusInfo(s *Session, p mhfpacket.MHFPacket) {
|
||||
resp.WriteUint32(uint32(gametime.TimeAdjusted().Unix()))
|
||||
resp.WriteUint32(count)
|
||||
resp.WriteBytes(bf.Data())
|
||||
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,7 +176,11 @@ func handleMsgMhfReceiveCafeDurationBonus(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf := byteframe.NewByteFrame()
|
||||
var count uint32
|
||||
bf.WriteUint32(0)
|
||||
rows, err := s.server.db.Queryx(`
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
rows, err := database.Queryx(`
|
||||
SELECT c.id, time_req, item_type, item_id, quantity
|
||||
FROM cafebonus c
|
||||
WHERE (
|
||||
@@ -168,9 +191,9 @@ func handleMsgMhfReceiveCafeDurationBonus(s *Session, p mhfpacket.MHFPacket) {
|
||||
SELECT ch.cafe_time + $2
|
||||
FROM characters ch
|
||||
WHERE ch.id = $1
|
||||
) >= time_req`, s.charID, gametime.TimeAdjusted().Unix()-s.sessionStart)
|
||||
) >= time_req`, s.CharID, gametime.TimeAdjusted().Unix()-s.sessionStart)
|
||||
if err != nil {
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
} else {
|
||||
for rows.Next() {
|
||||
cafeBonus := &CafeBonus{}
|
||||
@@ -186,15 +209,19 @@ func handleMsgMhfReceiveCafeDurationBonus(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
bf.Seek(0, io.SeekStart)
|
||||
bf.WriteUint32(count)
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
}
|
||||
|
||||
func handleMsgMhfPostCafeDurationBonusReceived(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfPostCafeDurationBonusReceived)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
var cafeBonus CafeBonus
|
||||
for _, cbID := range pkt.CafeBonusID {
|
||||
err := s.server.db.QueryRow(`
|
||||
err := database.QueryRow(`
|
||||
SELECT cb.id, item_type, quantity FROM cafebonus cb WHERE cb.id=$1
|
||||
`, cbID).Scan(&cafeBonus.ID, &cafeBonus.ItemType, &cafeBonus.Quantity)
|
||||
if err == nil {
|
||||
@@ -202,85 +229,101 @@ func handleMsgMhfPostCafeDurationBonusReceived(s *Session, p mhfpacket.MHFPacket
|
||||
addPointNetcafe(s, int(cafeBonus.Quantity))
|
||||
}
|
||||
}
|
||||
s.server.db.Exec("INSERT INTO public.cafe_accepted VALUES ($1, $2)", cbID, s.charID)
|
||||
database.Exec("INSERT INTO public.cafe_accepted VALUES ($1, $2)", cbID, s.CharID)
|
||||
}
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func addPointNetcafe(s *Session, p int) error {
|
||||
var points int
|
||||
err := s.server.db.QueryRow("SELECT netcafe_points FROM characters WHERE id = $1", s.charID).Scan(&points)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
err = database.QueryRow("SELECT netcafe_points FROM characters WHERE id = $1", s.CharID).Scan(&points)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if points+p > s.server.erupeConfig.GameplayOptions.MaximumNP {
|
||||
points = s.server.erupeConfig.GameplayOptions.MaximumNP
|
||||
if points+p > config.GetConfig().GameplayOptions.MaximumNP {
|
||||
points = config.GetConfig().GameplayOptions.MaximumNP
|
||||
} else {
|
||||
points += p
|
||||
}
|
||||
s.server.db.Exec("UPDATE characters SET netcafe_points=$1 WHERE id=$2", points, s.charID)
|
||||
database.Exec("UPDATE characters SET netcafe_points=$1 WHERE id=$2", points, s.CharID)
|
||||
return nil
|
||||
}
|
||||
|
||||
func handleMsgMhfStartBoostTime(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfStartBoostTime)
|
||||
bf := byteframe.NewByteFrame()
|
||||
boostLimit := gametime.TimeAdjusted().Add(time.Duration(s.server.erupeConfig.GameplayOptions.BoostTimeDuration) * time.Second)
|
||||
if s.server.erupeConfig.GameplayOptions.DisableBoostTime {
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
boostLimit := gametime.TimeAdjusted().Add(time.Duration(config.GetConfig().GameplayOptions.BoostTimeDuration) * time.Second)
|
||||
if config.GetConfig().GameplayOptions.DisableBoostTime {
|
||||
bf.WriteUint32(0)
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
return
|
||||
}
|
||||
s.server.db.Exec("UPDATE characters SET boost_time=$1 WHERE id=$2", boostLimit, s.charID)
|
||||
database.Exec("UPDATE characters SET boost_time=$1 WHERE id=$2", boostLimit, s.CharID)
|
||||
bf.WriteUint32(uint32(boostLimit.Unix()))
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfGetBoostTime(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetBoostTime)
|
||||
doAckBufSucceed(s, pkt.AckHandle, []byte{})
|
||||
DoAckBufSucceed(s, pkt.AckHandle, []byte{})
|
||||
}
|
||||
|
||||
func handleMsgMhfGetBoostTimeLimit(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetBoostTimeLimit)
|
||||
bf := byteframe.NewByteFrame()
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
var boostLimit time.Time
|
||||
err := s.server.db.QueryRow("SELECT boost_time FROM characters WHERE id=$1", s.charID).Scan(&boostLimit)
|
||||
err = database.QueryRow("SELECT boost_time FROM characters WHERE id=$1", s.CharID).Scan(&boostLimit)
|
||||
if err != nil {
|
||||
bf.WriteUint32(0)
|
||||
} else {
|
||||
bf.WriteUint32(uint32(boostLimit.Unix()))
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func handleMsgMhfGetBoostRight(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetBoostRight)
|
||||
var boostLimit time.Time
|
||||
err := s.server.db.QueryRow("SELECT boost_time FROM characters WHERE id=$1", s.charID).Scan(&boostLimit)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
err = database.QueryRow("SELECT boost_time FROM characters WHERE id=$1", s.CharID).Scan(&boostLimit)
|
||||
if err != nil {
|
||||
DoAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
return
|
||||
}
|
||||
if boostLimit.After(gametime.TimeAdjusted()) {
|
||||
doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x01})
|
||||
DoAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x01})
|
||||
} else {
|
||||
doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x02})
|
||||
DoAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x02})
|
||||
}
|
||||
}
|
||||
|
||||
func handleMsgMhfPostBoostTimeQuestReturn(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfPostBoostTimeQuestReturn)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
}
|
||||
|
||||
func handleMsgMhfPostBoostTime(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfPostBoostTime)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func handleMsgMhfPostBoostTimeLimit(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfPostBoostTimeLimit)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package channelserver
|
||||
|
||||
import (
|
||||
_config "erupe-ce/config"
|
||||
"erupe-ce/config"
|
||||
"erupe-ce/network/mhfpacket"
|
||||
"erupe-ce/utils/byteframe"
|
||||
ps "erupe-ce/utils/pascalstring"
|
||||
@@ -68,7 +68,7 @@ func handleMsgMhfEnumerateCampaign(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteInt16(event.MaxHR)
|
||||
bf.WriteInt16(event.MinSR)
|
||||
bf.WriteInt16(event.MaxSR)
|
||||
if _config.ErupeConfig.ClientID >= _config.G3 {
|
||||
if config.GetConfig().ClientID >= config.G3 {
|
||||
bf.WriteInt16(event.MinGR)
|
||||
bf.WriteInt16(event.MaxGR)
|
||||
}
|
||||
@@ -129,7 +129,7 @@ func handleMsgMhfEnumerateCampaign(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint16(link.CategoryID)
|
||||
bf.WriteUint32(link.CampaignID)
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfStateCampaign(s *Session, p mhfpacket.MHFPacket) {
|
||||
@@ -137,14 +137,14 @@ func handleMsgMhfStateCampaign(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint16(1)
|
||||
bf.WriteUint16(0)
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfApplyCampaign(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfApplyCampaign)
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint32(1)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfEnumerateItem(s *Session, p mhfpacket.MHFPacket) {
|
||||
@@ -167,10 +167,10 @@ func handleMsgMhfEnumerateItem(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint32(item.Unk4)
|
||||
bf.WriteUint32(item.Unk5)
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfAcquireItem(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfAcquireItem)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ func handleMsgMhfGetRyoudama(s *Session, p mhfpacket.MHFPacket) {
|
||||
data = append(data, bf)
|
||||
}
|
||||
}
|
||||
doAckEarthSucceed(s, pkt.AckHandle, data)
|
||||
DoAckEarthSucceed(s, pkt.AckHandle, data)
|
||||
}
|
||||
|
||||
func handleMsgMhfPostRyoudama(s *Session, p mhfpacket.MHFPacket) {}
|
||||
@@ -75,12 +75,12 @@ func handleMsgMhfPostRyoudama(s *Session, p mhfpacket.MHFPacket) {}
|
||||
func handleMsgMhfGetTinyBin(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetTinyBin)
|
||||
// requested after conquest quests
|
||||
doAckBufSucceed(s, pkt.AckHandle, []byte{})
|
||||
DoAckBufSucceed(s, pkt.AckHandle, []byte{})
|
||||
}
|
||||
|
||||
func handleMsgMhfPostTinyBin(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfPostTinyBin)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func handleMsgMhfCaravanMyScore(s *Session, p mhfpacket.MHFPacket) {
|
||||
@@ -92,7 +92,7 @@ func handleMsgMhfCaravanMyScore(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteInt32(0)
|
||||
bf.WriteInt32(0)
|
||||
*/
|
||||
doAckEarthSucceed(s, pkt.AckHandle, data)
|
||||
DoAckEarthSucceed(s, pkt.AckHandle, data)
|
||||
}
|
||||
|
||||
func handleMsgMhfCaravanRanking(s *Session, p mhfpacket.MHFPacket) {
|
||||
@@ -108,7 +108,7 @@ func handleMsgMhfCaravanRanking(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteInt32(1)
|
||||
bf.WriteBytes(stringsupport.PaddedString("Test", 14, true))
|
||||
*/
|
||||
doAckEarthSucceed(s, pkt.AckHandle, data)
|
||||
DoAckEarthSucceed(s, pkt.AckHandle, data)
|
||||
}
|
||||
|
||||
func handleMsgMhfCaravanMyRank(s *Session, p mhfpacket.MHFPacket) {
|
||||
@@ -119,5 +119,5 @@ func handleMsgMhfCaravanMyRank(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteInt32(0)
|
||||
bf.WriteInt32(0)
|
||||
*/
|
||||
doAckEarthSucceed(s, pkt.AckHandle, data)
|
||||
DoAckEarthSucceed(s, pkt.AckHandle, data)
|
||||
}
|
||||
|
||||
@@ -3,10 +3,11 @@ package channelserver
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
_config "erupe-ce/config"
|
||||
"erupe-ce/config"
|
||||
"erupe-ce/network/binpacket"
|
||||
"erupe-ce/network/mhfpacket"
|
||||
"erupe-ce/utils/byteframe"
|
||||
"erupe-ce/utils/db"
|
||||
"erupe-ce/utils/logger"
|
||||
"erupe-ce/utils/mhfcid"
|
||||
"erupe-ce/utils/mhfcourse"
|
||||
@@ -43,17 +44,17 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
commands map[string]_config.Command
|
||||
commands map[string]config.Command
|
||||
once sync.Once // Ensures that initialization happens only once
|
||||
commandsMu sync.Mutex // Mutex to ensure thread safety for commands map
|
||||
)
|
||||
|
||||
func (server *Server) initCommands() {
|
||||
func (server *ChannelServer) initCommands() {
|
||||
once.Do(func() {
|
||||
commands = make(map[string]_config.Command)
|
||||
commands = make(map[string]config.Command)
|
||||
|
||||
commandLogger := logger.Get().Named("command")
|
||||
cmds := _config.ErupeConfig.Commands
|
||||
cmds := config.GetConfig().Commands
|
||||
for _, cmd := range cmds {
|
||||
commands[cmd.Name] = cmd
|
||||
if cmd.Enabled {
|
||||
@@ -65,8 +66,8 @@ func (server *Server) initCommands() {
|
||||
})
|
||||
}
|
||||
|
||||
func sendDisabledCommandMessage(s *Session, cmd _config.Command) {
|
||||
sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.commands.disabled, cmd.Name))
|
||||
func sendDisabledCommandMessage(s *Session, cmd config.Command) {
|
||||
sendServerChatMessage(s, fmt.Sprintf(s.Server.i18n.commands.disabled, cmd.Name))
|
||||
}
|
||||
|
||||
func sendServerChatMessage(s *Session, message string) {
|
||||
@@ -92,7 +93,11 @@ func sendServerChatMessage(s *Session, message string) {
|
||||
}
|
||||
|
||||
func parseChatCommand(s *Session, command string) {
|
||||
args := strings.Split(command[len(s.server.erupeConfig.CommandPrefix):], " ")
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
args := strings.Split(command[len(config.GetConfig().CommandPrefix):], " ")
|
||||
switch args[0] {
|
||||
case commands["Ban"].Prefix:
|
||||
if s.isOp() {
|
||||
@@ -118,7 +123,7 @@ func parseChatCommand(s *Session, command string) {
|
||||
expiry = time.Now().Add(time.Duration(length) * time.Hour * 24 * 365)
|
||||
}
|
||||
} else {
|
||||
sendServerChatMessage(s, s.server.i18n.commands.ban.error)
|
||||
sendServerChatMessage(s, s.Server.i18n.commands.ban.error)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -126,39 +131,39 @@ func parseChatCommand(s *Session, command string) {
|
||||
if cid > 0 {
|
||||
var uid uint32
|
||||
var uname string
|
||||
err := s.server.db.QueryRow(`SELECT id, username FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)`, cid).Scan(&uid, &uname)
|
||||
err := database.QueryRow(`SELECT id, username FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)`, cid).Scan(&uid, &uname)
|
||||
if err == nil {
|
||||
if expiry.IsZero() {
|
||||
s.server.db.Exec(`INSERT INTO bans VALUES ($1)
|
||||
database.Exec(`INSERT INTO bans VALUES ($1)
|
||||
ON CONFLICT (user_id) DO UPDATE SET expires=NULL`, uid)
|
||||
sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.commands.ban.success, uname))
|
||||
sendServerChatMessage(s, fmt.Sprintf(s.Server.i18n.commands.ban.success, uname))
|
||||
} else {
|
||||
s.server.db.Exec(`INSERT INTO bans VALUES ($1, $2)
|
||||
database.Exec(`INSERT INTO bans VALUES ($1, $2)
|
||||
ON CONFLICT (user_id) DO UPDATE SET expires=$2`, uid, expiry)
|
||||
sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.commands.ban.success, uname)+fmt.Sprintf(s.server.i18n.commands.ban.length, expiry.Format(time.DateTime)))
|
||||
sendServerChatMessage(s, fmt.Sprintf(s.Server.i18n.commands.ban.success, uname)+fmt.Sprintf(s.Server.i18n.commands.ban.length, expiry.Format(time.DateTime)))
|
||||
}
|
||||
s.server.DisconnectUser(uid)
|
||||
s.Server.DisconnectUser(uid)
|
||||
} else {
|
||||
sendServerChatMessage(s, s.server.i18n.commands.ban.noUser)
|
||||
sendServerChatMessage(s, s.Server.i18n.commands.ban.noUser)
|
||||
}
|
||||
} else {
|
||||
sendServerChatMessage(s, s.server.i18n.commands.ban.invalid)
|
||||
sendServerChatMessage(s, s.Server.i18n.commands.ban.invalid)
|
||||
}
|
||||
} else {
|
||||
sendServerChatMessage(s, s.server.i18n.commands.ban.error)
|
||||
sendServerChatMessage(s, s.Server.i18n.commands.ban.error)
|
||||
}
|
||||
} else {
|
||||
sendServerChatMessage(s, s.server.i18n.commands.noOp)
|
||||
sendServerChatMessage(s, s.Server.i18n.commands.noOp)
|
||||
}
|
||||
case commands["Timer"].Prefix:
|
||||
if commands["Timer"].Enabled || s.isOp() {
|
||||
var state bool
|
||||
s.server.db.QueryRow(`SELECT COALESCE(timer, false) FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)`, s.charID).Scan(&state)
|
||||
s.server.db.Exec(`UPDATE users u SET timer=$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, !state, s.charID)
|
||||
database.QueryRow(`SELECT COALESCE(timer, false) FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)`, s.CharID).Scan(&state)
|
||||
database.Exec(`UPDATE users u SET timer=$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, !state, s.CharID)
|
||||
if state {
|
||||
sendServerChatMessage(s, s.server.i18n.commands.timer.disabled)
|
||||
sendServerChatMessage(s, s.Server.i18n.commands.timer.disabled)
|
||||
} else {
|
||||
sendServerChatMessage(s, s.server.i18n.commands.timer.enabled)
|
||||
sendServerChatMessage(s, s.Server.i18n.commands.timer.enabled)
|
||||
}
|
||||
} else {
|
||||
sendDisabledCommandMessage(s, commands["Timer"])
|
||||
@@ -167,56 +172,56 @@ func parseChatCommand(s *Session, command string) {
|
||||
if commands["PSN"].Enabled || s.isOp() {
|
||||
if len(args) > 1 {
|
||||
var exists int
|
||||
s.server.db.QueryRow(`SELECT count(*) FROM users WHERE psn_id = $1`, args[1]).Scan(&exists)
|
||||
database.QueryRow(`SELECT count(*) FROM users WHERE psn_id = $1`, args[1]).Scan(&exists)
|
||||
if exists == 0 {
|
||||
_, err := s.server.db.Exec(`UPDATE users u SET psn_id=$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, args[1], s.charID)
|
||||
_, err := database.Exec(`UPDATE users u SET psn_id=$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, args[1], s.CharID)
|
||||
if err == nil {
|
||||
sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.commands.psn.success, args[1]))
|
||||
sendServerChatMessage(s, fmt.Sprintf(s.Server.i18n.commands.psn.success, args[1]))
|
||||
}
|
||||
} else {
|
||||
sendServerChatMessage(s, s.server.i18n.commands.psn.exists)
|
||||
sendServerChatMessage(s, s.Server.i18n.commands.psn.exists)
|
||||
}
|
||||
} else {
|
||||
sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.commands.psn.error, commands["PSN"].Prefix))
|
||||
sendServerChatMessage(s, fmt.Sprintf(s.Server.i18n.commands.psn.error, commands["PSN"].Prefix))
|
||||
}
|
||||
} else {
|
||||
sendDisabledCommandMessage(s, commands["PSN"])
|
||||
}
|
||||
case commands["Reload"].Prefix:
|
||||
if commands["Reload"].Enabled || s.isOp() {
|
||||
sendServerChatMessage(s, s.server.i18n.commands.reload)
|
||||
sendServerChatMessage(s, s.Server.i18n.commands.reload)
|
||||
var temp mhfpacket.MHFPacket
|
||||
for _, object := range s.stage.objects {
|
||||
if object.ownerCharID == s.charID {
|
||||
if object.ownerCharID == s.CharID {
|
||||
continue
|
||||
}
|
||||
temp = &mhfpacket.MsgSysDeleteObject{ObjID: object.id}
|
||||
s.QueueSendMHF(temp)
|
||||
}
|
||||
for _, session := range s.server.sessions {
|
||||
for _, session := range s.Server.sessions {
|
||||
if s == session {
|
||||
continue
|
||||
}
|
||||
temp = &mhfpacket.MsgSysDeleteUser{CharID: session.charID}
|
||||
temp = &mhfpacket.MsgSysDeleteUser{CharID: session.CharID}
|
||||
s.QueueSendMHF(temp)
|
||||
}
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
for _, session := range s.server.sessions {
|
||||
for _, session := range s.Server.sessions {
|
||||
if s == session {
|
||||
continue
|
||||
}
|
||||
temp = &mhfpacket.MsgSysInsertUser{CharID: session.charID}
|
||||
temp = &mhfpacket.MsgSysInsertUser{CharID: session.CharID}
|
||||
s.QueueSendMHF(temp)
|
||||
for i := 0; i < 3; i++ {
|
||||
temp = &mhfpacket.MsgSysNotifyUserBinary{
|
||||
CharID: session.charID,
|
||||
CharID: session.CharID,
|
||||
BinaryType: uint8(i + 1),
|
||||
}
|
||||
s.QueueSendMHF(temp)
|
||||
}
|
||||
}
|
||||
for _, obj := range s.stage.objects {
|
||||
if obj.ownerCharID == s.charID {
|
||||
if obj.ownerCharID == s.CharID {
|
||||
continue
|
||||
}
|
||||
temp = &mhfpacket.MsgSysDuplicateObject{
|
||||
@@ -234,20 +239,20 @@ func parseChatCommand(s *Session, command string) {
|
||||
}
|
||||
case commands["KeyQuest"].Prefix:
|
||||
if commands["KeyQuest"].Enabled || s.isOp() {
|
||||
if s.server.erupeConfig.ClientID < _config.G10 {
|
||||
sendServerChatMessage(s, s.server.i18n.commands.kqf.version)
|
||||
if config.GetConfig().ClientID < config.G10 {
|
||||
sendServerChatMessage(s, s.Server.i18n.commands.kqf.version)
|
||||
} else {
|
||||
if len(args) > 1 {
|
||||
if args[1] == "get" {
|
||||
sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.commands.kqf.get, s.kqf))
|
||||
sendServerChatMessage(s, fmt.Sprintf(s.Server.i18n.commands.kqf.get, s.kqf))
|
||||
} else if args[1] == "set" {
|
||||
if len(args) > 2 && len(args[2]) == 16 {
|
||||
hexd, _ := hex.DecodeString(args[2])
|
||||
s.kqf = hexd
|
||||
s.kqfOverride = true
|
||||
sendServerChatMessage(s, s.server.i18n.commands.kqf.set.success)
|
||||
sendServerChatMessage(s, s.Server.i18n.commands.kqf.set.success)
|
||||
} else {
|
||||
sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.commands.kqf.set.error, commands["KeyQuest"].Prefix))
|
||||
sendServerChatMessage(s, fmt.Sprintf(s.Server.i18n.commands.kqf.set.error, commands["KeyQuest"].Prefix))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -259,14 +264,14 @@ func parseChatCommand(s *Session, command string) {
|
||||
if commands["Rights"].Enabled || s.isOp() {
|
||||
if len(args) > 1 {
|
||||
v, _ := strconv.Atoi(args[1])
|
||||
_, err := s.server.db.Exec("UPDATE users u SET rights=$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)", v, s.charID)
|
||||
_, err := database.Exec("UPDATE users u SET rights=$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)", v, s.CharID)
|
||||
if err == nil {
|
||||
sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.commands.rights.success, v))
|
||||
sendServerChatMessage(s, fmt.Sprintf(s.Server.i18n.commands.rights.success, v))
|
||||
} else {
|
||||
sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.commands.rights.error, commands["Rights"].Prefix))
|
||||
sendServerChatMessage(s, fmt.Sprintf(s.Server.i18n.commands.rights.error, commands["Rights"].Prefix))
|
||||
}
|
||||
} else {
|
||||
sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.commands.rights.error, commands["Rights"].Prefix))
|
||||
sendServerChatMessage(s, fmt.Sprintf(s.Server.i18n.commands.rights.error, commands["Rights"].Prefix))
|
||||
}
|
||||
} else {
|
||||
sendDisabledCommandMessage(s, commands["Rights"])
|
||||
@@ -277,7 +282,7 @@ func parseChatCommand(s *Session, command string) {
|
||||
for _, course := range mhfcourse.Courses() {
|
||||
for _, alias := range course.Aliases() {
|
||||
if strings.ToLower(args[1]) == strings.ToLower(alias) {
|
||||
if slices.Contains(s.server.erupeConfig.Courses, _config.Course{Name: course.Aliases()[0], Enabled: true}) {
|
||||
if slices.Contains(config.GetConfig().Courses, config.Course{Name: course.Aliases()[0], Enabled: true}) {
|
||||
var delta, rightsInt uint32
|
||||
if mhfcourse.CourseExists(course.ID, s.courses) {
|
||||
ei := slices.IndexFunc(s.courses, func(c mhfcourse.Course) bool {
|
||||
@@ -290,26 +295,26 @@ func parseChatCommand(s *Session, command string) {
|
||||
})
|
||||
if ei != -1 {
|
||||
delta = uint32(-1 * math.Pow(2, float64(course.ID)))
|
||||
sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.commands.course.disabled, course.Aliases()[0]))
|
||||
sendServerChatMessage(s, fmt.Sprintf(s.Server.i18n.commands.course.disabled, course.Aliases()[0]))
|
||||
}
|
||||
} else {
|
||||
delta = uint32(math.Pow(2, float64(course.ID)))
|
||||
sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.commands.course.enabled, course.Aliases()[0]))
|
||||
sendServerChatMessage(s, fmt.Sprintf(s.Server.i18n.commands.course.enabled, course.Aliases()[0]))
|
||||
}
|
||||
err := 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)
|
||||
err := database.QueryRow("SELECT rights FROM users u INNER JOIN characters c ON u.id = c.user_id WHERE c.id = $1", s.CharID).Scan(&rightsInt)
|
||||
if err == nil {
|
||||
s.server.db.Exec("UPDATE users u SET rights=$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)", rightsInt+delta, s.charID)
|
||||
database.Exec("UPDATE users u SET rights=$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)", rightsInt+delta, s.CharID)
|
||||
}
|
||||
updateRights(s)
|
||||
} else {
|
||||
sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.commands.course.locked, course.Aliases()[0]))
|
||||
sendServerChatMessage(s, fmt.Sprintf(s.Server.i18n.commands.course.locked, course.Aliases()[0]))
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.commands.course.error, commands["Course"].Prefix))
|
||||
sendServerChatMessage(s, fmt.Sprintf(s.Server.i18n.commands.course.error, commands["Course"].Prefix))
|
||||
}
|
||||
} else {
|
||||
sendDisabledCommandMessage(s, commands["Course"])
|
||||
@@ -317,50 +322,50 @@ func parseChatCommand(s *Session, command string) {
|
||||
case commands["Raviente"].Prefix:
|
||||
if commands["Raviente"].Enabled || s.isOp() {
|
||||
if len(args) > 1 {
|
||||
if s.server.getRaviSemaphore() != nil {
|
||||
if s.Server.getRaviSemaphore() != nil {
|
||||
switch args[1] {
|
||||
case "start":
|
||||
if s.server.raviente.register[1] == 0 {
|
||||
s.server.raviente.register[1] = s.server.raviente.register[3]
|
||||
sendServerChatMessage(s, s.server.i18n.commands.ravi.start.success)
|
||||
if s.Server.raviente.register[1] == 0 {
|
||||
s.Server.raviente.register[1] = s.Server.raviente.register[3]
|
||||
sendServerChatMessage(s, s.Server.i18n.commands.ravi.start.success)
|
||||
s.notifyRavi()
|
||||
} else {
|
||||
sendServerChatMessage(s, s.server.i18n.commands.ravi.start.error)
|
||||
sendServerChatMessage(s, s.Server.i18n.commands.ravi.start.error)
|
||||
}
|
||||
case "cm", "check", "checkmultiplier", "multiplier":
|
||||
sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.commands.ravi.multiplier, s.server.GetRaviMultiplier()))
|
||||
sendServerChatMessage(s, fmt.Sprintf(s.Server.i18n.commands.ravi.multiplier, s.Server.GetRaviMultiplier()))
|
||||
case "sr", "sendres", "resurrection", "ss", "sendsed", "rs", "reqsed":
|
||||
if s.server.erupeConfig.ClientID == _config.ZZ {
|
||||
if config.GetConfig().ClientID == config.ZZ {
|
||||
switch args[1] {
|
||||
case "sr", "sendres", "resurrection":
|
||||
if s.server.raviente.state[28] > 0 {
|
||||
sendServerChatMessage(s, s.server.i18n.commands.ravi.res.success)
|
||||
s.server.raviente.state[28] = 0
|
||||
if s.Server.raviente.state[28] > 0 {
|
||||
sendServerChatMessage(s, s.Server.i18n.commands.ravi.res.success)
|
||||
s.Server.raviente.state[28] = 0
|
||||
} else {
|
||||
sendServerChatMessage(s, s.server.i18n.commands.ravi.res.error)
|
||||
sendServerChatMessage(s, s.Server.i18n.commands.ravi.res.error)
|
||||
}
|
||||
case "ss", "sendsed":
|
||||
sendServerChatMessage(s, s.server.i18n.commands.ravi.sed.success)
|
||||
sendServerChatMessage(s, s.Server.i18n.commands.ravi.sed.success)
|
||||
// Total BerRavi HP
|
||||
HP := s.server.raviente.state[0] + s.server.raviente.state[1] + s.server.raviente.state[2] + s.server.raviente.state[3] + s.server.raviente.state[4]
|
||||
s.server.raviente.support[1] = HP
|
||||
HP := s.Server.raviente.state[0] + s.Server.raviente.state[1] + s.Server.raviente.state[2] + s.Server.raviente.state[3] + s.Server.raviente.state[4]
|
||||
s.Server.raviente.support[1] = HP
|
||||
case "rs", "reqsed":
|
||||
sendServerChatMessage(s, s.server.i18n.commands.ravi.request)
|
||||
sendServerChatMessage(s, s.Server.i18n.commands.ravi.request)
|
||||
// Total BerRavi HP
|
||||
HP := s.server.raviente.state[0] + s.server.raviente.state[1] + s.server.raviente.state[2] + s.server.raviente.state[3] + s.server.raviente.state[4]
|
||||
s.server.raviente.support[1] = HP + 1
|
||||
HP := s.Server.raviente.state[0] + s.Server.raviente.state[1] + s.Server.raviente.state[2] + s.Server.raviente.state[3] + s.Server.raviente.state[4]
|
||||
s.Server.raviente.support[1] = HP + 1
|
||||
}
|
||||
} else {
|
||||
sendServerChatMessage(s, s.server.i18n.commands.ravi.version)
|
||||
sendServerChatMessage(s, s.Server.i18n.commands.ravi.version)
|
||||
}
|
||||
default:
|
||||
sendServerChatMessage(s, s.server.i18n.commands.ravi.error)
|
||||
sendServerChatMessage(s, s.Server.i18n.commands.ravi.error)
|
||||
}
|
||||
} else {
|
||||
sendServerChatMessage(s, s.server.i18n.commands.ravi.noPlayers)
|
||||
sendServerChatMessage(s, s.Server.i18n.commands.ravi.noPlayers)
|
||||
}
|
||||
} else {
|
||||
sendServerChatMessage(s, s.server.i18n.commands.ravi.error)
|
||||
sendServerChatMessage(s, s.Server.i18n.commands.ravi.error)
|
||||
}
|
||||
} else {
|
||||
sendDisabledCommandMessage(s, commands["Raviente"])
|
||||
@@ -377,13 +382,13 @@ func parseChatCommand(s *Session, command string) {
|
||||
payload.WriteInt16(int16(y)) // Y
|
||||
payloadBytes := payload.Data()
|
||||
s.QueueSendMHF(&mhfpacket.MsgSysCastedBinary{
|
||||
CharID: s.charID,
|
||||
CharID: s.CharID,
|
||||
MessageType: BinaryMessageTypeState,
|
||||
RawDataPayload: payloadBytes,
|
||||
})
|
||||
sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.commands.teleport.success, x, y))
|
||||
sendServerChatMessage(s, fmt.Sprintf(s.Server.i18n.commands.teleport.success, x, y))
|
||||
} else {
|
||||
sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.commands.teleport.error, commands["Teleport"].Prefix))
|
||||
sendServerChatMessage(s, fmt.Sprintf(s.Server.i18n.commands.teleport.error, commands["Teleport"].Prefix))
|
||||
}
|
||||
} else {
|
||||
sendDisabledCommandMessage(s, commands["Teleport"])
|
||||
@@ -391,14 +396,14 @@ func parseChatCommand(s *Session, command string) {
|
||||
case commands["Discord"].Prefix:
|
||||
if commands["Discord"].Enabled || s.isOp() {
|
||||
var _token string
|
||||
err := s.server.db.QueryRow(`SELECT discord_token FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)`, s.charID).Scan(&_token)
|
||||
err := database.QueryRow(`SELECT discord_token FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)`, s.CharID).Scan(&_token)
|
||||
if err != nil {
|
||||
randToken := make([]byte, 4)
|
||||
rand.Read(randToken)
|
||||
_token = fmt.Sprintf("%x-%x", randToken[:2], randToken[2:])
|
||||
s.server.db.Exec(`UPDATE users u SET discord_token = $1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, _token, s.charID)
|
||||
database.Exec(`UPDATE users u SET discord_token = $1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, _token, s.CharID)
|
||||
}
|
||||
sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.commands.discord.success, _token))
|
||||
sendServerChatMessage(s, fmt.Sprintf(s.Server.i18n.commands.discord.success, _token))
|
||||
} else {
|
||||
sendDisabledCommandMessage(s, commands["Discord"])
|
||||
}
|
||||
@@ -406,7 +411,7 @@ func parseChatCommand(s *Session, command string) {
|
||||
if commands["Help"].Enabled || s.isOp() {
|
||||
for _, command := range commands {
|
||||
if command.Enabled || s.isOp() {
|
||||
sendServerChatMessage(s, fmt.Sprintf("%s%s: %s", s.server.erupeConfig.CommandPrefix, command.Prefix, command.Description))
|
||||
sendServerChatMessage(s, fmt.Sprintf("%s%s: %s", config.GetConfig().CommandPrefix, command.Prefix, command.Description))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -418,21 +423,24 @@ func parseChatCommand(s *Session, command string) {
|
||||
func handleMsgSysCastBinary(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgSysCastBinary)
|
||||
tmp := byteframe.NewByteFrameFromBytes(pkt.RawDataPayload)
|
||||
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
if pkt.BroadcastType == 0x03 && pkt.MessageType == 0x03 && len(pkt.RawDataPayload) == 0x10 {
|
||||
if tmp.ReadUint16() == 0x0002 && tmp.ReadUint8() == 0x18 {
|
||||
var timer bool
|
||||
s.server.db.QueryRow(`SELECT COALESCE(timer, false) FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)`, s.charID).Scan(&timer)
|
||||
database.QueryRow(`SELECT COALESCE(timer, false) FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)`, s.CharID).Scan(&timer)
|
||||
if timer {
|
||||
_ = tmp.ReadBytes(9)
|
||||
tmp.SetLE()
|
||||
frame := tmp.ReadUint32()
|
||||
sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.timer, frame/30/60/60, frame/30/60, frame/30%60, int(math.Round(float64(frame%30*100)/3)), frame))
|
||||
sendServerChatMessage(s, fmt.Sprintf(s.Server.i18n.timer, frame/30/60/60, frame/30/60, frame/30%60, int(math.Round(float64(frame%30*100)/3)), frame))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if s.server.erupeConfig.DebugOptions.QuestTools {
|
||||
if config.GetConfig().DebugOptions.QuestTools {
|
||||
if pkt.BroadcastType == 0x03 && pkt.MessageType == 0x02 && len(pkt.RawDataPayload) > 32 {
|
||||
// This is only correct most of the time
|
||||
tmp.ReadBytes(20)
|
||||
@@ -440,7 +448,7 @@ func handleMsgSysCastBinary(s *Session, p mhfpacket.MHFPacket) {
|
||||
x := tmp.ReadFloat32()
|
||||
y := tmp.ReadFloat32()
|
||||
z := tmp.ReadFloat32()
|
||||
s.logger.Debug("Coord", zap.Float32s("XYZ", []float32{x, y, z}))
|
||||
s.Logger.Debug("Coord", zap.Float32s("XYZ", []float32{x, y, z}))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -463,7 +471,7 @@ func handleMsgSysCastBinary(s *Session, p mhfpacket.MHFPacket) {
|
||||
msgBinTargeted = &binpacket.MsgBinTargeted{}
|
||||
err := msgBinTargeted.Parse(tmp)
|
||||
if err != nil {
|
||||
s.logger.Warn("Failed to parse targeted cast binary")
|
||||
s.Logger.Warn("Failed to parse targeted cast binary")
|
||||
return
|
||||
}
|
||||
realPayload = msgBinTargeted.RawDataPayload
|
||||
@@ -485,19 +493,19 @@ func handleMsgSysCastBinary(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.SetLE()
|
||||
chatMessage := &binpacket.MsgBinChat{}
|
||||
chatMessage.Parse(bf)
|
||||
if strings.HasPrefix(chatMessage.Message, s.server.erupeConfig.CommandPrefix) {
|
||||
if strings.HasPrefix(chatMessage.Message, config.GetConfig().CommandPrefix) {
|
||||
parseChatCommand(s, chatMessage.Message)
|
||||
return
|
||||
}
|
||||
if (pkt.BroadcastType == BroadcastTypeStage && s.stage.id == "sl1Ns200p0a0u0") || pkt.BroadcastType == BroadcastTypeWorld {
|
||||
s.server.DiscordChannelSend(chatMessage.SenderName, chatMessage.Message)
|
||||
s.Server.DiscordChannelSend(chatMessage.SenderName, chatMessage.Message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make the response to forward to the other client(s).
|
||||
resp := &mhfpacket.MsgSysCastedBinary{
|
||||
CharID: s.charID,
|
||||
CharID: s.CharID,
|
||||
BroadcastType: pkt.BroadcastType, // (The client never uses Type0 upon receiving)
|
||||
MessageType: pkt.MessageType,
|
||||
RawDataPayload: realPayload,
|
||||
@@ -506,7 +514,7 @@ func handleMsgSysCastBinary(s *Session, p mhfpacket.MHFPacket) {
|
||||
// Send to the proper recipients.
|
||||
switch pkt.BroadcastType {
|
||||
case BroadcastTypeWorld:
|
||||
s.server.WorldcastMHF(resp, s, nil)
|
||||
s.Server.WorldcastMHF(resp, s, nil)
|
||||
case BroadcastTypeStage:
|
||||
if returnToSender {
|
||||
s.stage.BroadcastMHF(resp, nil)
|
||||
@@ -515,16 +523,16 @@ func handleMsgSysCastBinary(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
case BroadcastTypeServer:
|
||||
if pkt.MessageType == 1 {
|
||||
raviSema := s.server.getRaviSemaphore()
|
||||
raviSema := s.Server.getRaviSemaphore()
|
||||
if raviSema != nil {
|
||||
raviSema.BroadcastMHF(resp, s)
|
||||
}
|
||||
} else {
|
||||
s.server.BroadcastMHF(resp, s)
|
||||
s.Server.BroadcastMHF(resp, s)
|
||||
}
|
||||
case BroadcastTypeTargeted:
|
||||
for _, targetID := range (*msgBinTargeted).TargetCharIDs {
|
||||
char := s.server.FindSessionByCharID(targetID)
|
||||
char := s.Server.FindSessionByCharID(targetID)
|
||||
|
||||
if char != nil {
|
||||
char.QueueSendMHF(resp)
|
||||
|
||||
@@ -3,9 +3,11 @@ package channelserver
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
_config "erupe-ce/config"
|
||||
"erupe-ce/config"
|
||||
"erupe-ce/utils/bfutil"
|
||||
"erupe-ce/utils/db"
|
||||
"erupe-ce/utils/stringsupport"
|
||||
"fmt"
|
||||
|
||||
"erupe-ce/network/mhfpacket"
|
||||
"erupe-ce/server/channelserver/compression/nullcomp"
|
||||
@@ -58,8 +60,8 @@ type CharacterSaveData struct {
|
||||
|
||||
func getPointers() map[SavePointer]int {
|
||||
pointers := map[SavePointer]int{pGender: 81, lBookshelfData: 5576}
|
||||
switch _config.ErupeConfig.ClientID {
|
||||
case _config.ZZ:
|
||||
switch config.GetConfig().ClientID {
|
||||
case config.ZZ:
|
||||
pointers[pWeaponID] = 128522
|
||||
pointers[pWeaponType] = 128789
|
||||
pointers[pHouseTier] = 129900
|
||||
@@ -72,9 +74,9 @@ func getPointers() map[SavePointer]int {
|
||||
pointers[pGardenData] = 142424
|
||||
pointers[pRP] = 142614
|
||||
pointers[pKQF] = 146720
|
||||
case _config.Z2, _config.Z1, _config.G101, _config.G10, _config.G91, _config.G9, _config.G81, _config.G8,
|
||||
_config.G7, _config.G61, _config.G6, _config.G52, _config.G51, _config.G5, _config.GG, _config.G32, _config.G31,
|
||||
_config.G3, _config.G2, _config.G1:
|
||||
case config.Z2, config.Z1, config.G101, config.G10, config.G91, config.G9, config.G81, config.G8,
|
||||
config.G7, config.G61, config.G6, config.G52, config.G51, config.G5, config.GG, config.G32, config.G31,
|
||||
config.G3, config.G2, config.G1:
|
||||
pointers[pWeaponID] = 92522
|
||||
pointers[pWeaponType] = 92789
|
||||
pointers[pHouseTier] = 93900
|
||||
@@ -87,7 +89,7 @@ func getPointers() map[SavePointer]int {
|
||||
pointers[pGardenData] = 106424
|
||||
pointers[pRP] = 106614
|
||||
pointers[pKQF] = 110720
|
||||
case _config.F5, _config.F4:
|
||||
case config.F5, config.F4:
|
||||
pointers[pWeaponID] = 60522
|
||||
pointers[pWeaponType] = 60789
|
||||
pointers[pHouseTier] = 61900
|
||||
@@ -98,7 +100,7 @@ func getPointers() map[SavePointer]int {
|
||||
pointers[pGalleryData] = 72064
|
||||
pointers[pGardenData] = 74424
|
||||
pointers[pRP] = 74614
|
||||
case _config.S6:
|
||||
case config.S6:
|
||||
pointers[pWeaponID] = 12522
|
||||
pointers[pWeaponType] = 12789
|
||||
pointers[pHouseTier] = 13900
|
||||
@@ -110,24 +112,28 @@ func getPointers() map[SavePointer]int {
|
||||
pointers[pGardenData] = 26424
|
||||
pointers[pRP] = 26614
|
||||
}
|
||||
if _config.ErupeConfig.ClientID == _config.G5 {
|
||||
if config.GetConfig().ClientID == config.G5 {
|
||||
pointers[lBookshelfData] = 5548
|
||||
} else if _config.ErupeConfig.ClientID <= _config.GG {
|
||||
} else if config.GetConfig().ClientID <= config.GG {
|
||||
pointers[lBookshelfData] = 4520
|
||||
}
|
||||
return pointers
|
||||
}
|
||||
|
||||
func GetCharacterSaveData(s *Session, charID uint32) (*CharacterSaveData, error) {
|
||||
result, err := s.server.db.Query("SELECT id, savedata, is_new_character, name FROM characters WHERE id = $1", charID)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get savedata", zap.Error(err), zap.Uint32("charID", charID))
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
result, err := database.Query("SELECT id, savedata, is_new_character, name FROM characters WHERE id = $1", charID)
|
||||
if err != nil {
|
||||
s.Logger.Error("Failed to get savedata", zap.Error(err), zap.Uint32("charID", charID))
|
||||
return nil, err
|
||||
}
|
||||
defer result.Close()
|
||||
if !result.Next() {
|
||||
err = errors.New("no savedata found")
|
||||
s.logger.Error("No savedata found", zap.Uint32("charID", charID))
|
||||
s.Logger.Error("No savedata found", zap.Uint32("charID", charID))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -136,7 +142,7 @@ func GetCharacterSaveData(s *Session, charID uint32) (*CharacterSaveData, error)
|
||||
}
|
||||
err = result.Scan(&saveData.CharID, &saveData.compSave, &saveData.IsNewCharacter, &saveData.Name)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to scan savedata", zap.Error(err), zap.Uint32("charID", charID))
|
||||
s.Logger.Error("Failed to scan savedata", zap.Error(err), zap.Uint32("charID", charID))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -146,7 +152,7 @@ func GetCharacterSaveData(s *Session, charID uint32) (*CharacterSaveData, error)
|
||||
|
||||
err = saveData.Decompress()
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to decompress savedata", zap.Error(err))
|
||||
s.Logger.Error("Failed to decompress savedata", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -156,6 +162,10 @@ func GetCharacterSaveData(s *Session, charID uint32) (*CharacterSaveData, error)
|
||||
}
|
||||
|
||||
func (save *CharacterSaveData) Save(s *Session) {
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
if !s.kqfOverride {
|
||||
s.kqf = save.KQF
|
||||
} else {
|
||||
@@ -164,10 +174,10 @@ func (save *CharacterSaveData) Save(s *Session) {
|
||||
|
||||
save.updateSaveDataWithStruct()
|
||||
|
||||
if _config.ErupeConfig.ClientID >= _config.G1 {
|
||||
if config.GetConfig().ClientID >= config.G1 {
|
||||
err := save.Compress()
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to compress savedata", zap.Error(err))
|
||||
s.Logger.Error("Failed to compress savedata", zap.Error(err))
|
||||
return
|
||||
}
|
||||
} else {
|
||||
@@ -175,14 +185,14 @@ func (save *CharacterSaveData) Save(s *Session) {
|
||||
save.compSave = save.decompSave
|
||||
}
|
||||
|
||||
_, err := s.server.db.Exec(`UPDATE characters SET savedata=$1, is_new_character=false, hr=$2, gr=$3, is_female=$4, weapon_type=$5, weapon_id=$6 WHERE id=$7
|
||||
_, err = database.Exec(`UPDATE characters SET savedata=$1, is_new_character=false, hr=$2, gr=$3, is_female=$4, weapon_type=$5, weapon_id=$6 WHERE id=$7
|
||||
`, save.compSave, save.HR, save.GR, save.Gender, save.WeaponType, save.WeaponID, save.CharID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to update savedata", zap.Error(err), zap.Uint32("charID", save.CharID))
|
||||
s.Logger.Error("Failed to update savedata", zap.Error(err), zap.Uint32("charID", save.CharID))
|
||||
}
|
||||
|
||||
s.server.db.Exec(`UPDATE user_binary SET house_tier=$1, house_data=$2, bookshelf=$3, gallery=$4, tore=$5, garden=$6 WHERE id=$7
|
||||
`, save.HouseTier, save.HouseData, save.BookshelfData, save.GalleryData, save.ToreData, save.GardenData, s.charID)
|
||||
database.Exec(`UPDATE user_binary SET house_tier=$1, house_data=$2, bookshelf=$3, gallery=$4, tore=$5, garden=$6 WHERE id=$7
|
||||
`, save.HouseTier, save.HouseData, save.BookshelfData, save.GalleryData, save.ToreData, save.GardenData, s.CharID)
|
||||
}
|
||||
|
||||
func (save *CharacterSaveData) Compress() error {
|
||||
@@ -207,10 +217,10 @@ func (save *CharacterSaveData) Decompress() error {
|
||||
func (save *CharacterSaveData) updateSaveDataWithStruct() {
|
||||
rpBytes := make([]byte, 2)
|
||||
binary.LittleEndian.PutUint16(rpBytes, save.RP)
|
||||
if _config.ErupeConfig.ClientID >= _config.F4 {
|
||||
if config.GetConfig().ClientID >= config.F4 {
|
||||
copy(save.decompSave[save.Pointers[pRP]:save.Pointers[pRP]+2], rpBytes)
|
||||
}
|
||||
if _config.ErupeConfig.ClientID >= _config.G10 {
|
||||
if config.GetConfig().ClientID >= config.G10 {
|
||||
copy(save.decompSave[save.Pointers[pKQF]:save.Pointers[pKQF]+8], save.KQF)
|
||||
}
|
||||
}
|
||||
@@ -224,7 +234,7 @@ func (save *CharacterSaveData) updateStructWithSaveData() {
|
||||
save.Gender = false
|
||||
}
|
||||
if !save.IsNewCharacter {
|
||||
if _config.ErupeConfig.ClientID >= _config.S6 {
|
||||
if config.GetConfig().ClientID >= config.S6 {
|
||||
save.RP = binary.LittleEndian.Uint16(save.decompSave[save.Pointers[pRP] : save.Pointers[pRP]+2])
|
||||
save.HouseTier = save.decompSave[save.Pointers[pHouseTier] : save.Pointers[pHouseTier]+5]
|
||||
save.HouseData = save.decompSave[save.Pointers[pHouseData] : save.Pointers[pHouseData]+195]
|
||||
@@ -235,12 +245,12 @@ func (save *CharacterSaveData) updateStructWithSaveData() {
|
||||
save.WeaponType = save.decompSave[save.Pointers[pWeaponType]]
|
||||
save.WeaponID = binary.LittleEndian.Uint16(save.decompSave[save.Pointers[pWeaponID] : save.Pointers[pWeaponID]+2])
|
||||
save.HR = binary.LittleEndian.Uint16(save.decompSave[save.Pointers[pHR] : save.Pointers[pHR]+2])
|
||||
if _config.ErupeConfig.ClientID >= _config.G1 {
|
||||
if config.GetConfig().ClientID >= config.G1 {
|
||||
if save.HR == uint16(999) {
|
||||
save.GR = grpToGR(int(binary.LittleEndian.Uint32(save.decompSave[save.Pointers[pGRP] : save.Pointers[pGRP]+4])))
|
||||
}
|
||||
}
|
||||
if _config.ErupeConfig.ClientID >= _config.G10 {
|
||||
if config.GetConfig().ClientID >= config.G10 {
|
||||
save.KQF = save.decompSave[save.Pointers[pKQF] : save.Pointers[pKQF]+8]
|
||||
}
|
||||
}
|
||||
@@ -250,5 +260,5 @@ func (save *CharacterSaveData) updateStructWithSaveData() {
|
||||
|
||||
func handleMsgMhfSexChanger(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfSexChanger)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
@@ -3,7 +3,9 @@ package channelserver
|
||||
import (
|
||||
"erupe-ce/network/mhfpacket"
|
||||
"erupe-ce/utils/byteframe"
|
||||
"erupe-ce/utils/db"
|
||||
"erupe-ce/utils/stringsupport"
|
||||
"fmt"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
@@ -11,15 +13,15 @@ import (
|
||||
func handleMsgSysEnumerateClient(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgSysEnumerateClient)
|
||||
|
||||
s.server.stagesLock.RLock()
|
||||
stage, ok := s.server.stages[pkt.StageID]
|
||||
s.Server.stagesLock.RLock()
|
||||
stage, ok := s.Server.stages[pkt.StageID]
|
||||
if !ok {
|
||||
s.server.stagesLock.RUnlock()
|
||||
s.logger.Warn("Can't enumerate clients for stage that doesn't exist!", zap.String("stageID", pkt.StageID))
|
||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
s.Server.stagesLock.RUnlock()
|
||||
s.Logger.Warn("Can't enumerate clients for stage that doesn't exist!", zap.String("stageID", pkt.StageID))
|
||||
DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
s.server.stagesLock.RUnlock()
|
||||
s.Server.stagesLock.RUnlock()
|
||||
|
||||
// Read-lock the stage and make the response with all of the charID's in the stage.
|
||||
resp := byteframe.NewByteFrame()
|
||||
@@ -52,23 +54,26 @@ func handleMsgSysEnumerateClient(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
stage.RUnlock()
|
||||
|
||||
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
s.logger.Debug("MsgSysEnumerateClient Done!")
|
||||
DoAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
s.Logger.Debug("MsgSysEnumerateClient Done!")
|
||||
}
|
||||
|
||||
func handleMsgMhfListMember(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfListMember)
|
||||
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
var csv string
|
||||
var count uint32
|
||||
resp := byteframe.NewByteFrame()
|
||||
resp.WriteUint32(0) // Blacklist count
|
||||
err := s.server.db.QueryRow("SELECT blocked FROM characters WHERE id=$1", s.charID).Scan(&csv)
|
||||
err = database.QueryRow("SELECT blocked FROM characters WHERE id=$1", s.CharID).Scan(&csv)
|
||||
if err == nil {
|
||||
cids := stringsupport.CSVElems(csv)
|
||||
for _, cid := range cids {
|
||||
var name string
|
||||
err = s.server.db.QueryRow("SELECT name FROM characters WHERE id=$1", cid).Scan(&name)
|
||||
err = database.QueryRow("SELECT name FROM characters WHERE id=$1", cid).Scan(&name)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
@@ -80,36 +85,40 @@ func handleMsgMhfListMember(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
resp.Seek(0, 0)
|
||||
resp.WriteUint32(count)
|
||||
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfOprMember(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfOprMember)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
var csv string
|
||||
for _, cid := range pkt.CharIDs {
|
||||
if pkt.Blacklist {
|
||||
err := s.server.db.QueryRow("SELECT blocked FROM characters WHERE id=$1", s.charID).Scan(&csv)
|
||||
err := database.QueryRow("SELECT blocked FROM characters WHERE id=$1", s.CharID).Scan(&csv)
|
||||
if err == nil {
|
||||
if pkt.Operation {
|
||||
csv = stringsupport.CSVRemove(csv, int(cid))
|
||||
} else {
|
||||
csv = stringsupport.CSVAdd(csv, int(cid))
|
||||
}
|
||||
s.server.db.Exec("UPDATE characters SET blocked=$1 WHERE id=$2", csv, s.charID)
|
||||
database.Exec("UPDATE characters SET blocked=$1 WHERE id=$2", csv, s.CharID)
|
||||
}
|
||||
} else { // Friendlist
|
||||
err := s.server.db.QueryRow("SELECT friends FROM characters WHERE id=$1", s.charID).Scan(&csv)
|
||||
err := database.QueryRow("SELECT friends FROM characters WHERE id=$1", s.CharID).Scan(&csv)
|
||||
if err == nil {
|
||||
if pkt.Operation {
|
||||
csv = stringsupport.CSVRemove(csv, int(cid))
|
||||
} else {
|
||||
csv = stringsupport.CSVAdd(csv, int(cid))
|
||||
}
|
||||
s.server.db.Exec("UPDATE characters SET friends=$1 WHERE id=$2", csv, s.charID)
|
||||
database.Exec("UPDATE characters SET friends=$1 WHERE id=$2", csv, s.CharID)
|
||||
}
|
||||
}
|
||||
}
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func handleMsgMhfShutClient(s *Session, p mhfpacket.MHFPacket) {}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
package channelserver
|
||||
|
||||
import (
|
||||
_config "erupe-ce/config"
|
||||
"erupe-ce/config"
|
||||
"erupe-ce/utils/db"
|
||||
"erupe-ce/utils/gametime"
|
||||
"erupe-ce/utils/mhfmon"
|
||||
"erupe-ce/utils/stringsupport"
|
||||
@@ -21,9 +22,13 @@ import (
|
||||
|
||||
func handleMsgMhfSavedata(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfSavedata)
|
||||
characterSaveData, err := GetCharacterSaveData(s, s.charID)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.logger.Error("failed to retrieve character save data from db", zap.Error(err), zap.Uint32("charID", s.charID))
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
characterSaveData, err := GetCharacterSaveData(s, s.CharID)
|
||||
if err != nil {
|
||||
s.Logger.Error("failed to retrieve character save data from db", zap.Error(err), zap.Uint32("charID", s.CharID))
|
||||
return
|
||||
}
|
||||
// Var to hold the decompressed savedata for updating the launcher response fields.
|
||||
@@ -32,26 +37,26 @@ func handleMsgMhfSavedata(s *Session, p mhfpacket.MHFPacket) {
|
||||
// diffs themselves are also potentially compressed
|
||||
diff, err := nullcomp.Decompress(pkt.RawDataPayload)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to decompress diff", zap.Error(err))
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
s.Logger.Error("Failed to decompress diff", zap.Error(err))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
// Perform diff.
|
||||
s.logger.Info("Diffing...")
|
||||
s.Logger.Info("Diffing...")
|
||||
characterSaveData.decompSave = deltacomp.ApplyDataDiff(diff, characterSaveData.decompSave)
|
||||
} else {
|
||||
dumpSaveData(s, pkt.RawDataPayload, "savedata")
|
||||
// Regular blob update.
|
||||
saveData, err := nullcomp.Decompress(pkt.RawDataPayload)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to decompress savedata from packet", zap.Error(err))
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
s.Logger.Error("Failed to decompress savedata from packet", zap.Error(err))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
if s.server.erupeConfig.SaveDumps.RawEnabled {
|
||||
if config.GetConfig().SaveDumps.RawEnabled {
|
||||
dumpSaveData(s, saveData, "raw-savedata")
|
||||
}
|
||||
s.logger.Info("Updating save with blob")
|
||||
s.Logger.Info("Updating save with blob")
|
||||
characterSaveData.decompSave = saveData
|
||||
}
|
||||
characterSaveData.updateStructWithSaveData()
|
||||
@@ -61,22 +66,22 @@ func handleMsgMhfSavedata(s *Session, p mhfpacket.MHFPacket) {
|
||||
s.Name = characterSaveData.Name
|
||||
}
|
||||
|
||||
if characterSaveData.Name == s.Name || _config.ErupeConfig.ClientID <= _config.S10 {
|
||||
if characterSaveData.Name == s.Name || config.GetConfig().ClientID <= config.S10 {
|
||||
characterSaveData.Save(s)
|
||||
s.logger.Info("Wrote recompressed savedata back to DB.")
|
||||
s.Logger.Info("Wrote recompressed savedata back to DB.")
|
||||
} else {
|
||||
s.rawConn.Close()
|
||||
s.logger.Warn("Save cancelled due to corruption.")
|
||||
if s.server.erupeConfig.DeleteOnSaveCorruption {
|
||||
s.server.db.Exec("UPDATE characters SET deleted=true WHERE id=$1", s.charID)
|
||||
s.Logger.Warn("Save cancelled due to corruption.")
|
||||
if config.GetConfig().DeleteOnSaveCorruption {
|
||||
database.Exec("UPDATE characters SET deleted=true WHERE id=$1", s.CharID)
|
||||
}
|
||||
return
|
||||
}
|
||||
_, err = s.server.db.Exec("UPDATE characters SET name=$1 WHERE id=$2", characterSaveData.Name, s.charID)
|
||||
_, err = database.Exec("UPDATE characters SET name=$1 WHERE id=$2", characterSaveData.Name, s.CharID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to update character name in db", zap.Error(err))
|
||||
s.Logger.Error("Failed to update character name in db", zap.Error(err))
|
||||
}
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func grpToGR(n int) uint16 {
|
||||
@@ -115,83 +120,95 @@ func grpToGR(n int) uint16 {
|
||||
}
|
||||
|
||||
func dumpSaveData(s *Session, data []byte, suffix string) {
|
||||
if !s.server.erupeConfig.SaveDumps.Enabled {
|
||||
if !config.GetConfig().SaveDumps.Enabled {
|
||||
return
|
||||
} else {
|
||||
dir := filepath.Join(s.server.erupeConfig.SaveDumps.OutputDir, fmt.Sprintf("%d", s.charID))
|
||||
path := filepath.Join(s.server.erupeConfig.SaveDumps.OutputDir, fmt.Sprintf("%d", s.charID), fmt.Sprintf("%d_%s.bin", s.charID, suffix))
|
||||
dir := filepath.Join(config.GetConfig().SaveDumps.OutputDir, fmt.Sprintf("%d", s.CharID))
|
||||
path := filepath.Join(config.GetConfig().SaveDumps.OutputDir, fmt.Sprintf("%d", s.CharID), fmt.Sprintf("%d_%s.bin", s.CharID, suffix))
|
||||
_, err := os.Stat(dir)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
err = os.MkdirAll(dir, os.ModePerm)
|
||||
if err != nil {
|
||||
s.logger.Error("Error dumping savedata, could not create folder")
|
||||
s.Logger.Error("Error dumping savedata, could not create folder")
|
||||
return
|
||||
}
|
||||
} else {
|
||||
s.logger.Error("Error dumping savedata")
|
||||
s.Logger.Error("Error dumping savedata")
|
||||
return
|
||||
}
|
||||
}
|
||||
err = os.WriteFile(path, data, 0644)
|
||||
if err != nil {
|
||||
s.logger.Error("Error dumping savedata, could not write file", zap.Error(err))
|
||||
s.Logger.Error("Error dumping savedata, could not write file", zap.Error(err))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func handleMsgMhfLoaddata(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfLoaddata)
|
||||
if _, err := os.Stat(filepath.Join(s.server.erupeConfig.BinPath, "save_override.bin")); err == nil {
|
||||
data, _ := os.ReadFile(filepath.Join(s.server.erupeConfig.BinPath, "save_override.bin"))
|
||||
doAckBufSucceed(s, pkt.AckHandle, data)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
if _, err := os.Stat(filepath.Join(config.GetConfig().BinPath, "save_override.bin")); err == nil {
|
||||
data, _ := os.ReadFile(filepath.Join(config.GetConfig().BinPath, "save_override.bin"))
|
||||
DoAckBufSucceed(s, pkt.AckHandle, data)
|
||||
return
|
||||
}
|
||||
|
||||
var data []byte
|
||||
err := s.server.db.QueryRow("SELECT savedata FROM characters WHERE id = $1", s.charID).Scan(&data)
|
||||
err = database.QueryRow("SELECT savedata FROM characters WHERE id = $1", s.CharID).Scan(&data)
|
||||
if err != nil || len(data) == 0 {
|
||||
s.logger.Warn(fmt.Sprintf("Failed to load savedata (CID: %d)", s.charID), zap.Error(err))
|
||||
s.Logger.Warn(fmt.Sprintf("Failed to load savedata (CID: %d)", s.CharID), zap.Error(err))
|
||||
s.rawConn.Close() // Terminate the connection
|
||||
return
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, data)
|
||||
DoAckBufSucceed(s, pkt.AckHandle, data)
|
||||
|
||||
decompSaveData, err := nullcomp.Decompress(data)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to decompress savedata", zap.Error(err))
|
||||
s.Logger.Error("Failed to decompress savedata", zap.Error(err))
|
||||
}
|
||||
bf := byteframe.NewByteFrameFromBytes(decompSaveData)
|
||||
bf.Seek(88, io.SeekStart)
|
||||
name := bf.ReadNullTerminatedBytes()
|
||||
s.server.userBinaryPartsLock.Lock()
|
||||
s.server.userBinaryParts[userBinaryPartID{charID: s.charID, index: 1}] = append(name, []byte{0x00}...)
|
||||
s.server.userBinaryPartsLock.Unlock()
|
||||
s.Server.userBinaryPartsLock.Lock()
|
||||
s.Server.userBinaryParts[userBinaryPartID{charID: s.CharID, index: 1}] = append(name, []byte{0x00}...)
|
||||
s.Server.userBinaryPartsLock.Unlock()
|
||||
s.Name = stringsupport.SJISToUTF8(name)
|
||||
}
|
||||
|
||||
func handleMsgMhfSaveScenarioData(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfSaveScenarioData)
|
||||
dumpSaveData(s, pkt.RawDataPayload, "scenario")
|
||||
_, err := s.server.db.Exec("UPDATE characters SET scenariodata = $1 WHERE id = $2", pkt.RawDataPayload, s.charID)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to update scenario data in db", zap.Error(err))
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
dumpSaveData(s, pkt.RawDataPayload, "scenario")
|
||||
_, err = database.Exec("UPDATE characters SET scenariodata = $1 WHERE id = $2", pkt.RawDataPayload, s.CharID)
|
||||
if err != nil {
|
||||
s.Logger.Error("Failed to update scenario data in db", zap.Error(err))
|
||||
}
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func handleMsgMhfLoadScenarioData(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfLoadScenarioData)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
var scenarioData []byte
|
||||
bf := byteframe.NewByteFrame()
|
||||
err := s.server.db.QueryRow("SELECT scenariodata FROM characters WHERE id = $1", s.charID).Scan(&scenarioData)
|
||||
err = database.QueryRow("SELECT scenariodata FROM characters WHERE id = $1", s.CharID).Scan(&scenarioData)
|
||||
if err != nil || len(scenarioData) < 10 {
|
||||
s.logger.Error("Failed to load scenariodata", zap.Error(err))
|
||||
s.Logger.Error("Failed to load scenariodata", zap.Error(err))
|
||||
bf.WriteBytes(make([]byte, 10))
|
||||
} else {
|
||||
bf.WriteBytes(scenarioData)
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
var paperGiftData = map[uint32][]PaperGift{
|
||||
@@ -1509,7 +1526,7 @@ func handleMsgMhfGetPaperData(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
default:
|
||||
if pkt.Unk2 < 1000 {
|
||||
s.logger.Info("PaperData request for unknown type", zap.Uint32("Unk2", pkt.Unk2))
|
||||
s.Logger.Info("PaperData request for unknown type", zap.Uint32("Unk2", pkt.Unk2))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1518,7 +1535,7 @@ func handleMsgMhfGetPaperData(s *Session, p mhfpacket.MHFPacket) {
|
||||
if ok {
|
||||
paperGift = paperGiftData[pkt.Unk2]
|
||||
} else {
|
||||
s.logger.Info("PaperGift request for unknown type", zap.Uint32("Unk2", pkt.Unk2))
|
||||
s.Logger.Info("PaperGift request for unknown type", zap.Uint32("Unk2", pkt.Unk2))
|
||||
}
|
||||
for _, gift := range paperGift {
|
||||
bf := byteframe.NewByteFrame()
|
||||
@@ -1528,7 +1545,7 @@ func handleMsgMhfGetPaperData(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint16(gift.Unk3)
|
||||
data = append(data, bf)
|
||||
}
|
||||
doAckEarthSucceed(s, pkt.AckHandle, data)
|
||||
DoAckEarthSucceed(s, pkt.AckHandle, data)
|
||||
} else if pkt.Unk2 == 0 {
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint16(uint16(len(paperMissions.Timetables)))
|
||||
@@ -1546,7 +1563,7 @@ func handleMsgMhfGetPaperData(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint16(mdata.Reward2ID)
|
||||
bf.WriteUint8(mdata.Reward2Quantity)
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
} else {
|
||||
for _, pdata := range paperData {
|
||||
bf := byteframe.NewByteFrame()
|
||||
@@ -1559,7 +1576,7 @@ func handleMsgMhfGetPaperData(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteInt16(pdata.Unk6)
|
||||
data = append(data, bf)
|
||||
}
|
||||
doAckEarthSucceed(s, pkt.AckHandle, data)
|
||||
DoAckEarthSucceed(s, pkt.AckHandle, data)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
package channelserver
|
||||
|
||||
import (
|
||||
_config "erupe-ce/config"
|
||||
"erupe-ce/config"
|
||||
"erupe-ce/network/mhfpacket"
|
||||
"erupe-ce/utils/byteframe"
|
||||
"erupe-ce/utils/db"
|
||||
ps "erupe-ce/utils/pascalstring"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"go.uber.org/zap"
|
||||
@@ -32,7 +34,11 @@ func handleMsgMhfEnumerateDistItem(s *Session, p mhfpacket.MHFPacket) {
|
||||
|
||||
var itemDists []Distribution
|
||||
bf := byteframe.NewByteFrame()
|
||||
rows, err := s.server.db.Queryx(`
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
rows, err := database.Queryx(`
|
||||
SELECT d.id, event_name, description, COALESCE(rights, 0) AS rights, COALESCE(selection, false) AS selection, times_acceptable,
|
||||
COALESCE(min_hr, -1) AS min_hr, COALESCE(max_hr, -1) AS max_hr,
|
||||
COALESCE(min_sr, -1) AS min_sr, COALESCE(max_sr, -1) AS max_sr,
|
||||
@@ -44,7 +50,7 @@ func handleMsgMhfEnumerateDistItem(s *Session, p mhfpacket.MHFPacket) {
|
||||
COALESCE(deadline, TO_TIMESTAMP(0)) AS deadline
|
||||
FROM distribution d
|
||||
WHERE character_id = $1 AND type = $2 OR character_id IS NULL AND type = $2 ORDER BY id DESC
|
||||
`, s.charID, pkt.DistType)
|
||||
`, s.CharID, pkt.DistType)
|
||||
|
||||
if err == nil {
|
||||
var itemDist Distribution
|
||||
@@ -64,7 +70,7 @@ func handleMsgMhfEnumerateDistItem(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint32(dist.Rights)
|
||||
bf.WriteUint16(dist.TimesAcceptable)
|
||||
bf.WriteUint16(dist.TimesAccepted)
|
||||
if _config.ErupeConfig.ClientID >= _config.G9 {
|
||||
if config.GetConfig().ClientID >= config.G9 {
|
||||
bf.WriteUint16(0) // Unk
|
||||
}
|
||||
bf.WriteInt16(dist.MinHR)
|
||||
@@ -73,29 +79,29 @@ func handleMsgMhfEnumerateDistItem(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteInt16(dist.MaxSR)
|
||||
bf.WriteInt16(dist.MinGR)
|
||||
bf.WriteInt16(dist.MaxGR)
|
||||
if _config.ErupeConfig.ClientID >= _config.G7 {
|
||||
if config.GetConfig().ClientID >= config.G7 {
|
||||
bf.WriteUint8(0) // Unk
|
||||
}
|
||||
if _config.ErupeConfig.ClientID >= _config.G6 {
|
||||
if config.GetConfig().ClientID >= config.G6 {
|
||||
bf.WriteUint16(0) // Unk
|
||||
}
|
||||
if _config.ErupeConfig.ClientID >= _config.G8 {
|
||||
if config.GetConfig().ClientID >= config.G8 {
|
||||
if dist.Selection {
|
||||
bf.WriteUint8(2) // Selection
|
||||
} else {
|
||||
bf.WriteUint8(0)
|
||||
}
|
||||
}
|
||||
if _config.ErupeConfig.ClientID >= _config.G7 {
|
||||
if config.GetConfig().ClientID >= config.G7 {
|
||||
bf.WriteUint16(0) // Unk
|
||||
bf.WriteUint16(0) // Unk
|
||||
}
|
||||
if _config.ErupeConfig.ClientID >= _config.G10 {
|
||||
if config.GetConfig().ClientID >= config.G10 {
|
||||
bf.WriteUint8(0) // Unk
|
||||
}
|
||||
ps.Uint8(bf, dist.EventName, true)
|
||||
k := 6
|
||||
if _config.ErupeConfig.ClientID >= _config.G8 {
|
||||
if config.GetConfig().ClientID >= config.G8 {
|
||||
k = 13
|
||||
}
|
||||
for i := 0; i < 6; i++ {
|
||||
@@ -104,7 +110,7 @@ func handleMsgMhfEnumerateDistItem(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint32(0)
|
||||
}
|
||||
}
|
||||
if _config.ErupeConfig.ClientID >= _config.Z2 {
|
||||
if config.GetConfig().ClientID >= config.Z2 {
|
||||
i := uint8(0)
|
||||
bf.WriteUint8(i)
|
||||
if i <= 10 {
|
||||
@@ -116,7 +122,7 @@ func handleMsgMhfEnumerateDistItem(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
}
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
type DistributionItem struct {
|
||||
@@ -127,8 +133,12 @@ type DistributionItem struct {
|
||||
}
|
||||
|
||||
func getDistributionItems(s *Session, i uint32) []DistributionItem {
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
var distItems []DistributionItem
|
||||
rows, err := s.server.db.Queryx(`SELECT id, item_type, COALESCE(item_id, 0) AS item_id, COALESCE(quantity, 0) AS quantity FROM distribution_items WHERE distribution_id=$1`, i)
|
||||
rows, err := database.Queryx(`SELECT id, item_type, COALESCE(item_id, 0) AS item_id, COALESCE(quantity, 0) AS quantity FROM distribution_items WHERE distribution_id=$1`, i)
|
||||
if err == nil {
|
||||
var distItem DistributionItem
|
||||
for rows.Next() {
|
||||
@@ -152,17 +162,21 @@ func handleMsgMhfApplyDistItem(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint8(item.ItemType)
|
||||
bf.WriteUint32(item.ItemID)
|
||||
bf.WriteUint32(item.Quantity)
|
||||
if _config.ErupeConfig.ClientID >= _config.G8 {
|
||||
if config.GetConfig().ClientID >= config.G8 {
|
||||
bf.WriteUint32(item.ID)
|
||||
}
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfAcquireDistItem(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfAcquireDistItem)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
if pkt.DistributionID > 0 {
|
||||
_, err := s.server.db.Exec(`INSERT INTO public.distributions_accepted VALUES ($1, $2)`, pkt.DistributionID, s.charID)
|
||||
_, err := database.Exec(`INSERT INTO public.distributions_accepted VALUES ($1, $2)`, pkt.DistributionID, s.CharID)
|
||||
if err == nil {
|
||||
distItems := getDistributionItems(s, pkt.DistributionID)
|
||||
for _, item := range distItems {
|
||||
@@ -170,13 +184,13 @@ func handleMsgMhfAcquireDistItem(s *Session, p mhfpacket.MHFPacket) {
|
||||
case 17:
|
||||
_ = addPointNetcafe(s, int(item.Quantity))
|
||||
case 19:
|
||||
s.server.db.Exec("UPDATE users u SET gacha_premium=gacha_premium+$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)", item.Quantity, s.charID)
|
||||
database.Exec("UPDATE users u SET gacha_premium=gacha_premium+$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)", item.Quantity, s.CharID)
|
||||
case 20:
|
||||
s.server.db.Exec("UPDATE users u SET gacha_trial=gacha_trial+$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)", item.Quantity, s.charID)
|
||||
database.Exec("UPDATE users u SET gacha_trial=gacha_trial+$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)", item.Quantity, s.CharID)
|
||||
case 21:
|
||||
s.server.db.Exec("UPDATE users u SET frontier_points=frontier_points+$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)", item.Quantity, s.charID)
|
||||
database.Exec("UPDATE users u SET frontier_points=frontier_points+$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)", item.Quantity, s.CharID)
|
||||
case 23:
|
||||
saveData, err := GetCharacterSaveData(s, s.charID)
|
||||
saveData, err := GetCharacterSaveData(s, s.CharID)
|
||||
if err == nil {
|
||||
saveData.RP += uint16(item.Quantity)
|
||||
saveData.Save(s)
|
||||
@@ -185,20 +199,24 @@ func handleMsgMhfAcquireDistItem(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
}
|
||||
}
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func handleMsgMhfGetDistDescription(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetDistDescription)
|
||||
var desc string
|
||||
err := s.server.db.QueryRow("SELECT description FROM distribution WHERE id = $1", pkt.DistributionID).Scan(&desc)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.logger.Error("Error parsing item distribution description", zap.Error(err))
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
var desc string
|
||||
err = database.QueryRow("SELECT description FROM distribution WHERE id = $1", pkt.DistributionID).Scan(&desc)
|
||||
if err != nil {
|
||||
s.Logger.Error("Error parsing item distribution description", zap.Error(err))
|
||||
DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
bf := byteframe.NewByteFrame()
|
||||
ps.Uint16(bf, desc, true)
|
||||
ps.Uint16(bf, "", false)
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
@@ -2,9 +2,11 @@ package channelserver
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
_config "erupe-ce/config"
|
||||
config "erupe-ce/config"
|
||||
"erupe-ce/utils/db"
|
||||
"erupe-ce/utils/gametime"
|
||||
"erupe-ce/utils/stringsupport"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"erupe-ce/network/mhfpacket"
|
||||
@@ -12,10 +14,18 @@ import (
|
||||
)
|
||||
|
||||
func cleanupDiva(s *Session) {
|
||||
s.server.db.Exec("DELETE FROM events WHERE event_type='diva'")
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
database.Exec("DELETE FROM events WHERE event_type='diva'")
|
||||
}
|
||||
|
||||
func generateDivaTimestamps(s *Session, start uint32, debug bool) []uint32 {
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
timestamps := make([]uint32, 6)
|
||||
midnight := gametime.TimeMidnight()
|
||||
if debug && start <= 3 {
|
||||
@@ -49,7 +59,7 @@ func generateDivaTimestamps(s *Session, start uint32, debug bool) []uint32 {
|
||||
cleanupDiva(s)
|
||||
// Generate a new diva defense, starting midnight tomorrow
|
||||
start = uint32(midnight.Add(24 * time.Hour).Unix())
|
||||
s.server.db.Exec("INSERT INTO events (event_type, start_time) VALUES ('diva', to_timestamp($1)::timestamp without time zone)", start)
|
||||
database.Exec("INSERT INTO events (event_type, start_time) VALUES ('diva', to_timestamp($1)::timestamp without time zone)", start)
|
||||
}
|
||||
timestamps[0] = start
|
||||
timestamps[1] = timestamps[0] + 601200
|
||||
@@ -63,29 +73,32 @@ func generateDivaTimestamps(s *Session, start uint32, debug bool) []uint32 {
|
||||
func handleMsgMhfGetUdSchedule(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetUdSchedule)
|
||||
bf := byteframe.NewByteFrame()
|
||||
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
id, start := uint32(0xCAFEBEEF), uint32(0)
|
||||
rows, _ := s.server.db.Queryx("SELECT id, (EXTRACT(epoch FROM start_time)::int) as start_time FROM events WHERE event_type='diva'")
|
||||
rows, _ := database.Queryx("SELECT id, (EXTRACT(epoch FROM start_time)::int) as start_time FROM events WHERE event_type='diva'")
|
||||
for rows.Next() {
|
||||
rows.Scan(&id, &start)
|
||||
}
|
||||
|
||||
var timestamps []uint32
|
||||
if s.server.erupeConfig.DebugOptions.DivaOverride >= 0 {
|
||||
if s.server.erupeConfig.DebugOptions.DivaOverride == 0 {
|
||||
if s.server.erupeConfig.ClientID >= _config.Z2 {
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 36))
|
||||
if config.GetConfig().DebugOptions.DivaOverride >= 0 {
|
||||
if config.GetConfig().DebugOptions.DivaOverride == 0 {
|
||||
if config.GetConfig().ClientID >= config.Z2 {
|
||||
DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 36))
|
||||
} else {
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 32))
|
||||
DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 32))
|
||||
}
|
||||
return
|
||||
}
|
||||
timestamps = generateDivaTimestamps(s, uint32(s.server.erupeConfig.DebugOptions.DivaOverride), true)
|
||||
timestamps = generateDivaTimestamps(s, uint32(config.GetConfig().DebugOptions.DivaOverride), true)
|
||||
} else {
|
||||
timestamps = generateDivaTimestamps(s, start, false)
|
||||
}
|
||||
|
||||
if s.server.erupeConfig.ClientID >= _config.Z2 {
|
||||
if config.GetConfig().ClientID >= config.Z2 {
|
||||
bf.WriteUint32(id)
|
||||
}
|
||||
for i := range timestamps {
|
||||
@@ -97,7 +110,7 @@ func handleMsgMhfGetUdSchedule(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint16(0x02) // Unk 00000010
|
||||
bf.WriteUint16(0x02) // Unk 00000010
|
||||
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfGetUdInfo(s *Session, p mhfpacket.MHFPacket) {
|
||||
@@ -117,45 +130,45 @@ func handleMsgMhfGetUdInfo(s *Session, p mhfpacket.MHFPacket) {
|
||||
resp.WriteUint32(uint32(udInfo.EndTime.Unix()))
|
||||
}
|
||||
|
||||
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfGetKijuInfo(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetKijuInfo)
|
||||
// Temporary canned response
|
||||
data, _ := hex.DecodeString("04965C959782CC8B468EEC00000000000000000000000000000000000000000000815C82A082E782B582DC82A982BA82CC82AB82B682E3815C0A965C959782C682CD96D282E98E7682A281420A95B782AD8ED282C997458B4382F0975E82A682E98142000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001018BAD8C8282CC8B468EEC00000000000000000000000000000000000000000000815C82AB82E582A482B082AB82CC82AB82B682E3815C0A8BAD8C8282C682CD8BAD82A290BA904681420A95B782AD8ED282CC97CD82F08CA482AC909F82DC82B78142200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003138C8B8F5782CC8B468EEC00000000000000000000000000000000000000000000815C82AF82C182B582E382A482CC82AB82B682E3815C0A8C8B8F5782C682CD8A6D8CC582BD82E9904D978A81420A8F5782DF82E982D982C782C98EEB906C82BD82BF82CC90B8905F97CD82C682C882E9814200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041189CC8CEC82CC8B468EEC00000000000000000000000000000000000000000000815C82A482BD82DC82E082E882CC82AB82B682E3815C0A89CC8CEC82C682CD89CC955082CC8CEC82E881420A8F5782DF82E982D982C782C98EEB906C82BD82BF82CC8E7882A682C682C882E9814220000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000212")
|
||||
doAckBufSucceed(s, pkt.AckHandle, data)
|
||||
DoAckBufSucceed(s, pkt.AckHandle, data)
|
||||
}
|
||||
|
||||
func handleMsgMhfSetKiju(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfSetKiju)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
}
|
||||
|
||||
func handleMsgMhfAddUdPoint(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfAddUdPoint)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
}
|
||||
|
||||
func handleMsgMhfGetUdMyPoint(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetUdMyPoint)
|
||||
// Temporary canned response
|
||||
data, _ := hex.DecodeString("00040000013C000000FA000000000000000000040000007E0000003C02000000000000000000000000000000000000000000000000000002000004CC00000438000000000000000000000000000000000000000000000000000000020000026E00000230000000000000000000020000007D0000007D000000000000000000000000000000000000000000000000000000")
|
||||
doAckBufSucceed(s, pkt.AckHandle, data)
|
||||
DoAckBufSucceed(s, pkt.AckHandle, data)
|
||||
}
|
||||
|
||||
func handleMsgMhfGetUdTotalPointInfo(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetUdTotalPointInfo)
|
||||
// Temporary canned response
|
||||
data, _ := hex.DecodeString("00000000000007A12000000000000F424000000000001E848000000000002DC6C000000000003D090000000000004C4B4000000000005B8D8000000000006ACFC000000000007A1200000000000089544000000000009896800000000000E4E1C00000000001312D0000000000017D78400000000001C9C3800000000002160EC00000000002625A000000000002AEA5400000000002FAF0800000000003473BC0000000000393870000000000042C1D800000000004C4B40000000000055D4A800000000005F5E10000000000008954400000000001C9C3800000000003473BC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001020300000000000000000000000000000000000000000000000000000000000000000000000000000000101F1420")
|
||||
doAckBufSucceed(s, pkt.AckHandle, data)
|
||||
DoAckBufSucceed(s, pkt.AckHandle, data)
|
||||
}
|
||||
|
||||
func handleMsgMhfGetUdSelectedColorInfo(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetUdSelectedColorInfo)
|
||||
|
||||
// Unk
|
||||
doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x01, 0x01, 0x01, 0x02, 0x03, 0x02, 0x00, 0x00})
|
||||
DoAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x01, 0x01, 0x01, 0x02, 0x03, 0x02, 0x00, 0x00})
|
||||
}
|
||||
|
||||
func handleMsgMhfGetUdMonsterPoint(s *Session, p mhfpacket.MHFPacket) {
|
||||
@@ -287,36 +300,36 @@ func handleMsgMhfGetUdMonsterPoint(s *Session, p mhfpacket.MHFPacket) {
|
||||
resp.WriteUint16(mp.Points)
|
||||
}
|
||||
|
||||
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfGetUdDailyPresentList(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetUdDailyPresentList)
|
||||
// Temporary canned response
|
||||
data, _ := hex.DecodeString("0100001600000A5397DF00000000000000000000000000000000")
|
||||
doAckBufSucceed(s, pkt.AckHandle, data)
|
||||
DoAckBufSucceed(s, pkt.AckHandle, data)
|
||||
}
|
||||
|
||||
func handleMsgMhfGetUdNormaPresentList(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetUdNormaPresentList)
|
||||
// Temporary canned response
|
||||
data, _ := hex.DecodeString("0100001600000A5397DF00000000000000000000000000000000")
|
||||
doAckBufSucceed(s, pkt.AckHandle, data)
|
||||
DoAckBufSucceed(s, pkt.AckHandle, data)
|
||||
}
|
||||
|
||||
func handleMsgMhfAcquireUdItem(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfAcquireUdItem)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
}
|
||||
|
||||
func handleMsgMhfGetUdRanking(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetUdRanking)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
}
|
||||
|
||||
func handleMsgMhfGetUdMyRanking(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetUdMyRanking)
|
||||
// Temporary canned response
|
||||
data, _ := hex.DecodeString("00000515000005150000CEB4000003CE000003CE0000CEB44D49444E494748542D414E47454C0000000000000000000000")
|
||||
doAckBufSucceed(s, pkt.AckHandle, data)
|
||||
DoAckBufSucceed(s, pkt.AckHandle, data)
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package channelserver
|
||||
|
||||
import (
|
||||
_config "erupe-ce/config"
|
||||
"erupe-ce/config"
|
||||
"erupe-ce/utils/db"
|
||||
"erupe-ce/utils/gametime"
|
||||
"erupe-ce/utils/token"
|
||||
"fmt"
|
||||
"math"
|
||||
"time"
|
||||
|
||||
@@ -45,7 +47,7 @@ func handleMsgMhfEnumerateEvent(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
}
|
||||
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
type activeFeature struct {
|
||||
@@ -55,7 +57,10 @@ type activeFeature struct {
|
||||
|
||||
func handleMsgMhfGetWeeklySchedule(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetWeeklySchedule)
|
||||
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
var features []activeFeature
|
||||
times := []time.Time{
|
||||
gametime.TimeMidnight().Add(-24 * time.Hour),
|
||||
@@ -65,12 +70,12 @@ func handleMsgMhfGetWeeklySchedule(s *Session, p mhfpacket.MHFPacket) {
|
||||
|
||||
for _, t := range times {
|
||||
var temp activeFeature
|
||||
err := s.server.db.QueryRowx(`SELECT start_time, featured FROM feature_weapon WHERE start_time=$1`, t).StructScan(&temp)
|
||||
err := database.QueryRowx(`SELECT start_time, featured FROM feature_weapon WHERE start_time=$1`, t).StructScan(&temp)
|
||||
if err != nil || temp.StartTime.IsZero() {
|
||||
weapons := token.RNG.Intn(s.server.erupeConfig.GameplayOptions.MaxFeatureWeapons-s.server.erupeConfig.GameplayOptions.MinFeatureWeapons+1) + s.server.erupeConfig.GameplayOptions.MinFeatureWeapons
|
||||
weapons := token.RNG.Intn(config.GetConfig().GameplayOptions.MaxFeatureWeapons-config.GetConfig().GameplayOptions.MinFeatureWeapons+1) + config.GetConfig().GameplayOptions.MinFeatureWeapons
|
||||
temp = generateFeatureWeapons(weapons)
|
||||
temp.StartTime = t
|
||||
s.server.db.Exec(`INSERT INTO feature_weapon VALUES ($1, $2)`, temp.StartTime, temp.ActiveFeatures)
|
||||
database.Exec(`INSERT INTO feature_weapon VALUES ($1, $2)`, temp.StartTime, temp.ActiveFeatures)
|
||||
}
|
||||
features = append(features, temp)
|
||||
}
|
||||
@@ -83,18 +88,18 @@ func handleMsgMhfGetWeeklySchedule(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint32(feature.ActiveFeatures)
|
||||
bf.WriteUint16(0)
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func generateFeatureWeapons(count int) activeFeature {
|
||||
_max := 14
|
||||
if _config.ErupeConfig.ClientID < _config.ZZ {
|
||||
if config.GetConfig().ClientID < config.ZZ {
|
||||
_max = 13
|
||||
}
|
||||
if _config.ErupeConfig.ClientID < _config.G10 {
|
||||
if config.GetConfig().ClientID < config.G10 {
|
||||
_max = 12
|
||||
}
|
||||
if _config.ErupeConfig.ClientID < _config.GG {
|
||||
if config.GetConfig().ClientID < config.GG {
|
||||
_max = 11
|
||||
}
|
||||
if count > _max {
|
||||
@@ -131,14 +136,17 @@ type loginBoost struct {
|
||||
|
||||
func handleMsgMhfGetKeepLoginBoostStatus(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetKeepLoginBoostStatus)
|
||||
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
bf := byteframe.NewByteFrame()
|
||||
|
||||
var loginBoosts []loginBoost
|
||||
rows, err := s.server.db.Queryx("SELECT week_req, expiration, reset FROM login_boost WHERE char_id=$1 ORDER BY week_req", s.charID)
|
||||
if err != nil || s.server.erupeConfig.GameplayOptions.DisableLoginBoost {
|
||||
rows, err := database.Queryx("SELECT week_req, expiration, reset FROM login_boost WHERE char_id=$1 ORDER BY week_req", s.CharID)
|
||||
if err != nil || config.GetConfig().GameplayOptions.DisableLoginBoost {
|
||||
rows.Close()
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 35))
|
||||
DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 35))
|
||||
return
|
||||
}
|
||||
for rows.Next() {
|
||||
@@ -156,7 +164,7 @@ func handleMsgMhfGetKeepLoginBoostStatus(s *Session, p mhfpacket.MHFPacket) {
|
||||
{WeekReq: 5, Expiration: temp},
|
||||
}
|
||||
for _, boost := range loginBoosts {
|
||||
s.server.db.Exec(`INSERT INTO login_boost VALUES ($1, $2, $3, $4)`, s.charID, boost.WeekReq, boost.Expiration, time.Time{})
|
||||
database.Exec(`INSERT INTO login_boost VALUES ($1, $2, $3, $4)`, s.CharID, boost.WeekReq, boost.Expiration, time.Time{})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,7 +173,7 @@ func handleMsgMhfGetKeepLoginBoostStatus(s *Session, p mhfpacket.MHFPacket) {
|
||||
if !boost.Reset.IsZero() && boost.Reset.Before(gametime.TimeAdjusted()) {
|
||||
boost.Expiration = gametime.TimeWeekStart()
|
||||
boost.Reset = time.Time{}
|
||||
s.server.db.Exec(`UPDATE login_boost SET expiration=$1, reset=$2 WHERE char_id=$3 AND week_req=$4`, boost.Expiration, boost.Reset, s.charID, boost.WeekReq)
|
||||
database.Exec(`UPDATE login_boost SET expiration=$1, reset=$2 WHERE char_id=$3 AND week_req=$4`, boost.Expiration, boost.Reset, s.CharID, boost.WeekReq)
|
||||
}
|
||||
|
||||
boost.WeekCount = uint8((gametime.TimeAdjusted().Unix()-boost.Expiration.Unix())/604800 + 1)
|
||||
@@ -191,7 +199,7 @@ func handleMsgMhfGetKeepLoginBoostStatus(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
}
|
||||
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfUseKeepLoginBoost(s *Session, p mhfpacket.MHFPacket) {
|
||||
@@ -208,13 +216,17 @@ func handleMsgMhfUseKeepLoginBoost(s *Session, p mhfpacket.MHFPacket) {
|
||||
expiration = gametime.TimeAdjusted().Add(240 * time.Minute)
|
||||
}
|
||||
bf.WriteUint32(uint32(expiration.Unix()))
|
||||
s.server.db.Exec(`UPDATE login_boost SET expiration=$1, reset=$2 WHERE char_id=$3 AND week_req=$4`, expiration, gametime.TimeWeekNext(), s.charID, pkt.BoostWeekUsed)
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
database.Exec(`UPDATE login_boost SET expiration=$1, reset=$2 WHERE char_id=$3 AND week_req=$4`, expiration, gametime.TimeWeekNext(), s.CharID, pkt.BoostWeekUsed)
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfGetRestrictionEvent(s *Session, p mhfpacket.MHFPacket) {}
|
||||
|
||||
func handleMsgMhfSetRestrictionEvent(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfSetRestrictionEvent)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
@@ -1,26 +1,36 @@
|
||||
package channelserver
|
||||
|
||||
import (
|
||||
_config "erupe-ce/config"
|
||||
"erupe-ce/config"
|
||||
"erupe-ce/network/mhfpacket"
|
||||
"erupe-ce/utils/byteframe"
|
||||
"erupe-ce/utils/db"
|
||||
"erupe-ce/utils/gametime"
|
||||
ps "erupe-ce/utils/pascalstring"
|
||||
"erupe-ce/utils/token"
|
||||
"fmt"
|
||||
"sort"
|
||||
"time"
|
||||
)
|
||||
|
||||
func handleMsgMhfSaveMezfesData(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfSaveMezfesData)
|
||||
s.server.db.Exec(`UPDATE characters SET mezfes=$1 WHERE id=$2`, pkt.RawDataPayload, s.charID)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
database.Exec(`UPDATE characters SET mezfes=$1 WHERE id=$2`, pkt.RawDataPayload, s.CharID)
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
}
|
||||
|
||||
func handleMsgMhfLoadMezfesData(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfLoadMezfesData)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
var data []byte
|
||||
s.server.db.QueryRow(`SELECT mezfes FROM characters WHERE id=$1`, s.charID).Scan(&data)
|
||||
database.QueryRow(`SELECT mezfes FROM characters WHERE id=$1`, s.CharID).Scan(&data)
|
||||
bf := byteframe.NewByteFrame()
|
||||
if len(data) > 0 {
|
||||
bf.WriteBytes(data)
|
||||
@@ -31,13 +41,13 @@ func handleMsgMhfLoadMezfesData(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint32(0)
|
||||
bf.WriteUint32(0)
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfEnumerateRanking(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfEnumerateRanking)
|
||||
bf := byteframe.NewByteFrame()
|
||||
state := s.server.erupeConfig.DebugOptions.TournamentOverride
|
||||
state := config.GetConfig().DebugOptions.TournamentOverride
|
||||
// Unk
|
||||
// Unk
|
||||
// Start?
|
||||
@@ -64,7 +74,7 @@ func handleMsgMhfEnumerateRanking(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint32(uint32(gametime.TimeAdjusted().Unix())) // TS Current Time
|
||||
bf.WriteUint8(3)
|
||||
bf.WriteBytes(make([]byte, 4))
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
return
|
||||
}
|
||||
bf.WriteUint32(uint32(gametime.TimeAdjusted().Unix())) // TS Current Time
|
||||
@@ -90,18 +100,26 @@ func handleMsgMhfEnumerateRanking(s *Session, p mhfpacket.MHFPacket) {
|
||||
psUint16 desc
|
||||
*/
|
||||
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func cleanupFesta(s *Session) {
|
||||
s.server.db.Exec("DELETE FROM events WHERE event_type='festa'")
|
||||
s.server.db.Exec("DELETE FROM festa_registrations")
|
||||
s.server.db.Exec("DELETE FROM festa_submissions")
|
||||
s.server.db.Exec("DELETE FROM festa_prizes_accepted")
|
||||
s.server.db.Exec("UPDATE guild_characters SET trial_vote=NULL")
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
database.Exec("DELETE FROM events WHERE event_type='festa'")
|
||||
database.Exec("DELETE FROM festa_registrations")
|
||||
database.Exec("DELETE FROM festa_submissions")
|
||||
database.Exec("DELETE FROM festa_prizes_accepted")
|
||||
database.Exec("UPDATE guild_characters SET trial_vote=NULL")
|
||||
}
|
||||
|
||||
func generateFestaTimestamps(s *Session, start uint32, debug bool) []uint32 {
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
timestamps := make([]uint32, 5)
|
||||
midnight := gametime.TimeMidnight()
|
||||
if debug && start <= 3 {
|
||||
@@ -132,7 +150,7 @@ func generateFestaTimestamps(s *Session, start uint32, debug bool) []uint32 {
|
||||
cleanupFesta(s)
|
||||
// Generate a new festa, starting midnight tomorrow
|
||||
start = uint32(midnight.Add(24 * time.Hour).Unix())
|
||||
s.server.db.Exec("INSERT INTO events (event_type, start_time) VALUES ('festa', to_timestamp($1)::timestamp without time zone)", start)
|
||||
database.Exec("INSERT INTO events (event_type, start_time) VALUES ('festa', to_timestamp($1)::timestamp without time zone)", start)
|
||||
}
|
||||
timestamps[0] = start
|
||||
timestamps[1] = timestamps[0] + 604800
|
||||
@@ -167,32 +185,35 @@ type FestaReward struct {
|
||||
func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfInfoFesta)
|
||||
bf := byteframe.NewByteFrame()
|
||||
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
id, start := uint32(0xDEADBEEF), uint32(0)
|
||||
rows, _ := s.server.db.Queryx("SELECT id, (EXTRACT(epoch FROM start_time)::int) as start_time FROM events WHERE event_type='festa'")
|
||||
rows, _ := database.Queryx("SELECT id, (EXTRACT(epoch FROM start_time)::int) as start_time FROM events WHERE event_type='festa'")
|
||||
for rows.Next() {
|
||||
rows.Scan(&id, &start)
|
||||
}
|
||||
|
||||
var timestamps []uint32
|
||||
if s.server.erupeConfig.DebugOptions.FestaOverride >= 0 {
|
||||
if s.server.erupeConfig.DebugOptions.FestaOverride == 0 {
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
if config.GetConfig().DebugOptions.FestaOverride >= 0 {
|
||||
if config.GetConfig().DebugOptions.FestaOverride == 0 {
|
||||
DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
timestamps = generateFestaTimestamps(s, uint32(s.server.erupeConfig.DebugOptions.FestaOverride), true)
|
||||
timestamps = generateFestaTimestamps(s, uint32(config.GetConfig().DebugOptions.FestaOverride), true)
|
||||
} else {
|
||||
timestamps = generateFestaTimestamps(s, start, false)
|
||||
}
|
||||
|
||||
if timestamps[0] > uint32(gametime.TimeAdjusted().Unix()) {
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
|
||||
var blueSouls, redSouls uint32
|
||||
s.server.db.QueryRow(`SELECT COALESCE(SUM(fs.souls), 0) AS souls FROM festa_registrations fr LEFT JOIN festa_submissions fs ON fr.guild_id = fs.guild_id AND fr.team = 'blue'`).Scan(&blueSouls)
|
||||
s.server.db.QueryRow(`SELECT COALESCE(SUM(fs.souls), 0) AS souls FROM festa_registrations fr LEFT JOIN festa_submissions fs ON fr.guild_id = fs.guild_id AND fr.team = 'red'`).Scan(&redSouls)
|
||||
database.QueryRow(`SELECT COALESCE(SUM(fs.souls), 0) AS souls FROM festa_registrations fr LEFT JOIN festa_submissions fs ON fr.guild_id = fs.guild_id AND fr.team = 'blue'`).Scan(&blueSouls)
|
||||
database.QueryRow(`SELECT COALESCE(SUM(fs.souls), 0) AS souls FROM festa_registrations fr LEFT JOIN festa_submissions fs ON fr.guild_id = fs.guild_id AND fr.team = 'red'`).Scan(&redSouls)
|
||||
|
||||
bf.WriteUint32(id)
|
||||
for _, timestamp := range timestamps {
|
||||
@@ -207,7 +228,7 @@ func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) {
|
||||
|
||||
var trials []FestaTrial
|
||||
var trial FestaTrial
|
||||
rows, _ = s.server.db.Queryx(`SELECT ft.*,
|
||||
rows, _ = database.Queryx(`SELECT ft.*,
|
||||
COALESCE(CASE
|
||||
WHEN COUNT(gc.id) FILTER (WHERE fr.team = 'blue' AND gc.trial_vote = ft.id) >
|
||||
COUNT(gc.id) FILTER (WHERE fr.team = 'red' AND gc.trial_vote = ft.id)
|
||||
@@ -236,7 +257,7 @@ func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint16(trial.Locale)
|
||||
bf.WriteUint16(trial.Reward)
|
||||
bf.WriteInt16(FestivalColorCodes[trial.Monopoly])
|
||||
if _config.ErupeConfig.ClientID >= _config.F4 { // Not in S6.0
|
||||
if config.GetConfig().ClientID >= config.F4 { // Not in S6.0
|
||||
bf.WriteUint16(trial.Unk)
|
||||
}
|
||||
}
|
||||
@@ -279,19 +300,19 @@ func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint16(reward.Quantity)
|
||||
bf.WriteUint16(reward.ItemID)
|
||||
// Not confirmed to be G1 but exists in G3
|
||||
if _config.ErupeConfig.ClientID >= _config.G1 {
|
||||
if config.GetConfig().ClientID >= config.G1 {
|
||||
bf.WriteUint16(reward.Unk5)
|
||||
bf.WriteUint16(reward.Unk6)
|
||||
bf.WriteUint8(reward.Unk7)
|
||||
}
|
||||
}
|
||||
if _config.ErupeConfig.ClientID <= _config.G61 {
|
||||
if s.server.erupeConfig.GameplayOptions.MaximumFP > 0xFFFF {
|
||||
s.server.erupeConfig.GameplayOptions.MaximumFP = 0xFFFF
|
||||
if config.GetConfig().ClientID <= config.G61 {
|
||||
if config.GetConfig().GameplayOptions.MaximumFP > 0xFFFF {
|
||||
config.GetConfig().GameplayOptions.MaximumFP = 0xFFFF
|
||||
}
|
||||
bf.WriteUint16(uint16(s.server.erupeConfig.GameplayOptions.MaximumFP))
|
||||
bf.WriteUint16(uint16(config.GetConfig().GameplayOptions.MaximumFP))
|
||||
} else {
|
||||
bf.WriteUint32(s.server.erupeConfig.GameplayOptions.MaximumFP)
|
||||
bf.WriteUint32(config.GetConfig().GameplayOptions.MaximumFP)
|
||||
}
|
||||
bf.WriteUint16(100) // Reward multiplier (%)
|
||||
|
||||
@@ -301,7 +322,7 @@ func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) {
|
||||
var guildID uint32
|
||||
var guildName string
|
||||
var guildTeam = FestivalColorNone
|
||||
s.server.db.QueryRow(`
|
||||
database.QueryRow(`
|
||||
SELECT fs.guild_id, g.name, fr.team, SUM(fs.souls) as _
|
||||
FROM festa_submissions fs
|
||||
LEFT JOIN festa_registrations fr ON fs.guild_id = fr.guild_id
|
||||
@@ -321,7 +342,7 @@ func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) {
|
||||
var guildName string
|
||||
var guildTeam = FestivalColorNone
|
||||
offset := 86400 * uint32(i)
|
||||
s.server.db.QueryRow(`
|
||||
database.QueryRow(`
|
||||
SELECT fs.guild_id, g.name, fr.team, SUM(fs.souls) as _
|
||||
FROM festa_submissions fs
|
||||
LEFT JOIN festa_registrations fr ON fs.guild_id = fr.guild_id
|
||||
@@ -348,27 +369,31 @@ func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint16(100) // Normal rate
|
||||
bf.WriteUint16(50) // 50% penalty
|
||||
|
||||
if _config.ErupeConfig.ClientID >= _config.G52 {
|
||||
if config.GetConfig().ClientID >= config.G52 {
|
||||
ps.Uint16(bf, "", false)
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
// state festa (U)ser
|
||||
func handleMsgMhfStateFestaU(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfStateFestaU)
|
||||
guild, err := GetGuildInfoByCharacterId(s, s.charID)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
guild, err := GetGuildInfoByCharacterId(s, s.CharID)
|
||||
applicant := false
|
||||
if guild != nil {
|
||||
applicant, _ = guild.HasApplicationForCharID(s, s.charID)
|
||||
applicant, _ = guild.HasApplicationForCharID(s, s.CharID)
|
||||
}
|
||||
if err != nil || guild == nil || applicant {
|
||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
var souls, exists uint32
|
||||
s.server.db.QueryRow(`SELECT COALESCE((SELECT SUM(souls) FROM festa_submissions WHERE character_id=$1), 0)`, 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)
|
||||
database.QueryRow(`SELECT COALESCE((SELECT SUM(souls) FROM festa_submissions WHERE character_id=$1), 0)`, s.CharID).Scan(&souls)
|
||||
err = database.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)
|
||||
if err != nil {
|
||||
@@ -378,16 +403,16 @@ func handleMsgMhfStateFestaU(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteBool(false)
|
||||
bf.WriteBool(true)
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
// state festa (G)uild
|
||||
func handleMsgMhfStateFestaG(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfStateFestaG)
|
||||
guild, err := GetGuildInfoByCharacterId(s, s.charID)
|
||||
guild, err := GetGuildInfoByCharacterId(s, s.CharID)
|
||||
applicant := false
|
||||
if guild != nil {
|
||||
applicant, _ = guild.HasApplicationForCharID(s, s.charID)
|
||||
applicant, _ = guild.HasApplicationForCharID(s, s.CharID)
|
||||
}
|
||||
resp := byteframe.NewByteFrame()
|
||||
if err != nil || guild == nil || applicant {
|
||||
@@ -396,7 +421,7 @@ func handleMsgMhfStateFestaG(s *Session, p mhfpacket.MHFPacket) {
|
||||
resp.WriteInt32(-1)
|
||||
resp.WriteInt32(0)
|
||||
resp.WriteInt32(0)
|
||||
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
return
|
||||
}
|
||||
resp.WriteUint32(guild.Souls)
|
||||
@@ -404,19 +429,19 @@ func handleMsgMhfStateFestaG(s *Session, p mhfpacket.MHFPacket) {
|
||||
resp.WriteInt32(1) // unk, rank?
|
||||
resp.WriteInt32(1) // unk
|
||||
resp.WriteInt32(1) // unk
|
||||
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfEnumerateFestaMember(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfEnumerateFestaMember)
|
||||
guild, err := GetGuildInfoByCharacterId(s, s.charID)
|
||||
guild, err := GetGuildInfoByCharacterId(s, s.CharID)
|
||||
if err != nil || guild == nil {
|
||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
members, err := GetGuildMembers(s, guild.ID, false)
|
||||
if err != nil {
|
||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
sort.Slice(members, func(i, j int) bool {
|
||||
@@ -433,70 +458,94 @@ func handleMsgMhfEnumerateFestaMember(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint16(0) // Unk
|
||||
for _, member := range validMembers {
|
||||
bf.WriteUint32(member.CharID)
|
||||
if _config.ErupeConfig.ClientID <= _config.Z1 {
|
||||
if config.GetConfig().ClientID <= config.Z1 {
|
||||
bf.WriteUint16(uint16(member.Souls))
|
||||
bf.WriteUint16(0)
|
||||
} else {
|
||||
bf.WriteUint32(member.Souls)
|
||||
}
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfVoteFesta(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfVoteFesta)
|
||||
s.server.db.Exec(`UPDATE guild_characters SET trial_vote=$1 WHERE character_id=$2`, pkt.TrialID, s.charID)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
database.Exec(`UPDATE guild_characters SET trial_vote=$1 WHERE character_id=$2`, pkt.TrialID, s.CharID)
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func handleMsgMhfEntryFesta(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfEntryFesta)
|
||||
guild, err := GetGuildInfoByCharacterId(s, s.charID)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
guild, err := GetGuildInfoByCharacterId(s, s.CharID)
|
||||
if err != nil || guild == nil {
|
||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
team := uint32(token.RNG.Intn(2))
|
||||
switch team {
|
||||
case 0:
|
||||
s.server.db.Exec("INSERT INTO festa_registrations VALUES ($1, 'blue')", guild.ID)
|
||||
database.Exec("INSERT INTO festa_registrations VALUES ($1, 'blue')", guild.ID)
|
||||
case 1:
|
||||
s.server.db.Exec("INSERT INTO festa_registrations VALUES ($1, 'red')", guild.ID)
|
||||
database.Exec("INSERT INTO festa_registrations VALUES ($1, 'red')", guild.ID)
|
||||
}
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint32(team)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfChargeFesta(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfChargeFesta)
|
||||
tx, _ := s.server.db.Begin()
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
tx, _ := database.Begin()
|
||||
for i := range pkt.Souls {
|
||||
if pkt.Souls[i] == 0 {
|
||||
continue
|
||||
}
|
||||
_, _ = tx.Exec(`INSERT INTO festa_submissions VALUES ($1, $2, $3, $4, now())`, s.charID, pkt.GuildID, i, pkt.Souls[i])
|
||||
_, _ = tx.Exec(`INSERT INTO festa_submissions VALUES ($1, $2, $3, $4, now())`, s.CharID, pkt.GuildID, i, pkt.Souls[i])
|
||||
}
|
||||
_ = tx.Commit()
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
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))
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
database.Exec("INSERT INTO public.festa_prizes_accepted VALUES (0, $1)", s.CharID)
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func handleMsgMhfAcquireFestaPersonalPrize(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfAcquireFestaPersonalPrize)
|
||||
s.server.db.Exec("INSERT INTO public.festa_prizes_accepted VALUES ($1, $2)", pkt.PrizeID, s.charID)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
database.Exec("INSERT INTO public.festa_prizes_accepted VALUES ($1, $2)", pkt.PrizeID, s.CharID)
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func handleMsgMhfAcquireFestaIntermediatePrize(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfAcquireFestaIntermediatePrize)
|
||||
s.server.db.Exec("INSERT INTO public.festa_prizes_accepted VALUES ($1, $2)", pkt.PrizeID, s.charID)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
database.Exec("INSERT INTO public.festa_prizes_accepted VALUES ($1, $2)", pkt.PrizeID, s.CharID)
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
type Prize struct {
|
||||
@@ -510,7 +559,11 @@ 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 = $1) AS claimed FROM festa_prizes fp WHERE type='personal'`, s.charID)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
rows, _ := database.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() {
|
||||
@@ -531,12 +584,16 @@ func handleMsgMhfEnumerateFestaPersonalPrize(s *Session, p mhfpacket.MHFPacket)
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint32(count)
|
||||
bf.WriteBytes(prizeData.Data())
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
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 = $1) AS claimed FROM festa_prizes fp WHERE type='guild'`, s.charID)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
rows, _ := database.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() {
|
||||
@@ -557,5 +614,5 @@ func handleMsgMhfEnumerateFestaIntermediatePrize(s *Session, p mhfpacket.MHFPack
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint32(count)
|
||||
bf.WriteBytes(prizeData.Data())
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,12 @@
|
||||
package channelserver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"erupe-ce/network/mhfpacket"
|
||||
"erupe-ce/utils/byteframe"
|
||||
"erupe-ce/utils/db"
|
||||
"erupe-ce/utils/gametime"
|
||||
"erupe-ce/utils/stringsupport"
|
||||
|
||||
@@ -20,13 +22,17 @@ type GuildAdventure struct {
|
||||
CollectedBy string `db:"collected_by"`
|
||||
}
|
||||
|
||||
func handleMsgMhfLoadGuildAdventure(s *Session, p mhfpacket.MHFPacket) {
|
||||
func HandleMsgMhfLoadGuildAdventure(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfLoadGuildAdventure)
|
||||
guild, _ := GetGuildInfoByCharacterId(s, s.charID)
|
||||
data, err := s.server.db.Queryx("SELECT id, destination, charge, depart, return, collected_by FROM guild_adventures WHERE guild_id = $1", guild.ID)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get guild adventures from db", zap.Error(err))
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 1))
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
guild, _ := GetGuildInfoByCharacterId(s, s.CharID)
|
||||
data, err := database.Queryx("SELECT id, destination, charge, depart, return, collected_by FROM guild_adventures WHERE guild_id = $1", guild.ID)
|
||||
if err != nil {
|
||||
s.Logger.Error("Failed to get guild adventures from db", zap.Error(err))
|
||||
DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 1))
|
||||
return
|
||||
}
|
||||
temp := byteframe.NewByteFrame()
|
||||
@@ -43,55 +49,71 @@ func handleMsgMhfLoadGuildAdventure(s *Session, p mhfpacket.MHFPacket) {
|
||||
temp.WriteUint32(adventureData.Charge)
|
||||
temp.WriteUint32(adventureData.Depart)
|
||||
temp.WriteUint32(adventureData.Return)
|
||||
temp.WriteBool(stringsupport.CSVContains(adventureData.CollectedBy, int(s.charID)))
|
||||
temp.WriteBool(stringsupport.CSVContains(adventureData.CollectedBy, int(s.CharID)))
|
||||
}
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint8(uint8(count))
|
||||
bf.WriteBytes(temp.Data())
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfRegistGuildAdventure(s *Session, p mhfpacket.MHFPacket) {
|
||||
func HandleMsgMhfRegistGuildAdventure(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfRegistGuildAdventure)
|
||||
guild, _ := GetGuildInfoByCharacterId(s, s.charID)
|
||||
_, err := s.server.db.Exec("INSERT INTO guild_adventures (guild_id, destination, depart, return) VALUES ($1, $2, $3, $4)", guild.ID, pkt.Destination, gametime.TimeAdjusted().Unix(), gametime.TimeAdjusted().Add(6*time.Hour).Unix())
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to register guild adventure", zap.Error(err))
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
guild, _ := GetGuildInfoByCharacterId(s, s.CharID)
|
||||
_, err = database.Exec("INSERT INTO guild_adventures (guild_id, destination, depart, return) VALUES ($1, $2, $3, $4)", guild.ID, pkt.Destination, gametime.TimeAdjusted().Unix(), gametime.TimeAdjusted().Add(6*time.Hour).Unix())
|
||||
if err != nil {
|
||||
s.Logger.Error("Failed to register guild adventure", zap.Error(err))
|
||||
}
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func handleMsgMhfAcquireGuildAdventure(s *Session, p mhfpacket.MHFPacket) {
|
||||
func HandleMsgMhfAcquireGuildAdventure(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfAcquireGuildAdventure)
|
||||
var collectedBy string
|
||||
err := s.server.db.QueryRow("SELECT collected_by FROM guild_adventures WHERE id = $1", pkt.ID).Scan(&collectedBy)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.logger.Error("Error parsing adventure collected by", zap.Error(err))
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
var collectedBy string
|
||||
err = database.QueryRow("SELECT collected_by FROM guild_adventures WHERE id = $1", pkt.ID).Scan(&collectedBy)
|
||||
if err != nil {
|
||||
s.Logger.Error("Error parsing adventure collected by", zap.Error(err))
|
||||
} else {
|
||||
collectedBy = stringsupport.CSVAdd(collectedBy, int(s.charID))
|
||||
_, err := s.server.db.Exec("UPDATE guild_adventures SET collected_by = $1 WHERE id = $2", collectedBy, pkt.ID)
|
||||
collectedBy = stringsupport.CSVAdd(collectedBy, int(s.CharID))
|
||||
_, err := database.Exec("UPDATE guild_adventures SET collected_by = $1 WHERE id = $2", collectedBy, pkt.ID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to collect adventure in db", zap.Error(err))
|
||||
s.Logger.Error("Failed to collect adventure in db", zap.Error(err))
|
||||
}
|
||||
}
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func handleMsgMhfChargeGuildAdventure(s *Session, p mhfpacket.MHFPacket) {
|
||||
func HandleMsgMhfChargeGuildAdventure(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfChargeGuildAdventure)
|
||||
_, err := s.server.db.Exec("UPDATE guild_adventures SET charge = charge + $1 WHERE id = $2", pkt.Amount, pkt.ID)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to charge guild adventure", zap.Error(err))
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
_, err = database.Exec("UPDATE guild_adventures SET charge = charge + $1 WHERE id = $2", pkt.Amount, pkt.ID)
|
||||
if err != nil {
|
||||
s.Logger.Error("Failed to charge guild adventure", zap.Error(err))
|
||||
}
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func handleMsgMhfRegistGuildAdventureDiva(s *Session, p mhfpacket.MHFPacket) {
|
||||
func HandleMsgMhfRegistGuildAdventureDiva(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfRegistGuildAdventureDiva)
|
||||
guild, _ := GetGuildInfoByCharacterId(s, s.charID)
|
||||
_, err := s.server.db.Exec("INSERT INTO guild_adventures (guild_id, destination, charge, depart, return) VALUES ($1, $2, $3, $4, $5)", guild.ID, pkt.Destination, pkt.Charge, gametime.TimeAdjusted().Unix(), gametime.TimeAdjusted().Add(1*time.Hour).Unix())
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to register guild adventure", zap.Error(err))
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
guild, _ := GetGuildInfoByCharacterId(s, s.CharID)
|
||||
_, err = database.Exec("INSERT INTO guild_adventures (guild_id, destination, charge, depart, return) VALUES ($1, $2, $3, $4, $5)", guild.ID, pkt.Destination, pkt.Charge, gametime.TimeAdjusted().Unix(), gametime.TimeAdjusted().Add(1*time.Hour).Unix())
|
||||
if err != nil {
|
||||
s.Logger.Error("Failed to register guild adventure", zap.Error(err))
|
||||
}
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package channelserver
|
||||
|
||||
import (
|
||||
"erupe-ce/utils/byteframe"
|
||||
"erupe-ce/utils/db"
|
||||
ps "erupe-ce/utils/pascalstring"
|
||||
"fmt"
|
||||
"time"
|
||||
@@ -45,12 +46,16 @@ type GuildAlliance struct {
|
||||
}
|
||||
|
||||
func GetAllianceData(s *Session, AllianceID uint32) (*GuildAlliance, error) {
|
||||
rows, err := s.server.db.Queryx(fmt.Sprintf(`
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
rows, err := database.Queryx(fmt.Sprintf(`
|
||||
%s
|
||||
WHERE ga.id = $1
|
||||
`, allianceInfoSelectQuery), AllianceID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to retrieve alliance data from database", zap.Error(err))
|
||||
s.Logger.Error("Failed to retrieve alliance data from database", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
@@ -68,13 +73,13 @@ func buildAllianceObjectFromDbResult(result *sqlx.Rows, err error, s *Session) (
|
||||
err = result.StructScan(alliance)
|
||||
|
||||
if err != nil {
|
||||
s.logger.Error("failed to retrieve alliance from database", zap.Error(err))
|
||||
s.Logger.Error("failed to retrieve alliance from database", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
parentGuild, err := GetGuildInfoByID(s, alliance.ParentGuildID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get parent guild info", zap.Error(err))
|
||||
s.Logger.Error("Failed to get parent guild info", zap.Error(err))
|
||||
return nil, err
|
||||
} else {
|
||||
alliance.ParentGuild = *parentGuild
|
||||
@@ -84,7 +89,7 @@ func buildAllianceObjectFromDbResult(result *sqlx.Rows, err error, s *Session) (
|
||||
if alliance.SubGuild1ID > 0 {
|
||||
subGuild1, err := GetGuildInfoByID(s, alliance.SubGuild1ID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get sub guild 1 info", zap.Error(err))
|
||||
s.Logger.Error("Failed to get sub guild 1 info", zap.Error(err))
|
||||
return nil, err
|
||||
} else {
|
||||
alliance.SubGuild1 = *subGuild1
|
||||
@@ -95,7 +100,7 @@ func buildAllianceObjectFromDbResult(result *sqlx.Rows, err error, s *Session) (
|
||||
if alliance.SubGuild2ID > 0 {
|
||||
subGuild2, err := GetGuildInfoByID(s, alliance.SubGuild2ID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get sub guild 2 info", zap.Error(err))
|
||||
s.Logger.Error("Failed to get sub guild 2 info", zap.Error(err))
|
||||
return nil, err
|
||||
} else {
|
||||
alliance.SubGuild2 = *subGuild2
|
||||
@@ -106,92 +111,99 @@ func buildAllianceObjectFromDbResult(result *sqlx.Rows, err error, s *Session) (
|
||||
return alliance, nil
|
||||
}
|
||||
|
||||
func handleMsgMhfCreateJoint(s *Session, p mhfpacket.MHFPacket) {
|
||||
func HandleMsgMhfCreateJoint(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfCreateJoint)
|
||||
_, err := s.server.db.Exec("INSERT INTO guild_alliances (name, parent_id) VALUES ($1, $2)", pkt.Name, pkt.GuildID)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to create guild alliance in db", zap.Error(err))
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x01, 0x01, 0x01, 0x01})
|
||||
_, err = database.Exec("INSERT INTO guild_alliances (name, parent_id) VALUES ($1, $2)", pkt.Name, pkt.GuildID)
|
||||
if err != nil {
|
||||
s.Logger.Error("Failed to create guild alliance in db", zap.Error(err))
|
||||
}
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x01, 0x01, 0x01, 0x01})
|
||||
}
|
||||
|
||||
func handleMsgMhfOperateJoint(s *Session, p mhfpacket.MHFPacket) {
|
||||
func HandleMsgMhfOperateJoint(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfOperateJoint)
|
||||
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
guild, err := GetGuildInfoByID(s, pkt.GuildID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get guild info", zap.Error(err))
|
||||
s.Logger.Error("Failed to get guild info", zap.Error(err))
|
||||
}
|
||||
alliance, err := GetAllianceData(s, pkt.AllianceID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get alliance info", zap.Error(err))
|
||||
s.Logger.Error("Failed to get alliance info", zap.Error(err))
|
||||
}
|
||||
|
||||
switch pkt.Action {
|
||||
case mhfpacket.OPERATE_JOINT_DISBAND:
|
||||
if guild.LeaderCharID == s.charID && alliance.ParentGuildID == guild.ID {
|
||||
_, err = s.server.db.Exec("DELETE FROM guild_alliances WHERE id=$1", alliance.ID)
|
||||
if guild.LeaderCharID == s.CharID && alliance.ParentGuildID == guild.ID {
|
||||
_, err = database.Exec("DELETE FROM guild_alliances WHERE id=$1", alliance.ID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to disband alliance", zap.Error(err))
|
||||
s.Logger.Error("Failed to disband alliance", zap.Error(err))
|
||||
}
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
} else {
|
||||
s.logger.Warn(
|
||||
s.Logger.Warn(
|
||||
"Non-owner of alliance attempted disband",
|
||||
zap.Uint32("CharID", s.charID),
|
||||
zap.Uint32("CharID", s.CharID),
|
||||
zap.Uint32("AllyID", alliance.ID),
|
||||
)
|
||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
case mhfpacket.OPERATE_JOINT_LEAVE:
|
||||
if guild.LeaderCharID == s.charID {
|
||||
if guild.LeaderCharID == s.CharID {
|
||||
if guild.ID == alliance.SubGuild1ID && alliance.SubGuild2ID > 0 {
|
||||
s.server.db.Exec(`UPDATE guild_alliances SET sub1_id = sub2_id, sub2_id = NULL WHERE id = $1`, alliance.ID)
|
||||
database.Exec(`UPDATE guild_alliances SET sub1_id = sub2_id, sub2_id = NULL WHERE id = $1`, alliance.ID)
|
||||
} else if guild.ID == alliance.SubGuild1ID && alliance.SubGuild2ID == 0 {
|
||||
s.server.db.Exec(`UPDATE guild_alliances SET sub1_id = NULL WHERE id = $1`, alliance.ID)
|
||||
database.Exec(`UPDATE guild_alliances SET sub1_id = NULL WHERE id = $1`, alliance.ID)
|
||||
} else {
|
||||
s.server.db.Exec(`UPDATE guild_alliances SET sub2_id = NULL WHERE id = $1`, alliance.ID)
|
||||
database.Exec(`UPDATE guild_alliances SET sub2_id = NULL WHERE id = $1`, alliance.ID)
|
||||
}
|
||||
// TODO: Handle deleting Alliance applications
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
} else {
|
||||
s.logger.Warn(
|
||||
s.Logger.Warn(
|
||||
"Non-owner of guild attempted alliance leave",
|
||||
zap.Uint32("CharID", s.charID),
|
||||
zap.Uint32("CharID", s.CharID),
|
||||
)
|
||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
case mhfpacket.OPERATE_JOINT_KICK:
|
||||
if alliance.ParentGuild.LeaderCharID == s.charID {
|
||||
if alliance.ParentGuild.LeaderCharID == s.CharID {
|
||||
kickedGuildID := pkt.Data1.ReadUint32()
|
||||
if kickedGuildID == alliance.SubGuild1ID && alliance.SubGuild2ID > 0 {
|
||||
s.server.db.Exec(`UPDATE guild_alliances SET sub1_id = sub2_id, sub2_id = NULL WHERE id = $1`, alliance.ID)
|
||||
database.Exec(`UPDATE guild_alliances SET sub1_id = sub2_id, sub2_id = NULL WHERE id = $1`, alliance.ID)
|
||||
} else if kickedGuildID == alliance.SubGuild1ID && alliance.SubGuild2ID == 0 {
|
||||
s.server.db.Exec(`UPDATE guild_alliances SET sub1_id = NULL WHERE id = $1`, alliance.ID)
|
||||
database.Exec(`UPDATE guild_alliances SET sub1_id = NULL WHERE id = $1`, alliance.ID)
|
||||
} else {
|
||||
s.server.db.Exec(`UPDATE guild_alliances SET sub2_id = NULL WHERE id = $1`, alliance.ID)
|
||||
database.Exec(`UPDATE guild_alliances SET sub2_id = NULL WHERE id = $1`, alliance.ID)
|
||||
}
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
} else {
|
||||
s.logger.Warn(
|
||||
s.Logger.Warn(
|
||||
"Non-owner of alliance attempted kick",
|
||||
zap.Uint32("CharID", s.charID),
|
||||
zap.Uint32("CharID", s.CharID),
|
||||
zap.Uint32("AllyID", alliance.ID),
|
||||
)
|
||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
default:
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
panic(fmt.Sprintf("Unhandled operate joint action '%d'", pkt.Action))
|
||||
}
|
||||
}
|
||||
|
||||
func handleMsgMhfInfoJoint(s *Session, p mhfpacket.MHFPacket) {
|
||||
func HandleMsgMhfInfoJoint(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfInfoJoint)
|
||||
bf := byteframe.NewByteFrame()
|
||||
alliance, err := GetAllianceData(s, pkt.AllianceID)
|
||||
if err != nil {
|
||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
} else {
|
||||
bf.WriteUint32(alliance.ID)
|
||||
bf.WriteUint32(uint32(alliance.CreatedAt.Unix()))
|
||||
@@ -229,6 +241,6 @@ func handleMsgMhfInfoJoint(s *Session, p mhfpacket.MHFPacket) {
|
||||
ps.Uint16(bf, alliance.SubGuild2.Name, true)
|
||||
ps.Uint16(bf, alliance.SubGuild2.LeaderName, true)
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package channelserver
|
||||
|
||||
import (
|
||||
"erupe-ce/utils/db"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
@@ -46,10 +47,14 @@ func (gm *GuildMember) IsSubLeader() bool {
|
||||
}
|
||||
|
||||
func (gm *GuildMember) Save(s *Session) error {
|
||||
_, err := s.server.db.Exec("UPDATE guild_characters SET avoid_leadership=$1, order_index=$2 WHERE character_id=$3", gm.AvoidLeadership, gm.OrderIndex, gm.CharID)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
_, err = database.Exec("UPDATE guild_characters SET avoid_leadership=$1, order_index=$2 WHERE character_id=$3", gm.AvoidLeadership, gm.OrderIndex, gm.CharID)
|
||||
|
||||
if err != nil {
|
||||
s.logger.Error(
|
||||
s.Logger.Error(
|
||||
"failed to update guild member data",
|
||||
zap.Error(err),
|
||||
zap.Uint32("charID", gm.CharID),
|
||||
@@ -87,13 +92,17 @@ SELECT * FROM (
|
||||
`
|
||||
|
||||
func GetGuildMembers(s *Session, guildID uint32, applicants bool) ([]*GuildMember, error) {
|
||||
rows, err := s.server.db.Queryx(fmt.Sprintf(`
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
rows, err := database.Queryx(fmt.Sprintf(`
|
||||
%s
|
||||
WHERE guild_id = $1 AND is_applicant = $2
|
||||
`, guildMembersSelectSQL), guildID, applicants)
|
||||
|
||||
if err != nil {
|
||||
s.logger.Error("failed to retrieve membership data for guild", zap.Error(err), zap.Uint32("guildID", guildID))
|
||||
s.Logger.Error("failed to retrieve membership data for guild", zap.Error(err), zap.Uint32("guildID", guildID))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -115,10 +124,15 @@ func GetGuildMembers(s *Session, guildID uint32, applicants bool) ([]*GuildMembe
|
||||
}
|
||||
|
||||
func GetCharacterGuildData(s *Session, charID uint32) (*GuildMember, error) {
|
||||
rows, err := s.server.db.Queryx(fmt.Sprintf("%s WHERE character_id=$1", guildMembersSelectSQL), charID)
|
||||
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
rows, err := database.Queryx(fmt.Sprintf("%s WHERE character_id=$1", guildMembersSelectSQL), charID)
|
||||
|
||||
if err != nil {
|
||||
s.logger.Error(fmt.Sprintf("failed to retrieve membership data for character '%d'", charID))
|
||||
s.Logger.Error(fmt.Sprintf("failed to retrieve membership data for character '%d'", charID))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -139,7 +153,7 @@ func buildGuildMemberObjectFromDBResult(rows *sqlx.Rows, err error, s *Session)
|
||||
err = rows.StructScan(&memberData)
|
||||
|
||||
if err != nil {
|
||||
s.logger.Error("failed to retrieve guild data from database", zap.Error(err))
|
||||
s.Logger.Error("failed to retrieve guild data from database", zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package channelserver
|
||||
import (
|
||||
"erupe-ce/network/mhfpacket"
|
||||
"erupe-ce/utils/byteframe"
|
||||
"erupe-ce/utils/db"
|
||||
"erupe-ce/utils/gametime"
|
||||
"erupe-ce/utils/stringsupport"
|
||||
"fmt"
|
||||
@@ -11,41 +12,44 @@ import (
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func handleMsgMhfPostGuildScout(s *Session, p mhfpacket.MHFPacket) {
|
||||
func HandleMsgMhfPostGuildScout(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfPostGuildScout)
|
||||
|
||||
actorCharGuildData, err := GetCharacterGuildData(s, s.charID)
|
||||
actorCharGuildData, err := GetCharacterGuildData(s, s.CharID)
|
||||
|
||||
if err != nil {
|
||||
doAckBufFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckBufFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if actorCharGuildData == nil || !actorCharGuildData.CanRecruit() {
|
||||
doAckBufFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckBufFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
|
||||
guildInfo, err := GetGuildInfoByID(s, actorCharGuildData.GuildID)
|
||||
|
||||
if err != nil {
|
||||
doAckBufFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckBufFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
panic(err)
|
||||
}
|
||||
|
||||
hasApplication, err := guildInfo.HasApplicationForCharID(s, pkt.CharID)
|
||||
|
||||
if err != nil {
|
||||
doAckBufFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckBufFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if hasApplication {
|
||||
doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x04})
|
||||
DoAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x04})
|
||||
return
|
||||
}
|
||||
|
||||
transaction, err := s.server.db.Begin()
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
transaction, err := database.Begin()
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@@ -55,16 +59,16 @@ func handleMsgMhfPostGuildScout(s *Session, p mhfpacket.MHFPacket) {
|
||||
|
||||
if err != nil {
|
||||
rollbackTransaction(s, transaction)
|
||||
doAckBufFail(s, pkt.AckHandle, nil)
|
||||
DoAckBufFail(s, pkt.AckHandle, nil)
|
||||
panic(err)
|
||||
}
|
||||
|
||||
mail := &Mail{
|
||||
SenderID: s.charID,
|
||||
SenderID: s.CharID,
|
||||
RecipientID: pkt.CharID,
|
||||
Subject: s.server.i18n.guild.invite.title,
|
||||
Subject: s.Server.i18n.guild.invite.title,
|
||||
Body: fmt.Sprintf(
|
||||
s.server.i18n.guild.invite.body,
|
||||
s.Server.i18n.guild.invite.body,
|
||||
guildInfo.Name,
|
||||
),
|
||||
IsGuildInvite: true,
|
||||
@@ -74,52 +78,52 @@ func handleMsgMhfPostGuildScout(s *Session, p mhfpacket.MHFPacket) {
|
||||
|
||||
if err != nil {
|
||||
rollbackTransaction(s, transaction)
|
||||
doAckBufFail(s, pkt.AckHandle, nil)
|
||||
DoAckBufFail(s, pkt.AckHandle, nil)
|
||||
return
|
||||
}
|
||||
|
||||
err = transaction.Commit()
|
||||
|
||||
if err != nil {
|
||||
doAckBufFail(s, pkt.AckHandle, nil)
|
||||
DoAckBufFail(s, pkt.AckHandle, nil)
|
||||
panic(err)
|
||||
}
|
||||
|
||||
doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
DoAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
}
|
||||
|
||||
func handleMsgMhfCancelGuildScout(s *Session, p mhfpacket.MHFPacket) {
|
||||
func HandleMsgMhfCancelGuildScout(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfCancelGuildScout)
|
||||
|
||||
guildCharData, err := GetCharacterGuildData(s, s.charID)
|
||||
guildCharData, err := GetCharacterGuildData(s, s.CharID)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if guildCharData == nil || !guildCharData.CanRecruit() {
|
||||
doAckBufFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckBufFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
|
||||
guild, err := GetGuildInfoByID(s, guildCharData.GuildID)
|
||||
|
||||
if err != nil {
|
||||
doAckBufFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckBufFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
|
||||
err = guild.CancelInvitation(s, pkt.InvitationID)
|
||||
|
||||
if err != nil {
|
||||
doAckBufFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckBufFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func handleMsgMhfAnswerGuildScout(s *Session, p mhfpacket.MHFPacket) {
|
||||
func HandleMsgMhfAnswerGuildScout(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfAnswerGuildScout)
|
||||
bf := byteframe.NewByteFrame()
|
||||
guild, err := GetGuildInfoByCharacterId(s, pkt.LeaderID)
|
||||
@@ -128,84 +132,87 @@ func handleMsgMhfAnswerGuildScout(s *Session, p mhfpacket.MHFPacket) {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
app, err := guild.GetApplicationForCharID(s, s.charID, GuildApplicationTypeInvited)
|
||||
app, err := guild.GetApplicationForCharID(s, s.CharID, GuildApplicationTypeInvited)
|
||||
|
||||
if app == nil || err != nil {
|
||||
s.logger.Warn(
|
||||
s.Logger.Warn(
|
||||
"Guild invite missing, deleted?",
|
||||
zap.Error(err),
|
||||
zap.Uint32("guildID", guild.ID),
|
||||
zap.Uint32("charID", s.charID),
|
||||
zap.Uint32("charID", s.CharID),
|
||||
)
|
||||
bf.WriteUint32(7)
|
||||
bf.WriteUint32(guild.ID)
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
return
|
||||
}
|
||||
|
||||
var mail []Mail
|
||||
if pkt.Answer {
|
||||
err = guild.AcceptApplication(s, s.charID)
|
||||
err = guild.AcceptApplication(s, s.CharID)
|
||||
mail = append(mail, Mail{
|
||||
RecipientID: s.charID,
|
||||
Subject: s.server.i18n.guild.invite.success.title,
|
||||
Body: fmt.Sprintf(s.server.i18n.guild.invite.success.body, guild.Name),
|
||||
RecipientID: s.CharID,
|
||||
Subject: s.Server.i18n.guild.invite.success.title,
|
||||
Body: fmt.Sprintf(s.Server.i18n.guild.invite.success.body, guild.Name),
|
||||
IsSystemMessage: true,
|
||||
})
|
||||
mail = append(mail, Mail{
|
||||
SenderID: s.charID,
|
||||
SenderID: s.CharID,
|
||||
RecipientID: pkt.LeaderID,
|
||||
Subject: s.server.i18n.guild.invite.accepted.title,
|
||||
Body: fmt.Sprintf(s.server.i18n.guild.invite.accepted.body, guild.Name),
|
||||
Subject: s.Server.i18n.guild.invite.accepted.title,
|
||||
Body: fmt.Sprintf(s.Server.i18n.guild.invite.accepted.body, guild.Name),
|
||||
IsSystemMessage: true,
|
||||
})
|
||||
} else {
|
||||
err = guild.RejectApplication(s, s.charID)
|
||||
err = guild.RejectApplication(s, s.CharID)
|
||||
mail = append(mail, Mail{
|
||||
RecipientID: s.charID,
|
||||
Subject: s.server.i18n.guild.invite.rejected.title,
|
||||
Body: fmt.Sprintf(s.server.i18n.guild.invite.rejected.body, guild.Name),
|
||||
RecipientID: s.CharID,
|
||||
Subject: s.Server.i18n.guild.invite.rejected.title,
|
||||
Body: fmt.Sprintf(s.Server.i18n.guild.invite.rejected.body, guild.Name),
|
||||
IsSystemMessage: true,
|
||||
})
|
||||
mail = append(mail, Mail{
|
||||
SenderID: s.charID,
|
||||
SenderID: s.CharID,
|
||||
RecipientID: pkt.LeaderID,
|
||||
Subject: s.server.i18n.guild.invite.declined.title,
|
||||
Body: fmt.Sprintf(s.server.i18n.guild.invite.declined.body, guild.Name),
|
||||
Subject: s.Server.i18n.guild.invite.declined.title,
|
||||
Body: fmt.Sprintf(s.Server.i18n.guild.invite.declined.body, guild.Name),
|
||||
IsSystemMessage: true,
|
||||
})
|
||||
}
|
||||
if err != nil {
|
||||
bf.WriteUint32(7)
|
||||
bf.WriteUint32(guild.ID)
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
} else {
|
||||
bf.WriteUint32(0)
|
||||
bf.WriteUint32(guild.ID)
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
for _, m := range mail {
|
||||
m.Send(s, nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func handleMsgMhfGetGuildScoutList(s *Session, p mhfpacket.MHFPacket) {
|
||||
func HandleMsgMhfGetGuildScoutList(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetGuildScoutList)
|
||||
|
||||
guildInfo, err := GetGuildInfoByCharacterId(s, s.charID)
|
||||
guildInfo, err := GetGuildInfoByCharacterId(s, s.CharID)
|
||||
|
||||
if guildInfo == nil && s.prevGuildID == 0 {
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
} else {
|
||||
guildInfo, err = GetGuildInfoByID(s, s.prevGuildID)
|
||||
if guildInfo == nil || err != nil {
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
rows, err := s.server.db.Queryx(`
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
rows, err := database.Queryx(`
|
||||
SELECT c.id, c.name, c.hr, c.gr, ga.actor_id
|
||||
FROM guild_applications ga
|
||||
JOIN characters c ON c.id = ga.character_id
|
||||
@@ -213,8 +220,8 @@ func handleMsgMhfGetGuildScoutList(s *Session, p mhfpacket.MHFPacket) {
|
||||
`, guildInfo.ID)
|
||||
|
||||
if err != nil {
|
||||
s.logger.Error("failed to retrieve scouted characters", zap.Error(err))
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
s.Logger.Error("failed to retrieve scouted characters", zap.Error(err))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -237,7 +244,7 @@ func handleMsgMhfGetGuildScoutList(s *Session, p mhfpacket.MHFPacket) {
|
||||
err = rows.Scan(&charID, &charName, &HR, &GR, &actorID)
|
||||
|
||||
if err != nil {
|
||||
doAckSimpleFail(s, pkt.AckHandle, nil)
|
||||
DoAckSimpleFail(s, pkt.AckHandle, nil)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -262,25 +269,28 @@ func handleMsgMhfGetGuildScoutList(s *Session, p mhfpacket.MHFPacket) {
|
||||
|
||||
bf.WriteUint32(count)
|
||||
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfGetRejectGuildScout(s *Session, p mhfpacket.MHFPacket) {
|
||||
func HandleMsgMhfGetRejectGuildScout(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetRejectGuildScout)
|
||||
|
||||
row := s.server.db.QueryRow("SELECT restrict_guild_scout FROM characters WHERE id=$1", s.charID)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
row := database.QueryRow("SELECT restrict_guild_scout FROM characters WHERE id=$1", s.CharID)
|
||||
|
||||
var currentStatus bool
|
||||
|
||||
err := row.Scan(¤tStatus)
|
||||
err = row.Scan(¤tStatus)
|
||||
|
||||
if err != nil {
|
||||
s.logger.Error(
|
||||
s.Logger.Error(
|
||||
"failed to retrieve character guild scout status",
|
||||
zap.Error(err),
|
||||
zap.Uint32("charID", s.charID),
|
||||
zap.Uint32("charID", s.CharID),
|
||||
)
|
||||
doAckSimpleFail(s, pkt.AckHandle, nil)
|
||||
DoAckSimpleFail(s, pkt.AckHandle, nil)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -290,23 +300,26 @@ func handleMsgMhfGetRejectGuildScout(s *Session, p mhfpacket.MHFPacket) {
|
||||
response = 0x01
|
||||
}
|
||||
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, response})
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, response})
|
||||
}
|
||||
|
||||
func handleMsgMhfSetRejectGuildScout(s *Session, p mhfpacket.MHFPacket) {
|
||||
func HandleMsgMhfSetRejectGuildScout(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfSetRejectGuildScout)
|
||||
|
||||
_, err := s.server.db.Exec("UPDATE characters SET restrict_guild_scout=$1 WHERE id=$2", pkt.Reject, s.charID)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
_, err = database.Exec("UPDATE characters SET restrict_guild_scout=$1 WHERE id=$2", pkt.Reject, s.CharID)
|
||||
|
||||
if err != nil {
|
||||
s.logger.Error(
|
||||
s.Logger.Error(
|
||||
"failed to update character guild scout status",
|
||||
zap.Error(err),
|
||||
zap.Uint32("charID", s.charID),
|
||||
zap.Uint32("charID", s.CharID),
|
||||
)
|
||||
doAckSimpleFail(s, pkt.AckHandle, nil)
|
||||
DoAckSimpleFail(s, pkt.AckHandle, nil)
|
||||
return
|
||||
}
|
||||
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, nil)
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, nil)
|
||||
}
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
package channelserver
|
||||
|
||||
import (
|
||||
"erupe-ce/config"
|
||||
"erupe-ce/network/mhfpacket"
|
||||
"erupe-ce/utils/byteframe"
|
||||
"erupe-ce/utils/db"
|
||||
"erupe-ce/utils/gametime"
|
||||
"erupe-ce/utils/stringsupport"
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -21,24 +24,27 @@ type TreasureHunt struct {
|
||||
Claimed bool `db:"claimed"`
|
||||
}
|
||||
|
||||
func handleMsgMhfEnumerateGuildTresure(s *Session, p mhfpacket.MHFPacket) {
|
||||
func HandleMsgMhfEnumerateGuildTresure(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfEnumerateGuildTresure)
|
||||
guild, err := GetGuildInfoByCharacterId(s, s.charID)
|
||||
guild, err := GetGuildInfoByCharacterId(s, s.CharID)
|
||||
if err != nil || guild == nil {
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
var hunts []TreasureHunt
|
||||
var hunt TreasureHunt
|
||||
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
switch pkt.MaxHunts {
|
||||
case 1:
|
||||
err = s.server.db.QueryRowx(`SELECT id, host_id, destination, level, start, hunt_data FROM guild_hunts WHERE host_id=$1 AND acquired=FALSE`, s.charID).StructScan(&hunt)
|
||||
err = database.QueryRowx(`SELECT id, host_id, destination, level, start, hunt_data FROM guild_hunts WHERE host_id=$1 AND acquired=FALSE`, s.CharID).StructScan(&hunt)
|
||||
if err == nil {
|
||||
hunts = append(hunts, hunt)
|
||||
}
|
||||
case 30:
|
||||
rows, err := s.server.db.Queryx(`SELECT gh.id, gh.host_id, gh.destination, gh.level, gh.start, gh.collected, gh.hunt_data,
|
||||
rows, err := database.Queryx(`SELECT gh.id, gh.host_id, gh.destination, gh.level, gh.start, gh.collected, gh.hunt_data,
|
||||
(SELECT COUNT(*) FROM guild_characters gc WHERE gc.treasure_hunt = gh.id AND gc.character_id <> $1) AS hunters,
|
||||
CASE
|
||||
WHEN ghc.character_id IS NOT NULL THEN true
|
||||
@@ -47,15 +53,15 @@ func handleMsgMhfEnumerateGuildTresure(s *Session, p mhfpacket.MHFPacket) {
|
||||
FROM guild_hunts gh
|
||||
LEFT JOIN guild_hunts_claimed ghc ON gh.id = ghc.hunt_id AND ghc.character_id = $1
|
||||
WHERE gh.guild_id=$2 AND gh.level=2 AND gh.acquired=TRUE
|
||||
`, s.charID, guild.ID)
|
||||
`, s.CharID, guild.ID)
|
||||
if err != nil {
|
||||
rows.Close()
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
} else {
|
||||
for rows.Next() {
|
||||
err = rows.StructScan(&hunt)
|
||||
if err == nil && hunt.Start.Add(time.Second*time.Duration(s.server.erupeConfig.GameplayOptions.TreasureHuntExpiry)).After(gametime.TimeAdjusted()) {
|
||||
if err == nil && hunt.Start.Add(time.Second*time.Duration(config.GetConfig().GameplayOptions.TreasureHuntExpiry)).After(gametime.TimeAdjusted()) {
|
||||
hunts = append(hunts, hunt)
|
||||
}
|
||||
}
|
||||
@@ -77,22 +83,22 @@ func handleMsgMhfEnumerateGuildTresure(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteBool(h.Claimed)
|
||||
bf.WriteBytes(h.HuntData)
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfRegistGuildTresure(s *Session, p mhfpacket.MHFPacket) {
|
||||
func HandleMsgMhfRegistGuildTresure(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfRegistGuildTresure)
|
||||
bf := byteframe.NewByteFrameFromBytes(pkt.Data)
|
||||
huntData := byteframe.NewByteFrame()
|
||||
guild, err := GetGuildInfoByCharacterId(s, s.charID)
|
||||
guild, err := GetGuildInfoByCharacterId(s, s.CharID)
|
||||
if err != nil || guild == nil {
|
||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
guildCats := getGuildAirouList(s)
|
||||
destination := bf.ReadUint32()
|
||||
level := bf.ReadUint32()
|
||||
huntData.WriteUint32(s.charID)
|
||||
huntData.WriteUint32(s.CharID)
|
||||
huntData.WriteBytes(stringsupport.PaddedString(s.Name, 18, true))
|
||||
catsUsed := ""
|
||||
for i := 0; i < 5; i++ {
|
||||
@@ -109,29 +115,41 @@ func handleMsgMhfRegistGuildTresure(s *Session, p mhfpacket.MHFPacket) {
|
||||
huntData.WriteBytes(bf.ReadBytes(9))
|
||||
}
|
||||
}
|
||||
s.server.db.Exec(`INSERT INTO guild_hunts (guild_id, host_id, destination, level, hunt_data, cats_used) VALUES ($1, $2, $3, $4, $5, $6)
|
||||
`, guild.ID, s.charID, destination, level, huntData.Data(), catsUsed)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
database.Exec(`INSERT INTO guild_hunts (guild_id, host_id, destination, level, hunt_data, cats_used) VALUES ($1, $2, $3, $4, $5, $6)
|
||||
`, guild.ID, s.CharID, destination, level, huntData.Data(), catsUsed)
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func handleMsgMhfAcquireGuildTresure(s *Session, p mhfpacket.MHFPacket) {
|
||||
func HandleMsgMhfAcquireGuildTresure(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfAcquireGuildTresure)
|
||||
s.server.db.Exec(`UPDATE guild_hunts SET acquired=true WHERE id=$1`, pkt.HuntID)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
database.Exec(`UPDATE guild_hunts SET acquired=true WHERE id=$1`, pkt.HuntID)
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func handleMsgMhfOperateGuildTresureReport(s *Session, p mhfpacket.MHFPacket) {
|
||||
func HandleMsgMhfOperateGuildTresureReport(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfOperateGuildTresureReport)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
switch pkt.State {
|
||||
case 0: // Report registration
|
||||
s.server.db.Exec(`UPDATE guild_characters SET treasure_hunt=$1 WHERE character_id=$2`, pkt.HuntID, s.charID)
|
||||
database.Exec(`UPDATE guild_characters SET treasure_hunt=$1 WHERE character_id=$2`, pkt.HuntID, s.CharID)
|
||||
case 1: // Collected by hunter
|
||||
s.server.db.Exec(`UPDATE guild_hunts SET collected=true WHERE id=$1`, pkt.HuntID)
|
||||
s.server.db.Exec(`UPDATE guild_characters SET treasure_hunt=NULL WHERE treasure_hunt=$1`, pkt.HuntID)
|
||||
database.Exec(`UPDATE guild_hunts SET collected=true WHERE id=$1`, pkt.HuntID)
|
||||
database.Exec(`UPDATE guild_characters SET treasure_hunt=NULL WHERE treasure_hunt=$1`, pkt.HuntID)
|
||||
case 2: // Claim treasure
|
||||
s.server.db.Exec(`INSERT INTO guild_hunts_claimed VALUES ($1, $2)`, pkt.HuntID, s.charID)
|
||||
database.Exec(`INSERT INTO guild_hunts_claimed VALUES ($1, $2)`, pkt.HuntID, s.CharID)
|
||||
}
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
type TreasureSouvenir struct {
|
||||
@@ -139,7 +157,7 @@ type TreasureSouvenir struct {
|
||||
Quantity uint32
|
||||
}
|
||||
|
||||
func handleMsgMhfGetGuildTresureSouvenir(s *Session, p mhfpacket.MHFPacket) {
|
||||
func HandleMsgMhfGetGuildTresureSouvenir(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetGuildTresureSouvenir)
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint32(0)
|
||||
@@ -149,10 +167,10 @@ func handleMsgMhfGetGuildTresureSouvenir(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint32(souvenir.Destination)
|
||||
bf.WriteUint32(souvenir.Quantity)
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfAcquireGuildTresureSouvenir(s *Session, p mhfpacket.MHFPacket) {
|
||||
func HandleMsgMhfAcquireGuildTresureSouvenir(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfAcquireGuildTresureSouvenir)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
package channelserver
|
||||
|
||||
import (
|
||||
_config "erupe-ce/config"
|
||||
"erupe-ce/config"
|
||||
"erupe-ce/network/mhfpacket"
|
||||
"erupe-ce/utils/byteframe"
|
||||
"erupe-ce/utils/db"
|
||||
"erupe-ce/utils/mhfitem"
|
||||
ps "erupe-ce/utils/pascalstring"
|
||||
"erupe-ce/utils/stringsupport"
|
||||
@@ -42,8 +43,12 @@ FROM warehouse
|
||||
|
||||
func handleMsgMhfUpdateInterior(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfUpdateInterior)
|
||||
s.server.db.Exec(`UPDATE user_binary SET house_furniture=$1 WHERE id=$2`, pkt.InteriorData, s.charID)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
database.Exec(`UPDATE user_binary SET house_furniture=$1 WHERE id=$2`, pkt.InteriorData, s.CharID)
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
type HouseData struct {
|
||||
@@ -57,6 +62,10 @@ type HouseData struct {
|
||||
|
||||
func handleMsgMhfEnumerateHouse(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfEnumerateHouse)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint16(0)
|
||||
var houses []HouseData
|
||||
@@ -65,18 +74,18 @@ func handleMsgMhfEnumerateHouse(s *Session, p mhfpacket.MHFPacket) {
|
||||
switch pkt.Method {
|
||||
case 1:
|
||||
var friendsList string
|
||||
s.server.db.QueryRow("SELECT friends FROM characters WHERE id=$1", s.charID).Scan(&friendsList)
|
||||
database.QueryRow("SELECT friends FROM characters WHERE id=$1", s.CharID).Scan(&friendsList)
|
||||
cids := stringsupport.CSVElems(friendsList)
|
||||
for _, cid := range cids {
|
||||
house := HouseData{}
|
||||
row := s.server.db.QueryRowx(houseQuery, cid)
|
||||
row := database.QueryRowx(houseQuery, cid)
|
||||
err := row.StructScan(&house)
|
||||
if err == nil {
|
||||
houses = append(houses, house)
|
||||
}
|
||||
}
|
||||
case 2:
|
||||
guild, err := GetGuildInfoByCharacterId(s, s.charID)
|
||||
guild, err := GetGuildInfoByCharacterId(s, s.CharID)
|
||||
if err != nil || guild == nil {
|
||||
break
|
||||
}
|
||||
@@ -86,7 +95,7 @@ func handleMsgMhfEnumerateHouse(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
for _, member := range guildMembers {
|
||||
house := HouseData{}
|
||||
row := s.server.db.QueryRowx(houseQuery, member.CharID)
|
||||
row := database.QueryRowx(houseQuery, member.CharID)
|
||||
err = row.StructScan(&house)
|
||||
if err == nil {
|
||||
houses = append(houses, house)
|
||||
@@ -96,7 +105,7 @@ func handleMsgMhfEnumerateHouse(s *Session, p mhfpacket.MHFPacket) {
|
||||
houseQuery = `SELECT c.id, hr, gr, name, COALESCE(ub.house_state, 2) as house_state, COALESCE(ub.house_password, '') as house_password
|
||||
FROM characters c LEFT JOIN user_binary ub ON ub.id = c.id WHERE name ILIKE $1`
|
||||
house := HouseData{}
|
||||
rows, _ := s.server.db.Queryx(houseQuery, fmt.Sprintf(`%%%s%%`, pkt.Name))
|
||||
rows, _ := database.Queryx(houseQuery, fmt.Sprintf(`%%%s%%`, pkt.Name))
|
||||
for rows.Next() {
|
||||
err := rows.StructScan(&house)
|
||||
if err == nil {
|
||||
@@ -105,7 +114,7 @@ func handleMsgMhfEnumerateHouse(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
case 4:
|
||||
house := HouseData{}
|
||||
row := s.server.db.QueryRowx(houseQuery, pkt.CharID)
|
||||
row := database.QueryRowx(houseQuery, pkt.CharID)
|
||||
err := row.StructScan(&house)
|
||||
if err == nil {
|
||||
houses = append(houses, house)
|
||||
@@ -122,39 +131,47 @@ func handleMsgMhfEnumerateHouse(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint8(0)
|
||||
}
|
||||
bf.WriteUint16(house.HR)
|
||||
if _config.ErupeConfig.ClientID >= _config.G10 {
|
||||
if config.GetConfig().ClientID >= config.G10 {
|
||||
bf.WriteUint16(house.GR)
|
||||
}
|
||||
ps.Uint8(bf, house.Name, true)
|
||||
}
|
||||
bf.Seek(0, 0)
|
||||
bf.WriteUint16(uint16(len(houses)))
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfUpdateHouse(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfUpdateHouse)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
// 01 = closed
|
||||
// 02 = open anyone
|
||||
// 03 = open friends
|
||||
// 04 = open guild
|
||||
// 05 = open friends+guild
|
||||
s.server.db.Exec(`UPDATE user_binary SET house_state=$1, house_password=$2 WHERE id=$3`, pkt.State, pkt.Password, s.charID)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
database.Exec(`UPDATE user_binary SET house_state=$1, house_password=$2 WHERE id=$3`, pkt.State, pkt.Password, s.CharID)
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func handleMsgMhfLoadHouse(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfLoadHouse)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
bf := byteframe.NewByteFrame()
|
||||
|
||||
var state uint8
|
||||
var password string
|
||||
s.server.db.QueryRow(`SELECT COALESCE(house_state, 2) as house_state, COALESCE(house_password, '') as house_password FROM user_binary WHERE id=$1
|
||||
database.QueryRow(`SELECT COALESCE(house_state, 2) as house_state, COALESCE(house_password, '') as house_password FROM user_binary WHERE id=$1
|
||||
`, pkt.CharID).Scan(&state, &password)
|
||||
|
||||
if pkt.Destination != 9 && len(pkt.Password) > 0 && pkt.CheckPass {
|
||||
if pkt.Password != password {
|
||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -165,10 +182,10 @@ func handleMsgMhfLoadHouse(s *Session, p mhfpacket.MHFPacket) {
|
||||
// Friends list verification
|
||||
if state == 3 || state == 5 {
|
||||
var friendsList string
|
||||
s.server.db.QueryRow(`SELECT friends FROM characters WHERE id=$1`, pkt.CharID).Scan(&friendsList)
|
||||
database.QueryRow(`SELECT friends FROM characters WHERE id=$1`, pkt.CharID).Scan(&friendsList)
|
||||
cids := stringsupport.CSVElems(friendsList)
|
||||
for _, cid := range cids {
|
||||
if uint32(cid) == s.charID {
|
||||
if uint32(cid) == s.CharID {
|
||||
allowed = true
|
||||
break
|
||||
}
|
||||
@@ -177,8 +194,8 @@ func handleMsgMhfLoadHouse(s *Session, p mhfpacket.MHFPacket) {
|
||||
|
||||
// Guild verification
|
||||
if state > 3 {
|
||||
ownGuild, err := GetGuildInfoByCharacterId(s, s.charID)
|
||||
isApplicant, _ := ownGuild.HasApplicationForCharID(s, s.charID)
|
||||
ownGuild, err := GetGuildInfoByCharacterId(s, s.CharID)
|
||||
isApplicant, _ := ownGuild.HasApplicationForCharID(s, s.CharID)
|
||||
if err == nil && ownGuild != nil {
|
||||
othersGuild, err := GetGuildInfoByCharacterId(s, pkt.CharID)
|
||||
if err == nil && othersGuild != nil {
|
||||
@@ -190,13 +207,13 @@ func handleMsgMhfLoadHouse(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
|
||||
if !allowed {
|
||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
var houseTier, houseData, houseFurniture, bookshelf, gallery, tore, garden []byte
|
||||
s.server.db.QueryRow(`SELECT house_tier, house_data, house_furniture, bookshelf, gallery, tore, garden FROM user_binary WHERE id=$1
|
||||
database.QueryRow(`SELECT house_tier, house_data, house_furniture, bookshelf, gallery, tore, garden FROM user_binary WHERE id=$1
|
||||
`, pkt.CharID).Scan(&houseTier, &houseData, &houseFurniture, &bookshelf, &gallery, &tore, &garden)
|
||||
if houseFurniture == nil {
|
||||
houseFurniture = make([]byte, 20)
|
||||
@@ -226,59 +243,76 @@ func handleMsgMhfLoadHouse(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
}
|
||||
if len(bf.Data()) == 0 {
|
||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
} else {
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
}
|
||||
|
||||
func handleMsgMhfGetMyhouseInfo(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetMyhouseInfo)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
var data []byte
|
||||
s.server.db.QueryRow(`SELECT mission FROM user_binary WHERE id=$1`, s.charID).Scan(&data)
|
||||
database.QueryRow(`SELECT mission FROM user_binary WHERE id=$1`, s.CharID).Scan(&data)
|
||||
if len(data) > 0 {
|
||||
doAckBufSucceed(s, pkt.AckHandle, data)
|
||||
DoAckBufSucceed(s, pkt.AckHandle, data)
|
||||
} else {
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 9))
|
||||
DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 9))
|
||||
}
|
||||
}
|
||||
|
||||
func handleMsgMhfUpdateMyhouseInfo(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfUpdateMyhouseInfo)
|
||||
s.server.db.Exec("UPDATE user_binary SET mission=$1 WHERE id=$2", pkt.Data, s.charID)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
database.Exec("UPDATE user_binary SET mission=$1 WHERE id=$2", pkt.Data, s.CharID)
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func handleMsgMhfLoadDecoMyset(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfLoadDecoMyset)
|
||||
var data []byte
|
||||
err := s.server.db.QueryRow("SELECT decomyset FROM characters WHERE id = $1", s.charID).Scan(&data)
|
||||
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to load decomyset", zap.Error(err))
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
var data []byte
|
||||
err = database.QueryRow("SELECT decomyset FROM characters WHERE id = $1", s.CharID).Scan(&data)
|
||||
if err != nil {
|
||||
s.Logger.Error("Failed to load decomyset", zap.Error(err))
|
||||
}
|
||||
if len(data) == 0 {
|
||||
data = []byte{0x01, 0x00}
|
||||
if s.server.erupeConfig.ClientID < _config.G10 {
|
||||
if config.GetConfig().ClientID < config.G10 {
|
||||
data = []byte{0x00, 0x00}
|
||||
}
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, data)
|
||||
DoAckBufSucceed(s, pkt.AckHandle, data)
|
||||
}
|
||||
|
||||
func handleMsgMhfSaveDecoMyset(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfSaveDecoMyset)
|
||||
var temp []byte
|
||||
err := s.server.db.QueryRow("SELECT decomyset FROM characters WHERE id = $1", s.charID).Scan(&temp)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to load decomyset", zap.Error(err))
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
var temp []byte
|
||||
err = database.QueryRow("SELECT decomyset FROM characters WHERE id = $1", s.CharID).Scan(&temp)
|
||||
if err != nil {
|
||||
s.Logger.Error("Failed to load decomyset", zap.Error(err))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
|
||||
// Version handling
|
||||
bf := byteframe.NewByteFrame()
|
||||
var size uint
|
||||
if s.server.erupeConfig.ClientID >= _config.G10 {
|
||||
if config.GetConfig().ClientID >= config.G10 {
|
||||
size = 76
|
||||
bf.WriteUint8(1)
|
||||
} else {
|
||||
@@ -314,8 +348,8 @@ func handleMsgMhfSaveDecoMyset(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
|
||||
dumpSaveData(s, bf.Data(), "decomyset")
|
||||
s.server.db.Exec("UPDATE characters SET decomyset=$1 WHERE id=$2", bf.Data(), s.charID)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
database.Exec("UPDATE characters SET decomyset=$1 WHERE id=$2", bf.Data(), s.CharID)
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
type Title struct {
|
||||
@@ -326,13 +360,17 @@ type Title struct {
|
||||
|
||||
func handleMsgMhfEnumerateTitle(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfEnumerateTitle)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
var count uint16
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint16(0)
|
||||
bf.WriteUint16(0) // Unk
|
||||
rows, err := s.server.db.Queryx("SELECT id, unlocked_at, updated_at FROM titles WHERE char_id=$1", s.charID)
|
||||
rows, err := database.Queryx("SELECT id, unlocked_at, updated_at FROM titles WHERE char_id=$1", s.CharID)
|
||||
if err != nil {
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
return
|
||||
}
|
||||
for rows.Next() {
|
||||
@@ -349,35 +387,47 @@ func handleMsgMhfEnumerateTitle(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
bf.Seek(0, io.SeekStart)
|
||||
bf.WriteUint16(count)
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfAcquireTitle(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfAcquireTitle)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
for _, title := range pkt.TitleIDs {
|
||||
var exists int
|
||||
err := s.server.db.QueryRow(`SELECT count(*) FROM titles WHERE id=$1 AND char_id=$2`, title, s.charID).Scan(&exists)
|
||||
err := database.QueryRow(`SELECT count(*) FROM titles WHERE id=$1 AND char_id=$2`, title, s.CharID).Scan(&exists)
|
||||
if err != nil || exists == 0 {
|
||||
s.server.db.Exec(`INSERT INTO titles VALUES ($1, $2, now(), now())`, title, s.charID)
|
||||
database.Exec(`INSERT INTO titles VALUES ($1, $2, now(), now())`, title, s.CharID)
|
||||
} else {
|
||||
s.server.db.Exec(`UPDATE titles SET updated_at=now() WHERE id=$1 AND char_id=$2`, title, s.charID)
|
||||
database.Exec(`UPDATE titles SET updated_at=now() WHERE id=$1 AND char_id=$2`, title, s.CharID)
|
||||
}
|
||||
}
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func handleMsgMhfResetTitle(s *Session, p mhfpacket.MHFPacket) {}
|
||||
|
||||
func initializeWarehouse(s *Session) {
|
||||
var t int
|
||||
err := s.server.db.QueryRow("SELECT character_id FROM warehouse WHERE character_id=$1", s.charID).Scan(&t)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.server.db.Exec("INSERT INTO warehouse (character_id) VALUES ($1)", s.charID)
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
var t int
|
||||
err = database.QueryRow("SELECT character_id FROM warehouse WHERE character_id=$1", s.CharID).Scan(&t)
|
||||
if err != nil {
|
||||
database.Exec("INSERT INTO warehouse (character_id) VALUES ($1)", s.CharID)
|
||||
}
|
||||
}
|
||||
|
||||
func handleMsgMhfOperateWarehouse(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfOperateWarehouse)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
initializeWarehouse(s)
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint8(pkt.Operation)
|
||||
@@ -386,7 +436,7 @@ func handleMsgMhfOperateWarehouse(s *Session, p mhfpacket.MHFPacket) {
|
||||
var count uint8
|
||||
itemNames := make([]string, 10)
|
||||
equipNames := make([]string, 10)
|
||||
s.server.db.QueryRow(fmt.Sprintf("%s WHERE character_id=$1", warehouseNamesQuery), s.charID).Scan(&itemNames[0],
|
||||
database.QueryRow(fmt.Sprintf("%s WHERE character_id=$1", warehouseNamesQuery), s.CharID).Scan(&itemNames[0],
|
||||
&itemNames[1], &itemNames[2], &itemNames[3], &itemNames[4], &itemNames[5], &itemNames[6], &itemNames[7], &itemNames[8], &itemNames[9], &equipNames[0],
|
||||
&equipNames[1], &equipNames[2], &equipNames[3], &equipNames[4], &equipNames[5], &equipNames[6], &equipNames[7], &equipNames[8], &equipNames[9])
|
||||
bf.WriteUint32(0)
|
||||
@@ -415,9 +465,9 @@ func handleMsgMhfOperateWarehouse(s *Session, p mhfpacket.MHFPacket) {
|
||||
case 2:
|
||||
switch pkt.BoxType {
|
||||
case 0:
|
||||
s.server.db.Exec(fmt.Sprintf("UPDATE warehouse SET item%dname=$1 WHERE character_id=$2", pkt.BoxIndex), pkt.Name, s.charID)
|
||||
database.Exec(fmt.Sprintf("UPDATE warehouse SET item%dname=$1 WHERE character_id=$2", pkt.BoxIndex), pkt.Name, s.CharID)
|
||||
case 1:
|
||||
s.server.db.Exec(fmt.Sprintf("UPDATE warehouse SET equip%dname=$1 WHERE character_id=$2", pkt.BoxIndex), pkt.Name, s.charID)
|
||||
database.Exec(fmt.Sprintf("UPDATE warehouse SET equip%dname=$1 WHERE character_id=$2", pkt.BoxIndex), pkt.Name, s.CharID)
|
||||
}
|
||||
case 3:
|
||||
bf.WriteUint32(0) // Usage renewal time, >1 = disabled
|
||||
@@ -433,28 +483,40 @@ func handleMsgMhfOperateWarehouse(s *Session, p mhfpacket.MHFPacket) {
|
||||
// 2 = Rename
|
||||
// 3 = Get usage limit
|
||||
// 4 = Get gift box names (doesn't do anything?)
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func addWarehouseItem(s *Session, item mhfitem.MHFItemStack) {
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
giftBox := warehouseGetItems(s, 10)
|
||||
item.WarehouseID = token.RNG.Uint32()
|
||||
giftBox = append(giftBox, item)
|
||||
s.server.db.Exec("UPDATE warehouse SET item10=$1 WHERE character_id=$2", mhfitem.SerializeWarehouseItems(giftBox), s.charID)
|
||||
database.Exec("UPDATE warehouse SET item10=$1 WHERE character_id=$2", mhfitem.SerializeWarehouseItems(giftBox), s.CharID)
|
||||
}
|
||||
|
||||
func addWarehouseEquipment(s *Session, equipment mhfitem.MHFEquipment) {
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
giftBox := warehouseGetEquipment(s, 10)
|
||||
equipment.WarehouseID = token.RNG.Uint32()
|
||||
giftBox = append(giftBox, equipment)
|
||||
s.server.db.Exec("UPDATE warehouse SET equip10=$1 WHERE character_id=$2", mhfitem.SerializeWarehouseEquipment(giftBox), s.charID)
|
||||
database.Exec("UPDATE warehouse SET equip10=$1 WHERE character_id=$2", mhfitem.SerializeWarehouseEquipment(giftBox), s.CharID)
|
||||
}
|
||||
|
||||
func warehouseGetItems(s *Session, index uint8) []mhfitem.MHFItemStack {
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
initializeWarehouse(s)
|
||||
var data []byte
|
||||
var items []mhfitem.MHFItemStack
|
||||
s.server.db.QueryRow(fmt.Sprintf(`SELECT item%d FROM warehouse WHERE character_id=$1`, index), s.charID).Scan(&data)
|
||||
database.QueryRow(fmt.Sprintf(`SELECT item%d FROM warehouse WHERE character_id=$1`, index), s.CharID).Scan(&data)
|
||||
if len(data) > 0 {
|
||||
box := byteframe.NewByteFrameFromBytes(data)
|
||||
numStacks := box.ReadUint16()
|
||||
@@ -467,9 +529,13 @@ func warehouseGetItems(s *Session, index uint8) []mhfitem.MHFItemStack {
|
||||
}
|
||||
|
||||
func warehouseGetEquipment(s *Session, index uint8) []mhfitem.MHFEquipment {
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
var data []byte
|
||||
var equipment []mhfitem.MHFEquipment
|
||||
s.server.db.QueryRow(fmt.Sprintf(`SELECT equip%d FROM warehouse WHERE character_id=$1`, index), s.charID).Scan(&data)
|
||||
database.QueryRow(fmt.Sprintf(`SELECT equip%d FROM warehouse WHERE character_id=$1`, index), s.CharID).Scan(&data)
|
||||
if len(data) > 0 {
|
||||
box := byteframe.NewByteFrameFromBytes(data)
|
||||
numStacks := box.ReadUint16()
|
||||
@@ -493,18 +559,22 @@ func handleMsgMhfEnumerateWarehouse(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteBytes(mhfitem.SerializeWarehouseEquipment(equipment))
|
||||
}
|
||||
if bf.Index() > 0 {
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
} else {
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
}
|
||||
|
||||
func handleMsgMhfUpdateWarehouse(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfUpdateWarehouse)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
switch pkt.BoxType {
|
||||
case 0:
|
||||
newStacks := mhfitem.DiffItemStacks(warehouseGetItems(s, pkt.BoxIndex), pkt.UpdatedItems)
|
||||
s.server.db.Exec(fmt.Sprintf(`UPDATE warehouse SET item%d=$1 WHERE character_id=$2`, pkt.BoxIndex), mhfitem.SerializeWarehouseItems(newStacks), s.charID)
|
||||
database.Exec(fmt.Sprintf(`UPDATE warehouse SET item%d=$1 WHERE character_id=$2`, pkt.BoxIndex), mhfitem.SerializeWarehouseItems(newStacks), s.CharID)
|
||||
case 1:
|
||||
var fEquip []mhfitem.MHFEquipment
|
||||
oEquips := warehouseGetEquipment(s, pkt.BoxIndex)
|
||||
@@ -528,7 +598,7 @@ func handleMsgMhfUpdateWarehouse(s *Session, p mhfpacket.MHFPacket) {
|
||||
fEquip = append(fEquip, oEquip)
|
||||
}
|
||||
}
|
||||
s.server.db.Exec(fmt.Sprintf(`UPDATE warehouse SET equip%d=$1 WHERE character_id=$2`, pkt.BoxIndex), mhfitem.SerializeWarehouseEquipment(fEquip), s.charID)
|
||||
database.Exec(fmt.Sprintf(`UPDATE warehouse SET equip%d=$1 WHERE character_id=$2`, pkt.BoxIndex), mhfitem.SerializeWarehouseEquipment(fEquip), s.CharID)
|
||||
}
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ package channelserver
|
||||
import (
|
||||
"erupe-ce/network/mhfpacket"
|
||||
"erupe-ce/utils/byteframe"
|
||||
"erupe-ce/utils/db"
|
||||
"fmt"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
@@ -10,37 +12,49 @@ import (
|
||||
func handleMsgMhfAddKouryouPoint(s *Session, p mhfpacket.MHFPacket) {
|
||||
// hunting with both ranks maxed gets you these
|
||||
pkt := p.(*mhfpacket.MsgMhfAddKouryouPoint)
|
||||
var points int
|
||||
err := s.server.db.QueryRow("UPDATE characters SET kouryou_point=COALESCE(kouryou_point + $1, $1) WHERE id=$2 RETURNING kouryou_point", pkt.KouryouPoints, s.charID).Scan(&points)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to update KouryouPoint in db", zap.Error(err))
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
var points int
|
||||
err = database.QueryRow("UPDATE characters SET kouryou_point=COALESCE(kouryou_point + $1, $1) WHERE id=$2 RETURNING kouryou_point", pkt.KouryouPoints, s.CharID).Scan(&points)
|
||||
if err != nil {
|
||||
s.Logger.Error("Failed to update KouryouPoint in db", zap.Error(err))
|
||||
}
|
||||
resp := byteframe.NewByteFrame()
|
||||
resp.WriteUint32(uint32(points))
|
||||
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfGetKouryouPoint(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetKouryouPoint)
|
||||
var points int
|
||||
err := s.server.db.QueryRow("SELECT COALESCE(kouryou_point, 0) FROM characters WHERE id = $1", s.charID).Scan(&points)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get kouryou_point savedata from db", zap.Error(err))
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
var points int
|
||||
err = database.QueryRow("SELECT COALESCE(kouryou_point, 0) FROM characters WHERE id = $1", s.CharID).Scan(&points)
|
||||
if err != nil {
|
||||
s.Logger.Error("Failed to get kouryou_point savedata from db", zap.Error(err))
|
||||
}
|
||||
resp := byteframe.NewByteFrame()
|
||||
resp.WriteUint32(uint32(points))
|
||||
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfExchangeKouryouPoint(s *Session, p mhfpacket.MHFPacket) {
|
||||
// spent at the guildmaster, 10000 a roll
|
||||
var points int
|
||||
pkt := p.(*mhfpacket.MsgMhfExchangeKouryouPoint)
|
||||
err := s.server.db.QueryRow("UPDATE characters SET kouryou_point=kouryou_point - $1 WHERE id=$2 RETURNING kouryou_point", pkt.KouryouPoints, s.charID).Scan(&points)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to update platemyset savedata in db", zap.Error(err))
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
err = database.QueryRow("UPDATE characters SET kouryou_point=kouryou_point - $1 WHERE id=$2 RETURNING kouryou_point", pkt.KouryouPoints, s.CharID).Scan(&points)
|
||||
if err != nil {
|
||||
s.Logger.Error("Failed to update platemyset savedata in db", zap.Error(err))
|
||||
}
|
||||
resp := byteframe.NewByteFrame()
|
||||
resp.WriteUint32(uint32(points))
|
||||
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
}
|
||||
|
||||
@@ -2,7 +2,9 @@ package channelserver
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"erupe-ce/utils/db"
|
||||
"erupe-ce/utils/stringsupport"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"erupe-ce/network/binpacket"
|
||||
@@ -31,21 +33,23 @@ type Mail struct {
|
||||
}
|
||||
|
||||
func (m *Mail) Send(s *Session, transaction *sql.Tx) error {
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
query := `
|
||||
INSERT INTO mail (sender_id, recipient_id, subject, body, attached_item, attached_item_amount, is_guild_invite, is_sys_message)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
|
||||
`
|
||||
|
||||
var err error
|
||||
|
||||
if transaction == nil {
|
||||
_, err = s.server.db.Exec(query, m.SenderID, m.RecipientID, m.Subject, m.Body, m.AttachedItemID, m.AttachedItemAmount, m.IsGuildInvite, m.IsSystemMessage)
|
||||
_, err = database.Exec(query, m.SenderID, m.RecipientID, m.Subject, m.Body, m.AttachedItemID, m.AttachedItemAmount, m.IsGuildInvite, m.IsSystemMessage)
|
||||
} else {
|
||||
_, err = transaction.Exec(query, m.SenderID, m.RecipientID, m.Subject, m.Body, m.AttachedItemID, m.AttachedItemAmount, m.IsGuildInvite, m.IsSystemMessage)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
s.logger.Error(
|
||||
s.Logger.Error(
|
||||
"failed to send mail",
|
||||
zap.Error(err),
|
||||
zap.Uint32("senderID", m.SenderID),
|
||||
@@ -64,12 +68,16 @@ func (m *Mail) Send(s *Session, transaction *sql.Tx) error {
|
||||
}
|
||||
|
||||
func (m *Mail) MarkRead(s *Session) error {
|
||||
_, err := s.server.db.Exec(`
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
_, err = database.Exec(`
|
||||
UPDATE mail SET read = true WHERE id = $1
|
||||
`, m.ID)
|
||||
|
||||
if err != nil {
|
||||
s.logger.Error(
|
||||
s.Logger.Error(
|
||||
"failed to mark mail as read",
|
||||
zap.Error(err),
|
||||
zap.Int("mailID", m.ID),
|
||||
@@ -81,7 +89,11 @@ func (m *Mail) MarkRead(s *Session) error {
|
||||
}
|
||||
|
||||
func GetMailListForCharacter(s *Session, charID uint32) ([]Mail, error) {
|
||||
rows, err := s.server.db.Queryx(`
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
rows, err := database.Queryx(`
|
||||
SELECT
|
||||
m.id,
|
||||
m.sender_id,
|
||||
@@ -105,7 +117,7 @@ func GetMailListForCharacter(s *Session, charID uint32) ([]Mail, error) {
|
||||
`, charID)
|
||||
|
||||
if err != nil {
|
||||
s.logger.Error("failed to get mail for character", zap.Error(err), zap.Uint32("charID", charID))
|
||||
s.Logger.Error("failed to get mail for character", zap.Error(err), zap.Uint32("charID", charID))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -129,7 +141,11 @@ func GetMailListForCharacter(s *Session, charID uint32) ([]Mail, error) {
|
||||
}
|
||||
|
||||
func GetMailByID(s *Session, ID int) (*Mail, error) {
|
||||
row := s.server.db.QueryRowx(`
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
row := database.QueryRowx(`
|
||||
SELECT
|
||||
m.id,
|
||||
m.sender_id,
|
||||
@@ -154,10 +170,10 @@ func GetMailByID(s *Session, ID int) (*Mail, error) {
|
||||
|
||||
mail := &Mail{}
|
||||
|
||||
err := row.StructScan(mail)
|
||||
err = row.StructScan(mail)
|
||||
|
||||
if err != nil {
|
||||
s.logger.Error(
|
||||
s.Logger.Error(
|
||||
"failed to retrieve mail",
|
||||
zap.Error(err),
|
||||
zap.Int("mailID", ID),
|
||||
@@ -190,11 +206,15 @@ func SendMailNotification(s *Session, m *Mail, recipient *Session) {
|
||||
}
|
||||
|
||||
func getCharacterName(s *Session, charID uint32) string {
|
||||
row := s.server.db.QueryRow("SELECT name FROM characters WHERE id = $1", charID)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
row := database.QueryRow("SELECT name FROM characters WHERE id = $1", charID)
|
||||
|
||||
charName := ""
|
||||
|
||||
err := row.Scan(&charName)
|
||||
err = row.Scan(&charName)
|
||||
|
||||
if err != nil {
|
||||
return ""
|
||||
@@ -204,32 +224,35 @@ func getCharacterName(s *Session, charID uint32) string {
|
||||
|
||||
func handleMsgMhfReadMail(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfReadMail)
|
||||
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
mailId := s.mailList[pkt.AccIndex]
|
||||
if mailId == 0 {
|
||||
doAckBufSucceed(s, pkt.AckHandle, []byte{0})
|
||||
DoAckBufSucceed(s, pkt.AckHandle, []byte{0})
|
||||
return
|
||||
}
|
||||
|
||||
mail, err := GetMailByID(s, mailId)
|
||||
if err != nil {
|
||||
doAckBufSucceed(s, pkt.AckHandle, []byte{0})
|
||||
DoAckBufSucceed(s, pkt.AckHandle, []byte{0})
|
||||
return
|
||||
}
|
||||
|
||||
s.server.db.Exec(`UPDATE mail SET read = true WHERE id = $1`, mail.ID)
|
||||
database.Exec(`UPDATE mail SET read = true WHERE id = $1`, mail.ID)
|
||||
bf := byteframe.NewByteFrame()
|
||||
body := stringsupport.UTF8ToSJIS(mail.Body)
|
||||
bf.WriteNullTerminatedBytes(body)
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfListMail(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfListMail)
|
||||
|
||||
mail, err := GetMailListForCharacter(s, s.charID)
|
||||
mail, err := GetMailListForCharacter(s, s.CharID)
|
||||
if err != nil {
|
||||
doAckBufSucceed(s, pkt.AckHandle, []byte{0})
|
||||
DoAckBufSucceed(s, pkt.AckHandle, []byte{0})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -290,64 +313,71 @@ func handleMsgMhfListMail(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
}
|
||||
|
||||
doAckBufSucceed(s, pkt.AckHandle, msg.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, msg.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfOprtMail(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfOprtMail)
|
||||
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
mail, err := GetMailByID(s, s.mailList[pkt.AccIndex])
|
||||
if err != nil {
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
|
||||
switch pkt.Operation {
|
||||
case mhfpacket.OperateMailDelete:
|
||||
s.server.db.Exec(`UPDATE mail SET deleted = true WHERE id = $1`, mail.ID)
|
||||
database.Exec(`UPDATE mail SET deleted = true WHERE id = $1`, mail.ID)
|
||||
case mhfpacket.OperateMailLock:
|
||||
s.server.db.Exec(`UPDATE mail SET locked = TRUE WHERE id = $1`, mail.ID)
|
||||
database.Exec(`UPDATE mail SET locked = TRUE WHERE id = $1`, mail.ID)
|
||||
case mhfpacket.OperateMailUnlock:
|
||||
s.server.db.Exec(`UPDATE mail SET locked = FALSE WHERE id = $1`, mail.ID)
|
||||
database.Exec(`UPDATE mail SET locked = FALSE WHERE id = $1`, mail.ID)
|
||||
case mhfpacket.OperateMailAcquireItem:
|
||||
s.server.db.Exec(`UPDATE mail SET attached_item_received = TRUE WHERE id = $1`, mail.ID)
|
||||
database.Exec(`UPDATE mail SET attached_item_received = TRUE WHERE id = $1`, mail.ID)
|
||||
}
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func handleMsgMhfSendMail(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfSendMail)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
query := `
|
||||
INSERT INTO mail (sender_id, recipient_id, subject, body, attached_item, attached_item_amount, is_guild_invite)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
||||
`
|
||||
|
||||
if pkt.RecipientID == 0 { // Guild mail
|
||||
g, err := GetGuildInfoByCharacterId(s, s.charID)
|
||||
g, err := GetGuildInfoByCharacterId(s, s.CharID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get guild info for mail")
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
s.Logger.Error("Failed to get guild info for mail")
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
gm, err := GetGuildMembers(s, g.ID, false)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to get guild members for mail")
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
s.Logger.Error("Failed to get guild members for mail")
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
for i := 0; i < len(gm); i++ {
|
||||
_, err := s.server.db.Exec(query, s.charID, gm[i].CharID, pkt.Subject, pkt.Body, 0, 0, false)
|
||||
_, err := database.Exec(query, s.CharID, gm[i].CharID, pkt.Subject, pkt.Body, 0, 0, false)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to send mail")
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
s.Logger.Error("Failed to send mail")
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_, err := s.server.db.Exec(query, s.charID, pkt.RecipientID, pkt.Subject, pkt.Body, pkt.ItemID, pkt.Quantity, false)
|
||||
_, err := database.Exec(query, s.CharID, pkt.RecipientID, pkt.Subject, pkt.Body, pkt.ItemID, pkt.Quantity, false)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to send mail")
|
||||
s.Logger.Error("Failed to send mail")
|
||||
}
|
||||
}
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
package channelserver
|
||||
|
||||
import (
|
||||
_config "erupe-ce/config"
|
||||
config "erupe-ce/config"
|
||||
"erupe-ce/network/mhfpacket"
|
||||
"erupe-ce/server/channelserver/compression/deltacomp"
|
||||
"erupe-ce/server/channelserver/compression/nullcomp"
|
||||
|
||||
"erupe-ce/utils/byteframe"
|
||||
"erupe-ce/utils/db"
|
||||
"erupe-ce/utils/gametime"
|
||||
"erupe-ce/utils/stringsupport"
|
||||
"fmt"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
@@ -17,22 +20,30 @@ import (
|
||||
func handleMsgMhfLoadPartner(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfLoadPartner)
|
||||
var data []byte
|
||||
err := s.server.db.QueryRow("SELECT partner FROM characters WHERE id = $1", s.charID).Scan(&data)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
err = database.QueryRow("SELECT partner FROM characters WHERE id = $1", s.CharID).Scan(&data)
|
||||
if len(data) == 0 {
|
||||
s.logger.Error("Failed to load partner", zap.Error(err))
|
||||
s.Logger.Error("Failed to load partner", zap.Error(err))
|
||||
data = make([]byte, 9)
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, data)
|
||||
DoAckBufSucceed(s, pkt.AckHandle, data)
|
||||
}
|
||||
|
||||
func handleMsgMhfSavePartner(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfSavePartner)
|
||||
dumpSaveData(s, pkt.RawDataPayload, "partner")
|
||||
_, err := s.server.db.Exec("UPDATE characters SET partner=$1 WHERE id=$2", pkt.RawDataPayload, s.charID)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to save partner", zap.Error(err))
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
dumpSaveData(s, pkt.RawDataPayload, "partner")
|
||||
_, err = database.Exec("UPDATE characters SET partner=$1 WHERE id=$2", pkt.RawDataPayload, s.CharID)
|
||||
if err != nil {
|
||||
s.Logger.Error("Failed to save partner", zap.Error(err))
|
||||
}
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
}
|
||||
|
||||
func handleMsgMhfLoadLegendDispatch(s *Session, p mhfpacket.MHFPacket) {
|
||||
@@ -51,36 +62,44 @@ func handleMsgMhfLoadLegendDispatch(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint32(dispatch.Unk)
|
||||
bf.WriteUint32(dispatch.Timestamp)
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfLoadHunterNavi(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfLoadHunterNavi)
|
||||
naviLength := 552
|
||||
if s.server.erupeConfig.ClientID <= _config.G7 {
|
||||
if config.GetConfig().ClientID <= config.G7 {
|
||||
naviLength = 280
|
||||
}
|
||||
var data []byte
|
||||
err := s.server.db.QueryRow("SELECT hunternavi FROM characters WHERE id = $1", s.charID).Scan(&data)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
err = database.QueryRow("SELECT hunternavi FROM characters WHERE id = $1", s.CharID).Scan(&data)
|
||||
if len(data) == 0 {
|
||||
s.logger.Error("Failed to load hunternavi", zap.Error(err))
|
||||
s.Logger.Error("Failed to load hunternavi", zap.Error(err))
|
||||
data = make([]byte, naviLength)
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, data)
|
||||
DoAckBufSucceed(s, pkt.AckHandle, data)
|
||||
}
|
||||
|
||||
func handleMsgMhfSaveHunterNavi(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfSaveHunterNavi)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
if pkt.IsDataDiff {
|
||||
naviLength := 552
|
||||
if s.server.erupeConfig.ClientID <= _config.G7 {
|
||||
if config.GetConfig().ClientID <= config.G7 {
|
||||
naviLength = 280
|
||||
}
|
||||
var data []byte
|
||||
// Load existing save
|
||||
err := s.server.db.QueryRow("SELECT hunternavi FROM characters WHERE id = $1", s.charID).Scan(&data)
|
||||
err := database.QueryRow("SELECT hunternavi FROM characters WHERE id = $1", s.CharID).Scan(&data)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to load hunternavi", zap.Error(err))
|
||||
s.Logger.Error("Failed to load hunternavi", zap.Error(err))
|
||||
}
|
||||
|
||||
// Check if we actually had any hunternavi data, using a blank buffer if not.
|
||||
@@ -90,22 +109,22 @@ func handleMsgMhfSaveHunterNavi(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
|
||||
// Perform diff and compress it to write back to db
|
||||
s.logger.Info("Diffing...")
|
||||
s.Logger.Info("Diffing...")
|
||||
saveOutput := deltacomp.ApplyDataDiff(pkt.RawDataPayload, data)
|
||||
_, err = s.server.db.Exec("UPDATE characters SET hunternavi=$1 WHERE id=$2", saveOutput, s.charID)
|
||||
_, err = database.Exec("UPDATE characters SET hunternavi=$1 WHERE id=$2", saveOutput, s.CharID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to save hunternavi", zap.Error(err))
|
||||
s.Logger.Error("Failed to save hunternavi", zap.Error(err))
|
||||
}
|
||||
s.logger.Info("Wrote recompressed hunternavi back to DB")
|
||||
s.Logger.Info("Wrote recompressed hunternavi back to DB")
|
||||
} else {
|
||||
dumpSaveData(s, pkt.RawDataPayload, "hunternavi")
|
||||
// simply update database, no extra processing
|
||||
_, err := s.server.db.Exec("UPDATE characters SET hunternavi=$1 WHERE id=$2", pkt.RawDataPayload, s.charID)
|
||||
_, err := database.Exec("UPDATE characters SET hunternavi=$1 WHERE id=$2", pkt.RawDataPayload, s.CharID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to save hunternavi", zap.Error(err))
|
||||
s.Logger.Error("Failed to save hunternavi", zap.Error(err))
|
||||
}
|
||||
}
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
}
|
||||
|
||||
func handleMsgMhfMercenaryHuntdata(s *Session, p mhfpacket.MHFPacket) {
|
||||
@@ -116,9 +135,9 @@ func handleMsgMhfMercenaryHuntdata(s *Session, p mhfpacket.MHFPacket) {
|
||||
// struct Hunt
|
||||
// uint32 HuntID
|
||||
// uint32 MonID
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 1))
|
||||
DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 1))
|
||||
} else {
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 0))
|
||||
DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 0))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,39 +151,51 @@ func handleMsgMhfEnumerateMercenaryLog(s *Session, p mhfpacket.MHFPacket) {
|
||||
// []byte Name (len 18)
|
||||
// uint8 Unk
|
||||
// uint8 Unk
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfCreateMercenary(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfCreateMercenary)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
bf := byteframe.NewByteFrame()
|
||||
var nextID uint32
|
||||
_ = s.server.db.QueryRow("SELECT nextval('rasta_id_seq')").Scan(&nextID)
|
||||
s.server.db.Exec("UPDATE characters SET rasta_id=$1 WHERE id=$2", nextID, s.charID)
|
||||
_ = database.QueryRow("SELECT nextval('rasta_id_seq')").Scan(&nextID)
|
||||
database.Exec("UPDATE characters SET rasta_id=$1 WHERE id=$2", nextID, s.CharID)
|
||||
bf.WriteUint32(nextID)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfSaveMercenary(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfSaveMercenary)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
dumpSaveData(s, pkt.MercData, "mercenary")
|
||||
if len(pkt.MercData) > 0 {
|
||||
temp := byteframe.NewByteFrameFromBytes(pkt.MercData)
|
||||
s.server.db.Exec("UPDATE characters SET savemercenary=$1, rasta_id=$2 WHERE id=$3", pkt.MercData, temp.ReadUint32(), s.charID)
|
||||
database.Exec("UPDATE characters SET savemercenary=$1, rasta_id=$2 WHERE id=$3", pkt.MercData, temp.ReadUint32(), s.CharID)
|
||||
}
|
||||
s.server.db.Exec("UPDATE characters SET gcp=$1, pact_id=$2 WHERE id=$3", pkt.GCP, pkt.PactMercID, s.charID)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
database.Exec("UPDATE characters SET gcp=$1, pact_id=$2 WHERE id=$3", pkt.GCP, pkt.PactMercID, s.CharID)
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
}
|
||||
|
||||
func handleMsgMhfReadMercenaryW(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfReadMercenaryW)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
bf := byteframe.NewByteFrame()
|
||||
|
||||
var pactID, cid uint32
|
||||
var name string
|
||||
s.server.db.QueryRow("SELECT pact_id FROM characters WHERE id=$1", s.charID).Scan(&pactID)
|
||||
database.QueryRow("SELECT pact_id FROM characters WHERE id=$1", s.CharID).Scan(&pactID)
|
||||
if pactID > 0 {
|
||||
s.server.db.QueryRow("SELECT name, id FROM characters WHERE rasta_id = $1", pactID).Scan(&name, &cid)
|
||||
database.QueryRow("SELECT name, id FROM characters WHERE rasta_id = $1", pactID).Scan(&name, &cid)
|
||||
bf.WriteUint8(1) // numLends
|
||||
bf.WriteUint32(pactID)
|
||||
bf.WriteUint32(cid)
|
||||
@@ -179,7 +210,7 @@ func handleMsgMhfReadMercenaryW(s *Session, p mhfpacket.MHFPacket) {
|
||||
var loans uint8
|
||||
temp := byteframe.NewByteFrame()
|
||||
if pkt.Op < 2 {
|
||||
rows, _ := s.server.db.Query("SELECT name, id, pact_id FROM characters WHERE pact_id=(SELECT rasta_id FROM characters WHERE id=$1)", s.charID)
|
||||
rows, _ := database.Query("SELECT name, id, pact_id FROM characters WHERE pact_id=(SELECT rasta_id FROM characters WHERE id=$1)", s.CharID)
|
||||
for rows.Next() {
|
||||
err := rows.Scan(&name, &cid, &pactID)
|
||||
if err != nil {
|
||||
@@ -199,8 +230,8 @@ func handleMsgMhfReadMercenaryW(s *Session, p mhfpacket.MHFPacket) {
|
||||
if pkt.Op < 1 {
|
||||
var data []byte
|
||||
var gcp uint32
|
||||
s.server.db.QueryRow("SELECT savemercenary FROM characters WHERE id=$1", s.charID).Scan(&data)
|
||||
s.server.db.QueryRow("SELECT COALESCE(gcp, 0) FROM characters WHERE id=$1", s.charID).Scan(&gcp)
|
||||
database.QueryRow("SELECT savemercenary FROM characters WHERE id=$1", s.CharID).Scan(&data)
|
||||
database.QueryRow("SELECT COALESCE(gcp, 0) FROM characters WHERE id=$1", s.CharID).Scan(&gcp)
|
||||
|
||||
if len(data) == 0 {
|
||||
bf.WriteBool(false)
|
||||
@@ -211,53 +242,69 @@ func handleMsgMhfReadMercenaryW(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint32(gcp)
|
||||
}
|
||||
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfReadMercenaryM(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfReadMercenaryM)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
var data []byte
|
||||
s.server.db.QueryRow("SELECT savemercenary FROM characters WHERE id = $1", pkt.CharID).Scan(&data)
|
||||
database.QueryRow("SELECT savemercenary FROM characters WHERE id = $1", pkt.CharID).Scan(&data)
|
||||
resp := byteframe.NewByteFrame()
|
||||
if len(data) == 0 {
|
||||
resp.WriteBool(false)
|
||||
} else {
|
||||
resp.WriteBytes(data)
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfContractMercenary(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfContractMercenary)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
switch pkt.Op {
|
||||
case 0: // Form loan
|
||||
s.server.db.Exec("UPDATE characters SET pact_id=$1 WHERE id=$2", pkt.PactMercID, pkt.CID)
|
||||
database.Exec("UPDATE characters SET pact_id=$1 WHERE id=$2", pkt.PactMercID, pkt.CID)
|
||||
case 1: // Cancel lend
|
||||
s.server.db.Exec("UPDATE characters SET pact_id=0 WHERE id=$1", s.charID)
|
||||
database.Exec("UPDATE characters SET pact_id=0 WHERE id=$1", s.CharID)
|
||||
case 2: // Cancel loan
|
||||
s.server.db.Exec("UPDATE characters SET pact_id=0 WHERE id=$1", pkt.CID)
|
||||
database.Exec("UPDATE characters SET pact_id=0 WHERE id=$1", pkt.CID)
|
||||
}
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func handleMsgMhfLoadOtomoAirou(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfLoadOtomoAirou)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
var data []byte
|
||||
err := s.server.db.QueryRow("SELECT otomoairou FROM characters WHERE id = $1", s.charID).Scan(&data)
|
||||
err = database.QueryRow("SELECT otomoairou FROM characters WHERE id = $1", s.CharID).Scan(&data)
|
||||
if len(data) == 0 {
|
||||
s.logger.Error("Failed to load otomoairou", zap.Error(err))
|
||||
s.Logger.Error("Failed to load otomoairou", zap.Error(err))
|
||||
data = make([]byte, 10)
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, data)
|
||||
DoAckBufSucceed(s, pkt.AckHandle, data)
|
||||
}
|
||||
|
||||
func handleMsgMhfSaveOtomoAirou(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfSaveOtomoAirou)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
dumpSaveData(s, pkt.RawDataPayload, "otomoairou")
|
||||
decomp, err := nullcomp.Decompress(pkt.RawDataPayload[1:])
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to decompress airou", zap.Error(err))
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
s.Logger.Error("Failed to decompress airou", zap.Error(err))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
bf := byteframe.NewByteFrameFromBytes(decomp)
|
||||
@@ -270,7 +317,7 @@ func handleMsgMhfSaveOtomoAirou(s *Session, p mhfpacket.MHFPacket) {
|
||||
dataLen := bf.ReadUint32()
|
||||
catID := bf.ReadUint32()
|
||||
if catID == 0 {
|
||||
_ = s.server.db.QueryRow("SELECT nextval('airou_id_seq')").Scan(&catID)
|
||||
_ = database.QueryRow("SELECT nextval('airou_id_seq')").Scan(&catID)
|
||||
}
|
||||
exists := bf.ReadBool()
|
||||
data := bf.ReadBytes(uint(dataLen) - 5)
|
||||
@@ -287,12 +334,12 @@ func handleMsgMhfSaveOtomoAirou(s *Session, p mhfpacket.MHFPacket) {
|
||||
save.WriteUint8(catsExist)
|
||||
comp, err := nullcomp.Compress(save.Data())
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to compress airou", zap.Error(err))
|
||||
s.Logger.Error("Failed to compress airou", zap.Error(err))
|
||||
} else {
|
||||
comp = append([]byte{0x01}, comp...)
|
||||
s.server.db.Exec("UPDATE characters SET otomoairou=$1 WHERE id=$2", comp, s.charID)
|
||||
database.Exec("UPDATE characters SET otomoairou=$1 WHERE id=$2", comp, s.CharID)
|
||||
}
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func handleMsgMhfEnumerateAiroulist(s *Session, p mhfpacket.MHFPacket) {
|
||||
@@ -311,7 +358,7 @@ func handleMsgMhfEnumerateAiroulist(s *Session, p mhfpacket.MHFPacket) {
|
||||
resp.WriteUint16(cat.WeaponID)
|
||||
resp.WriteUint32(0) // 32 bit unix timestamp, either time at which the cat stops being fatigued or the time at which it started
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
}
|
||||
|
||||
type Airou struct {
|
||||
@@ -326,17 +373,21 @@ type Airou struct {
|
||||
}
|
||||
|
||||
func getGuildAirouList(s *Session) []Airou {
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
var guildCats []Airou
|
||||
bannedCats := make(map[uint32]int)
|
||||
guild, err := GetGuildInfoByCharacterId(s, s.charID)
|
||||
guild, err := GetGuildInfoByCharacterId(s, s.CharID)
|
||||
if err != nil {
|
||||
return guildCats
|
||||
}
|
||||
rows, err := s.server.db.Query(`SELECT cats_used FROM guild_hunts gh
|
||||
rows, err := database.Query(`SELECT cats_used FROM guild_hunts gh
|
||||
INNER JOIN characters c ON gh.host_id = c.id WHERE c.id=$1
|
||||
`, s.charID)
|
||||
`, s.CharID)
|
||||
if err != nil {
|
||||
s.logger.Warn("Failed to get recently used airous", zap.Error(err))
|
||||
s.Logger.Warn("Failed to get recently used airous", zap.Error(err))
|
||||
return guildCats
|
||||
}
|
||||
|
||||
@@ -347,19 +398,19 @@ func getGuildAirouList(s *Session) []Airou {
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if startTemp.Add(time.Second * time.Duration(s.server.erupeConfig.GameplayOptions.TreasureHuntPartnyaCooldown)).Before(gametime.TimeAdjusted()) {
|
||||
if startTemp.Add(time.Second * time.Duration(config.GetConfig().GameplayOptions.TreasureHuntPartnyaCooldown)).Before(gametime.TimeAdjusted()) {
|
||||
for i, j := range stringsupport.CSVElems(csvTemp) {
|
||||
bannedCats[uint32(j)] = i
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rows, err = s.server.db.Query(`SELECT c.otomoairou FROM characters c
|
||||
rows, err = database.Query(`SELECT c.otomoairou FROM characters c
|
||||
INNER JOIN guild_characters gc ON gc.character_id = c.id
|
||||
WHERE gc.guild_id = $1 AND c.otomoairou IS NOT NULL
|
||||
ORDER BY c.id LIMIT 60`, guild.ID)
|
||||
if err != nil {
|
||||
s.logger.Warn("Selecting otomoairou based on guild failed", zap.Error(err))
|
||||
s.Logger.Warn("Selecting otomoairou based on guild failed", zap.Error(err))
|
||||
return guildCats
|
||||
}
|
||||
|
||||
@@ -373,7 +424,7 @@ func getGuildAirouList(s *Session) []Airou {
|
||||
if data[0] == 1 {
|
||||
decomp, err := nullcomp.Decompress(data[1:])
|
||||
if err != nil {
|
||||
s.logger.Warn("decomp failure", zap.Error(err))
|
||||
s.Logger.Warn("decomp failure", zap.Error(err))
|
||||
continue
|
||||
}
|
||||
bf := byteframe.NewByteFrameFromBytes(decomp)
|
||||
|
||||
@@ -3,6 +3,7 @@ package channelserver
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"erupe-ce/config"
|
||||
"erupe-ce/network/mhfpacket"
|
||||
"erupe-ce/utils/byteframe"
|
||||
)
|
||||
@@ -13,18 +14,18 @@ func handleMsgSysCreateObject(s *Session, p mhfpacket.MHFPacket) {
|
||||
s.stage.Lock()
|
||||
newObj := &Object{
|
||||
id: s.NextObjectID(),
|
||||
ownerCharID: s.charID,
|
||||
ownerCharID: s.CharID,
|
||||
x: pkt.X,
|
||||
y: pkt.Y,
|
||||
z: pkt.Z,
|
||||
}
|
||||
s.stage.objects[s.charID] = newObj
|
||||
s.stage.objects[s.CharID] = newObj
|
||||
s.stage.Unlock()
|
||||
|
||||
// Response to our requesting client.
|
||||
resp := byteframe.NewByteFrame()
|
||||
resp.WriteUint32(newObj.id) // New local obj handle.
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, resp.Data())
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, resp.Data())
|
||||
// Duplicate the object creation to all sessions in the same stage.
|
||||
dupObjUpdate := &mhfpacket.MsgSysDuplicateObject{
|
||||
ObjID: newObj.id,
|
||||
@@ -34,7 +35,7 @@ func handleMsgSysCreateObject(s *Session, p mhfpacket.MHFPacket) {
|
||||
OwnerCharID: newObj.ownerCharID,
|
||||
}
|
||||
|
||||
s.logger.Info(fmt.Sprintf("Broadcasting new object: %s (%d)", s.Name, newObj.id))
|
||||
s.Logger.Info(fmt.Sprintf("Broadcasting new object: %s (%d)", s.Name, newObj.id))
|
||||
s.stage.BroadcastMHF(dupObjUpdate, s)
|
||||
}
|
||||
|
||||
@@ -42,11 +43,11 @@ func handleMsgSysDeleteObject(s *Session, p mhfpacket.MHFPacket) {}
|
||||
|
||||
func handleMsgSysPositionObject(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgSysPositionObject)
|
||||
if s.server.erupeConfig.DebugOptions.LogInboundMessages {
|
||||
if config.GetConfig().DebugOptions.LogInboundMessages {
|
||||
fmt.Printf("[%s] with objectID [%d] move to (%f,%f,%f)\n\n", s.Name, pkt.ObjID, pkt.X, pkt.Y, pkt.Z)
|
||||
}
|
||||
s.stage.Lock()
|
||||
object, ok := s.stage.objects[s.charID]
|
||||
object, ok := s.stage.objects[s.CharID]
|
||||
if ok {
|
||||
object.x = pkt.X
|
||||
object.y = pkt.Y
|
||||
@@ -64,16 +65,16 @@ func handleMsgSysDuplicateObject(s *Session, p mhfpacket.MHFPacket) {}
|
||||
func handleMsgSysSetObjectBinary(s *Session, p mhfpacket.MHFPacket) {
|
||||
_ = p.(*mhfpacket.MsgSysSetObjectBinary)
|
||||
/* This causes issues with PS3 as this actually sends with endiness!
|
||||
for _, session := range s.server.sessions {
|
||||
if session.charID == s.charID {
|
||||
s.server.userBinaryPartsLock.Lock()
|
||||
s.server.userBinaryParts[userBinaryPartID{charID: s.charID, index: 3}] = pkt.RawDataPayload
|
||||
s.server.userBinaryPartsLock.Unlock()
|
||||
for _, session := range s.Server.sessions {
|
||||
if session.CharID == s.CharID {
|
||||
s.Server.userBinaryPartsLock.Lock()
|
||||
s.Server.userBinaryParts[userBinaryPartID{charID: s.CharID, index: 3}] = pkt.RawDataPayload
|
||||
s.Server.userBinaryPartsLock.Unlock()
|
||||
msg := &mhfpacket.MsgSysNotifyUserBinary{
|
||||
CharID: s.charID,
|
||||
CharID: s.CharID,
|
||||
BinaryType: 3,
|
||||
}
|
||||
s.server.BroadcastMHF(msg, s)
|
||||
s.Server.BroadcastMHF(msg, s)
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -4,40 +4,50 @@ import (
|
||||
"erupe-ce/network/mhfpacket"
|
||||
"erupe-ce/server/channelserver/compression/deltacomp"
|
||||
"erupe-ce/server/channelserver/compression/nullcomp"
|
||||
"erupe-ce/utils/db"
|
||||
"fmt"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func handleMsgMhfLoadPlateData(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfLoadPlateData)
|
||||
var data []byte
|
||||
err := s.server.db.QueryRow("SELECT platedata FROM characters WHERE id = $1", s.charID).Scan(&data)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to load platedata", zap.Error(err))
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, data)
|
||||
err = database.QueryRow("SELECT platedata FROM characters WHERE id = $1", s.CharID).Scan(&data)
|
||||
if err != nil {
|
||||
s.Logger.Error("Failed to load platedata", zap.Error(err))
|
||||
}
|
||||
DoAckBufSucceed(s, pkt.AckHandle, data)
|
||||
}
|
||||
|
||||
func handleMsgMhfSavePlateData(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfSavePlateData)
|
||||
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
if pkt.IsDataDiff {
|
||||
var data []byte
|
||||
|
||||
// Load existing save
|
||||
err := s.server.db.QueryRow("SELECT platedata FROM characters WHERE id = $1", s.charID).Scan(&data)
|
||||
err := database.QueryRow("SELECT platedata FROM characters WHERE id = $1", s.CharID).Scan(&data)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to load platedata", zap.Error(err))
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
s.Logger.Error("Failed to load platedata", zap.Error(err))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
return
|
||||
}
|
||||
|
||||
if len(data) > 0 {
|
||||
// Decompress
|
||||
s.logger.Info("Decompressing...")
|
||||
s.Logger.Info("Decompressing...")
|
||||
data, err = nullcomp.Decompress(data)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to decompress platedata", zap.Error(err))
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
s.Logger.Error("Failed to decompress platedata", zap.Error(err))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
return
|
||||
}
|
||||
} else {
|
||||
@@ -46,66 +56,73 @@ func handleMsgMhfSavePlateData(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
|
||||
// Perform diff and compress it to write back to db
|
||||
s.logger.Info("Diffing...")
|
||||
s.Logger.Info("Diffing...")
|
||||
saveOutput, err := nullcomp.Compress(deltacomp.ApplyDataDiff(pkt.RawDataPayload, data))
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to diff and compress platedata", zap.Error(err))
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
s.Logger.Error("Failed to diff and compress platedata", zap.Error(err))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
return
|
||||
}
|
||||
|
||||
_, err = s.server.db.Exec("UPDATE characters SET platedata=$1 WHERE id=$2", saveOutput, s.charID)
|
||||
_, err = database.Exec("UPDATE characters SET platedata=$1 WHERE id=$2", saveOutput, s.CharID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to save platedata", zap.Error(err))
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
s.Logger.Error("Failed to save platedata", zap.Error(err))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
return
|
||||
}
|
||||
|
||||
s.logger.Info("Wrote recompressed platedata back to DB")
|
||||
s.Logger.Info("Wrote recompressed platedata back to DB")
|
||||
} else {
|
||||
dumpSaveData(s, pkt.RawDataPayload, "platedata")
|
||||
// simply update database, no extra processing
|
||||
_, err := s.server.db.Exec("UPDATE characters SET platedata=$1 WHERE id=$2", pkt.RawDataPayload, s.charID)
|
||||
_, err := database.Exec("UPDATE characters SET platedata=$1 WHERE id=$2", pkt.RawDataPayload, s.CharID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to save platedata", zap.Error(err))
|
||||
s.Logger.Error("Failed to save platedata", zap.Error(err))
|
||||
}
|
||||
}
|
||||
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
}
|
||||
|
||||
func handleMsgMhfLoadPlateBox(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfLoadPlateBox)
|
||||
var data []byte
|
||||
err := s.server.db.QueryRow("SELECT platebox FROM characters WHERE id = $1", s.charID).Scan(&data)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to load platebox", zap.Error(err))
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, data)
|
||||
err = database.QueryRow("SELECT platebox FROM characters WHERE id = $1", s.CharID).Scan(&data)
|
||||
if err != nil {
|
||||
s.Logger.Error("Failed to load platebox", zap.Error(err))
|
||||
}
|
||||
DoAckBufSucceed(s, pkt.AckHandle, data)
|
||||
}
|
||||
|
||||
func handleMsgMhfSavePlateBox(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfSavePlateBox)
|
||||
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
if pkt.IsDataDiff {
|
||||
var data []byte
|
||||
|
||||
// Load existing save
|
||||
err := s.server.db.QueryRow("SELECT platebox FROM characters WHERE id = $1", s.charID).Scan(&data)
|
||||
err := database.QueryRow("SELECT platebox FROM characters WHERE id = $1", s.CharID).Scan(&data)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to load platebox", zap.Error(err))
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
s.Logger.Error("Failed to load platebox", zap.Error(err))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
return
|
||||
}
|
||||
|
||||
// Decompress
|
||||
if len(data) > 0 {
|
||||
// Decompress
|
||||
s.logger.Info("Decompressing...")
|
||||
s.Logger.Info("Decompressing...")
|
||||
data, err = nullcomp.Decompress(data)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to decompress platebox", zap.Error(err))
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
s.Logger.Error("Failed to decompress platebox", zap.Error(err))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
return
|
||||
}
|
||||
} else {
|
||||
@@ -114,51 +131,59 @@ func handleMsgMhfSavePlateBox(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
|
||||
// Perform diff and compress it to write back to db
|
||||
s.logger.Info("Diffing...")
|
||||
s.Logger.Info("Diffing...")
|
||||
saveOutput, err := nullcomp.Compress(deltacomp.ApplyDataDiff(pkt.RawDataPayload, data))
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to diff and compress platebox", zap.Error(err))
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
s.Logger.Error("Failed to diff and compress platebox", zap.Error(err))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
return
|
||||
}
|
||||
|
||||
_, err = s.server.db.Exec("UPDATE characters SET platebox=$1 WHERE id=$2", saveOutput, s.charID)
|
||||
_, err = database.Exec("UPDATE characters SET platebox=$1 WHERE id=$2", saveOutput, s.CharID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to save platebox", zap.Error(err))
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
s.Logger.Error("Failed to save platebox", zap.Error(err))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
return
|
||||
}
|
||||
|
||||
s.logger.Info("Wrote recompressed platebox back to DB")
|
||||
s.Logger.Info("Wrote recompressed platebox back to DB")
|
||||
} else {
|
||||
dumpSaveData(s, pkt.RawDataPayload, "platebox")
|
||||
// simply update database, no extra processing
|
||||
_, err := s.server.db.Exec("UPDATE characters SET platebox=$1 WHERE id=$2", pkt.RawDataPayload, s.charID)
|
||||
_, err := database.Exec("UPDATE characters SET platebox=$1 WHERE id=$2", pkt.RawDataPayload, s.CharID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to save platebox", zap.Error(err))
|
||||
s.Logger.Error("Failed to save platebox", zap.Error(err))
|
||||
}
|
||||
}
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
}
|
||||
|
||||
func handleMsgMhfLoadPlateMyset(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfLoadPlateMyset)
|
||||
var data []byte
|
||||
err := s.server.db.QueryRow("SELECT platemyset FROM characters WHERE id = $1", s.charID).Scan(&data)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
err = database.QueryRow("SELECT platemyset FROM characters WHERE id = $1", s.CharID).Scan(&data)
|
||||
if len(data) == 0 {
|
||||
s.logger.Error("Failed to load platemyset", zap.Error(err))
|
||||
s.Logger.Error("Failed to load platemyset", zap.Error(err))
|
||||
data = make([]byte, 1920)
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, data)
|
||||
DoAckBufSucceed(s, pkt.AckHandle, data)
|
||||
}
|
||||
|
||||
func handleMsgMhfSavePlateMyset(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfSavePlateMyset)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
// looks to always return the full thing, simply update database, no extra processing
|
||||
dumpSaveData(s, pkt.RawDataPayload, "platemyset")
|
||||
_, err := s.server.db.Exec("UPDATE characters SET platemyset=$1 WHERE id=$2", pkt.RawDataPayload, s.charID)
|
||||
_, err = database.Exec("UPDATE characters SET platemyset=$1 WHERE id=$2", pkt.RawDataPayload, s.CharID)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to save platemyset", zap.Error(err))
|
||||
s.Logger.Error("Failed to save platemyset", zap.Error(err))
|
||||
}
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
}
|
||||
|
||||
@@ -4,10 +4,11 @@ import (
|
||||
"database/sql"
|
||||
"encoding/binary"
|
||||
"erupe-ce/utils/byteframe"
|
||||
"erupe-ce/utils/db"
|
||||
"erupe-ce/utils/decryption"
|
||||
"erupe-ce/utils/gametime"
|
||||
|
||||
_config "erupe-ce/config"
|
||||
"erupe-ce/config"
|
||||
"erupe-ce/network/mhfpacket"
|
||||
ps "erupe-ce/utils/pascalstring"
|
||||
"fmt"
|
||||
@@ -62,16 +63,16 @@ func BackportQuest(data []byte) []byte {
|
||||
}
|
||||
|
||||
fillLength := uint32(108)
|
||||
if _config.ErupeConfig.ClientID <= _config.S6 {
|
||||
if config.GetConfig().ClientID <= config.S6 {
|
||||
fillLength = 44
|
||||
} else if _config.ErupeConfig.ClientID <= _config.F5 {
|
||||
} else if config.GetConfig().ClientID <= config.F5 {
|
||||
fillLength = 52
|
||||
} else if _config.ErupeConfig.ClientID <= _config.G101 {
|
||||
} else if config.GetConfig().ClientID <= config.G101 {
|
||||
fillLength = 76
|
||||
}
|
||||
|
||||
copy(data[wp:wp+fillLength], data[rp:rp+fillLength])
|
||||
if _config.ErupeConfig.ClientID <= _config.G91 {
|
||||
if config.GetConfig().ClientID <= config.G91 {
|
||||
patterns := [][]byte{
|
||||
{0x0A, 0x00, 0x01, 0x33, 0xD7, 0x00}, // 10% Armor Sphere -> Stone
|
||||
{0x06, 0x00, 0x02, 0x33, 0xD8, 0x00}, // 6% Armor Sphere+ -> Iron Ore
|
||||
@@ -94,8 +95,8 @@ func handleMsgSysGetFile(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgSysGetFile)
|
||||
|
||||
if pkt.IsScenario {
|
||||
if s.server.erupeConfig.DebugOptions.QuestTools {
|
||||
s.logger.Debug(
|
||||
if config.GetConfig().DebugOptions.QuestTools {
|
||||
s.Logger.Debug(
|
||||
"Scenario",
|
||||
zap.Uint8("CategoryID", pkt.ScenarioIdentifer.CategoryID),
|
||||
zap.Uint32("MainID", pkt.ScenarioIdentifer.MainID),
|
||||
@@ -105,49 +106,49 @@ func handleMsgSysGetFile(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
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 := os.ReadFile(filepath.Join(s.server.erupeConfig.BinPath, fmt.Sprintf("scenarios/%s.bin", filename)))
|
||||
data, err := os.ReadFile(filepath.Join(config.GetConfig().BinPath, fmt.Sprintf("scenarios/%s.bin", filename)))
|
||||
if err != nil {
|
||||
s.logger.Error(fmt.Sprintf("Failed to open file: %s/scenarios/%s.bin", s.server.erupeConfig.BinPath, filename))
|
||||
s.Logger.Error(fmt.Sprintf("Failed to open file: %s/scenarios/%s.bin", config.GetConfig().BinPath, filename))
|
||||
// This will crash the game.
|
||||
doAckBufSucceed(s, pkt.AckHandle, data)
|
||||
DoAckBufSucceed(s, pkt.AckHandle, data)
|
||||
return
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, data)
|
||||
DoAckBufSucceed(s, pkt.AckHandle, data)
|
||||
} else {
|
||||
if s.server.erupeConfig.DebugOptions.QuestTools {
|
||||
s.logger.Debug(
|
||||
if config.GetConfig().DebugOptions.QuestTools {
|
||||
s.Logger.Debug(
|
||||
"Quest",
|
||||
zap.String("Filename", pkt.Filename),
|
||||
)
|
||||
}
|
||||
|
||||
if s.server.erupeConfig.GameplayOptions.SeasonOverride {
|
||||
if config.GetConfig().GameplayOptions.SeasonOverride {
|
||||
pkt.Filename = seasonConversion(s, pkt.Filename)
|
||||
}
|
||||
|
||||
data, err := os.ReadFile(filepath.Join(s.server.erupeConfig.BinPath, fmt.Sprintf("quests/%s.bin", pkt.Filename)))
|
||||
data, err := os.ReadFile(filepath.Join(config.GetConfig().BinPath, fmt.Sprintf("quests/%s.bin", pkt.Filename)))
|
||||
if err != nil {
|
||||
s.logger.Error(fmt.Sprintf("Failed to open file: %s/quests/%s.bin", s.server.erupeConfig.BinPath, pkt.Filename))
|
||||
s.Logger.Error(fmt.Sprintf("Failed to open file: %s/quests/%s.bin", config.GetConfig().BinPath, pkt.Filename))
|
||||
// This will crash the game.
|
||||
doAckBufSucceed(s, pkt.AckHandle, data)
|
||||
DoAckBufSucceed(s, pkt.AckHandle, data)
|
||||
return
|
||||
}
|
||||
if _config.ErupeConfig.ClientID <= _config.Z1 && s.server.erupeConfig.DebugOptions.AutoQuestBackport {
|
||||
if config.GetConfig().ClientID <= config.Z1 && config.GetConfig().DebugOptions.AutoQuestBackport {
|
||||
data = BackportQuest(decryption.UnpackSimple(data))
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, data)
|
||||
DoAckBufSucceed(s, pkt.AckHandle, data)
|
||||
}
|
||||
}
|
||||
|
||||
func seasonConversion(s *Session, questFile string) string {
|
||||
filename := fmt.Sprintf("%s%d", questFile[:6], s.server.Season())
|
||||
filename := fmt.Sprintf("%s%d", questFile[:6], s.Server.Season())
|
||||
|
||||
// Return the seasonal file
|
||||
if _, err := os.Stat(filepath.Join(s.server.erupeConfig.BinPath, fmt.Sprintf("quests/%s.bin", filename))); err == nil {
|
||||
if _, err := os.Stat(filepath.Join(config.GetConfig().BinPath, fmt.Sprintf("quests/%s.bin", filename))); err == nil {
|
||||
return filename
|
||||
} else {
|
||||
// Attempt to return the requested quest file if the seasonal file doesn't exist
|
||||
if _, err = os.Stat(filepath.Join(s.server.erupeConfig.BinPath, fmt.Sprintf("quests/%s.bin", questFile))); err == nil {
|
||||
if _, err = os.Stat(filepath.Join(config.GetConfig().BinPath, fmt.Sprintf("quests/%s.bin", questFile))); err == nil {
|
||||
return questFile
|
||||
}
|
||||
|
||||
@@ -169,34 +170,42 @@ func seasonConversion(s *Session, questFile string) string {
|
||||
func handleMsgMhfLoadFavoriteQuest(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfLoadFavoriteQuest)
|
||||
var data []byte
|
||||
err := s.server.db.QueryRow("SELECT savefavoritequest FROM characters WHERE id = $1", s.charID).Scan(&data)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
err = database.QueryRow("SELECT savefavoritequest FROM characters WHERE id = $1", s.CharID).Scan(&data)
|
||||
if err == nil && len(data) > 0 {
|
||||
doAckBufSucceed(s, pkt.AckHandle, data)
|
||||
DoAckBufSucceed(s, pkt.AckHandle, data)
|
||||
} else {
|
||||
doAckBufSucceed(s, pkt.AckHandle, []byte{0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})
|
||||
DoAckBufSucceed(s, pkt.AckHandle, []byte{0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})
|
||||
}
|
||||
}
|
||||
|
||||
func handleMsgMhfSaveFavoriteQuest(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfSaveFavoriteQuest)
|
||||
dumpSaveData(s, pkt.Data, "favquest")
|
||||
s.server.db.Exec("UPDATE characters SET savefavoritequest=$1 WHERE id=$2", pkt.Data, s.charID)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
database.Exec("UPDATE characters SET savefavoritequest=$1 WHERE id=$2", pkt.Data, s.CharID)
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
}
|
||||
|
||||
func loadQuestFile(s *Session, questId int) []byte {
|
||||
data, exists := s.server.questCacheData[questId]
|
||||
if exists && s.server.questCacheTime[questId].Add(time.Duration(s.server.erupeConfig.QuestCacheExpiry)*time.Second).After(time.Now()) {
|
||||
data, exists := s.Server.questCacheData[questId]
|
||||
if exists && s.Server.questCacheTime[questId].Add(time.Duration(config.GetConfig().QuestCacheExpiry)*time.Second).After(time.Now()) {
|
||||
return data
|
||||
}
|
||||
|
||||
file, err := os.ReadFile(filepath.Join(s.server.erupeConfig.BinPath, fmt.Sprintf("quests/%05dd0.bin", questId)))
|
||||
file, err := os.ReadFile(filepath.Join(config.GetConfig().BinPath, fmt.Sprintf("quests/%05dd0.bin", questId)))
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
decrypted := decryption.UnpackSimple(file)
|
||||
if _config.ErupeConfig.ClientID <= _config.Z1 && s.server.erupeConfig.DebugOptions.AutoQuestBackport {
|
||||
if config.GetConfig().ClientID <= config.Z1 && config.GetConfig().DebugOptions.AutoQuestBackport {
|
||||
decrypted = BackportQuest(decrypted)
|
||||
}
|
||||
fileBytes := byteframe.NewByteFrameFromBytes(decrypted)
|
||||
@@ -204,13 +213,13 @@ func loadQuestFile(s *Session, questId int) []byte {
|
||||
fileBytes.Seek(int64(fileBytes.ReadUint32()), 0)
|
||||
|
||||
bodyLength := 320
|
||||
if _config.ErupeConfig.ClientID <= _config.S6 {
|
||||
if config.GetConfig().ClientID <= config.S6 {
|
||||
bodyLength = 160
|
||||
} else if _config.ErupeConfig.ClientID <= _config.F5 {
|
||||
} else if config.GetConfig().ClientID <= config.F5 {
|
||||
bodyLength = 168
|
||||
} else if _config.ErupeConfig.ClientID <= _config.G101 {
|
||||
} else if config.GetConfig().ClientID <= config.G101 {
|
||||
bodyLength = 192
|
||||
} else if _config.ErupeConfig.ClientID <= _config.Z1 {
|
||||
} else if config.GetConfig().ClientID <= config.Z1 {
|
||||
bodyLength = 224
|
||||
}
|
||||
|
||||
@@ -240,8 +249,8 @@ func loadQuestFile(s *Session, questId int) []byte {
|
||||
}
|
||||
questBody.WriteBytes(newStrings.Data())
|
||||
|
||||
s.server.questCacheData[questId] = questBody.Data()
|
||||
s.server.questCacheTime[questId] = time.Now()
|
||||
s.Server.questCacheData[questId] = questBody.Data()
|
||||
s.Server.questCacheTime[questId] = time.Now()
|
||||
return questBody.Data()
|
||||
}
|
||||
|
||||
@@ -263,15 +272,15 @@ func makeEventQuest(s *Session, rows *sql.Rows) ([]byte, error) {
|
||||
bf.WriteUint8(0) // Unk
|
||||
switch questType {
|
||||
case 16:
|
||||
bf.WriteUint8(s.server.erupeConfig.GameplayOptions.RegularRavienteMaxPlayers)
|
||||
bf.WriteUint8(config.GetConfig().GameplayOptions.RegularRavienteMaxPlayers)
|
||||
case 22:
|
||||
bf.WriteUint8(s.server.erupeConfig.GameplayOptions.ViolentRavienteMaxPlayers)
|
||||
bf.WriteUint8(config.GetConfig().GameplayOptions.ViolentRavienteMaxPlayers)
|
||||
case 40:
|
||||
bf.WriteUint8(s.server.erupeConfig.GameplayOptions.BerserkRavienteMaxPlayers)
|
||||
bf.WriteUint8(config.GetConfig().GameplayOptions.BerserkRavienteMaxPlayers)
|
||||
case 50:
|
||||
bf.WriteUint8(s.server.erupeConfig.GameplayOptions.ExtremeRavienteMaxPlayers)
|
||||
bf.WriteUint8(config.GetConfig().GameplayOptions.ExtremeRavienteMaxPlayers)
|
||||
case 51:
|
||||
bf.WriteUint8(s.server.erupeConfig.GameplayOptions.SmallBerserkRavienteMaxPlayers)
|
||||
bf.WriteUint8(config.GetConfig().GameplayOptions.SmallBerserkRavienteMaxPlayers)
|
||||
default:
|
||||
bf.WriteUint8(maxPlayers)
|
||||
}
|
||||
@@ -282,7 +291,7 @@ func makeEventQuest(s *Session, rows *sql.Rows) ([]byte, error) {
|
||||
bf.WriteBool(true)
|
||||
}
|
||||
bf.WriteUint16(0) // Unk
|
||||
if _config.ErupeConfig.ClientID >= _config.G2 {
|
||||
if config.GetConfig().ClientID >= config.G2 {
|
||||
bf.WriteUint32(mark)
|
||||
}
|
||||
bf.WriteUint16(0) // Unk
|
||||
@@ -295,7 +304,7 @@ func makeEventQuest(s *Session, rows *sql.Rows) ([]byte, error) {
|
||||
bf.Seek(25, 0)
|
||||
flagByte := bf.ReadUint8()
|
||||
bf.Seek(25, 0)
|
||||
if s.server.erupeConfig.GameplayOptions.SeasonOverride {
|
||||
if config.GetConfig().GameplayOptions.SeasonOverride {
|
||||
bf.WriteUint8(flagByte & 0b11100000)
|
||||
} else {
|
||||
// Allow for seasons to be specified in database, otherwise use the one in the file.
|
||||
@@ -326,11 +335,14 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) {
|
||||
var totalCount, returnedCount uint16
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint16(0)
|
||||
|
||||
rows, err := s.server.db.Query("SELECT id, COALESCE(max_players, 4) AS max_players, quest_type, quest_id, COALESCE(mark, 0) AS mark, COALESCE(flags, -1), start_time, COALESCE(active_days, 0) AS active_days, COALESCE(inactive_days, 0) AS inactive_days FROM event_quests ORDER BY quest_id")
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
rows, err := database.Query("SELECT id, COALESCE(max_players, 4) AS max_players, quest_type, quest_id, COALESCE(mark, 0) AS mark, COALESCE(flags, -1), start_time, COALESCE(active_days, 0) AS active_days, COALESCE(inactive_days, 0) AS inactive_days FROM event_quests ORDER BY quest_id")
|
||||
if err == nil {
|
||||
currentTime := time.Now()
|
||||
tx, _ := s.server.db.Begin()
|
||||
tx, _ := database.Begin()
|
||||
|
||||
for rows.Next() {
|
||||
var id, mark uint32
|
||||
@@ -340,7 +352,7 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) {
|
||||
|
||||
err = rows.Scan(&id, &maxPlayers, &questType, &questId, &mark, &flags, &startTime, &activeDays, &inactiveDays)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to scan event quest row", zap.Error(err))
|
||||
s.Logger.Error("Failed to scan event quest row", zap.Error(err))
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -375,11 +387,11 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) {
|
||||
|
||||
data, err := makeEventQuest(s, rows)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to make event quest", zap.Error(err))
|
||||
s.Logger.Error("Failed to make event quest", zap.Error(err))
|
||||
continue
|
||||
} else {
|
||||
if len(data) > 896 || len(data) < 352 {
|
||||
s.logger.Error("Invalid quest data length", zap.Int("len", len(data)))
|
||||
s.Logger.Error("Invalid quest data length", zap.Int("len", len(data)))
|
||||
continue
|
||||
} else {
|
||||
totalCount++
|
||||
@@ -504,54 +516,54 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) {
|
||||
{ID: 1180, Value: 5},
|
||||
}
|
||||
|
||||
tuneValues = append(tuneValues, tuneValue{1020, uint16(s.server.erupeConfig.GameplayOptions.GCPMultiplier * 100)})
|
||||
tuneValues = append(tuneValues, tuneValue{1020, uint16(config.GetConfig().GameplayOptions.GCPMultiplier * 100)})
|
||||
|
||||
tuneValues = append(tuneValues, tuneValue{1029, uint16(s.server.erupeConfig.GameplayOptions.GUrgentRate * 100)})
|
||||
tuneValues = append(tuneValues, tuneValue{1029, uint16(config.GetConfig().GameplayOptions.GUrgentRate * 100)})
|
||||
|
||||
if s.server.erupeConfig.GameplayOptions.DisableHunterNavi {
|
||||
if config.GetConfig().GameplayOptions.DisableHunterNavi {
|
||||
tuneValues = append(tuneValues, tuneValue{1037, 1})
|
||||
}
|
||||
|
||||
if s.server.erupeConfig.GameplayOptions.EnableKaijiEvent {
|
||||
if config.GetConfig().GameplayOptions.EnableKaijiEvent {
|
||||
tuneValues = append(tuneValues, tuneValue{1106, 1})
|
||||
}
|
||||
|
||||
if s.server.erupeConfig.GameplayOptions.EnableHiganjimaEvent {
|
||||
if config.GetConfig().GameplayOptions.EnableHiganjimaEvent {
|
||||
tuneValues = append(tuneValues, tuneValue{1144, 1})
|
||||
}
|
||||
|
||||
if s.server.erupeConfig.GameplayOptions.EnableNierEvent {
|
||||
if config.GetConfig().GameplayOptions.EnableNierEvent {
|
||||
tuneValues = append(tuneValues, tuneValue{1153, 1})
|
||||
}
|
||||
|
||||
if s.server.erupeConfig.GameplayOptions.DisableRoad {
|
||||
if config.GetConfig().GameplayOptions.DisableRoad {
|
||||
tuneValues = append(tuneValues, tuneValue{1155, 1})
|
||||
}
|
||||
|
||||
// get_hrp_rate_from_rank
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3000, uint16(s.server.erupeConfig.GameplayOptions.HRPMultiplier*100))...)
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3338, uint16(s.server.erupeConfig.GameplayOptions.HRPMultiplierNC*100))...)
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3000, uint16(config.GetConfig().GameplayOptions.HRPMultiplier*100))...)
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3338, uint16(config.GetConfig().GameplayOptions.HRPMultiplierNC*100))...)
|
||||
// get_srp_rate_from_rank
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3013, uint16(s.server.erupeConfig.GameplayOptions.SRPMultiplier*100))...)
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3351, uint16(s.server.erupeConfig.GameplayOptions.SRPMultiplierNC*100))...)
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3013, uint16(config.GetConfig().GameplayOptions.SRPMultiplier*100))...)
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3351, uint16(config.GetConfig().GameplayOptions.SRPMultiplierNC*100))...)
|
||||
// get_grp_rate_from_rank
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3026, uint16(s.server.erupeConfig.GameplayOptions.GRPMultiplier*100))...)
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3364, uint16(s.server.erupeConfig.GameplayOptions.GRPMultiplierNC*100))...)
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3026, uint16(config.GetConfig().GameplayOptions.GRPMultiplier*100))...)
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3364, uint16(config.GetConfig().GameplayOptions.GRPMultiplierNC*100))...)
|
||||
// get_gsrp_rate_from_rank
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3039, uint16(s.server.erupeConfig.GameplayOptions.GSRPMultiplier*100))...)
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3377, uint16(s.server.erupeConfig.GameplayOptions.GSRPMultiplierNC*100))...)
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3039, uint16(config.GetConfig().GameplayOptions.GSRPMultiplier*100))...)
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3377, uint16(config.GetConfig().GameplayOptions.GSRPMultiplierNC*100))...)
|
||||
// get_zeny_rate_from_hrank
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3052, uint16(s.server.erupeConfig.GameplayOptions.ZennyMultiplier*100))...)
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3390, uint16(s.server.erupeConfig.GameplayOptions.ZennyMultiplierNC*100))...)
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3052, uint16(config.GetConfig().GameplayOptions.ZennyMultiplier*100))...)
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3390, uint16(config.GetConfig().GameplayOptions.ZennyMultiplierNC*100))...)
|
||||
// get_zeny_rate_from_grank
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3078, uint16(s.server.erupeConfig.GameplayOptions.GZennyMultiplier*100))...)
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3416, uint16(s.server.erupeConfig.GameplayOptions.GZennyMultiplierNC*100))...)
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3078, uint16(config.GetConfig().GameplayOptions.GZennyMultiplier*100))...)
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3416, uint16(config.GetConfig().GameplayOptions.GZennyMultiplierNC*100))...)
|
||||
// get_reward_rate_from_hrank
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3104, uint16(s.server.erupeConfig.GameplayOptions.MaterialMultiplier*100))...)
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3442, uint16(s.server.erupeConfig.GameplayOptions.MaterialMultiplierNC*100))...)
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3104, uint16(config.GetConfig().GameplayOptions.MaterialMultiplier*100))...)
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3442, uint16(config.GetConfig().GameplayOptions.MaterialMultiplierNC*100))...)
|
||||
// get_reward_rate_from_grank
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3130, uint16(s.server.erupeConfig.GameplayOptions.GMaterialMultiplier*100))...)
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3468, uint16(s.server.erupeConfig.GameplayOptions.GMaterialMultiplierNC*100))...)
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3130, uint16(config.GetConfig().GameplayOptions.GMaterialMultiplier*100))...)
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3468, uint16(config.GetConfig().GameplayOptions.GMaterialMultiplierNC*100))...)
|
||||
// get_lottery_rate_from_hrank
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3156, 0)...)
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3494, 0)...)
|
||||
@@ -559,11 +571,11 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) {
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3182, 0)...)
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3520, 0)...)
|
||||
// get_hagi_rate_from_hrank
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3208, s.server.erupeConfig.GameplayOptions.ExtraCarves)...)
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3546, s.server.erupeConfig.GameplayOptions.ExtraCarvesNC)...)
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3208, config.GetConfig().GameplayOptions.ExtraCarves)...)
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3546, config.GetConfig().GameplayOptions.ExtraCarvesNC)...)
|
||||
// get_hagi_rate_from_grank
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3234, s.server.erupeConfig.GameplayOptions.GExtraCarves)...)
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3572, s.server.erupeConfig.GameplayOptions.GExtraCarvesNC)...)
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3234, config.GetConfig().GameplayOptions.GExtraCarves)...)
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3572, config.GetConfig().GameplayOptions.GExtraCarvesNC)...)
|
||||
// get_nboost_transcend_rate_from_hrank
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3286, 200)...)
|
||||
tuneValues = append(tuneValues, getTuneValueRange(3312, 300)...)
|
||||
@@ -580,23 +592,23 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) {
|
||||
tuneValues = temp
|
||||
|
||||
tuneLimit := 770
|
||||
if _config.ErupeConfig.ClientID <= _config.G1 {
|
||||
if config.GetConfig().ClientID <= config.G1 {
|
||||
tuneLimit = 256
|
||||
} else if _config.ErupeConfig.ClientID <= _config.G3 {
|
||||
} else if config.GetConfig().ClientID <= config.G3 {
|
||||
tuneLimit = 283
|
||||
} else if _config.ErupeConfig.ClientID <= _config.GG {
|
||||
} else if config.GetConfig().ClientID <= config.GG {
|
||||
tuneLimit = 315
|
||||
} else if _config.ErupeConfig.ClientID <= _config.G61 {
|
||||
} else if config.GetConfig().ClientID <= config.G61 {
|
||||
tuneLimit = 332
|
||||
} else if _config.ErupeConfig.ClientID <= _config.G7 {
|
||||
} else if config.GetConfig().ClientID <= config.G7 {
|
||||
tuneLimit = 339
|
||||
} else if _config.ErupeConfig.ClientID <= _config.G81 {
|
||||
} else if config.GetConfig().ClientID <= config.G81 {
|
||||
tuneLimit = 396
|
||||
} else if _config.ErupeConfig.ClientID <= _config.G91 {
|
||||
} else if config.GetConfig().ClientID <= config.G91 {
|
||||
tuneLimit = 694
|
||||
} else if _config.ErupeConfig.ClientID <= _config.G101 {
|
||||
} else if config.GetConfig().ClientID <= config.G101 {
|
||||
tuneLimit = 704
|
||||
} else if _config.ErupeConfig.ClientID <= _config.Z2 {
|
||||
} else if config.GetConfig().ClientID <= config.Z2 {
|
||||
tuneLimit = 750
|
||||
}
|
||||
if len(tuneValues) > tuneLimit {
|
||||
@@ -644,7 +656,7 @@ func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.Seek(0, io.SeekStart)
|
||||
bf.WriteUint16(returnedCount)
|
||||
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func getTuneValueRange(start uint16, value uint16) []tuneValue {
|
||||
@@ -682,5 +694,5 @@ func handleMsgMhfGetUdBonusQuestInfo(s *Session, p mhfpacket.MHFPacket) {
|
||||
resp.WriteUint8(q.Unk6)
|
||||
}
|
||||
|
||||
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package channelserver
|
||||
|
||||
import (
|
||||
"erupe-ce/config"
|
||||
"erupe-ce/network/mhfpacket"
|
||||
"erupe-ce/utils/byteframe"
|
||||
"strings"
|
||||
@@ -10,14 +11,14 @@ func handleMsgMhfRegisterEvent(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfRegisterEvent)
|
||||
bf := byteframe.NewByteFrame()
|
||||
// Some kind of check if there's already a session
|
||||
if pkt.Unk1 && s.server.getRaviSemaphore() == nil {
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
if pkt.Unk1 && s.Server.getRaviSemaphore() == nil {
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
bf.WriteUint8(uint8(pkt.WorldID))
|
||||
bf.WriteUint8(uint8(pkt.LandID))
|
||||
bf.WriteUint16(s.server.raviente.id)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
|
||||
bf.WriteUint16(s.Server.raviente.id)
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfReleaseEvent(s *Session, p mhfpacket.MHFPacket) {
|
||||
@@ -71,23 +72,23 @@ func handleMsgSysOperateRegister(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf = byteframe.NewByteFrame()
|
||||
|
||||
var _old, _new uint32
|
||||
s.server.raviente.Lock()
|
||||
s.Server.raviente.Lock()
|
||||
for _, update := range raviUpdates {
|
||||
switch update.Op {
|
||||
case 2:
|
||||
_old, _new = s.server.UpdateRavi(pkt.SemaphoreID, update.Dest, update.Data, true)
|
||||
_old, _new = s.Server.UpdateRavi(pkt.SemaphoreID, update.Dest, update.Data, true)
|
||||
case 13, 14:
|
||||
_old, _new = s.server.UpdateRavi(pkt.SemaphoreID, update.Dest, update.Data, false)
|
||||
_old, _new = s.Server.UpdateRavi(pkt.SemaphoreID, update.Dest, update.Data, false)
|
||||
}
|
||||
bf.WriteUint8(1)
|
||||
bf.WriteUint8(update.Dest)
|
||||
bf.WriteUint32(_old)
|
||||
bf.WriteUint32(_new)
|
||||
}
|
||||
s.server.raviente.Unlock()
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
s.Server.raviente.Unlock()
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
|
||||
if s.server.erupeConfig.GameplayOptions.LowLatencyRaviente {
|
||||
if config.GetConfig().GameplayOptions.LowLatencyRaviente {
|
||||
s.notifyRavi()
|
||||
}
|
||||
}
|
||||
@@ -100,31 +101,31 @@ func handleMsgSysLoadRegister(s *Session, p mhfpacket.MHFPacket) {
|
||||
for i := uint8(0); i < pkt.Values; i++ {
|
||||
switch pkt.RegisterID {
|
||||
case 0x40000:
|
||||
bf.WriteUint32(s.server.raviente.state[i])
|
||||
bf.WriteUint32(s.Server.raviente.state[i])
|
||||
case 0x50000:
|
||||
bf.WriteUint32(s.server.raviente.support[i])
|
||||
bf.WriteUint32(s.Server.raviente.support[i])
|
||||
case 0x60000:
|
||||
bf.WriteUint32(s.server.raviente.register[i])
|
||||
bf.WriteUint32(s.Server.raviente.register[i])
|
||||
}
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func (s *Session) notifyRavi() {
|
||||
sema := s.server.getRaviSemaphore()
|
||||
sema := s.Server.getRaviSemaphore()
|
||||
if sema == nil {
|
||||
return
|
||||
}
|
||||
var temp mhfpacket.MHFPacket
|
||||
for i := 0; i < 3; i++ {
|
||||
temp = &mhfpacket.MsgSysLoadRegister{RegisterID: uint32(0x40000 + i*0x10000)}
|
||||
if s.server.erupeConfig.GameplayOptions.LowLatencyRaviente {
|
||||
if config.GetConfig().GameplayOptions.LowLatencyRaviente {
|
||||
for session := range sema.clients {
|
||||
session.QueueSendMHF(temp)
|
||||
}
|
||||
} else {
|
||||
for session := range sema.clients {
|
||||
if session.charID == s.charID {
|
||||
if session.CharID == s.CharID {
|
||||
session.QueueSendMHF(temp)
|
||||
}
|
||||
}
|
||||
@@ -132,7 +133,7 @@ func (s *Session) notifyRavi() {
|
||||
}
|
||||
}
|
||||
|
||||
func (server *Server) getRaviSemaphore() *Semaphore {
|
||||
func (server *ChannelServer) getRaviSemaphore() *Semaphore {
|
||||
for _, semaphore := range server.semaphore {
|
||||
if strings.HasPrefix(semaphore.name, "hs_l0") && strings.HasSuffix(semaphore.name, "3") {
|
||||
return semaphore
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package channelserver
|
||||
|
||||
import (
|
||||
"erupe-ce/config"
|
||||
"erupe-ce/utils/db"
|
||||
ps "erupe-ce/utils/pascalstring"
|
||||
"fmt"
|
||||
"os"
|
||||
@@ -18,11 +20,15 @@ func handleMsgMhfSaveRengokuData(s *Session, p mhfpacket.MHFPacket) {
|
||||
// saved every floor on road, holds values such as floors progressed, points etc.
|
||||
// can be safely handled by the client
|
||||
pkt := p.(*mhfpacket.MsgMhfSaveRengokuData)
|
||||
dumpSaveData(s, pkt.RawDataPayload, "rengoku")
|
||||
_, err := s.server.db.Exec("UPDATE characters SET rengokudata=$1 WHERE id=$2", pkt.RawDataPayload, s.charID)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to save rengokudata", zap.Error(err))
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
dumpSaveData(s, pkt.RawDataPayload, "rengoku")
|
||||
_, err = database.Exec("UPDATE characters SET rengokudata=$1 WHERE id=$2", pkt.RawDataPayload, s.CharID)
|
||||
if err != nil {
|
||||
s.Logger.Error("Failed to save rengokudata", zap.Error(err))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
bf := byteframe.NewByteFrameFromBytes(pkt.RawDataPayload)
|
||||
@@ -33,23 +39,27 @@ func handleMsgMhfSaveRengokuData(s *Session, p mhfpacket.MHFPacket) {
|
||||
maxStageSp := bf.ReadUint32()
|
||||
maxScoreSp := bf.ReadUint32()
|
||||
var t int
|
||||
err = s.server.db.QueryRow("SELECT character_id FROM rengoku_score WHERE character_id=$1", s.charID).Scan(&t)
|
||||
err = database.QueryRow("SELECT character_id FROM rengoku_score WHERE character_id=$1", s.CharID).Scan(&t)
|
||||
if err != nil {
|
||||
s.server.db.Exec("INSERT INTO rengoku_score (character_id) VALUES ($1)", s.charID)
|
||||
database.Exec("INSERT INTO rengoku_score (character_id) VALUES ($1)", s.CharID)
|
||||
}
|
||||
s.server.db.Exec("UPDATE rengoku_score SET max_stages_mp=$1, max_points_mp=$2, max_stages_sp=$3, max_points_sp=$4 WHERE character_id=$5", maxStageMp, maxScoreMp, maxStageSp, maxScoreSp, s.charID)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
database.Exec("UPDATE rengoku_score SET max_stages_mp=$1, max_points_mp=$2, max_stages_sp=$3, max_points_sp=$4 WHERE character_id=$5", maxStageMp, maxScoreMp, maxStageSp, maxScoreSp, s.CharID)
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func handleMsgMhfLoadRengokuData(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfLoadRengokuData)
|
||||
var data []byte
|
||||
err := s.server.db.QueryRow("SELECT rengokudata FROM characters WHERE id = $1", s.charID).Scan(&data)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to load rengokudata", zap.Error(err))
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
err = database.QueryRow("SELECT rengokudata FROM characters WHERE id = $1", s.CharID).Scan(&data)
|
||||
if err != nil {
|
||||
s.Logger.Error("Failed to load rengokudata", zap.Error(err))
|
||||
}
|
||||
if len(data) > 0 {
|
||||
doAckBufSucceed(s, pkt.AckHandle, data)
|
||||
DoAckBufSucceed(s, pkt.AckHandle, data)
|
||||
} else {
|
||||
resp := byteframe.NewByteFrame()
|
||||
resp.WriteUint32(0)
|
||||
@@ -87,18 +97,18 @@ func handleMsgMhfLoadRengokuData(s *Session, p mhfpacket.MHFPacket) {
|
||||
resp.WriteUint32(0)
|
||||
resp.WriteUint32(0)
|
||||
|
||||
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
}
|
||||
}
|
||||
|
||||
func handleMsgMhfGetRengokuBinary(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetRengokuBinary)
|
||||
// a (massively out of date) version resides in the game's /dat/ folder or up to date can be pulled from packets
|
||||
data, err := os.ReadFile(filepath.Join(s.server.erupeConfig.BinPath, "rengoku_data.bin"))
|
||||
data, err := os.ReadFile(filepath.Join(config.GetConfig().BinPath, "rengoku_data.bin"))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, data)
|
||||
DoAckBufSucceed(s, pkt.AckHandle, data)
|
||||
}
|
||||
|
||||
const rengokuScoreQuery = `, c.name FROM rengoku_score rs
|
||||
@@ -113,15 +123,15 @@ type RengokuScore struct {
|
||||
func handleMsgMhfEnumerateRengokuRanking(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfEnumerateRengokuRanking)
|
||||
|
||||
guild, _ := GetGuildInfoByCharacterId(s, s.charID)
|
||||
isApplicant, _ := guild.HasApplicationForCharID(s, s.charID)
|
||||
guild, _ := GetGuildInfoByCharacterId(s, s.CharID)
|
||||
isApplicant, _ := guild.HasApplicationForCharID(s, s.CharID)
|
||||
if isApplicant {
|
||||
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))
|
||||
DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 11))
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -131,25 +141,28 @@ func handleMsgMhfEnumerateRengokuRanking(s *Session, p mhfpacket.MHFPacket) {
|
||||
i := uint32(1)
|
||||
bf := byteframe.NewByteFrame()
|
||||
scoreData := byteframe.NewByteFrame()
|
||||
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
var rows *sqlx.Rows
|
||||
switch pkt.Leaderboard {
|
||||
case 0:
|
||||
rows, _ = s.server.db.Queryx(fmt.Sprintf("SELECT max_stages_mp AS score %s ORDER BY max_stages_mp DESC", rengokuScoreQuery))
|
||||
rows, _ = database.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))
|
||||
rows, _ = database.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)
|
||||
rows, _ = database.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)
|
||||
rows, _ = database.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))
|
||||
rows, _ = database.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))
|
||||
rows, _ = database.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)
|
||||
rows, _ = database.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)
|
||||
rows, _ = database.Queryx(fmt.Sprintf("SELECT max_points_sp AS score %s WHERE guild_id=$1 ORDER BY max_points_sp DESC", rengokuScoreQuery), guild.ID)
|
||||
}
|
||||
|
||||
for rows.Next() {
|
||||
@@ -177,7 +190,7 @@ func handleMsgMhfEnumerateRengokuRanking(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
bf.WriteUint8(uint8(i) - 1)
|
||||
bf.WriteBytes(scoreData.Data())
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfGetRengokuRankingRank(s *Session, p mhfpacket.MHFPacket) {
|
||||
@@ -186,5 +199,5 @@ func handleMsgMhfGetRengokuRankingRank(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint32(0) // Max stage overall MP rank
|
||||
bf.WriteUint32(0) // Max RdP overall MP rank
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
@@ -6,14 +6,14 @@ func handleMsgSysReserve188(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgSysReserve188)
|
||||
|
||||
// Left as raw bytes because I couldn't easily find the request or resp parser function in the binary.
|
||||
doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
DoAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
}
|
||||
|
||||
func handleMsgSysReserve18B(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgSysReserve18B)
|
||||
|
||||
// Left as raw bytes because I couldn't easily find the request or resp parser function in the binary.
|
||||
doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x3C})
|
||||
DoAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x3C})
|
||||
}
|
||||
|
||||
func handleMsgSysReserve55(s *Session, p mhfpacket.MHFPacket) {}
|
||||
|
||||
@@ -12,21 +12,21 @@ func handleMsgMhfGetAdditionalBeatReward(s *Session, p mhfpacket.MHFPacket) {
|
||||
// Actual response in packet captures are all just giant batches of null bytes
|
||||
// I'm assuming this is because it used to be tied to an actual event and
|
||||
// they never bothered killing off the packet when they made it static
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 0x104))
|
||||
DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 0x104))
|
||||
}
|
||||
|
||||
func handleMsgMhfGetUdRankingRewardList(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetUdRankingRewardList)
|
||||
// Temporary canned response
|
||||
data, _ := hex.DecodeString("0100001600000A5397DF00000000000000000000000000000000")
|
||||
doAckBufSucceed(s, pkt.AckHandle, data)
|
||||
DoAckBufSucceed(s, pkt.AckHandle, data)
|
||||
}
|
||||
|
||||
func handleMsgMhfGetRewardSong(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetRewardSong)
|
||||
// Temporary canned response
|
||||
data, _ := hex.DecodeString("0100001600000A5397DF00000000000000000000000000000000")
|
||||
doAckBufSucceed(s, pkt.AckHandle, data)
|
||||
DoAckBufSucceed(s, pkt.AckHandle, data)
|
||||
}
|
||||
|
||||
func handleMsgMhfUseRewardSong(s *Session, p mhfpacket.MHFPacket) {}
|
||||
@@ -39,7 +39,7 @@ func handleMsgMhfAcquireMonthlyReward(s *Session, p mhfpacket.MHFPacket) {
|
||||
resp := byteframe.NewByteFrame()
|
||||
resp.WriteUint32(0)
|
||||
|
||||
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfAcceptReadReward(s *Session, p mhfpacket.MHFPacket) {}
|
||||
|
||||
@@ -12,7 +12,7 @@ func handleMsgMhfGetBreakSeibatuLevelReward(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteInt32(0)
|
||||
bf.WriteInt32(0)
|
||||
bf.WriteInt32(0)
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
type WeeklySeibatuRankingReward struct {
|
||||
@@ -40,7 +40,7 @@ func handleMsgMhfGetWeeklySeibatuRankingReward(s *Session, p mhfpacket.MHFPacket
|
||||
bf.WriteInt32(reward.Unk5)
|
||||
data = append(data, bf)
|
||||
}
|
||||
doAckEarthSucceed(s, pkt.AckHandle, data)
|
||||
DoAckEarthSucceed(s, pkt.AckHandle, data)
|
||||
}
|
||||
|
||||
func handleMsgMhfGetFixedSeibatuRankingTable(s *Session, p mhfpacket.MHFPacket) {
|
||||
@@ -49,7 +49,7 @@ func handleMsgMhfGetFixedSeibatuRankingTable(s *Session, p mhfpacket.MHFPacket)
|
||||
bf.WriteInt32(0)
|
||||
bf.WriteInt32(0)
|
||||
bf.WriteBytes(make([]byte, 32))
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfReadBeatLevel(s *Session, p mhfpacket.MHFPacket) {
|
||||
@@ -65,7 +65,7 @@ func handleMsgMhfReadBeatLevel(s *Session, p mhfpacket.MHFPacket) {
|
||||
resp.WriteUint32(1)
|
||||
}
|
||||
|
||||
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfReadLastWeekBeatRanking(s *Session, p mhfpacket.MHFPacket) {
|
||||
@@ -75,13 +75,13 @@ func handleMsgMhfReadLastWeekBeatRanking(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteInt32(0)
|
||||
bf.WriteInt32(0)
|
||||
bf.WriteInt32(0)
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfUpdateBeatLevel(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfUpdateBeatLevel)
|
||||
|
||||
doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
DoAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
}
|
||||
|
||||
func handleMsgMhfReadBeatLevelAllRanking(s *Session, p mhfpacket.MHFPacket) {
|
||||
@@ -96,11 +96,11 @@ func handleMsgMhfReadBeatLevelAllRanking(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint32(0)
|
||||
bf.WriteBytes(make([]byte, 32))
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfReadBeatLevelMyRanking(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfReadBeatLevelMyRanking)
|
||||
bf := byteframe.NewByteFrame()
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
@@ -11,39 +11,39 @@ import (
|
||||
)
|
||||
|
||||
func removeSessionFromSemaphore(s *Session) {
|
||||
s.server.semaphoreLock.Lock()
|
||||
for _, semaphore := range s.server.semaphore {
|
||||
s.Server.semaphoreLock.Lock()
|
||||
for _, semaphore := range s.Server.semaphore {
|
||||
if _, exists := semaphore.clients[s]; exists {
|
||||
delete(semaphore.clients, s)
|
||||
}
|
||||
}
|
||||
s.server.semaphoreLock.Unlock()
|
||||
s.Server.semaphoreLock.Unlock()
|
||||
}
|
||||
|
||||
func handleMsgSysCreateSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgSysCreateSemaphore)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x03, 0x00, 0x0d})
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x03, 0x00, 0x0d})
|
||||
}
|
||||
|
||||
func destructEmptySemaphores(s *Session) {
|
||||
s.server.semaphoreLock.Lock()
|
||||
for id, sema := range s.server.semaphore {
|
||||
s.Server.semaphoreLock.Lock()
|
||||
for id, sema := range s.Server.semaphore {
|
||||
if len(sema.clients) == 0 {
|
||||
delete(s.server.semaphore, id)
|
||||
delete(s.Server.semaphore, id)
|
||||
if strings.HasPrefix(id, "hs_l0") {
|
||||
s.server.resetRaviente()
|
||||
s.Server.resetRaviente()
|
||||
}
|
||||
s.logger.Debug("Destructed semaphore", zap.String("sema.name", id))
|
||||
s.Logger.Debug("Destructed semaphore", zap.String("sema.name", id))
|
||||
}
|
||||
}
|
||||
s.server.semaphoreLock.Unlock()
|
||||
s.Server.semaphoreLock.Unlock()
|
||||
}
|
||||
|
||||
func handleMsgSysDeleteSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgSysDeleteSemaphore)
|
||||
destructEmptySemaphores(s)
|
||||
s.server.semaphoreLock.Lock()
|
||||
for id, sema := range s.server.semaphore {
|
||||
s.Server.semaphoreLock.Lock()
|
||||
for id, sema := range s.Server.semaphore {
|
||||
if sema.id == pkt.SemaphoreID {
|
||||
for session := range sema.clients {
|
||||
if s == session {
|
||||
@@ -51,22 +51,22 @@ func handleMsgSysDeleteSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
}
|
||||
if len(sema.clients) == 0 {
|
||||
delete(s.server.semaphore, id)
|
||||
delete(s.Server.semaphore, id)
|
||||
if strings.HasPrefix(id, "hs_l0") {
|
||||
s.server.resetRaviente()
|
||||
s.Server.resetRaviente()
|
||||
}
|
||||
s.logger.Debug("Destructed semaphore", zap.String("sema.name", id))
|
||||
s.Logger.Debug("Destructed semaphore", zap.String("sema.name", id))
|
||||
}
|
||||
}
|
||||
}
|
||||
s.server.semaphoreLock.Unlock()
|
||||
s.Server.semaphoreLock.Unlock()
|
||||
}
|
||||
|
||||
func handleMsgSysCreateAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgSysCreateAcquireSemaphore)
|
||||
SemaphoreID := pkt.SemaphoreID
|
||||
|
||||
if s.server.HasSemaphore(s) {
|
||||
if s.Server.HasSemaphore(s) {
|
||||
s.semaphoreMode = !s.semaphoreMode
|
||||
}
|
||||
if s.semaphoreMode {
|
||||
@@ -75,22 +75,22 @@ func handleMsgSysCreateAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
||||
s.semaphoreID[0]++
|
||||
}
|
||||
|
||||
newSemaphore, exists := s.server.semaphore[SemaphoreID]
|
||||
newSemaphore, exists := s.Server.semaphore[SemaphoreID]
|
||||
if !exists {
|
||||
s.server.semaphoreLock.Lock()
|
||||
s.Server.semaphoreLock.Lock()
|
||||
if strings.HasPrefix(SemaphoreID, "hs_l0") {
|
||||
suffix, _ := strconv.Atoi(pkt.SemaphoreID[len(pkt.SemaphoreID)-1:])
|
||||
s.server.semaphore[SemaphoreID] = &Semaphore{
|
||||
s.Server.semaphore[SemaphoreID] = &Semaphore{
|
||||
name: pkt.SemaphoreID,
|
||||
id: uint32((suffix + 1) * 0x10000),
|
||||
clients: make(map[*Session]uint32),
|
||||
maxPlayers: 127,
|
||||
}
|
||||
} else {
|
||||
s.server.semaphore[SemaphoreID] = NewSemaphore(s, SemaphoreID, 1)
|
||||
s.Server.semaphore[SemaphoreID] = NewSemaphore(s, SemaphoreID, 1)
|
||||
}
|
||||
newSemaphore = s.server.semaphore[SemaphoreID]
|
||||
s.server.semaphoreLock.Unlock()
|
||||
newSemaphore = s.Server.semaphore[SemaphoreID]
|
||||
s.Server.semaphoreLock.Unlock()
|
||||
}
|
||||
|
||||
newSemaphore.Lock()
|
||||
@@ -99,7 +99,7 @@ func handleMsgSysCreateAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
||||
if _, exists := newSemaphore.clients[s]; exists {
|
||||
bf.WriteUint32(newSemaphore.id)
|
||||
} else if uint16(len(newSemaphore.clients)) < newSemaphore.maxPlayers {
|
||||
newSemaphore.clients[s] = s.charID
|
||||
newSemaphore.clients[s] = s.CharID
|
||||
s.Lock()
|
||||
s.semaphore = newSemaphore
|
||||
s.Unlock()
|
||||
@@ -107,18 +107,18 @@ func handleMsgSysCreateAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
||||
} else {
|
||||
bf.WriteUint32(0)
|
||||
}
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgSysAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgSysAcquireSemaphore)
|
||||
if sema, exists := s.server.semaphore[pkt.SemaphoreID]; exists {
|
||||
if sema, exists := s.Server.semaphore[pkt.SemaphoreID]; exists {
|
||||
sema.host = s
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint32(sema.id)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
|
||||
} else {
|
||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,10 +129,10 @@ func handleMsgSysReleaseSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
||||
func handleMsgSysCheckSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgSysCheckSemaphore)
|
||||
resp := []byte{0x00, 0x00, 0x00, 0x00}
|
||||
s.server.semaphoreLock.Lock()
|
||||
if _, exists := s.server.semaphore[pkt.SemaphoreID]; exists {
|
||||
s.Server.semaphoreLock.Lock()
|
||||
if _, exists := s.Server.semaphore[pkt.SemaphoreID]; exists {
|
||||
resp = []byte{0x00, 0x00, 0x00, 0x01}
|
||||
}
|
||||
s.server.semaphoreLock.Unlock()
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, resp)
|
||||
s.Server.semaphoreLock.Unlock()
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, resp)
|
||||
}
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package channelserver
|
||||
|
||||
import (
|
||||
_config "erupe-ce/config"
|
||||
"erupe-ce/config"
|
||||
"erupe-ce/network/mhfpacket"
|
||||
"erupe-ce/utils/byteframe"
|
||||
"erupe-ce/utils/db"
|
||||
"erupe-ce/utils/gametime"
|
||||
ps "erupe-ce/utils/pascalstring"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
)
|
||||
|
||||
@@ -62,7 +64,7 @@ func writeShopItems(bf *byteframe.ByteFrame, items []ShopItem) {
|
||||
bf.WriteUint16(uint16(len(items)))
|
||||
bf.WriteUint16(uint16(len(items)))
|
||||
for _, item := range items {
|
||||
if _config.ErupeConfig.ClientID >= _config.Z2 {
|
||||
if config.GetConfig().ClientID >= config.Z2 {
|
||||
bf.WriteUint32(item.ID)
|
||||
}
|
||||
bf.WriteUint32(item.ItemID)
|
||||
@@ -70,19 +72,19 @@ func writeShopItems(bf *byteframe.ByteFrame, items []ShopItem) {
|
||||
bf.WriteUint16(item.Quantity)
|
||||
bf.WriteUint16(item.MinHR)
|
||||
bf.WriteUint16(item.MinSR)
|
||||
if _config.ErupeConfig.ClientID >= _config.Z2 {
|
||||
if config.GetConfig().ClientID >= config.Z2 {
|
||||
bf.WriteUint16(item.MinGR)
|
||||
}
|
||||
bf.WriteUint8(0) // Unk
|
||||
bf.WriteUint8(item.StoreLevel)
|
||||
if _config.ErupeConfig.ClientID >= _config.Z2 {
|
||||
if config.GetConfig().ClientID >= config.Z2 {
|
||||
bf.WriteUint16(item.MaxQuantity)
|
||||
bf.WriteUint16(item.UsedQuantity)
|
||||
}
|
||||
if _config.ErupeConfig.ClientID == _config.Z1 {
|
||||
if config.GetConfig().ClientID == config.Z1 {
|
||||
bf.WriteUint8(uint8(item.RoadFloors))
|
||||
bf.WriteUint8(uint8(item.RoadFatalis))
|
||||
} else if _config.ErupeConfig.ClientID >= _config.Z2 {
|
||||
} else if config.GetConfig().ClientID >= config.Z2 {
|
||||
bf.WriteUint16(item.RoadFloors)
|
||||
bf.WriteUint16(item.RoadFatalis)
|
||||
}
|
||||
@@ -92,10 +94,14 @@ func writeShopItems(bf *byteframe.ByteFrame, items []ShopItem) {
|
||||
func getShopItems(s *Session, shopType uint8, shopID uint32) []ShopItem {
|
||||
var items []ShopItem
|
||||
var temp ShopItem
|
||||
rows, err := s.server.db.Queryx(`SELECT id, item_id, cost, quantity, min_hr, min_sr, min_gr, store_level, max_quantity,
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
rows, err := database.Queryx(`SELECT id, item_id, cost, quantity, min_hr, min_sr, min_gr, store_level, max_quantity,
|
||||
COALESCE((SELECT bought FROM shop_items_bought WHERE shop_item_id=si.id AND character_id=$3), 0) as used_quantity,
|
||||
road_floors, road_fatalis FROM shop_items si WHERE shop_type=$1 AND shop_id=$2
|
||||
`, shopType, shopID, s.charID)
|
||||
`, shopType, shopID, s.CharID)
|
||||
if err == nil {
|
||||
for rows.Next() {
|
||||
err = rows.StructScan(&temp)
|
||||
@@ -110,6 +116,10 @@ func getShopItems(s *Session, shopType uint8, shopID uint32) []ShopItem {
|
||||
|
||||
func handleMsgMhfEnumerateShop(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfEnumerateShop)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
// Generic Shop IDs
|
||||
// 0: basic item
|
||||
// 1: gatherables
|
||||
@@ -123,14 +133,14 @@ func handleMsgMhfEnumerateShop(s *Session, p mhfpacket.MHFPacket) {
|
||||
switch pkt.ShopType {
|
||||
case 1: // Running gachas
|
||||
// Fundamentally, gacha works completely differently, just hide it for now.
|
||||
if _config.ErupeConfig.ClientID <= _config.G7 {
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
if config.GetConfig().ClientID <= config.G7 {
|
||||
DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
|
||||
rows, err := s.server.db.Queryx("SELECT id, min_gr, min_hr, name, url_banner, url_feature, url_thumbnail, wide, recommended, gacha_type, hidden FROM gacha_shop")
|
||||
rows, err := database.Queryx("SELECT id, min_gr, min_hr, name, url_banner, url_feature, url_thumbnail, wide, recommended, gacha_type, hidden FROM gacha_shop")
|
||||
if err != nil {
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
bf := byteframe.NewByteFrame()
|
||||
@@ -156,7 +166,7 @@ func handleMsgMhfEnumerateShop(s *Session, p mhfpacket.MHFPacket) {
|
||||
ps.Uint8(bf, g.Name, true)
|
||||
ps.Uint8(bf, g.URLBanner, false)
|
||||
ps.Uint8(bf, g.URLFeature, false)
|
||||
if _config.ErupeConfig.ClientID >= _config.G10 {
|
||||
if config.GetConfig().ClientID >= config.G10 {
|
||||
bf.WriteBool(g.Wide)
|
||||
ps.Uint8(bf, g.URLThumbnail, false)
|
||||
}
|
||||
@@ -166,23 +176,23 @@ func handleMsgMhfEnumerateShop(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint16(0)
|
||||
}
|
||||
bf.WriteUint8(g.GachaType)
|
||||
if _config.ErupeConfig.ClientID >= _config.G10 {
|
||||
if config.GetConfig().ClientID >= config.G10 {
|
||||
bf.WriteBool(g.Hidden)
|
||||
}
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
case 2: // Actual gacha
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint32(pkt.ShopID)
|
||||
var gachaType int
|
||||
s.server.db.QueryRow(`SELECT gacha_type FROM gacha_shop WHERE id = $1`, pkt.ShopID).Scan(&gachaType)
|
||||
rows, err := s.server.db.Queryx(`SELECT entry_type, id, item_type, item_number, item_quantity, weight, rarity, rolls, daily_limit, frontier_points, COALESCE(name, '') AS name FROM gacha_entries WHERE gacha_id = $1 ORDER BY weight DESC`, pkt.ShopID)
|
||||
database.QueryRow(`SELECT gacha_type FROM gacha_shop WHERE id = $1`, pkt.ShopID).Scan(&gachaType)
|
||||
rows, err := database.Queryx(`SELECT entry_type, id, item_type, item_number, item_quantity, weight, rarity, rolls, daily_limit, frontier_points, COALESCE(name, '') AS name FROM gacha_entries WHERE gacha_id = $1 ORDER BY weight DESC`, pkt.ShopID)
|
||||
if err != nil {
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
var divisor float64
|
||||
s.server.db.QueryRow(`SELECT COALESCE(SUM(weight) / 100000.0, 0) AS chance FROM gacha_entries WHERE gacha_id = $1`, pkt.ShopID).Scan(&divisor)
|
||||
database.QueryRow(`SELECT COALESCE(SUM(weight) / 100000.0, 0) AS chance FROM gacha_entries WHERE gacha_id = $1`, pkt.ShopID).Scan(&divisor)
|
||||
|
||||
var entry GachaEntry
|
||||
var entries []GachaEntry
|
||||
@@ -209,7 +219,7 @@ func handleMsgMhfEnumerateShop(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint8(ge.Rarity)
|
||||
bf.WriteUint8(ge.Rolls)
|
||||
|
||||
rows, err = s.server.db.Queryx(`SELECT item_type, item_id, quantity FROM gacha_items WHERE entry_id=$1`, ge.ID)
|
||||
rows, err = database.Queryx(`SELECT item_type, item_id, quantity FROM gacha_items WHERE entry_id=$1`, ge.ID)
|
||||
if err != nil {
|
||||
bf.WriteUint8(0)
|
||||
} else {
|
||||
@@ -235,7 +245,7 @@ func handleMsgMhfEnumerateShop(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint16(gi.Quantity)
|
||||
}
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
case 3: // Hunting Festival Exchange
|
||||
fallthrough
|
||||
case 4: // N Points, 0-6
|
||||
@@ -257,7 +267,7 @@ func handleMsgMhfEnumerateShop(s *Session, p mhfpacket.MHFPacket) {
|
||||
items = items[:pkt.Limit]
|
||||
}
|
||||
writeShopItems(bf, items)
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -265,57 +275,73 @@ func handleMsgMhfAcquireExchangeShop(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfAcquireExchangeShop)
|
||||
bf := byteframe.NewByteFrameFromBytes(pkt.RawDataPayload)
|
||||
exchanges := int(bf.ReadUint16())
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
for i := 0; i < exchanges; i++ {
|
||||
itemHash := bf.ReadUint32()
|
||||
if itemHash == 0 {
|
||||
continue
|
||||
}
|
||||
buyCount := bf.ReadUint32()
|
||||
s.server.db.Exec(`INSERT INTO shop_items_bought (character_id, shop_item_id, bought)
|
||||
database.Exec(`INSERT INTO shop_items_bought (character_id, shop_item_id, bought)
|
||||
VALUES ($1,$2,$3) ON CONFLICT (character_id, shop_item_id)
|
||||
DO UPDATE SET bought = bought + $3
|
||||
WHERE EXCLUDED.character_id=$1 AND EXCLUDED.shop_item_id=$2
|
||||
`, s.charID, itemHash, buyCount)
|
||||
`, s.CharID, itemHash, buyCount)
|
||||
}
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
}
|
||||
|
||||
func handleMsgMhfGetGachaPlayHistory(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetGachaPlayHistory)
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint8(1)
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfGetGachaPoint(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetGachaPoint)
|
||||
var fp, gp, gt uint32
|
||||
s.server.db.QueryRow("SELECT COALESCE(frontier_points, 0), COALESCE(gacha_premium, 0), COALESCE(gacha_trial, 0) FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)", s.charID).Scan(&fp, &gp, >)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
database.QueryRow("SELECT COALESCE(frontier_points, 0), COALESCE(gacha_premium, 0), COALESCE(gacha_trial, 0) FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)", s.CharID).Scan(&fp, &gp, >)
|
||||
resp := byteframe.NewByteFrame()
|
||||
resp.WriteUint32(gp)
|
||||
resp.WriteUint32(gt)
|
||||
resp.WriteUint32(fp)
|
||||
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfUseGachaPoint(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfUseGachaPoint)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
if pkt.TrialCoins > 0 {
|
||||
s.server.db.Exec(`UPDATE users u SET gacha_trial=gacha_trial-$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, pkt.TrialCoins, s.charID)
|
||||
database.Exec(`UPDATE users u SET gacha_trial=gacha_trial-$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, pkt.TrialCoins, s.CharID)
|
||||
}
|
||||
if pkt.PremiumCoins > 0 {
|
||||
s.server.db.Exec(`UPDATE users u SET gacha_premium=gacha_premium-$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, pkt.PremiumCoins, s.charID)
|
||||
database.Exec(`UPDATE users u SET gacha_premium=gacha_premium-$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, pkt.PremiumCoins, s.CharID)
|
||||
}
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func spendGachaCoin(s *Session, quantity uint16) {
|
||||
var gt uint16
|
||||
s.server.db.QueryRow(`SELECT COALESCE(gacha_trial, 0) FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)`, s.charID).Scan(>)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
database.QueryRow(`SELECT COALESCE(gacha_trial, 0) FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)`, s.CharID).Scan(>)
|
||||
if quantity <= gt {
|
||||
s.server.db.Exec(`UPDATE users u SET gacha_trial=gacha_trial-$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, quantity, s.charID)
|
||||
database.Exec(`UPDATE users u SET gacha_trial=gacha_trial-$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, quantity, s.CharID)
|
||||
} else {
|
||||
s.server.db.Exec(`UPDATE users u SET gacha_premium=gacha_premium-$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, quantity, s.charID)
|
||||
database.Exec(`UPDATE users u SET gacha_premium=gacha_premium-$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)`, quantity, s.CharID)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -323,7 +349,11 @@ func transactGacha(s *Session, gachaID uint32, rollID uint8) (error, int) {
|
||||
var itemType uint8
|
||||
var itemNumber uint16
|
||||
var rolls int
|
||||
err := s.server.db.QueryRowx(`SELECT item_type, item_number, rolls FROM gacha_entries WHERE gacha_id = $1 AND entry_type = $2`, gachaID, rollID).Scan(&itemType, &itemNumber, &rolls)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
err = database.QueryRowx(`SELECT item_type, item_number, rolls FROM gacha_entries WHERE gacha_id = $1 AND entry_type = $2`, gachaID, rollID).Scan(&itemType, &itemNumber, &rolls)
|
||||
if err != nil {
|
||||
return err, 0
|
||||
}
|
||||
@@ -344,7 +374,7 @@ func transactGacha(s *Session, gachaID uint32, rollID uint8) (error, int) {
|
||||
case 20:
|
||||
spendGachaCoin(s, itemNumber)
|
||||
case 21:
|
||||
s.server.db.Exec("UPDATE users u SET frontier_points=frontier_points-$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)", itemNumber, s.charID)
|
||||
database.Exec("UPDATE users u SET frontier_points=frontier_points-$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)", itemNumber, s.CharID)
|
||||
}
|
||||
return nil, rolls
|
||||
}
|
||||
@@ -352,7 +382,11 @@ func transactGacha(s *Session, gachaID uint32, rollID uint8) (error, int) {
|
||||
func getGuaranteedItems(s *Session, gachaID uint32, rollID uint8) []GachaItem {
|
||||
var rewards []GachaItem
|
||||
var reward GachaItem
|
||||
items, err := s.server.db.Queryx(`SELECT item_type, item_id, quantity FROM gacha_items WHERE entry_id = (SELECT id FROM gacha_entries WHERE entry_type = $1 AND gacha_id = $2)`, rollID, gachaID)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
items, err := database.Queryx(`SELECT item_type, item_id, quantity FROM gacha_items WHERE entry_id = (SELECT id FROM gacha_entries WHERE entry_type = $1 AND gacha_id = $2)`, rollID, gachaID)
|
||||
if err == nil {
|
||||
for items.Next() {
|
||||
items.StructScan(&reward)
|
||||
@@ -364,7 +398,11 @@ func getGuaranteedItems(s *Session, gachaID uint32, rollID uint8) []GachaItem {
|
||||
|
||||
func addGachaItem(s *Session, items []GachaItem) {
|
||||
var data []byte
|
||||
s.server.db.QueryRow(`SELECT gacha_items FROM characters WHERE id = $1`, s.charID).Scan(&data)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
database.QueryRow(`SELECT gacha_items FROM characters WHERE id = $1`, s.CharID).Scan(&data)
|
||||
if len(data) > 0 {
|
||||
numItems := int(data[0])
|
||||
data = data[1:]
|
||||
@@ -384,7 +422,7 @@ func addGachaItem(s *Session, items []GachaItem) {
|
||||
newItem.WriteUint16(items[i].ItemID)
|
||||
newItem.WriteUint16(items[i].Quantity)
|
||||
}
|
||||
s.server.db.Exec(`UPDATE characters SET gacha_items = $1 WHERE id = $2`, newItem.Data(), s.charID)
|
||||
database.Exec(`UPDATE characters SET gacha_items = $1 WHERE id = $2`, newItem.Data(), s.CharID)
|
||||
}
|
||||
|
||||
func getRandomEntries(entries []GachaEntry, rolls int, isBox bool) ([]GachaEntry, error) {
|
||||
@@ -419,7 +457,11 @@ func getRandomEntries(entries []GachaEntry, rolls int, isBox bool) ([]GachaEntry
|
||||
func handleMsgMhfReceiveGachaItem(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfReceiveGachaItem)
|
||||
var data []byte
|
||||
err := s.server.db.QueryRow("SELECT COALESCE(gacha_items, $2) FROM characters WHERE id = $1", s.charID, []byte{0x00}).Scan(&data)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
err = database.QueryRow("SELECT COALESCE(gacha_items, $2) FROM characters WHERE id = $1", s.CharID, []byte{0x00}).Scan(&data)
|
||||
if err != nil {
|
||||
data = []byte{0x00}
|
||||
}
|
||||
@@ -429,9 +471,9 @@ func handleMsgMhfReceiveGachaItem(s *Session, p mhfpacket.MHFPacket) {
|
||||
resp := byteframe.NewByteFrame()
|
||||
resp.WriteUint8(36)
|
||||
resp.WriteBytes(data[1:181])
|
||||
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
} else {
|
||||
doAckBufSucceed(s, pkt.AckHandle, data)
|
||||
DoAckBufSucceed(s, pkt.AckHandle, data)
|
||||
}
|
||||
|
||||
if !pkt.Freeze {
|
||||
@@ -439,9 +481,9 @@ func handleMsgMhfReceiveGachaItem(s *Session, p mhfpacket.MHFPacket) {
|
||||
update := byteframe.NewByteFrame()
|
||||
update.WriteUint8(uint8(len(data[181:]) / 5))
|
||||
update.WriteBytes(data[181:])
|
||||
s.server.db.Exec("UPDATE characters SET gacha_items = $1 WHERE id = $2", update.Data(), s.charID)
|
||||
database.Exec("UPDATE characters SET gacha_items = $1 WHERE id = $2", update.Data(), s.CharID)
|
||||
} else {
|
||||
s.server.db.Exec("UPDATE characters SET gacha_items = null WHERE id = $1", s.charID)
|
||||
database.Exec("UPDATE characters SET gacha_items = null WHERE id = $1", s.CharID)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -453,15 +495,19 @@ func handleMsgMhfPlayNormalGacha(s *Session, p mhfpacket.MHFPacket) {
|
||||
var entry GachaEntry
|
||||
var rewards []GachaItem
|
||||
var reward GachaItem
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
err, rolls := transactGacha(s, pkt.GachaID, pkt.RollType)
|
||||
if err != nil {
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 1))
|
||||
DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 1))
|
||||
return
|
||||
}
|
||||
|
||||
rows, err := s.server.db.Queryx(`SELECT id, weight, rarity FROM gacha_entries WHERE gacha_id = $1 AND entry_type = 100 ORDER BY weight DESC`, pkt.GachaID)
|
||||
rows, err := database.Queryx(`SELECT id, weight, rarity FROM gacha_entries WHERE gacha_id = $1 AND entry_type = 100 ORDER BY weight DESC`, pkt.GachaID)
|
||||
if err != nil {
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 1))
|
||||
DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 1))
|
||||
return
|
||||
}
|
||||
for rows.Next() {
|
||||
@@ -475,7 +521,7 @@ func handleMsgMhfPlayNormalGacha(s *Session, p mhfpacket.MHFPacket) {
|
||||
rewardEntries, err := getRandomEntries(entries, rolls, false)
|
||||
temp := byteframe.NewByteFrame()
|
||||
for i := range rewardEntries {
|
||||
rows, err = s.server.db.Queryx(`SELECT item_type, item_id, quantity FROM gacha_items WHERE entry_id = $1`, rewardEntries[i].ID)
|
||||
rows, err = database.Queryx(`SELECT item_type, item_id, quantity FROM gacha_items WHERE entry_id = $1`, rewardEntries[i].ID)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
@@ -494,7 +540,7 @@ func handleMsgMhfPlayNormalGacha(s *Session, p mhfpacket.MHFPacket) {
|
||||
|
||||
bf.WriteUint8(uint8(len(rewards)))
|
||||
bf.WriteBytes(temp.Data())
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
addGachaItem(s, rewards)
|
||||
}
|
||||
|
||||
@@ -507,16 +553,20 @@ func handleMsgMhfPlayStepupGacha(s *Session, p mhfpacket.MHFPacket) {
|
||||
var reward GachaItem
|
||||
err, rolls := transactGacha(s, pkt.GachaID, pkt.RollType)
|
||||
if err != nil {
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 1))
|
||||
DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 1))
|
||||
return
|
||||
}
|
||||
s.server.db.Exec("UPDATE users u SET frontier_points=frontier_points+(SELECT frontier_points FROM gacha_entries WHERE gacha_id = $1 AND entry_type = $2) WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$3)", pkt.GachaID, pkt.RollType, s.charID)
|
||||
s.server.db.Exec(`DELETE FROM gacha_stepup WHERE gacha_id = $1 AND character_id = $2`, pkt.GachaID, s.charID)
|
||||
s.server.db.Exec(`INSERT INTO gacha_stepup (gacha_id, step, character_id) VALUES ($1, $2, $3)`, pkt.GachaID, pkt.RollType+1, s.charID)
|
||||
|
||||
rows, err := s.server.db.Queryx(`SELECT id, weight, rarity FROM gacha_entries WHERE gacha_id = $1 AND entry_type = 100 ORDER BY weight DESC`, pkt.GachaID)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 1))
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
database.Exec("UPDATE users u SET frontier_points=frontier_points+(SELECT frontier_points FROM gacha_entries WHERE gacha_id = $1 AND entry_type = $2) WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$3)", pkt.GachaID, pkt.RollType, s.CharID)
|
||||
database.Exec(`DELETE FROM gacha_stepup WHERE gacha_id = $1 AND character_id = $2`, pkt.GachaID, s.CharID)
|
||||
database.Exec(`INSERT INTO gacha_stepup (gacha_id, step, character_id) VALUES ($1, $2, $3)`, pkt.GachaID, pkt.RollType+1, s.CharID)
|
||||
|
||||
rows, err := database.Queryx(`SELECT id, weight, rarity FROM gacha_entries WHERE gacha_id = $1 AND entry_type = 100 ORDER BY weight DESC`, pkt.GachaID)
|
||||
if err != nil {
|
||||
DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 1))
|
||||
return
|
||||
}
|
||||
for rows.Next() {
|
||||
@@ -531,7 +581,7 @@ func handleMsgMhfPlayStepupGacha(s *Session, p mhfpacket.MHFPacket) {
|
||||
rewardEntries, err := getRandomEntries(entries, rolls, false)
|
||||
temp := byteframe.NewByteFrame()
|
||||
for i := range rewardEntries {
|
||||
rows, err = s.server.db.Queryx(`SELECT item_type, item_id, quantity FROM gacha_items WHERE entry_id = $1`, rewardEntries[i].ID)
|
||||
rows, err = database.Queryx(`SELECT item_type, item_id, quantity FROM gacha_items WHERE entry_id = $1`, rewardEntries[i].ID)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
@@ -557,7 +607,7 @@ func handleMsgMhfPlayStepupGacha(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint8(0)
|
||||
}
|
||||
bf.WriteBytes(temp.Data())
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
addGachaItem(s, rewards)
|
||||
addGachaItem(s, guaranteedItems)
|
||||
}
|
||||
@@ -566,24 +616,32 @@ func handleMsgMhfGetStepupStatus(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetStepupStatus)
|
||||
// TODO: Reset daily (noon)
|
||||
var step uint8
|
||||
s.server.db.QueryRow(`SELECT step FROM gacha_stepup WHERE gacha_id = $1 AND character_id = $2`, pkt.GachaID, s.charID).Scan(&step)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
database.QueryRow(`SELECT step FROM gacha_stepup WHERE gacha_id = $1 AND character_id = $2`, pkt.GachaID, s.CharID).Scan(&step)
|
||||
var stepCheck int
|
||||
s.server.db.QueryRow(`SELECT COUNT(1) FROM gacha_entries WHERE gacha_id = $1 AND entry_type = $2`, pkt.GachaID, step).Scan(&stepCheck)
|
||||
database.QueryRow(`SELECT COUNT(1) FROM gacha_entries WHERE gacha_id = $1 AND entry_type = $2`, pkt.GachaID, step).Scan(&stepCheck)
|
||||
if stepCheck == 0 {
|
||||
s.server.db.Exec(`DELETE FROM gacha_stepup WHERE gacha_id = $1 AND character_id = $2`, pkt.GachaID, s.charID)
|
||||
database.Exec(`DELETE FROM gacha_stepup WHERE gacha_id = $1 AND character_id = $2`, pkt.GachaID, s.CharID)
|
||||
step = 0
|
||||
}
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint8(step)
|
||||
bf.WriteUint32(uint32(gametime.TimeAdjusted().Unix()))
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfGetBoxGachaInfo(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetBoxGachaInfo)
|
||||
entries, err := s.server.db.Queryx(`SELECT entry_id FROM gacha_box WHERE gacha_id = $1 AND character_id = $2`, pkt.GachaID, s.charID)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 1))
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
entries, err := database.Queryx(`SELECT entry_id FROM gacha_box WHERE gacha_id = $1 AND character_id = $2`, pkt.GachaID, s.CharID)
|
||||
if err != nil {
|
||||
DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 1))
|
||||
return
|
||||
}
|
||||
var entryIDs []uint32
|
||||
@@ -598,7 +656,7 @@ func handleMsgMhfGetBoxGachaInfo(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint32(entryIDs[i])
|
||||
bf.WriteBool(true)
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfPlayBoxGacha(s *Session, p mhfpacket.MHFPacket) {
|
||||
@@ -610,12 +668,16 @@ func handleMsgMhfPlayBoxGacha(s *Session, p mhfpacket.MHFPacket) {
|
||||
var reward GachaItem
|
||||
err, rolls := transactGacha(s, pkt.GachaID, pkt.RollType)
|
||||
if err != nil {
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 1))
|
||||
DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 1))
|
||||
return
|
||||
}
|
||||
rows, err := s.server.db.Queryx(`SELECT id, weight, rarity FROM gacha_entries WHERE gacha_id = $1 AND entry_type = 100 ORDER BY weight DESC`, pkt.GachaID)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 1))
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
rows, err := database.Queryx(`SELECT id, weight, rarity FROM gacha_entries WHERE gacha_id = $1 AND entry_type = 100 ORDER BY weight DESC`, pkt.GachaID)
|
||||
if err != nil {
|
||||
DoAckBufSucceed(s, pkt.AckHandle, make([]byte, 1))
|
||||
return
|
||||
}
|
||||
for rows.Next() {
|
||||
@@ -626,11 +688,11 @@ func handleMsgMhfPlayBoxGacha(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
rewardEntries, err := getRandomEntries(entries, rolls, true)
|
||||
for i := range rewardEntries {
|
||||
items, err := s.server.db.Queryx(`SELECT item_type, item_id, quantity FROM gacha_items WHERE entry_id = $1`, rewardEntries[i].ID)
|
||||
items, err := database.Queryx(`SELECT item_type, item_id, quantity FROM gacha_items WHERE entry_id = $1`, rewardEntries[i].ID)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
s.server.db.Exec(`INSERT INTO gacha_box (gacha_id, entry_id, character_id) VALUES ($1, $2, $3)`, pkt.GachaID, rewardEntries[i].ID, s.charID)
|
||||
database.Exec(`INSERT INTO gacha_box (gacha_id, entry_id, character_id) VALUES ($1, $2, $3)`, pkt.GachaID, rewardEntries[i].ID, s.CharID)
|
||||
for items.Next() {
|
||||
err = items.StructScan(&reward)
|
||||
if err == nil {
|
||||
@@ -645,38 +707,50 @@ func handleMsgMhfPlayBoxGacha(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint16(r.Quantity)
|
||||
bf.WriteUint8(0)
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
addGachaItem(s, rewards)
|
||||
}
|
||||
|
||||
func handleMsgMhfResetBoxGachaInfo(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfResetBoxGachaInfo)
|
||||
s.server.db.Exec("DELETE FROM gacha_box WHERE gacha_id = $1 AND character_id = $2", pkt.GachaID, s.charID)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
database.Exec("DELETE FROM gacha_box WHERE gacha_id = $1 AND character_id = $2", pkt.GachaID, s.CharID)
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func handleMsgMhfExchangeFpoint2Item(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfExchangeFpoint2Item)
|
||||
var balance uint32
|
||||
var itemValue, quantity int
|
||||
s.server.db.QueryRow("SELECT quantity, fpoints FROM fpoint_items WHERE id=$1", pkt.TradeID).Scan(&quantity, &itemValue)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
database.QueryRow("SELECT quantity, fpoints FROM fpoint_items WHERE id=$1", pkt.TradeID).Scan(&quantity, &itemValue)
|
||||
cost := (int(pkt.Quantity) * quantity) * itemValue
|
||||
s.server.db.QueryRow("UPDATE users u SET frontier_points=frontier_points::int - $1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2) RETURNING frontier_points", cost, s.charID).Scan(&balance)
|
||||
database.QueryRow("UPDATE users u SET frontier_points=frontier_points::int - $1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2) RETURNING frontier_points", cost, s.CharID).Scan(&balance)
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint32(balance)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfExchangeItem2Fpoint(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfExchangeItem2Fpoint)
|
||||
var balance uint32
|
||||
var itemValue, quantity int
|
||||
s.server.db.QueryRow("SELECT quantity, fpoints FROM fpoint_items WHERE id=$1", pkt.TradeID).Scan(&quantity, &itemValue)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
database.QueryRow("SELECT quantity, fpoints FROM fpoint_items WHERE id=$1", pkt.TradeID).Scan(&quantity, &itemValue)
|
||||
cost := (int(pkt.Quantity) / quantity) * itemValue
|
||||
s.server.db.QueryRow("UPDATE users u SET frontier_points=COALESCE(frontier_points::int + $1, $1) WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2) RETURNING frontier_points", cost, s.charID).Scan(&balance)
|
||||
database.QueryRow("UPDATE users u SET frontier_points=COALESCE(frontier_points::int + $1, $1) WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2) RETURNING frontier_points", cost, s.CharID).Scan(&balance)
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint32(balance)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
type FPointExchange struct {
|
||||
@@ -695,7 +769,11 @@ func handleMsgMhfGetFpointExchangeList(s *Session, p mhfpacket.MHFPacket) {
|
||||
var exchange FPointExchange
|
||||
var exchanges []FPointExchange
|
||||
var buyables uint16
|
||||
rows, err := s.server.db.Queryx(`SELECT id, item_type, item_id, quantity, fpoints, buyable FROM fpoint_items ORDER BY buyable DESC`)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
rows, err := database.Queryx(`SELECT id, item_type, item_id, quantity, fpoints, buyable FROM fpoint_items ORDER BY buyable DESC`)
|
||||
if err == nil {
|
||||
for rows.Next() {
|
||||
err = rows.StructScan(&exchange)
|
||||
@@ -708,7 +786,7 @@ func handleMsgMhfGetFpointExchangeList(s *Session, p mhfpacket.MHFPacket) {
|
||||
exchanges = append(exchanges, exchange)
|
||||
}
|
||||
}
|
||||
if _config.ErupeConfig.ClientID <= _config.Z2 {
|
||||
if config.GetConfig().ClientID <= config.Z2 {
|
||||
bf.WriteUint8(uint8(len(exchanges)))
|
||||
bf.WriteUint8(uint8(buyables))
|
||||
} else {
|
||||
@@ -726,12 +804,12 @@ func handleMsgMhfGetFpointExchangeList(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint16(e.FPoints)
|
||||
}
|
||||
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfPlayFreeGacha(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfPlayFreeGacha)
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint32(1)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
@@ -14,38 +14,38 @@ import (
|
||||
|
||||
func handleMsgSysCreateStage(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgSysCreateStage)
|
||||
s.server.Lock()
|
||||
defer s.server.Unlock()
|
||||
if _, exists := s.server.stages[pkt.StageID]; exists {
|
||||
doAckSimpleFail(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
s.Server.Lock()
|
||||
defer s.Server.Unlock()
|
||||
if _, exists := s.Server.stages[pkt.StageID]; exists {
|
||||
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})
|
||||
s.Server.stages[stage.id] = stage
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
}
|
||||
}
|
||||
|
||||
func handleMsgSysStageDestruct(s *Session, p mhfpacket.MHFPacket) {}
|
||||
|
||||
func doStageTransfer(s *Session, ackHandle uint32, stageID string) {
|
||||
s.server.Lock()
|
||||
stage, exists := s.server.stages[stageID]
|
||||
s.server.Unlock()
|
||||
s.Server.Lock()
|
||||
stage, exists := s.Server.stages[stageID]
|
||||
s.Server.Unlock()
|
||||
|
||||
if exists {
|
||||
stage.Lock()
|
||||
stage.clients[s] = s.charID
|
||||
stage.clients[s] = s.CharID
|
||||
stage.Unlock()
|
||||
} else { // Create new stage object
|
||||
s.server.Lock()
|
||||
s.server.stages[stageID] = NewStage(stageID)
|
||||
stage = s.server.stages[stageID]
|
||||
s.server.Unlock()
|
||||
s.Server.Lock()
|
||||
s.Server.stages[stageID] = NewStage(stageID)
|
||||
stage = s.Server.stages[stageID]
|
||||
s.Server.Unlock()
|
||||
stage.Lock()
|
||||
stage.host = s
|
||||
stage.clients[s] = s.charID
|
||||
stage.clients[s] = s.CharID
|
||||
stage.Unlock()
|
||||
}
|
||||
|
||||
@@ -56,14 +56,14 @@ func doStageTransfer(s *Session, ackHandle uint32, stageID string) {
|
||||
|
||||
// Save our new stage ID and pointer to the new stage itself.
|
||||
s.Lock()
|
||||
s.stage = s.server.stages[stageID]
|
||||
s.stage = s.Server.stages[stageID]
|
||||
s.Unlock()
|
||||
|
||||
// Tell the client to cleanup its current stage objects.
|
||||
s.QueueSendMHF(&mhfpacket.MsgSysCleanupObject{})
|
||||
|
||||
// Confirm the stage entry.
|
||||
doAckSimpleSucceed(s, ackHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
DoAckSimpleSucceed(s, ackHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
|
||||
var temp mhfpacket.MHFPacket
|
||||
|
||||
@@ -71,15 +71,15 @@ func doStageTransfer(s *Session, ackHandle uint32, stageID string) {
|
||||
if !s.userEnteredStage {
|
||||
s.userEnteredStage = true
|
||||
|
||||
for _, session := range s.server.sessions {
|
||||
for _, session := range s.Server.sessions {
|
||||
if s == session {
|
||||
continue
|
||||
}
|
||||
temp = &mhfpacket.MsgSysInsertUser{CharID: session.charID}
|
||||
temp = &mhfpacket.MsgSysInsertUser{CharID: session.CharID}
|
||||
s.QueueSendMHF(temp)
|
||||
for i := 0; i < 3; i++ {
|
||||
temp = &mhfpacket.MsgSysNotifyUserBinary{
|
||||
CharID: session.charID,
|
||||
CharID: session.CharID,
|
||||
BinaryType: uint8(i + 1),
|
||||
}
|
||||
s.QueueSendMHF(temp)
|
||||
@@ -89,10 +89,10 @@ func doStageTransfer(s *Session, ackHandle uint32, stageID string) {
|
||||
|
||||
if s.stage != nil { // avoids lock up when using bed for dream quests
|
||||
// Notify the client to duplicate the existing objects.
|
||||
s.logger.Info(fmt.Sprintf("Sending existing stage objects to %s", s.Name))
|
||||
s.Logger.Info(fmt.Sprintf("Sending existing stage objects to %s", s.Name))
|
||||
s.stage.RLock()
|
||||
for _, obj := range s.stage.objects {
|
||||
if obj.ownerCharID == s.charID {
|
||||
if obj.ownerCharID == s.CharID {
|
||||
continue
|
||||
}
|
||||
temp = &mhfpacket.MsgSysDuplicateObject{
|
||||
@@ -110,14 +110,14 @@ func doStageTransfer(s *Session, ackHandle uint32, stageID string) {
|
||||
}
|
||||
|
||||
func destructEmptyStages(s *Session) {
|
||||
s.server.Lock()
|
||||
defer s.server.Unlock()
|
||||
for _, stage := range s.server.stages {
|
||||
s.Server.Lock()
|
||||
defer s.Server.Unlock()
|
||||
for _, stage := range s.Server.stages {
|
||||
// Destroy empty Quest/My series/Guild stages.
|
||||
if stage.id[3:5] == "Qs" || stage.id[3:5] == "Ms" || stage.id[3:5] == "Gs" || stage.id[3:5] == "Ls" {
|
||||
if len(stage.reservedClientSlots) == 0 && len(stage.clients) == 0 {
|
||||
delete(s.server.stages, stage.id)
|
||||
s.logger.Debug("Destructed stage", zap.String("stage.id", stage.id))
|
||||
delete(s.Server.stages, stage.id)
|
||||
s.Logger.Debug("Destructed stage", zap.String("stage.id", stage.id))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -128,9 +128,9 @@ func removeSessionFromStage(s *Session) {
|
||||
delete(s.stage.clients, s)
|
||||
|
||||
// Delete old stage objects owned by the client.
|
||||
s.logger.Info("Sending notification to old stage clients")
|
||||
s.Logger.Info("Sending notification to old stage clients")
|
||||
for _, object := range s.stage.objects {
|
||||
if object.ownerCharID == s.charID {
|
||||
if object.ownerCharID == s.CharID {
|
||||
s.stage.BroadcastMHF(&mhfpacket.MsgSysDeleteObject{ObjID: object.id}, s)
|
||||
delete(s.stage.objects, object.ownerCharID)
|
||||
}
|
||||
@@ -140,8 +140,8 @@ func removeSessionFromStage(s *Session) {
|
||||
}
|
||||
|
||||
func isStageFull(s *Session, StageID string) bool {
|
||||
if stage, exists := s.server.stages[StageID]; exists {
|
||||
if _, exists := stage.reservedClientSlots[s.charID]; exists {
|
||||
if stage, exists := s.Server.stages[StageID]; exists {
|
||||
if _, exists := stage.reservedClientSlots[s.CharID]; exists {
|
||||
return false
|
||||
}
|
||||
return len(stage.reservedClientSlots)+len(stage.clients) >= int(stage.maxPlayers)
|
||||
@@ -153,14 +153,14 @@ func handleMsgSysEnterStage(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgSysEnterStage)
|
||||
|
||||
if isStageFull(s, pkt.StageID) {
|
||||
doAckSimpleFail(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x01})
|
||||
DoAckSimpleFail(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x01})
|
||||
return
|
||||
}
|
||||
|
||||
// Push our current stage ID to the movement stack before entering another one.
|
||||
if s.stage != nil {
|
||||
s.stage.Lock()
|
||||
s.stage.reservedClientSlots[s.charID] = false
|
||||
s.stage.reservedClientSlots[s.CharID] = false
|
||||
s.stage.Unlock()
|
||||
s.stageMoveStack.Push(s.stage.id)
|
||||
}
|
||||
@@ -183,16 +183,16 @@ func handleMsgSysBackStage(s *Session, p mhfpacket.MHFPacket) {
|
||||
|
||||
if isStageFull(s, backStage) {
|
||||
s.stageMoveStack.Push(backStage)
|
||||
doAckSimpleFail(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x01})
|
||||
DoAckSimpleFail(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x01})
|
||||
return
|
||||
}
|
||||
|
||||
if _, exists := s.stage.reservedClientSlots[s.charID]; exists {
|
||||
delete(s.stage.reservedClientSlots, s.charID)
|
||||
if _, exists := s.stage.reservedClientSlots[s.CharID]; exists {
|
||||
delete(s.stage.reservedClientSlots, s.CharID)
|
||||
}
|
||||
|
||||
if _, exists := s.server.stages[backStage].reservedClientSlots[s.charID]; exists {
|
||||
delete(s.server.stages[backStage].reservedClientSlots, s.charID)
|
||||
if _, exists := s.Server.stages[backStage].reservedClientSlots[s.CharID]; exists {
|
||||
delete(s.Server.stages[backStage].reservedClientSlots, s.CharID)
|
||||
}
|
||||
|
||||
doStageTransfer(s, pkt.AckHandle, backStage)
|
||||
@@ -202,7 +202,7 @@ func handleMsgSysMoveStage(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgSysMoveStage)
|
||||
|
||||
if isStageFull(s, pkt.StageID) {
|
||||
doAckSimpleFail(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x01})
|
||||
DoAckSimpleFail(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x01})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -213,12 +213,12 @@ func handleMsgSysLeaveStage(s *Session, p mhfpacket.MHFPacket) {}
|
||||
|
||||
func handleMsgSysLockStage(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgSysLockStage)
|
||||
if stage, exists := s.server.stages[pkt.StageID]; exists {
|
||||
if stage, exists := s.Server.stages[pkt.StageID]; exists {
|
||||
stage.Lock()
|
||||
stage.locked = true
|
||||
stage.Unlock()
|
||||
}
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func handleMsgSysUnlockStage(s *Session, p mhfpacket.MHFPacket) {
|
||||
@@ -227,13 +227,13 @@ func handleMsgSysUnlockStage(s *Session, p mhfpacket.MHFPacket) {
|
||||
defer s.reservationStage.RUnlock()
|
||||
|
||||
for charID := range s.reservationStage.reservedClientSlots {
|
||||
session := s.server.FindSessionByCharID(charID)
|
||||
session := s.Server.FindSessionByCharID(charID)
|
||||
if session != nil {
|
||||
session.QueueSendMHF(&mhfpacket.MsgSysStageDestruct{})
|
||||
}
|
||||
}
|
||||
|
||||
delete(s.server.stages, s.reservationStage.id)
|
||||
delete(s.Server.stages, s.reservationStage.id)
|
||||
}
|
||||
|
||||
destructEmptyStages(s)
|
||||
@@ -241,40 +241,40 @@ func handleMsgSysUnlockStage(s *Session, p mhfpacket.MHFPacket) {
|
||||
|
||||
func handleMsgSysReserveStage(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgSysReserveStage)
|
||||
if stage, exists := s.server.stages[pkt.StageID]; exists {
|
||||
if stage, exists := s.Server.stages[pkt.StageID]; exists {
|
||||
stage.Lock()
|
||||
defer stage.Unlock()
|
||||
if _, exists := stage.reservedClientSlots[s.charID]; exists {
|
||||
if _, exists := stage.reservedClientSlots[s.CharID]; exists {
|
||||
switch pkt.Ready {
|
||||
case 1: // 0x01
|
||||
stage.reservedClientSlots[s.charID] = false
|
||||
stage.reservedClientSlots[s.CharID] = false
|
||||
case 17: // 0x11
|
||||
stage.reservedClientSlots[s.charID] = true
|
||||
stage.reservedClientSlots[s.CharID] = true
|
||||
}
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
} else if uint16(len(stage.reservedClientSlots)) < stage.maxPlayers {
|
||||
if stage.locked {
|
||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
if len(stage.password) > 0 {
|
||||
if stage.password != s.stagePass {
|
||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
}
|
||||
stage.reservedClientSlots[s.charID] = false
|
||||
stage.reservedClientSlots[s.CharID] = false
|
||||
// Save the reservation stage in the session for later use in MsgSysUnreserveStage.
|
||||
s.Lock()
|
||||
s.reservationStage = stage
|
||||
s.Unlock()
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
} else {
|
||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
} else {
|
||||
s.logger.Error("Failed to get stage", zap.String("StageID", pkt.StageID))
|
||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
s.Logger.Error("Failed to get stage", zap.String("StageID", pkt.StageID))
|
||||
DoAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -285,8 +285,8 @@ func handleMsgSysUnreserveStage(s *Session, p mhfpacket.MHFPacket) {
|
||||
s.Unlock()
|
||||
if stage != nil {
|
||||
stage.Lock()
|
||||
if _, exists := stage.reservedClientSlots[s.charID]; exists {
|
||||
delete(stage.reservedClientSlots, s.charID)
|
||||
if _, exists := stage.reservedClientSlots[s.CharID]; exists {
|
||||
delete(stage.reservedClientSlots, s.CharID)
|
||||
}
|
||||
stage.Unlock()
|
||||
}
|
||||
@@ -300,7 +300,7 @@ func handleMsgSysSetStagePass(s *Session, p mhfpacket.MHFPacket) {
|
||||
if stage != nil {
|
||||
stage.Lock()
|
||||
// Will only exist if host.
|
||||
if _, exists := stage.reservedClientSlots[s.charID]; exists {
|
||||
if _, exists := stage.reservedClientSlots[s.CharID]; exists {
|
||||
stage.password = pkt.Password
|
||||
}
|
||||
stage.Unlock()
|
||||
@@ -314,78 +314,78 @@ func handleMsgSysSetStagePass(s *Session, p mhfpacket.MHFPacket) {
|
||||
|
||||
func handleMsgSysSetStageBinary(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgSysSetStageBinary)
|
||||
if stage, exists := s.server.stages[pkt.StageID]; exists {
|
||||
if stage, exists := s.Server.stages[pkt.StageID]; exists {
|
||||
stage.Lock()
|
||||
stage.rawBinaryData[stageBinaryKey{pkt.BinaryType0, pkt.BinaryType1}] = pkt.RawDataPayload
|
||||
stage.Unlock()
|
||||
} else {
|
||||
s.logger.Warn("Failed to get stage", zap.String("StageID", pkt.StageID))
|
||||
s.Logger.Warn("Failed to get stage", zap.String("StageID", pkt.StageID))
|
||||
}
|
||||
}
|
||||
|
||||
func handleMsgSysGetStageBinary(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgSysGetStageBinary)
|
||||
if stage, exists := s.server.stages[pkt.StageID]; exists {
|
||||
if stage, exists := s.Server.stages[pkt.StageID]; exists {
|
||||
stage.Lock()
|
||||
if binaryData, exists := stage.rawBinaryData[stageBinaryKey{pkt.BinaryType0, pkt.BinaryType1}]; exists {
|
||||
doAckBufSucceed(s, pkt.AckHandle, binaryData)
|
||||
DoAckBufSucceed(s, pkt.AckHandle, binaryData)
|
||||
} else if pkt.BinaryType1 == 4 {
|
||||
// Unknown binary type that is supposedly generated server side
|
||||
// Temporary response
|
||||
doAckBufSucceed(s, pkt.AckHandle, []byte{})
|
||||
DoAckBufSucceed(s, pkt.AckHandle, []byte{})
|
||||
} else {
|
||||
s.logger.Warn("Failed to get stage binary", zap.Uint8("BinaryType0", pkt.BinaryType0), zap.Uint8("pkt.BinaryType1", pkt.BinaryType1))
|
||||
s.logger.Warn("Sending blank stage binary")
|
||||
doAckBufSucceed(s, pkt.AckHandle, []byte{})
|
||||
s.Logger.Warn("Failed to get stage binary", zap.Uint8("BinaryType0", pkt.BinaryType0), zap.Uint8("pkt.BinaryType1", pkt.BinaryType1))
|
||||
s.Logger.Warn("Sending blank stage binary")
|
||||
DoAckBufSucceed(s, pkt.AckHandle, []byte{})
|
||||
}
|
||||
stage.Unlock()
|
||||
} else {
|
||||
s.logger.Warn("Failed to get stage", zap.String("StageID", pkt.StageID))
|
||||
s.Logger.Warn("Failed to get stage", zap.String("StageID", pkt.StageID))
|
||||
}
|
||||
s.logger.Debug("MsgSysGetStageBinary Done!")
|
||||
s.Logger.Debug("MsgSysGetStageBinary Done!")
|
||||
}
|
||||
|
||||
func handleMsgSysWaitStageBinary(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgSysWaitStageBinary)
|
||||
if stage, exists := s.server.stages[pkt.StageID]; exists {
|
||||
if stage, exists := s.Server.stages[pkt.StageID]; exists {
|
||||
if pkt.BinaryType0 == 1 && pkt.BinaryType1 == 12 {
|
||||
// This might contain the hunter count, or max player count?
|
||||
doAckBufSucceed(s, pkt.AckHandle, []byte{0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})
|
||||
DoAckBufSucceed(s, pkt.AckHandle, []byte{0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})
|
||||
return
|
||||
}
|
||||
for {
|
||||
s.logger.Debug("MsgSysWaitStageBinary before lock and get stage")
|
||||
s.Logger.Debug("MsgSysWaitStageBinary before lock and get stage")
|
||||
stage.Lock()
|
||||
stageBinary, gotBinary := stage.rawBinaryData[stageBinaryKey{pkt.BinaryType0, pkt.BinaryType1}]
|
||||
stage.Unlock()
|
||||
s.logger.Debug("MsgSysWaitStageBinary after lock and get stage")
|
||||
s.Logger.Debug("MsgSysWaitStageBinary after lock and get stage")
|
||||
if gotBinary {
|
||||
doAckBufSucceed(s, pkt.AckHandle, stageBinary)
|
||||
DoAckBufSucceed(s, pkt.AckHandle, stageBinary)
|
||||
break
|
||||
} else {
|
||||
s.logger.Debug("Waiting stage binary", zap.Uint8("BinaryType0", pkt.BinaryType0), zap.Uint8("pkt.BinaryType1", pkt.BinaryType1))
|
||||
s.Logger.Debug("Waiting stage binary", zap.Uint8("BinaryType0", pkt.BinaryType0), zap.Uint8("pkt.BinaryType1", pkt.BinaryType1))
|
||||
time.Sleep(1 * time.Second)
|
||||
continue
|
||||
}
|
||||
}
|
||||
} else {
|
||||
s.logger.Warn("Failed to get stage", zap.String("StageID", pkt.StageID))
|
||||
s.Logger.Warn("Failed to get stage", zap.String("StageID", pkt.StageID))
|
||||
}
|
||||
s.logger.Debug("MsgSysWaitStageBinary Done!")
|
||||
s.Logger.Debug("MsgSysWaitStageBinary Done!")
|
||||
}
|
||||
|
||||
func handleMsgSysEnumerateStage(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgSysEnumerateStage)
|
||||
|
||||
// Read-lock the server stage map.
|
||||
s.server.stagesLock.RLock()
|
||||
defer s.server.stagesLock.RUnlock()
|
||||
s.Server.stagesLock.RLock()
|
||||
defer s.Server.stagesLock.RUnlock()
|
||||
|
||||
// Build the response
|
||||
bf := byteframe.NewByteFrame()
|
||||
var joinable uint16
|
||||
bf.WriteUint16(0)
|
||||
for sid, stage := range s.server.stages {
|
||||
for sid, stage := range s.Server.stages {
|
||||
stage.RLock()
|
||||
|
||||
if len(stage.reservedClientSlots) == 0 && len(stage.clients) == 0 {
|
||||
@@ -420,5 +420,5 @@ func handleMsgSysEnumerateStage(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.Seek(0, 0)
|
||||
bf.WriteUint16(joinable)
|
||||
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -103,12 +103,12 @@ func handleMsgMhfInfoTournament(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
}
|
||||
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfEntryTournament(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfEntryTournament)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
type TournamentReward struct {
|
||||
@@ -127,5 +127,5 @@ func handleMsgMhfAcquireTournament(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint16(reward.Unk1)
|
||||
bf.WriteUint16(reward.Unk2)
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package channelserver
|
||||
|
||||
import (
|
||||
_config "erupe-ce/config"
|
||||
"erupe-ce/config"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
|
||||
"erupe-ce/network/mhfpacket"
|
||||
"erupe-ce/utils/byteframe"
|
||||
"erupe-ce/utils/db"
|
||||
"erupe-ce/utils/stringsupport"
|
||||
)
|
||||
|
||||
@@ -59,15 +60,18 @@ func handleMsgMhfGetTowerInfo(s *Session, p mhfpacket.MHFPacket) {
|
||||
History: []TowerInfoHistory{{make([]int16, 5), make([]int16, 5)}},
|
||||
Level: []TowerInfoLevel{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
||||
}
|
||||
|
||||
var tempSkills string
|
||||
err := s.server.db.QueryRow(`SELECT COALESCE(tr, 0), COALESCE(trp, 0), COALESCE(tsp, 0), COALESCE(block1, 0), COALESCE(block2, 0), COALESCE(skills, $1) FROM tower WHERE char_id=$2
|
||||
`, EmptyTowerCSV(64), s.charID).Scan(&towerInfo.TRP[0].TR, &towerInfo.TRP[0].TRP, &towerInfo.Skill[0].TSP, &towerInfo.Level[0].Floors, &towerInfo.Level[1].Floors, &tempSkills)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.server.db.Exec(`INSERT INTO tower (char_id) VALUES ($1)`, s.charID)
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
var tempSkills string
|
||||
err = database.QueryRow(`SELECT COALESCE(tr, 0), COALESCE(trp, 0), COALESCE(tsp, 0), COALESCE(block1, 0), COALESCE(block2, 0), COALESCE(skills, $1) FROM tower WHERE char_id=$2
|
||||
`, EmptyTowerCSV(64), s.CharID).Scan(&towerInfo.TRP[0].TR, &towerInfo.TRP[0].TRP, &towerInfo.Skill[0].TSP, &towerInfo.Level[0].Floors, &towerInfo.Level[1].Floors, &tempSkills)
|
||||
if err != nil {
|
||||
database.Exec(`INSERT INTO tower (char_id) VALUES ($1)`, s.CharID)
|
||||
}
|
||||
|
||||
if _config.ErupeConfig.ClientID <= _config.G7 {
|
||||
if config.GetConfig().ClientID <= config.G7 {
|
||||
towerInfo.Level = towerInfo.Level[:1]
|
||||
}
|
||||
|
||||
@@ -113,14 +117,14 @@ func handleMsgMhfGetTowerInfo(s *Session, p mhfpacket.MHFPacket) {
|
||||
data = append(data, bf)
|
||||
}
|
||||
}
|
||||
doAckEarthSucceed(s, pkt.AckHandle, data)
|
||||
DoAckEarthSucceed(s, pkt.AckHandle, data)
|
||||
}
|
||||
|
||||
func handleMsgMhfPostTowerInfo(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfPostTowerInfo)
|
||||
|
||||
if s.server.erupeConfig.DebugOptions.QuestTools {
|
||||
s.logger.Debug(
|
||||
if config.GetConfig().DebugOptions.QuestTools {
|
||||
s.Logger.Debug(
|
||||
p.Opcode().String(),
|
||||
zap.Uint32("InfoType", pkt.InfoType),
|
||||
zap.Uint32("Unk1", pkt.Unk1),
|
||||
@@ -134,17 +138,20 @@ func handleMsgMhfPostTowerInfo(s *Session, p mhfpacket.MHFPacket) {
|
||||
zap.Int64("Unk9", pkt.Unk9),
|
||||
)
|
||||
}
|
||||
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
switch pkt.InfoType {
|
||||
case 2:
|
||||
var skills string
|
||||
s.server.db.QueryRow(`SELECT COALESCE(skills, $1) FROM tower WHERE char_id=$2`, EmptyTowerCSV(64), s.charID).Scan(&skills)
|
||||
s.server.db.Exec(`UPDATE tower SET skills=$1, tsp=tsp-$2 WHERE char_id=$3`, stringsupport.CSVSetIndex(skills, int(pkt.Skill), stringsupport.CSVGetIndex(skills, int(pkt.Skill))+1), pkt.Cost, s.charID)
|
||||
database.QueryRow(`SELECT COALESCE(skills, $1) FROM tower WHERE char_id=$2`, EmptyTowerCSV(64), s.CharID).Scan(&skills)
|
||||
database.Exec(`UPDATE tower SET skills=$1, tsp=tsp-$2 WHERE char_id=$3`, stringsupport.CSVSetIndex(skills, int(pkt.Skill), stringsupport.CSVGetIndex(skills, int(pkt.Skill))+1), pkt.Cost, s.CharID)
|
||||
case 1, 7:
|
||||
// This might give too much TSP? No idea what the rate is supposed to be
|
||||
s.server.db.Exec(`UPDATE tower SET tr=$1, trp=COALESCE(trp, 0)+$2, tsp=COALESCE(tsp, 0)+$3, block1=COALESCE(block1, 0)+$4 WHERE char_id=$5`, pkt.TR, pkt.TRP, pkt.Cost, pkt.Block1, s.charID)
|
||||
database.Exec(`UPDATE tower SET tr=$1, trp=COALESCE(trp, 0)+$2, tsp=COALESCE(tsp, 0)+$3, block1=COALESCE(block1, 0)+$4 WHERE char_id=$5`, pkt.TR, pkt.TRP, pkt.Cost, pkt.Block1, s.CharID)
|
||||
}
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
// Default missions
|
||||
@@ -250,7 +257,10 @@ func handleMsgMhfGetTenrouirai(s *Session, p mhfpacket.MHFPacket) {
|
||||
Data: tenrouiraiData,
|
||||
Ticket: []TenrouiraiTicket{{0, 0, 0}},
|
||||
}
|
||||
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
switch pkt.Unk1 {
|
||||
case 1:
|
||||
for _, tdata := range tenrouirai.Data {
|
||||
@@ -284,8 +294,8 @@ func handleMsgMhfGetTenrouirai(s *Session, p mhfpacket.MHFPacket) {
|
||||
data = append(data, bf)
|
||||
}
|
||||
case 4:
|
||||
s.server.db.QueryRow(`SELECT tower_mission_page FROM guilds WHERE id=$1`, pkt.GuildID).Scan(&tenrouirai.Progress[0].Page)
|
||||
s.server.db.QueryRow(`SELECT SUM(tower_mission_1) AS _, SUM(tower_mission_2) AS _, SUM(tower_mission_3) AS _ FROM guild_characters WHERE guild_id=$1
|
||||
database.QueryRow(`SELECT tower_mission_page FROM guilds WHERE id=$1`, pkt.GuildID).Scan(&tenrouirai.Progress[0].Page)
|
||||
database.QueryRow(`SELECT SUM(tower_mission_1) AS _, SUM(tower_mission_2) AS _, SUM(tower_mission_3) AS _ FROM guild_characters WHERE guild_id=$1
|
||||
`, pkt.GuildID).Scan(&tenrouirai.Progress[0].Mission1, &tenrouirai.Progress[0].Mission2, &tenrouirai.Progress[0].Mission3)
|
||||
|
||||
if tenrouirai.Progress[0].Mission1 > tenrouiraiData[(tenrouirai.Progress[0].Page*3)-3].Goal {
|
||||
@@ -313,7 +323,7 @@ func handleMsgMhfGetTenrouirai(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt.Unk3 = 3
|
||||
}
|
||||
}
|
||||
rows, _ := s.server.db.Query(fmt.Sprintf(`SELECT name, tower_mission_%d FROM guild_characters gc INNER JOIN characters c ON gc.character_id = c.id WHERE guild_id=$1 AND tower_mission_%d IS NOT NULL ORDER BY tower_mission_%d DESC`, pkt.Unk3, pkt.Unk3, pkt.Unk3), pkt.GuildID)
|
||||
rows, _ := database.Query(fmt.Sprintf(`SELECT name, tower_mission_%d FROM guild_characters gc INNER JOIN characters c ON gc.character_id = c.id WHERE guild_id=$1 AND tower_mission_%d IS NOT NULL ORDER BY tower_mission_%d DESC`, pkt.Unk3, pkt.Unk3, pkt.Unk3), pkt.GuildID)
|
||||
for rows.Next() {
|
||||
temp := TenrouiraiCharScore{}
|
||||
rows.Scan(&temp.Name, &temp.Score)
|
||||
@@ -326,7 +336,7 @@ func handleMsgMhfGetTenrouirai(s *Session, p mhfpacket.MHFPacket) {
|
||||
data = append(data, bf)
|
||||
}
|
||||
case 6:
|
||||
s.server.db.QueryRow(`SELECT tower_rp FROM guilds WHERE id=$1`, pkt.GuildID).Scan(&tenrouirai.Ticket[0].RP)
|
||||
database.QueryRow(`SELECT tower_rp FROM guilds WHERE id=$1`, pkt.GuildID).Scan(&tenrouirai.Ticket[0].RP)
|
||||
for _, ticket := range tenrouirai.Ticket {
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint8(ticket.Unk0)
|
||||
@@ -336,14 +346,17 @@ func handleMsgMhfGetTenrouirai(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
}
|
||||
|
||||
doAckEarthSucceed(s, pkt.AckHandle, data)
|
||||
DoAckEarthSucceed(s, pkt.AckHandle, data)
|
||||
}
|
||||
|
||||
func handleMsgMhfPostTenrouirai(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfPostTenrouirai)
|
||||
|
||||
if s.server.erupeConfig.DebugOptions.QuestTools {
|
||||
s.logger.Debug(
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
if config.GetConfig().DebugOptions.QuestTools {
|
||||
s.Logger.Debug(
|
||||
p.Opcode().String(),
|
||||
zap.Uint8("Unk0", pkt.Unk0),
|
||||
zap.Uint8("Op", pkt.Op),
|
||||
@@ -360,7 +373,7 @@ func handleMsgMhfPostTenrouirai(s *Session, p mhfpacket.MHFPacket) {
|
||||
|
||||
if pkt.Op == 2 {
|
||||
var page, requirement, donated int
|
||||
s.server.db.QueryRow(`SELECT tower_mission_page, tower_rp FROM guilds WHERE id=$1`, pkt.GuildID).Scan(&page, &donated)
|
||||
database.QueryRow(`SELECT tower_mission_page, tower_rp FROM guilds WHERE id=$1`, pkt.GuildID).Scan(&page, &donated)
|
||||
|
||||
for i := 0; i < (page*3)+1; i++ {
|
||||
requirement += int(tenrouiraiData[i].Cost)
|
||||
@@ -368,24 +381,24 @@ func handleMsgMhfPostTenrouirai(s *Session, p mhfpacket.MHFPacket) {
|
||||
|
||||
bf := byteframe.NewByteFrame()
|
||||
|
||||
sd, err := GetCharacterSaveData(s, s.charID)
|
||||
sd, err := GetCharacterSaveData(s, s.CharID)
|
||||
if err == nil && sd != nil {
|
||||
sd.RP -= pkt.DonatedRP
|
||||
sd.Save(s)
|
||||
if donated+int(pkt.DonatedRP) >= requirement {
|
||||
s.server.db.Exec(`UPDATE guilds SET tower_mission_page=tower_mission_page+1 WHERE id=$1`, pkt.GuildID)
|
||||
s.server.db.Exec(`UPDATE guild_characters SET tower_mission_1=NULL, tower_mission_2=NULL, tower_mission_3=NULL WHERE guild_id=$1`, pkt.GuildID)
|
||||
database.Exec(`UPDATE guilds SET tower_mission_page=tower_mission_page+1 WHERE id=$1`, pkt.GuildID)
|
||||
database.Exec(`UPDATE guild_characters SET tower_mission_1=NULL, tower_mission_2=NULL, tower_mission_3=NULL WHERE guild_id=$1`, pkt.GuildID)
|
||||
pkt.DonatedRP = uint16(requirement - donated)
|
||||
}
|
||||
bf.WriteUint32(uint32(pkt.DonatedRP))
|
||||
s.server.db.Exec(`UPDATE guilds SET tower_rp=tower_rp+$1 WHERE id=$2`, pkt.DonatedRP, pkt.GuildID)
|
||||
database.Exec(`UPDATE guilds SET tower_rp=tower_rp+$1 WHERE id=$2`, pkt.DonatedRP, pkt.GuildID)
|
||||
} else {
|
||||
bf.WriteUint32(0)
|
||||
}
|
||||
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
|
||||
} else {
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -405,7 +418,7 @@ func handleMsgMhfPresentBox(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteInt32(0)
|
||||
bf.WriteInt32(0)
|
||||
*/
|
||||
doAckEarthSucceed(s, pkt.AckHandle, data)
|
||||
DoAckEarthSucceed(s, pkt.AckHandle, data)
|
||||
}
|
||||
|
||||
type GemInfo struct {
|
||||
@@ -425,9 +438,12 @@ func handleMsgMhfGetGemInfo(s *Session, p mhfpacket.MHFPacket) {
|
||||
var data []*byteframe.ByteFrame
|
||||
gemInfo := []GemInfo{}
|
||||
gemHistory := []GemHistory{}
|
||||
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
var tempGems string
|
||||
s.server.db.QueryRow(`SELECT COALESCE(gems, $1) FROM tower WHERE char_id=$2`, EmptyTowerCSV(30), s.charID).Scan(&tempGems)
|
||||
database.QueryRow(`SELECT COALESCE(gems, $1) FROM tower WHERE char_id=$2`, EmptyTowerCSV(30), s.CharID).Scan(&tempGems)
|
||||
for i, v := range stringsupport.CSVElems(tempGems) {
|
||||
gemInfo = append(gemInfo, GemInfo{uint16((i / 5 << 8) + (i%5 + 1)), uint16(v)})
|
||||
}
|
||||
@@ -450,14 +466,14 @@ func handleMsgMhfGetGemInfo(s *Session, p mhfpacket.MHFPacket) {
|
||||
data = append(data, bf)
|
||||
}
|
||||
}
|
||||
doAckEarthSucceed(s, pkt.AckHandle, data)
|
||||
DoAckEarthSucceed(s, pkt.AckHandle, data)
|
||||
}
|
||||
|
||||
func handleMsgMhfPostGemInfo(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfPostGemInfo)
|
||||
|
||||
if s.server.erupeConfig.DebugOptions.QuestTools {
|
||||
s.logger.Debug(
|
||||
if config.GetConfig().DebugOptions.QuestTools {
|
||||
s.Logger.Debug(
|
||||
p.Opcode().String(),
|
||||
zap.Uint32("Op", pkt.Op),
|
||||
zap.Uint32("Unk1", pkt.Unk1),
|
||||
@@ -468,25 +484,28 @@ func handleMsgMhfPostGemInfo(s *Session, p mhfpacket.MHFPacket) {
|
||||
zap.Int32("Unk6", pkt.Unk6),
|
||||
)
|
||||
}
|
||||
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
var gems string
|
||||
s.server.db.QueryRow(`SELECT COALESCE(gems, $1) FROM tower WHERE char_id=$2`, EmptyTowerCSV(30), s.charID).Scan(&gems)
|
||||
database.QueryRow(`SELECT COALESCE(gems, $1) FROM tower WHERE char_id=$2`, EmptyTowerCSV(30), s.CharID).Scan(&gems)
|
||||
switch pkt.Op {
|
||||
case 1: // Add gem
|
||||
i := int((pkt.Gem >> 8 * 5) + (pkt.Gem - pkt.Gem&0xFF00 - 1%5))
|
||||
s.server.db.Exec(`UPDATE tower SET gems=$1 WHERE char_id=$2`, stringsupport.CSVSetIndex(gems, i, stringsupport.CSVGetIndex(gems, i)+int(pkt.Quantity)), s.charID)
|
||||
database.Exec(`UPDATE tower SET gems=$1 WHERE char_id=$2`, stringsupport.CSVSetIndex(gems, i, stringsupport.CSVGetIndex(gems, i)+int(pkt.Quantity)), s.CharID)
|
||||
case 2: // Transfer gem
|
||||
// no way im doing this for now
|
||||
}
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func handleMsgMhfGetNotice(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetNotice)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func handleMsgMhfPostNotice(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfPostNotice)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"erupe-ce/network/mhfpacket"
|
||||
"erupe-ce/utils/db"
|
||||
)
|
||||
|
||||
func handleMsgSysInsertUser(s *Session, p mhfpacket.MHFPacket) {}
|
||||
@@ -12,44 +13,50 @@ func handleMsgSysDeleteUser(s *Session, p mhfpacket.MHFPacket) {}
|
||||
|
||||
func handleMsgSysSetUserBinary(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgSysSetUserBinary)
|
||||
s.server.userBinaryPartsLock.Lock()
|
||||
s.server.userBinaryParts[userBinaryPartID{charID: s.charID, index: pkt.BinaryType}] = pkt.RawDataPayload
|
||||
s.server.userBinaryPartsLock.Unlock()
|
||||
|
||||
var exists []byte
|
||||
err := s.server.db.QueryRow("SELECT type2 FROM user_binary WHERE id=$1", s.charID).Scan(&exists)
|
||||
s.Server.userBinaryPartsLock.Lock()
|
||||
s.Server.userBinaryParts[userBinaryPartID{charID: s.CharID, index: pkt.BinaryType}] = pkt.RawDataPayload
|
||||
s.Server.userBinaryPartsLock.Unlock()
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.server.db.Exec("INSERT INTO user_binary (id) VALUES ($1)", s.charID)
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
var exists []byte
|
||||
err = database.QueryRow("SELECT type2 FROM user_binary WHERE id=$1", s.CharID).Scan(&exists)
|
||||
if err != nil {
|
||||
database.Exec("INSERT INTO user_binary (id) VALUES ($1)", s.CharID)
|
||||
}
|
||||
|
||||
s.server.db.Exec(fmt.Sprintf("UPDATE user_binary SET type%d=$1 WHERE id=$2", pkt.BinaryType), pkt.RawDataPayload, s.charID)
|
||||
database.Exec(fmt.Sprintf("UPDATE user_binary SET type%d=$1 WHERE id=$2", pkt.BinaryType), pkt.RawDataPayload, s.CharID)
|
||||
|
||||
msg := &mhfpacket.MsgSysNotifyUserBinary{
|
||||
CharID: s.charID,
|
||||
CharID: s.CharID,
|
||||
BinaryType: pkt.BinaryType,
|
||||
}
|
||||
|
||||
s.server.BroadcastMHF(msg, s)
|
||||
s.Server.BroadcastMHF(msg, s)
|
||||
}
|
||||
|
||||
func handleMsgSysGetUserBinary(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgSysGetUserBinary)
|
||||
|
||||
// Try to get the data.
|
||||
s.server.userBinaryPartsLock.RLock()
|
||||
defer s.server.userBinaryPartsLock.RUnlock()
|
||||
data, ok := s.server.userBinaryParts[userBinaryPartID{charID: pkt.CharID, index: pkt.BinaryType}]
|
||||
|
||||
s.Server.userBinaryPartsLock.RLock()
|
||||
defer s.Server.userBinaryPartsLock.RUnlock()
|
||||
data, ok := s.Server.userBinaryParts[userBinaryPartID{charID: pkt.CharID, index: pkt.BinaryType}]
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
// If we can't get the real data, try to get it from the database.
|
||||
if !ok {
|
||||
err := s.server.db.QueryRow(fmt.Sprintf("SELECT type%d FROM user_binary WHERE id=$1", pkt.BinaryType), pkt.CharID).Scan(&data)
|
||||
err = database.QueryRow(fmt.Sprintf("SELECT type%d FROM user_binary WHERE id=$1", pkt.BinaryType), pkt.CharID).Scan(&data)
|
||||
if err != nil {
|
||||
doAckBufFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
DoAckBufFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
} else {
|
||||
doAckBufSucceed(s, pkt.AckHandle, data)
|
||||
DoAckBufSucceed(s, pkt.AckHandle, data)
|
||||
}
|
||||
} else {
|
||||
doAckBufSucceed(s, pkt.AckHandle, data)
|
||||
DoAckBufSucceed(s, pkt.AckHandle, data)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
)
|
||||
|
||||
// BroadcastMHF queues a MHFPacket to be sent to all sessions.
|
||||
func (server *Server) BroadcastMHF(pkt mhfpacket.MHFPacket, ignoredSession *Session) {
|
||||
func (server *ChannelServer) BroadcastMHF(pkt mhfpacket.MHFPacket, ignoredSession *Session) {
|
||||
// Broadcast the data.
|
||||
server.Lock()
|
||||
defer server.Unlock()
|
||||
@@ -22,7 +22,7 @@ func (server *Server) BroadcastMHF(pkt mhfpacket.MHFPacket, ignoredSession *Sess
|
||||
}
|
||||
}
|
||||
|
||||
func (server *Server) WorldcastMHF(pkt mhfpacket.MHFPacket, ignoredSession *Session, ignoredChannel *Server) {
|
||||
func (server *ChannelServer) WorldcastMHF(pkt mhfpacket.MHFPacket, ignoredSession *Session, ignoredChannel *ChannelServer) {
|
||||
for _, c := range server.Channels {
|
||||
if c == ignoredChannel {
|
||||
continue
|
||||
@@ -32,7 +32,7 @@ func (server *Server) WorldcastMHF(pkt mhfpacket.MHFPacket, ignoredSession *Sess
|
||||
}
|
||||
|
||||
// BroadcastChatMessage broadcasts a simple chat message to all the sessions.
|
||||
func (server *Server) BroadcastChatMessage(message string) {
|
||||
func (server *ChannelServer) BroadcastChatMessage(message string) {
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.SetLE()
|
||||
msgBinChat := &binpacket.MsgBinChat{
|
||||
@@ -50,7 +50,7 @@ func (server *Server) BroadcastChatMessage(message string) {
|
||||
}, nil)
|
||||
}
|
||||
|
||||
func (server *Server) BroadcastRaviente(ip uint32, port uint16, stage []byte, _type uint8) {
|
||||
func (server *ChannelServer) BroadcastRaviente(ip uint32, port uint16, stage []byte, _type uint8) {
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.SetLE()
|
||||
bf.WriteUint16(0) // Unk
|
||||
|
||||
@@ -6,23 +6,21 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
_config "erupe-ce/config"
|
||||
"erupe-ce/config"
|
||||
"erupe-ce/server/discordbot"
|
||||
"erupe-ce/utils/db"
|
||||
"erupe-ce/utils/gametime"
|
||||
"erupe-ce/utils/logger"
|
||||
|
||||
"github.com/jmoiron/sqlx"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// Config struct allows configuring the server.
|
||||
type Config struct {
|
||||
ID uint16
|
||||
DB *sqlx.DB
|
||||
DiscordBot *discordbot.DiscordBot
|
||||
ErupeConfig *_config.Config
|
||||
Name string
|
||||
Enable bool
|
||||
ID uint16
|
||||
DiscordBot *discordbot.DiscordBot
|
||||
Name string
|
||||
Enable bool
|
||||
}
|
||||
|
||||
// Map key type for a user binary part.
|
||||
@@ -31,17 +29,16 @@ type userBinaryPartID struct {
|
||||
index uint8
|
||||
}
|
||||
|
||||
// Server is a MHF channel server.
|
||||
type Server struct {
|
||||
// ChannelServer is a MHF channel server.
|
||||
type ChannelServer struct {
|
||||
sync.Mutex
|
||||
Channels []*Server
|
||||
Channels []*ChannelServer
|
||||
ID uint16
|
||||
GlobalID string
|
||||
IP string
|
||||
Port uint16
|
||||
logger logger.Logger
|
||||
db *sqlx.DB
|
||||
erupeConfig *_config.Config
|
||||
erupeConfig *config.Config
|
||||
acceptConns chan net.Conn
|
||||
deleteConns chan net.Conn
|
||||
sessions map[net.Conn]*Session
|
||||
@@ -76,7 +73,7 @@ type Server struct {
|
||||
}
|
||||
|
||||
// NewServer creates a new Server type.
|
||||
func NewServer(config *Config) *Server {
|
||||
func NewServer(config *Config) *ChannelServer {
|
||||
stageNames := []string{
|
||||
"sl1Ns200p0a0u0", // Mezeporta
|
||||
"sl1Ns211p0a0u0", // Rasta bar
|
||||
@@ -90,11 +87,9 @@ func NewServer(config *Config) *Server {
|
||||
for _, name := range stageNames {
|
||||
stages[name] = NewStage(name)
|
||||
}
|
||||
server := &Server{
|
||||
server := &ChannelServer{
|
||||
ID: config.ID,
|
||||
logger: logger.Get().Named("channel-" + fmt.Sprint(config.ID)),
|
||||
db: config.DB,
|
||||
erupeConfig: config.ErupeConfig,
|
||||
acceptConns: make(chan net.Conn),
|
||||
deleteConns: make(chan net.Conn),
|
||||
sessions: make(map[net.Conn]*Session),
|
||||
@@ -121,7 +116,7 @@ func NewServer(config *Config) *Server {
|
||||
}
|
||||
|
||||
// Start starts the server in a new goroutine.
|
||||
func (server *Server) Start() error {
|
||||
func (server *ChannelServer) Start() error {
|
||||
l, err := net.Listen("tcp", fmt.Sprintf(":%d", server.Port))
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -130,9 +125,8 @@ func (server *Server) Start() error {
|
||||
|
||||
go server.acceptClients()
|
||||
go server.manageSessions()
|
||||
|
||||
// Start the discord bot for chat integration.
|
||||
if server.erupeConfig.Discord.Enabled && server.discordBot != nil {
|
||||
if config.GetConfig().Discord.Enabled && server.discordBot != nil {
|
||||
server.discordBot.Session.AddHandler(server.onDiscordMessage)
|
||||
server.discordBot.Session.AddHandler(server.onInteraction)
|
||||
}
|
||||
@@ -141,7 +135,7 @@ func (server *Server) Start() error {
|
||||
}
|
||||
|
||||
// Shutdown tries to shut down the server gracefully.
|
||||
func (server *Server) Shutdown() {
|
||||
func (server *ChannelServer) Shutdown() {
|
||||
server.Lock()
|
||||
server.isShuttingDown = true
|
||||
server.Unlock()
|
||||
@@ -151,7 +145,7 @@ func (server *Server) Shutdown() {
|
||||
close(server.acceptConns)
|
||||
}
|
||||
|
||||
func (server *Server) acceptClients() {
|
||||
func (server *ChannelServer) acceptClients() {
|
||||
for {
|
||||
conn, err := server.listener.Accept()
|
||||
if err != nil {
|
||||
@@ -170,7 +164,7 @@ func (server *Server) acceptClients() {
|
||||
}
|
||||
}
|
||||
|
||||
func (server *Server) manageSessions() {
|
||||
func (server *ChannelServer) manageSessions() {
|
||||
for {
|
||||
select {
|
||||
case newConn := <-server.acceptConns:
|
||||
@@ -201,10 +195,10 @@ func (server *Server) manageSessions() {
|
||||
}
|
||||
}
|
||||
|
||||
func (server *Server) FindSessionByCharID(charID uint32) *Session {
|
||||
func (server *ChannelServer) FindSessionByCharID(charID uint32) *Session {
|
||||
for _, c := range server.Channels {
|
||||
for _, session := range c.sessions {
|
||||
if session.charID == charID {
|
||||
if session.CharID == charID {
|
||||
return session
|
||||
}
|
||||
}
|
||||
@@ -212,10 +206,14 @@ func (server *Server) FindSessionByCharID(charID uint32) *Session {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (server *Server) DisconnectUser(uid uint32) {
|
||||
func (server *ChannelServer) DisconnectUser(uid uint32) {
|
||||
var cid uint32
|
||||
var cids []uint32
|
||||
rows, _ := server.db.Query(`SELECT id FROM characters WHERE user_id=$1`, uid)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
server.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
rows, _ := database.Query(`SELECT id FROM characters WHERE user_id=$1`, uid)
|
||||
for rows.Next() {
|
||||
rows.Scan(&cid)
|
||||
cids = append(cids, cid)
|
||||
@@ -223,7 +221,7 @@ func (server *Server) DisconnectUser(uid uint32) {
|
||||
for _, c := range server.Channels {
|
||||
for _, session := range c.sessions {
|
||||
for _, cid := range cids {
|
||||
if session.charID == cid {
|
||||
if session.CharID == cid {
|
||||
session.rawConn.Close()
|
||||
break
|
||||
}
|
||||
@@ -232,7 +230,7 @@ func (server *Server) DisconnectUser(uid uint32) {
|
||||
}
|
||||
}
|
||||
|
||||
func (server *Server) FindObjectByChar(charID uint32) *Object {
|
||||
func (server *ChannelServer) FindObjectByChar(charID uint32) *Object {
|
||||
server.stagesLock.RLock()
|
||||
defer server.stagesLock.RUnlock()
|
||||
for _, stage := range server.stages {
|
||||
@@ -250,7 +248,7 @@ func (server *Server) FindObjectByChar(charID uint32) *Object {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (server *Server) HasSemaphore(ses *Session) bool {
|
||||
func (server *ChannelServer) HasSemaphore(ses *Session) bool {
|
||||
for _, semaphore := range server.semaphore {
|
||||
if semaphore.host == ses {
|
||||
return true
|
||||
@@ -259,7 +257,7 @@ func (server *Server) HasSemaphore(ses *Session) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (server *Server) Season() uint8 {
|
||||
func (server *ChannelServer) Season() uint8 {
|
||||
sid := int64(((server.ID & 0xFF00) - 4096) / 256)
|
||||
return uint8(((gametime.TimeAdjusted().Unix() / 86400) + sid) % 3)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package channelserver
|
||||
|
||||
import (
|
||||
"erupe-ce/utils/db"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
@@ -15,7 +16,7 @@ type Player struct {
|
||||
QuestID int
|
||||
}
|
||||
|
||||
func getPlayerSlice(server *Server) []Player {
|
||||
func getPlayerSlice(server *ChannelServer) []Player {
|
||||
var p []Player
|
||||
var questIndex int
|
||||
|
||||
@@ -40,7 +41,7 @@ func getPlayerSlice(server *Server) []Player {
|
||||
return p
|
||||
}
|
||||
|
||||
func getCharacterList(server *Server) string {
|
||||
func getCharacterList(server *ChannelServer) string {
|
||||
questEmojis := []string{
|
||||
":person_in_lotus_position:",
|
||||
":white_circle:",
|
||||
@@ -69,11 +70,15 @@ func getCharacterList(server *Server) string {
|
||||
}
|
||||
|
||||
// onInteraction handles slash commands
|
||||
func (server *Server) onInteraction(ds *discordgo.Session, i *discordgo.InteractionCreate) {
|
||||
func (server *ChannelServer) onInteraction(ds *discordgo.Session, i *discordgo.InteractionCreate) {
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
server.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
switch i.Interaction.ApplicationCommandData().Name {
|
||||
case "link":
|
||||
var temp string
|
||||
err := server.db.QueryRow(`UPDATE users SET discord_id = $1 WHERE discord_token = $2 RETURNING discord_id`, i.Member.User.ID, i.ApplicationCommandData().Options[0].StringValue()).Scan(&temp)
|
||||
err := database.QueryRow(`UPDATE users SET discord_id = $1 WHERE discord_token = $2 RETURNING discord_id`, i.Member.User.ID, i.ApplicationCommandData().Options[0].StringValue()).Scan(&temp)
|
||||
if err == nil {
|
||||
ds.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
||||
@@ -93,7 +98,7 @@ func (server *Server) onInteraction(ds *discordgo.Session, i *discordgo.Interact
|
||||
}
|
||||
case "password":
|
||||
password, _ := bcrypt.GenerateFromPassword([]byte(i.ApplicationCommandData().Options[0].StringValue()), 10)
|
||||
_, err := server.db.Exec(`UPDATE users SET password = $1 WHERE discord_id = $2`, password, i.Member.User.ID)
|
||||
_, err := database.Exec(`UPDATE users SET password = $1 WHERE discord_id = $2`, password, i.Member.User.ID)
|
||||
if err == nil {
|
||||
ds.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
|
||||
Type: discordgo.InteractionResponseChannelMessageWithSource,
|
||||
@@ -115,7 +120,7 @@ func (server *Server) onInteraction(ds *discordgo.Session, i *discordgo.Interact
|
||||
}
|
||||
|
||||
// onDiscordMessage handles receiving messages from discord and forwarding them ingame.
|
||||
func (server *Server) onDiscordMessage(ds *discordgo.Session, m *discordgo.MessageCreate) {
|
||||
func (server *ChannelServer) onDiscordMessage(ds *discordgo.Session, m *discordgo.MessageCreate) {
|
||||
// Ignore messages from bots, or messages that are not in the correct channel.
|
||||
if m.Author.Bot || m.ChannelID != server.erupeConfig.Discord.RelayChannel.RelayChannelID {
|
||||
return
|
||||
@@ -148,14 +153,14 @@ func (server *Server) onDiscordMessage(ds *discordgo.Session, m *discordgo.Messa
|
||||
server.BroadcastChatMessage(messages[i])
|
||||
}
|
||||
}
|
||||
func (server *Server) DiscordChannelSend(charName string, content string) {
|
||||
func (server *ChannelServer) DiscordChannelSend(charName string, content string) {
|
||||
if server.erupeConfig.Discord.Enabled && server.discordBot != nil {
|
||||
message := fmt.Sprintf("**%s**: %s", charName, content)
|
||||
server.discordBot.RealtimeChannelSend(message)
|
||||
}
|
||||
}
|
||||
|
||||
func (server *Server) DiscordScreenShotSend(charName string, title string, description string, articleToken string) {
|
||||
func (server *ChannelServer) DiscordScreenShotSend(charName string, title string, description string, articleToken string) {
|
||||
if server.erupeConfig.Discord.Enabled && server.discordBot != nil {
|
||||
imageUrl := fmt.Sprintf("%s:%d/api/ss/bbs/%s", server.erupeConfig.Screenshots.Host, server.erupeConfig.Screenshots.Port, articleToken)
|
||||
message := fmt.Sprintf("**%s**: %s - %s %s", charName, title, description, imageUrl)
|
||||
|
||||
@@ -155,14 +155,14 @@ func init() {
|
||||
handlerTable[network.MSG_MHF_CARAVAN_MY_SCORE] = handleMsgMhfCaravanMyScore
|
||||
handlerTable[network.MSG_MHF_CARAVAN_RANKING] = handleMsgMhfCaravanRanking
|
||||
handlerTable[network.MSG_MHF_CARAVAN_MY_RANK] = handleMsgMhfCaravanMyRank
|
||||
handlerTable[network.MSG_MHF_CREATE_GUILD] = handleMsgMhfCreateGuild
|
||||
handlerTable[network.MSG_MHF_OPERATE_GUILD] = handleMsgMhfOperateGuild
|
||||
handlerTable[network.MSG_MHF_OPERATE_GUILD_MEMBER] = handleMsgMhfOperateGuildMember
|
||||
handlerTable[network.MSG_MHF_INFO_GUILD] = handleMsgMhfInfoGuild
|
||||
handlerTable[network.MSG_MHF_ENUMERATE_GUILD] = handleMsgMhfEnumerateGuild
|
||||
handlerTable[network.MSG_MHF_UPDATE_GUILD] = handleMsgMhfUpdateGuild
|
||||
handlerTable[network.MSG_MHF_ARRANGE_GUILD_MEMBER] = handleMsgMhfArrangeGuildMember
|
||||
handlerTable[network.MSG_MHF_ENUMERATE_GUILD_MEMBER] = handleMsgMhfEnumerateGuildMember
|
||||
handlerTable[network.MSG_MHF_CREATE_GUILD] = HandleMsgMhfCreateGuild
|
||||
handlerTable[network.MSG_MHF_OPERATE_GUILD] = HandleMsgMhfOperateGuild
|
||||
handlerTable[network.MSG_MHF_OPERATE_GUILD_MEMBER] = HandleMsgMhfOperateGuildMember
|
||||
handlerTable[network.MSG_MHF_INFO_GUILD] = HandleMsgMhfInfoGuild
|
||||
handlerTable[network.MSG_MHF_ENUMERATE_GUILD] = HandleMsgMhfEnumerateGuild
|
||||
handlerTable[network.MSG_MHF_UPDATE_GUILD] = HandleMsgMhfUpdateGuild
|
||||
handlerTable[network.MSG_MHF_ARRANGE_GUILD_MEMBER] = HandleMsgMhfArrangeGuildMember
|
||||
handlerTable[network.MSG_MHF_ENUMERATE_GUILD_MEMBER] = HandleMsgMhfEnumerateGuildMember
|
||||
handlerTable[network.MSG_MHF_ENUMERATE_CAMPAIGN] = handleMsgMhfEnumerateCampaign
|
||||
handlerTable[network.MSG_MHF_STATE_CAMPAIGN] = handleMsgMhfStateCampaign
|
||||
handlerTable[network.MSG_MHF_APPLY_CAMPAIGN] = handleMsgMhfApplyCampaign
|
||||
@@ -170,7 +170,7 @@ func init() {
|
||||
handlerTable[network.MSG_MHF_ACQUIRE_ITEM] = handleMsgMhfAcquireItem
|
||||
handlerTable[network.MSG_MHF_TRANSFER_ITEM] = handleMsgMhfTransferItem
|
||||
handlerTable[network.MSG_MHF_MERCENARY_HUNTDATA] = handleMsgMhfMercenaryHuntdata
|
||||
handlerTable[network.MSG_MHF_ENTRY_ROOKIE_GUILD] = handleMsgMhfEntryRookieGuild
|
||||
handlerTable[network.MSG_MHF_ENTRY_ROOKIE_GUILD] = HandleMsgMhfEntryRookieGuild
|
||||
handlerTable[network.MSG_MHF_ENUMERATE_QUEST] = handleMsgMhfEnumerateQuest
|
||||
handlerTable[network.MSG_MHF_ENUMERATE_EVENT] = handleMsgMhfEnumerateEvent
|
||||
handlerTable[network.MSG_MHF_ENUMERATE_PRICE] = handleMsgMhfEnumeratePrice
|
||||
@@ -187,14 +187,14 @@ func init() {
|
||||
handlerTable[network.MSG_MHF_UPDATE_WAREHOUSE] = handleMsgMhfUpdateWarehouse
|
||||
handlerTable[network.MSG_MHF_ACQUIRE_TITLE] = handleMsgMhfAcquireTitle
|
||||
handlerTable[network.MSG_MHF_ENUMERATE_TITLE] = handleMsgMhfEnumerateTitle
|
||||
handlerTable[network.MSG_MHF_ENUMERATE_GUILD_ITEM] = handleMsgMhfEnumerateGuildItem
|
||||
handlerTable[network.MSG_MHF_UPDATE_GUILD_ITEM] = handleMsgMhfUpdateGuildItem
|
||||
handlerTable[network.MSG_MHF_ENUMERATE_GUILD_ITEM] = HandleMsgMhfEnumerateGuildItem
|
||||
handlerTable[network.MSG_MHF_UPDATE_GUILD_ITEM] = HandleMsgMhfUpdateGuildItem
|
||||
handlerTable[network.MSG_MHF_ENUMERATE_UNION_ITEM] = handleMsgMhfEnumerateUnionItem
|
||||
handlerTable[network.MSG_MHF_UPDATE_UNION_ITEM] = handleMsgMhfUpdateUnionItem
|
||||
handlerTable[network.MSG_MHF_CREATE_JOINT] = handleMsgMhfCreateJoint
|
||||
handlerTable[network.MSG_MHF_OPERATE_JOINT] = handleMsgMhfOperateJoint
|
||||
handlerTable[network.MSG_MHF_INFO_JOINT] = handleMsgMhfInfoJoint
|
||||
handlerTable[network.MSG_MHF_UPDATE_GUILD_ICON] = handleMsgMhfUpdateGuildIcon
|
||||
handlerTable[network.MSG_MHF_CREATE_JOINT] = HandleMsgMhfCreateJoint
|
||||
handlerTable[network.MSG_MHF_OPERATE_JOINT] = HandleMsgMhfOperateJoint
|
||||
handlerTable[network.MSG_MHF_INFO_JOINT] = HandleMsgMhfInfoJoint
|
||||
handlerTable[network.MSG_MHF_UPDATE_GUILD_ICON] = HandleMsgMhfUpdateGuildIcon
|
||||
handlerTable[network.MSG_MHF_INFO_FESTA] = handleMsgMhfInfoFesta
|
||||
handlerTable[network.MSG_MHF_ENTRY_FESTA] = handleMsgMhfEntryFesta
|
||||
handlerTable[network.MSG_MHF_CHARGE_FESTA] = handleMsgMhfChargeFesta
|
||||
@@ -207,8 +207,8 @@ func init() {
|
||||
handlerTable[network.MSG_MHF_UPDATE_CAFEPOINT] = handleMsgMhfUpdateCafepoint
|
||||
handlerTable[network.MSG_MHF_CHECK_DAILY_CAFEPOINT] = handleMsgMhfCheckDailyCafepoint
|
||||
handlerTable[network.MSG_MHF_GET_COG_INFO] = handleMsgMhfGetCogInfo
|
||||
handlerTable[network.MSG_MHF_CHECK_MONTHLY_ITEM] = handleMsgMhfCheckMonthlyItem
|
||||
handlerTable[network.MSG_MHF_ACQUIRE_MONTHLY_ITEM] = handleMsgMhfAcquireMonthlyItem
|
||||
handlerTable[network.MSG_MHF_CHECK_MONTHLY_ITEM] = HandleMsgMhfCheckMonthlyItem
|
||||
handlerTable[network.MSG_MHF_ACQUIRE_MONTHLY_ITEM] = HandleMsgMhfAcquireMonthlyItem
|
||||
handlerTable[network.MSG_MHF_CHECK_WEEKLY_STAMP] = handleMsgMhfCheckWeeklyStamp
|
||||
handlerTable[network.MSG_MHF_EXCHANGE_WEEKLY_STAMP] = handleMsgMhfExchangeWeeklyStamp
|
||||
handlerTable[network.MSG_MHF_CREATE_MERCENARY] = handleMsgMhfCreateMercenary
|
||||
@@ -238,8 +238,8 @@ func init() {
|
||||
handlerTable[network.MSG_MHF_GET_MYHOUSE_INFO] = handleMsgMhfGetMyhouseInfo
|
||||
handlerTable[network.MSG_MHF_UPDATE_MYHOUSE_INFO] = handleMsgMhfUpdateMyhouseInfo
|
||||
handlerTable[network.MSG_MHF_GET_WEEKLY_SCHEDULE] = handleMsgMhfGetWeeklySchedule
|
||||
handlerTable[network.MSG_MHF_ENUMERATE_INV_GUILD] = handleMsgMhfEnumerateInvGuild
|
||||
handlerTable[network.MSG_MHF_OPERATION_INV_GUILD] = handleMsgMhfOperationInvGuild
|
||||
handlerTable[network.MSG_MHF_ENUMERATE_INV_GUILD] = HandleMsgMhfEnumerateInvGuild
|
||||
handlerTable[network.MSG_MHF_OPERATION_INV_GUILD] = HandleMsgMhfOperationInvGuild
|
||||
handlerTable[network.MSG_MHF_STAMPCARD_STAMP] = handleMsgMhfStampcardStamp
|
||||
handlerTable[network.MSG_MHF_STAMPCARD_PRIZE] = handleMsgMhfStampcardPrize
|
||||
handlerTable[network.MSG_MHF_UNRESERVE_SRG] = handleMsgMhfUnreserveSrg
|
||||
@@ -247,8 +247,8 @@ func init() {
|
||||
handlerTable[network.MSG_MHF_SAVE_PLATE_DATA] = handleMsgMhfSavePlateData
|
||||
handlerTable[network.MSG_MHF_LOAD_PLATE_BOX] = handleMsgMhfLoadPlateBox
|
||||
handlerTable[network.MSG_MHF_SAVE_PLATE_BOX] = handleMsgMhfSavePlateBox
|
||||
handlerTable[network.MSG_MHF_READ_GUILDCARD] = handleMsgMhfReadGuildcard
|
||||
handlerTable[network.MSG_MHF_UPDATE_GUILDCARD] = handleMsgMhfUpdateGuildcard
|
||||
handlerTable[network.MSG_MHF_READ_GUILDCARD] = HandleMsgMhfReadGuildcard
|
||||
handlerTable[network.MSG_MHF_UPDATE_GUILDCARD] = HandleMsgMhfUpdateGuildcard
|
||||
handlerTable[network.MSG_MHF_READ_BEAT_LEVEL] = handleMsgMhfReadBeatLevel
|
||||
handlerTable[network.MSG_MHF_UPDATE_BEAT_LEVEL] = handleMsgMhfUpdateBeatLevel
|
||||
handlerTable[network.MSG_MHF_READ_BEAT_LEVEL_ALL_RANKING] = handleMsgMhfReadBeatLevelAllRanking
|
||||
@@ -264,38 +264,38 @@ func init() {
|
||||
handlerTable[network.MSG_MHF_GET_EARTH_STATUS] = handleMsgMhfGetEarthStatus
|
||||
handlerTable[network.MSG_MHF_LOAD_PARTNER] = handleMsgMhfLoadPartner
|
||||
handlerTable[network.MSG_MHF_SAVE_PARTNER] = handleMsgMhfSavePartner
|
||||
handlerTable[network.MSG_MHF_GET_GUILD_MISSION_LIST] = handleMsgMhfGetGuildMissionList
|
||||
handlerTable[network.MSG_MHF_GET_GUILD_MISSION_RECORD] = handleMsgMhfGetGuildMissionRecord
|
||||
handlerTable[network.MSG_MHF_ADD_GUILD_MISSION_COUNT] = handleMsgMhfAddGuildMissionCount
|
||||
handlerTable[network.MSG_MHF_SET_GUILD_MISSION_TARGET] = handleMsgMhfSetGuildMissionTarget
|
||||
handlerTable[network.MSG_MHF_CANCEL_GUILD_MISSION_TARGET] = handleMsgMhfCancelGuildMissionTarget
|
||||
handlerTable[network.MSG_MHF_GET_GUILD_MISSION_LIST] = HandleMsgMhfGetGuildMissionList
|
||||
handlerTable[network.MSG_MHF_GET_GUILD_MISSION_RECORD] = HandleMsgMhfGetGuildMissionRecord
|
||||
handlerTable[network.MSG_MHF_ADD_GUILD_MISSION_COUNT] = HandleMsgMhfAddGuildMissionCount
|
||||
handlerTable[network.MSG_MHF_SET_GUILD_MISSION_TARGET] = HandleMsgMhfSetGuildMissionTarget
|
||||
handlerTable[network.MSG_MHF_CANCEL_GUILD_MISSION_TARGET] = HandleMsgMhfCancelGuildMissionTarget
|
||||
handlerTable[network.MSG_MHF_LOAD_OTOMO_AIROU] = handleMsgMhfLoadOtomoAirou
|
||||
handlerTable[network.MSG_MHF_SAVE_OTOMO_AIROU] = handleMsgMhfSaveOtomoAirou
|
||||
handlerTable[network.MSG_MHF_ENUMERATE_GUILD_TRESURE] = handleMsgMhfEnumerateGuildTresure
|
||||
handlerTable[network.MSG_MHF_ENUMERATE_GUILD_TRESURE] = HandleMsgMhfEnumerateGuildTresure
|
||||
handlerTable[network.MSG_MHF_ENUMERATE_AIROULIST] = handleMsgMhfEnumerateAiroulist
|
||||
handlerTable[network.MSG_MHF_REGIST_GUILD_TRESURE] = handleMsgMhfRegistGuildTresure
|
||||
handlerTable[network.MSG_MHF_ACQUIRE_GUILD_TRESURE] = handleMsgMhfAcquireGuildTresure
|
||||
handlerTable[network.MSG_MHF_OPERATE_GUILD_TRESURE_REPORT] = handleMsgMhfOperateGuildTresureReport
|
||||
handlerTable[network.MSG_MHF_GET_GUILD_TRESURE_SOUVENIR] = handleMsgMhfGetGuildTresureSouvenir
|
||||
handlerTable[network.MSG_MHF_ACQUIRE_GUILD_TRESURE_SOUVENIR] = handleMsgMhfAcquireGuildTresureSouvenir
|
||||
handlerTable[network.MSG_MHF_REGIST_GUILD_TRESURE] = HandleMsgMhfRegistGuildTresure
|
||||
handlerTable[network.MSG_MHF_ACQUIRE_GUILD_TRESURE] = HandleMsgMhfAcquireGuildTresure
|
||||
handlerTable[network.MSG_MHF_OPERATE_GUILD_TRESURE_REPORT] = HandleMsgMhfOperateGuildTresureReport
|
||||
handlerTable[network.MSG_MHF_GET_GUILD_TRESURE_SOUVENIR] = HandleMsgMhfGetGuildTresureSouvenir
|
||||
handlerTable[network.MSG_MHF_ACQUIRE_GUILD_TRESURE_SOUVENIR] = HandleMsgMhfAcquireGuildTresureSouvenir
|
||||
handlerTable[network.MSG_MHF_ENUMERATE_FESTA_INTERMEDIATE_PRIZE] = handleMsgMhfEnumerateFestaIntermediatePrize
|
||||
handlerTable[network.MSG_MHF_ACQUIRE_FESTA_INTERMEDIATE_PRIZE] = handleMsgMhfAcquireFestaIntermediatePrize
|
||||
handlerTable[network.MSG_MHF_LOAD_DECO_MYSET] = handleMsgMhfLoadDecoMyset
|
||||
handlerTable[network.MSG_MHF_SAVE_DECO_MYSET] = handleMsgMhfSaveDecoMyset
|
||||
handlerTable[network.MSG_MHF_reserve10F] = handleMsgMhfReserve10F
|
||||
handlerTable[network.MSG_MHF_LOAD_GUILD_COOKING] = handleMsgMhfLoadGuildCooking
|
||||
handlerTable[network.MSG_MHF_REGIST_GUILD_COOKING] = handleMsgMhfRegistGuildCooking
|
||||
handlerTable[network.MSG_MHF_LOAD_GUILD_ADVENTURE] = handleMsgMhfLoadGuildAdventure
|
||||
handlerTable[network.MSG_MHF_REGIST_GUILD_ADVENTURE] = handleMsgMhfRegistGuildAdventure
|
||||
handlerTable[network.MSG_MHF_ACQUIRE_GUILD_ADVENTURE] = handleMsgMhfAcquireGuildAdventure
|
||||
handlerTable[network.MSG_MHF_CHARGE_GUILD_ADVENTURE] = handleMsgMhfChargeGuildAdventure
|
||||
handlerTable[network.MSG_MHF_LOAD_GUILD_COOKING] = HandleMsgMhfLoadGuildCooking
|
||||
handlerTable[network.MSG_MHF_REGIST_GUILD_COOKING] = HandleMsgMhfRegistGuildCooking
|
||||
handlerTable[network.MSG_MHF_LOAD_GUILD_ADVENTURE] = HandleMsgMhfLoadGuildAdventure
|
||||
handlerTable[network.MSG_MHF_REGIST_GUILD_ADVENTURE] = HandleMsgMhfRegistGuildAdventure
|
||||
handlerTable[network.MSG_MHF_ACQUIRE_GUILD_ADVENTURE] = HandleMsgMhfAcquireGuildAdventure
|
||||
handlerTable[network.MSG_MHF_CHARGE_GUILD_ADVENTURE] = HandleMsgMhfChargeGuildAdventure
|
||||
handlerTable[network.MSG_MHF_LOAD_LEGEND_DISPATCH] = handleMsgMhfLoadLegendDispatch
|
||||
handlerTable[network.MSG_MHF_LOAD_HUNTER_NAVI] = handleMsgMhfLoadHunterNavi
|
||||
handlerTable[network.MSG_MHF_SAVE_HUNTER_NAVI] = handleMsgMhfSaveHunterNavi
|
||||
handlerTable[network.MSG_MHF_REGIST_SPABI_TIME] = handleMsgMhfRegistSpabiTime
|
||||
handlerTable[network.MSG_MHF_GET_GUILD_WEEKLY_BONUS_MASTER] = handleMsgMhfGetGuildWeeklyBonusMaster
|
||||
handlerTable[network.MSG_MHF_GET_GUILD_WEEKLY_BONUS_ACTIVE_COUNT] = handleMsgMhfGetGuildWeeklyBonusActiveCount
|
||||
handlerTable[network.MSG_MHF_ADD_GUILD_WEEKLY_BONUS_EXCEPTIONAL_USER] = handleMsgMhfAddGuildWeeklyBonusExceptionalUser
|
||||
handlerTable[network.MSG_MHF_GET_GUILD_WEEKLY_BONUS_MASTER] = HandleMsgMhfGetGuildWeeklyBonusMaster
|
||||
handlerTable[network.MSG_MHF_GET_GUILD_WEEKLY_BONUS_ACTIVE_COUNT] = HandleMsgMhfGetGuildWeeklyBonusActiveCount
|
||||
handlerTable[network.MSG_MHF_ADD_GUILD_WEEKLY_BONUS_EXCEPTIONAL_USER] = HandleMsgMhfAddGuildWeeklyBonusExceptionalUser
|
||||
handlerTable[network.MSG_MHF_GET_TOWER_INFO] = handleMsgMhfGetTowerInfo
|
||||
handlerTable[network.MSG_MHF_POST_TOWER_INFO] = handleMsgMhfPostTowerInfo
|
||||
handlerTable[network.MSG_MHF_GET_GEM_INFO] = handleMsgMhfGetGemInfo
|
||||
@@ -328,7 +328,7 @@ func init() {
|
||||
handlerTable[network.MSG_MHF_GET_TINY_BIN] = handleMsgMhfGetTinyBin
|
||||
handlerTable[network.MSG_MHF_POST_TINY_BIN] = handleMsgMhfPostTinyBin
|
||||
handlerTable[network.MSG_MHF_GET_SENYU_DAILY_COUNT] = handleMsgMhfGetSenyuDailyCount
|
||||
handlerTable[network.MSG_MHF_GET_GUILD_TARGET_MEMBER_NUM] = handleMsgMhfGetGuildTargetMemberNum
|
||||
handlerTable[network.MSG_MHF_GET_GUILD_TARGET_MEMBER_NUM] = HandleMsgMhfGetGuildTargetMemberNum
|
||||
handlerTable[network.MSG_MHF_GET_BOOST_RIGHT] = handleMsgMhfGetBoostRight
|
||||
handlerTable[network.MSG_MHF_START_BOOST_TIME] = handleMsgMhfStartBoostTime
|
||||
handlerTable[network.MSG_MHF_POST_BOOST_TIME_QUEST_RETURN] = handleMsgMhfPostBoostTimeQuestReturn
|
||||
@@ -341,19 +341,19 @@ func init() {
|
||||
handlerTable[network.MSG_MHF_POST_RYOUDAMA] = handleMsgMhfPostRyoudama
|
||||
handlerTable[network.MSG_MHF_GET_TENROUIRAI] = handleMsgMhfGetTenrouirai
|
||||
handlerTable[network.MSG_MHF_POST_TENROUIRAI] = handleMsgMhfPostTenrouirai
|
||||
handlerTable[network.MSG_MHF_POST_GUILD_SCOUT] = handleMsgMhfPostGuildScout
|
||||
handlerTable[network.MSG_MHF_CANCEL_GUILD_SCOUT] = handleMsgMhfCancelGuildScout
|
||||
handlerTable[network.MSG_MHF_ANSWER_GUILD_SCOUT] = handleMsgMhfAnswerGuildScout
|
||||
handlerTable[network.MSG_MHF_GET_GUILD_SCOUT_LIST] = handleMsgMhfGetGuildScoutList
|
||||
handlerTable[network.MSG_MHF_GET_GUILD_MANAGE_RIGHT] = handleMsgMhfGetGuildManageRight
|
||||
handlerTable[network.MSG_MHF_SET_GUILD_MANAGE_RIGHT] = handleMsgMhfSetGuildManageRight
|
||||
handlerTable[network.MSG_MHF_POST_GUILD_SCOUT] = HandleMsgMhfPostGuildScout
|
||||
handlerTable[network.MSG_MHF_CANCEL_GUILD_SCOUT] = HandleMsgMhfCancelGuildScout
|
||||
handlerTable[network.MSG_MHF_ANSWER_GUILD_SCOUT] = HandleMsgMhfAnswerGuildScout
|
||||
handlerTable[network.MSG_MHF_GET_GUILD_SCOUT_LIST] = HandleMsgMhfGetGuildScoutList
|
||||
handlerTable[network.MSG_MHF_GET_GUILD_MANAGE_RIGHT] = HandleMsgMhfGetGuildManageRight
|
||||
handlerTable[network.MSG_MHF_SET_GUILD_MANAGE_RIGHT] = HandleMsgMhfSetGuildManageRight
|
||||
handlerTable[network.MSG_MHF_PLAY_NORMAL_GACHA] = handleMsgMhfPlayNormalGacha
|
||||
handlerTable[network.MSG_MHF_GET_DAILY_MISSION_MASTER] = handleMsgMhfGetDailyMissionMaster
|
||||
handlerTable[network.MSG_MHF_GET_DAILY_MISSION_PERSONAL] = handleMsgMhfGetDailyMissionPersonal
|
||||
handlerTable[network.MSG_MHF_SET_DAILY_MISSION_PERSONAL] = handleMsgMhfSetDailyMissionPersonal
|
||||
handlerTable[network.MSG_MHF_GET_GACHA_PLAY_HISTORY] = handleMsgMhfGetGachaPlayHistory
|
||||
handlerTable[network.MSG_MHF_GET_REJECT_GUILD_SCOUT] = handleMsgMhfGetRejectGuildScout
|
||||
handlerTable[network.MSG_MHF_SET_REJECT_GUILD_SCOUT] = handleMsgMhfSetRejectGuildScout
|
||||
handlerTable[network.MSG_MHF_GET_REJECT_GUILD_SCOUT] = HandleMsgMhfGetRejectGuildScout
|
||||
handlerTable[network.MSG_MHF_SET_REJECT_GUILD_SCOUT] = HandleMsgMhfSetRejectGuildScout
|
||||
handlerTable[network.MSG_MHF_GET_CA_ACHIEVEMENT_HIST] = handleMsgMhfGetCaAchievementHist
|
||||
handlerTable[network.MSG_MHF_SET_CA_ACHIEVEMENT_HIST] = handleMsgMhfSetCaAchievementHist
|
||||
handlerTable[network.MSG_MHF_GET_KEEP_LOGIN_BOOST_STATUS] = handleMsgMhfGetKeepLoginBoostStatus
|
||||
@@ -378,8 +378,8 @@ func init() {
|
||||
handlerTable[network.MSG_MHF_GET_UD_RANKING] = handleMsgMhfGetUdRanking
|
||||
handlerTable[network.MSG_MHF_GET_UD_MY_RANKING] = handleMsgMhfGetUdMyRanking
|
||||
handlerTable[network.MSG_MHF_ACQUIRE_MONTHLY_REWARD] = handleMsgMhfAcquireMonthlyReward
|
||||
handlerTable[network.MSG_MHF_GET_UD_GUILD_MAP_INFO] = handleMsgMhfGetUdGuildMapInfo
|
||||
handlerTable[network.MSG_MHF_GENERATE_UD_GUILD_MAP] = handleMsgMhfGenerateUdGuildMap
|
||||
handlerTable[network.MSG_MHF_GET_UD_GUILD_MAP_INFO] = HandleMsgMhfGetUdGuildMapInfo
|
||||
handlerTable[network.MSG_MHF_GENERATE_UD_GUILD_MAP] = HandleMsgMhfGenerateUdGuildMap
|
||||
handlerTable[network.MSG_MHF_GET_UD_TACTICS_POINT] = handleMsgMhfGetUdTacticsPoint
|
||||
handlerTable[network.MSG_MHF_ADD_UD_TACTICS_POINT] = handleMsgMhfAddUdTacticsPoint
|
||||
handlerTable[network.MSG_MHF_GET_UD_TACTICS_RANKING] = handleMsgMhfGetUdTacticsRanking
|
||||
@@ -396,7 +396,7 @@ func init() {
|
||||
handlerTable[network.MSG_MHF_SEX_CHANGER] = handleMsgMhfSexChanger
|
||||
handlerTable[network.MSG_MHF_GET_LOBBY_CROWD] = handleMsgMhfGetLobbyCrowd
|
||||
handlerTable[network.MSG_SYS_reserve180] = handleMsgSysReserve180
|
||||
handlerTable[network.MSG_MHF_GUILD_HUNTDATA] = handleMsgMhfGuildHuntdata
|
||||
handlerTable[network.MSG_MHF_GUILD_HUNTDATA] = HandleMsgMhfGuildHuntdata
|
||||
handlerTable[network.MSG_MHF_ADD_KOURYOU_POINT] = handleMsgMhfAddKouryouPoint
|
||||
handlerTable[network.MSG_MHF_GET_KOURYOU_POINT] = handleMsgMhfGetKouryouPoint
|
||||
handlerTable[network.MSG_MHF_EXCHANGE_KOURYOU_POINT] = handleMsgMhfExchangeKouryouPoint
|
||||
@@ -427,12 +427,12 @@ func init() {
|
||||
handlerTable[network.MSG_MHF_LOAD_MEZFES_DATA] = handleMsgMhfLoadMezfesData
|
||||
handlerTable[network.MSG_SYS_reserve19E] = handleMsgSysReserve19E
|
||||
handlerTable[network.MSG_SYS_reserve19F] = handleMsgSysReserve19F
|
||||
handlerTable[network.MSG_MHF_UPDATE_FORCE_GUILD_RANK] = handleMsgMhfUpdateForceGuildRank
|
||||
handlerTable[network.MSG_MHF_UPDATE_FORCE_GUILD_RANK] = HandleMsgMhfUpdateForceGuildRank
|
||||
handlerTable[network.MSG_MHF_RESET_TITLE] = handleMsgMhfResetTitle
|
||||
handlerTable[network.MSG_MHF_ENUMERATE_GUILD_MESSAGE_BOARD] = handleMsgMhfEnumerateGuildMessageBoard
|
||||
handlerTable[network.MSG_MHF_UPDATE_GUILD_MESSAGE_BOARD] = handleMsgMhfUpdateGuildMessageBoard
|
||||
handlerTable[network.MSG_MHF_ENUMERATE_GUILD_MESSAGE_BOARD] = HandleMsgMhfEnumerateGuildMessageBoard
|
||||
handlerTable[network.MSG_MHF_UPDATE_GUILD_MESSAGE_BOARD] = HandleMsgMhfUpdateGuildMessageBoard
|
||||
handlerTable[network.MSG_SYS_reserve1A4] = handleMsgSysReserve1A4
|
||||
handlerTable[network.MSG_MHF_REGIST_GUILD_ADVENTURE_DIVA] = handleMsgMhfRegistGuildAdventureDiva
|
||||
handlerTable[network.MSG_MHF_REGIST_GUILD_ADVENTURE_DIVA] = HandleMsgMhfRegistGuildAdventureDiva
|
||||
handlerTable[network.MSG_SYS_reserve1A6] = handleMsgSysReserve1A6
|
||||
handlerTable[network.MSG_SYS_reserve1A7] = handleMsgSysReserve1A7
|
||||
handlerTable[network.MSG_SYS_reserve1A8] = handleMsgSysReserve1A8
|
||||
@@ -1,5 +1,9 @@
|
||||
package channelserver
|
||||
|
||||
import (
|
||||
"erupe-ce/config"
|
||||
)
|
||||
|
||||
type i18n struct {
|
||||
language string
|
||||
cafe struct {
|
||||
@@ -101,9 +105,9 @@ type i18n struct {
|
||||
}
|
||||
}
|
||||
|
||||
func getLangStrings(server *Server) i18n {
|
||||
func getLangStrings(server *ChannelServer) i18n {
|
||||
var i i18n
|
||||
switch server.erupeConfig.Language {
|
||||
switch config.GetConfig().Language {
|
||||
case "jp":
|
||||
i.language = "日本語"
|
||||
i.cafe.reset = "%d/%dにリセット"
|
||||
|
||||
@@ -13,7 +13,7 @@ type Raviente struct {
|
||||
support []uint32
|
||||
}
|
||||
|
||||
func (server *Server) resetRaviente() {
|
||||
func (server *ChannelServer) resetRaviente() {
|
||||
for _, semaphore := range server.semaphore {
|
||||
if strings.HasPrefix(semaphore.name, "hs_l0") {
|
||||
return
|
||||
@@ -26,7 +26,7 @@ func (server *Server) resetRaviente() {
|
||||
server.raviente.support = make([]uint32, 30)
|
||||
}
|
||||
|
||||
func (server *Server) GetRaviMultiplier() float64 {
|
||||
func (server *ChannelServer) GetRaviMultiplier() float64 {
|
||||
raviSema := server.getRaviSemaphore()
|
||||
if raviSema != nil {
|
||||
var minPlayers int
|
||||
@@ -43,7 +43,7 @@ func (server *Server) GetRaviMultiplier() float64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (server *Server) UpdateRavi(semaID uint32, index uint8, value uint32, update bool) (uint32, uint32) {
|
||||
func (server *ChannelServer) UpdateRavi(semaID uint32, index uint8, value uint32, update bool) (uint32, uint32) {
|
||||
var prev uint32
|
||||
var dest *[]uint32
|
||||
switch semaID {
|
||||
|
||||
@@ -3,29 +3,29 @@ package channelserver
|
||||
import (
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
_config "erupe-ce/config"
|
||||
"erupe-ce/config"
|
||||
"erupe-ce/network"
|
||||
"erupe-ce/network/mhfpacket"
|
||||
"erupe-ce/utils/byteframe"
|
||||
"erupe-ce/utils/db"
|
||||
"erupe-ce/utils/gametime"
|
||||
"erupe-ce/utils/logger"
|
||||
"erupe-ce/utils/mhfcourse"
|
||||
"erupe-ce/utils/stringstack"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"erupe-ce/network"
|
||||
"erupe-ce/network/mhfpacket"
|
||||
"erupe-ce/utils/byteframe"
|
||||
"erupe-ce/utils/logger"
|
||||
"erupe-ce/utils/stringstack"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// Session holds state for the channel server connection.
|
||||
type Session struct {
|
||||
sync.Mutex
|
||||
logger logger.Logger
|
||||
server *Server
|
||||
Logger logger.Logger
|
||||
Server *ChannelServer
|
||||
rawConn net.Conn
|
||||
cryptConn *network.CryptConn
|
||||
sendPackets chan mhfpacket.MHFPacket
|
||||
@@ -37,7 +37,7 @@ type Session struct {
|
||||
reservationStage *Stage // Required for the stateful MsgSysUnreserveStage packet.
|
||||
stagePass string // Temporary storage
|
||||
prevGuildID uint32 // Stores the last GuildID used in InfoGuild
|
||||
charID uint32
|
||||
CharID uint32
|
||||
logKey []byte
|
||||
sessionStart int64
|
||||
courses []mhfcourse.Course
|
||||
@@ -66,10 +66,10 @@ type Session struct {
|
||||
}
|
||||
|
||||
// NewSession creates a new Session type.
|
||||
func NewSession(server *Server, conn net.Conn) *Session {
|
||||
func NewSession(server *ChannelServer, conn net.Conn) *Session {
|
||||
s := &Session{
|
||||
logger: server.logger.Named(conn.RemoteAddr().String()),
|
||||
server: server,
|
||||
Logger: server.logger.Named(conn.RemoteAddr().String()),
|
||||
Server: server,
|
||||
rawConn: conn,
|
||||
cryptConn: network.NewCryptConn(conn),
|
||||
sendPackets: make(chan mhfpacket.MHFPacket, 20),
|
||||
@@ -85,7 +85,7 @@ func NewSession(server *Server, conn net.Conn) *Session {
|
||||
|
||||
// Start starts the session packet send and recv loop(s).
|
||||
func (s *Session) Start() {
|
||||
s.logger.Debug("New connection", zap.String("RemoteAddr", s.rawConn.RemoteAddr().String()))
|
||||
s.Logger.Debug("New 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()
|
||||
@@ -97,7 +97,7 @@ func (s *Session) QueueSendMHF(pkt mhfpacket.MHFPacket) {
|
||||
select {
|
||||
case s.sendPackets <- pkt:
|
||||
default:
|
||||
s.logger.Warn("Packet queue too full, dropping!")
|
||||
s.Logger.Warn("Packet queue too full, dropping!")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,11 +123,11 @@ func (s *Session) sendLoop() {
|
||||
if len(buffer) > 0 {
|
||||
err := s.cryptConn.SendPacket(buffer)
|
||||
if err != nil {
|
||||
s.logger.Warn("Failed to send packet")
|
||||
s.Logger.Warn("Failed to send packet")
|
||||
}
|
||||
buffer = buffer[:0]
|
||||
}
|
||||
time.Sleep(time.Duration(_config.ErupeConfig.LoopDelay) * time.Millisecond)
|
||||
time.Sleep(time.Duration(config.GetConfig().LoopDelay) * time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,16 +143,16 @@ func (s *Session) recvLoop() {
|
||||
}
|
||||
pkt, err := s.cryptConn.ReadPacket()
|
||||
if err == io.EOF {
|
||||
s.logger.Info(fmt.Sprintf("[%s] Disconnected", s.Name))
|
||||
s.Logger.Info(fmt.Sprintf("[%s] Disconnected", s.Name))
|
||||
logoutPlayer(s)
|
||||
return
|
||||
} else if err != nil {
|
||||
s.logger.Warn("Error on ReadPacket, exiting recv loop", zap.Error(err))
|
||||
s.Logger.Warn("Error on ReadPacket, exiting recv loop", zap.Error(err))
|
||||
logoutPlayer(s)
|
||||
return
|
||||
}
|
||||
s.handlePacketGroup(pkt)
|
||||
time.Sleep(time.Duration(_config.ErupeConfig.LoopDelay) * time.Millisecond)
|
||||
time.Sleep(time.Duration(config.GetConfig().LoopDelay) * time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,9 +220,9 @@ func ignored(opcode network.PacketID) bool {
|
||||
}
|
||||
|
||||
func (s *Session) logMessage(opcode uint16, data []byte, sender string, recipient string) {
|
||||
if sender == "Server" && !s.server.erupeConfig.DebugOptions.LogOutboundMessages {
|
||||
if sender == "Server" && !config.GetConfig().DebugOptions.LogOutboundMessages {
|
||||
return
|
||||
} else if sender != "Server" && !s.server.erupeConfig.DebugOptions.LogInboundMessages {
|
||||
} else if sender != "Server" && !config.GetConfig().DebugOptions.LogInboundMessages {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -240,8 +240,8 @@ func (s *Session) logMessage(opcode uint16, data []byte, sender string, recipien
|
||||
fmt.Printf("[%s] -> [%s]\n", sender, recipient)
|
||||
}
|
||||
fmt.Printf("Opcode: (Dec: %d Hex: 0x%04X Name: %s) \n", opcode, opcode, opcodePID)
|
||||
if s.server.erupeConfig.DebugOptions.LogMessageData {
|
||||
if len(data) <= s.server.erupeConfig.DebugOptions.MaxHexdumpLength {
|
||||
if config.GetConfig().DebugOptions.LogMessageData {
|
||||
if len(data) <= config.GetConfig().DebugOptions.MaxHexdumpLength {
|
||||
fmt.Printf("Data [%d bytes]:\n%s\n", len(data), hex.Dump(data))
|
||||
} else {
|
||||
fmt.Printf("Data [%d bytes]: (Too long!)\n\n", len(data))
|
||||
@@ -254,23 +254,23 @@ func (s *Session) logMessage(opcode uint16, data []byte, sender string, recipien
|
||||
func (s *Session) SetObjectID() {
|
||||
for i := uint16(1); i < 127; i++ {
|
||||
exists := false
|
||||
for _, j := range s.server.objectIDs {
|
||||
for _, j := range s.Server.objectIDs {
|
||||
if i == j {
|
||||
exists = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !exists {
|
||||
s.server.objectIDs[s] = i
|
||||
s.Server.objectIDs[s] = i
|
||||
return
|
||||
}
|
||||
}
|
||||
s.server.objectIDs[s] = 0
|
||||
s.Server.objectIDs[s] = 0
|
||||
}
|
||||
|
||||
func (s *Session) NextObjectID() uint32 {
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint16(s.server.objectIDs[s])
|
||||
bf.WriteUint16(s.Server.objectIDs[s])
|
||||
s.objectIndex++
|
||||
bf.WriteUint16(s.objectIndex)
|
||||
bf.Seek(0, 0)
|
||||
@@ -287,7 +287,11 @@ func (s *Session) GetSemaphoreID() uint32 {
|
||||
|
||||
func (s *Session) isOp() bool {
|
||||
var op bool
|
||||
err := s.server.db.QueryRow(`SELECT op FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)`, s.charID).Scan(&op)
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
s.Logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
err = database.QueryRow(`SELECT op FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)`, s.CharID).Scan(&op)
|
||||
if err == nil && op {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package discordbot
|
||||
|
||||
import (
|
||||
_config "erupe-ce/config"
|
||||
"erupe-ce/config"
|
||||
"erupe-ce/utils/logger"
|
||||
"regexp"
|
||||
|
||||
@@ -38,18 +38,14 @@ var Commands = []*discordgo.ApplicationCommand{
|
||||
|
||||
type DiscordBot struct {
|
||||
Session *discordgo.Session
|
||||
config *_config.Config
|
||||
config *config.Config
|
||||
logger logger.Logger
|
||||
MainGuild *discordgo.Guild
|
||||
RelayChannel *discordgo.Channel
|
||||
}
|
||||
|
||||
type Options struct {
|
||||
Config *_config.Config
|
||||
}
|
||||
|
||||
func NewDiscordBot(options Options) (discordBot *DiscordBot, err error) {
|
||||
session, err := discordgo.New("Bot " + options.Config.Discord.BotToken)
|
||||
func NewDiscordBot() (discordBot *DiscordBot, err error) {
|
||||
session, err := discordgo.New("Bot " + config.GetConfig().Discord.BotToken)
|
||||
discordLogger := logger.Get().Named("discord")
|
||||
if err != nil {
|
||||
discordLogger.Fatal("Discord failed", zap.Error(err))
|
||||
@@ -58,8 +54,8 @@ func NewDiscordBot(options Options) (discordBot *DiscordBot, err error) {
|
||||
|
||||
var relayChannel *discordgo.Channel
|
||||
|
||||
if options.Config.Discord.RelayChannel.Enabled {
|
||||
relayChannel, err = session.Channel(options.Config.Discord.RelayChannel.RelayChannelID)
|
||||
if config.GetConfig().Discord.RelayChannel.Enabled {
|
||||
relayChannel, err = session.Channel(config.GetConfig().Discord.RelayChannel.RelayChannelID)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
@@ -68,7 +64,7 @@ func NewDiscordBot(options Options) (discordBot *DiscordBot, err error) {
|
||||
}
|
||||
|
||||
discordBot = &DiscordBot{
|
||||
config: options.Config,
|
||||
config: config.GetConfig(),
|
||||
logger: discordLogger,
|
||||
Session: session,
|
||||
RelayChannel: relayChannel,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package entranceserver
|
||||
package entrance
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
@@ -8,45 +8,33 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
_config "erupe-ce/config"
|
||||
"erupe-ce/config"
|
||||
"erupe-ce/network"
|
||||
"erupe-ce/utils/logger"
|
||||
|
||||
"github.com/jmoiron/sqlx"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// Server is a MHF entrance server.
|
||||
type Server struct {
|
||||
// EntranceServer is a MHF entrance server.
|
||||
type EntranceServer struct {
|
||||
sync.Mutex
|
||||
logger logger.Logger
|
||||
erupeConfig *_config.Config
|
||||
db *sqlx.DB
|
||||
listener net.Listener
|
||||
isShuttingDown bool
|
||||
}
|
||||
|
||||
// Config struct allows configuring the server.
|
||||
type Config struct {
|
||||
Logger logger.Logger
|
||||
DB *sqlx.DB
|
||||
ErupeConfig *_config.Config
|
||||
}
|
||||
|
||||
// NewServer creates a new Server type.
|
||||
func NewServer(config *Config) *Server {
|
||||
server := &Server{
|
||||
logger: config.Logger,
|
||||
erupeConfig: config.ErupeConfig,
|
||||
db: config.DB,
|
||||
func NewServer() *EntranceServer {
|
||||
server := &EntranceServer{
|
||||
logger: logger.Get().Named("entrance"),
|
||||
}
|
||||
return server
|
||||
}
|
||||
|
||||
// Start starts the server in a new goroutine.
|
||||
func (server *Server) Start() error {
|
||||
func (server *EntranceServer) Start() error {
|
||||
|
||||
l, err := net.Listen("tcp", fmt.Sprintf(":%d", server.erupeConfig.Entrance.Port))
|
||||
l, err := net.Listen("tcp", fmt.Sprintf(":%d", config.GetConfig().Entrance.Port))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -59,7 +47,7 @@ func (server *Server) Start() error {
|
||||
}
|
||||
|
||||
// Shutdown exits the server gracefully.
|
||||
func (server *Server) Shutdown() {
|
||||
func (server *EntranceServer) Shutdown() {
|
||||
server.logger.Debug("Shutting down...")
|
||||
|
||||
server.Lock()
|
||||
@@ -71,7 +59,7 @@ func (server *Server) Shutdown() {
|
||||
}
|
||||
|
||||
// acceptClients handles accepting new clients in a loop.
|
||||
func (server *Server) acceptClients() {
|
||||
func (server *EntranceServer) acceptClients() {
|
||||
for {
|
||||
conn, err := server.listener.Accept()
|
||||
if err != nil {
|
||||
@@ -92,7 +80,7 @@ func (server *Server) acceptClients() {
|
||||
}
|
||||
}
|
||||
|
||||
func (server *Server) handleEntranceServerConnection(conn net.Conn) {
|
||||
func (server *EntranceServer) handleEntranceServerConnection(conn net.Conn) {
|
||||
defer conn.Close()
|
||||
// Client initalizes the connection with a one-time buffer of 8 NULL bytes.
|
||||
nullInit := make([]byte, 8)
|
||||
@@ -113,7 +101,7 @@ func (server *Server) handleEntranceServerConnection(conn net.Conn) {
|
||||
return
|
||||
}
|
||||
|
||||
if server.erupeConfig.DebugOptions.LogInboundMessages {
|
||||
if config.GetConfig().DebugOptions.LogInboundMessages {
|
||||
fmt.Printf("[Client] -> [Server]\nData [%d bytes]:\n%s\n", len(pkt), hex.Dump(pkt))
|
||||
}
|
||||
|
||||
@@ -121,7 +109,7 @@ func (server *Server) handleEntranceServerConnection(conn net.Conn) {
|
||||
if strings.Split(conn.RemoteAddr().String(), ":")[0] == "127.0.0.1" {
|
||||
local = true
|
||||
}
|
||||
data := makeSv2Resp(server.erupeConfig, server, local)
|
||||
data := makeSv2Resp(server, local)
|
||||
if len(pkt) > 5 {
|
||||
data = append(data, makeUsrResp(pkt, server)...)
|
||||
}
|
||||
@@ -1,39 +1,41 @@
|
||||
package entranceserver
|
||||
package entrance
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
_config "erupe-ce/config"
|
||||
"erupe-ce/config"
|
||||
"erupe-ce/network/crypto/bin8"
|
||||
"erupe-ce/utils/byteframe"
|
||||
"erupe-ce/utils/db"
|
||||
"erupe-ce/utils/gametime"
|
||||
|
||||
"erupe-ce/utils/stringsupport"
|
||||
"fmt"
|
||||
"net"
|
||||
)
|
||||
|
||||
func encodeServerInfo(config *_config.Config, server *Server, local bool) []byte {
|
||||
serverInfos := config.Entrance.Entries
|
||||
func encodeServerInfo(server *EntranceServer, local bool) []byte {
|
||||
serverInfos := config.GetConfig().Entrance.Entries
|
||||
bf := byteframe.NewByteFrame()
|
||||
|
||||
for serverIdx, si := range serverInfos {
|
||||
// Prevent MezFes Worlds displaying on Z1
|
||||
if config.ClientID <= _config.Z1 {
|
||||
if config.GetConfig().ClientID <= config.Z1 {
|
||||
if si.Type == 6 {
|
||||
continue
|
||||
}
|
||||
}
|
||||
if config.ClientID <= _config.G6 {
|
||||
if config.GetConfig().ClientID <= config.G6 {
|
||||
if si.Type == 5 {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if si.IP == "" {
|
||||
si.IP = config.Host
|
||||
si.IP = config.GetConfig().Host
|
||||
}
|
||||
if local {
|
||||
bf.WriteUint32(0x0100007F) // 127.0.0.1
|
||||
bf.WriteUint32(binary.LittleEndian.Uint32(net.ParseIP("127.0.0.1").To4()))
|
||||
} else {
|
||||
bf.WriteUint32(binary.LittleEndian.Uint32(net.ParseIP(si.IP).To4()))
|
||||
}
|
||||
@@ -42,36 +44,40 @@ func encodeServerInfo(config *_config.Config, server *Server, local bool) []byte
|
||||
bf.WriteUint16(uint16(len(si.Channels)))
|
||||
bf.WriteUint8(si.Type)
|
||||
bf.WriteUint8(uint8(((gametime.TimeAdjusted().Unix() / 86400) + int64(serverIdx)) % 3))
|
||||
if server.erupeConfig.ClientID >= _config.G1 {
|
||||
if config.GetConfig().ClientID >= config.G1 {
|
||||
bf.WriteUint8(si.Recommended)
|
||||
}
|
||||
|
||||
fullName := append(append(stringsupport.UTF8ToSJIS(si.Name), []byte{0x00}...), stringsupport.UTF8ToSJIS(si.Description)...)
|
||||
if server.erupeConfig.ClientID >= _config.G1 && server.erupeConfig.ClientID <= _config.G5 {
|
||||
if config.GetConfig().ClientID >= config.G1 && config.GetConfig().ClientID <= config.G5 {
|
||||
bf.WriteUint8(uint8(len(fullName)))
|
||||
bf.WriteBytes(fullName)
|
||||
} else {
|
||||
if server.erupeConfig.ClientID >= _config.G51 {
|
||||
if config.GetConfig().ClientID >= config.G51 {
|
||||
bf.WriteUint8(0) // Ignored
|
||||
}
|
||||
bf.WriteBytes(stringsupport.PaddedString(string(fullName), 65, false))
|
||||
}
|
||||
|
||||
if server.erupeConfig.ClientID >= _config.GG {
|
||||
if config.GetConfig().ClientID >= config.GG {
|
||||
bf.WriteUint32(si.AllowedClientFlags)
|
||||
}
|
||||
|
||||
for channelIdx, ci := range si.Channels {
|
||||
sid := (serverIdx<<8 | 4096) + (channelIdx | 16)
|
||||
if _config.ErupeConfig.DebugOptions.ProxyPort != 0 {
|
||||
bf.WriteUint16(_config.ErupeConfig.DebugOptions.ProxyPort)
|
||||
if config.GetConfig().DebugOptions.ProxyPort != 0 {
|
||||
bf.WriteUint16(config.GetConfig().DebugOptions.ProxyPort)
|
||||
} else {
|
||||
bf.WriteUint16(ci.Port)
|
||||
}
|
||||
bf.WriteUint16(uint16(channelIdx | 16))
|
||||
bf.WriteUint16(ci.MaxPlayers)
|
||||
var currentPlayers uint16
|
||||
server.db.QueryRow("SELECT current_players FROM servers WHERE server_id=$1", sid).Scan(¤tPlayers)
|
||||
database, err := db.GetDB() // Capture both return values
|
||||
if err != nil {
|
||||
server.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
database.QueryRow("SELECT current_players FROM servers WHERE server_id=$1", sid).Scan(¤tPlayers)
|
||||
bf.WriteUint16(currentPlayers)
|
||||
bf.WriteUint16(0)
|
||||
bf.WriteUint16(0)
|
||||
@@ -86,7 +92,7 @@ func encodeServerInfo(config *_config.Config, server *Server, local bool) []byte
|
||||
}
|
||||
}
|
||||
bf.WriteUint32(uint32(gametime.TimeAdjusted().Unix()))
|
||||
bf.WriteUint32(uint32(server.erupeConfig.GameplayOptions.ClanMemberLimits[len(server.erupeConfig.GameplayOptions.ClanMemberLimits)-1][1]))
|
||||
bf.WriteUint32(uint32(config.GetConfig().GameplayOptions.ClanMemberLimits[len(config.GetConfig().GameplayOptions.ClanMemberLimits)-1][1]))
|
||||
return bf.Data()
|
||||
}
|
||||
|
||||
@@ -108,11 +114,11 @@ func makeHeader(data []byte, respType string, entryCount uint16, key byte) []byt
|
||||
return bf.Data()
|
||||
}
|
||||
|
||||
func makeSv2Resp(config *_config.Config, server *Server, local bool) []byte {
|
||||
serverInfos := config.Entrance.Entries
|
||||
func makeSv2Resp(server *EntranceServer, local bool) []byte {
|
||||
serverInfos := config.GetConfig().Entrance.Entries
|
||||
// Decrease by the number of MezFes Worlds
|
||||
var mf int
|
||||
if config.ClientID <= _config.Z1 {
|
||||
if config.GetConfig().ClientID <= config.Z1 {
|
||||
for _, si := range serverInfos {
|
||||
if si.Type == 6 {
|
||||
mf++
|
||||
@@ -121,21 +127,21 @@ func makeSv2Resp(config *_config.Config, server *Server, local bool) []byte {
|
||||
}
|
||||
// and Return Worlds
|
||||
var ret int
|
||||
if config.ClientID <= _config.G6 {
|
||||
if config.GetConfig().ClientID <= config.G6 {
|
||||
for _, si := range serverInfos {
|
||||
if si.Type == 5 {
|
||||
ret++
|
||||
}
|
||||
}
|
||||
}
|
||||
rawServerData := encodeServerInfo(config, server, local)
|
||||
rawServerData := encodeServerInfo(server, local)
|
||||
|
||||
if server.erupeConfig.DebugOptions.LogOutboundMessages {
|
||||
if config.GetConfig().DebugOptions.LogOutboundMessages {
|
||||
fmt.Printf("[Server] -> [Client]\nData [%d bytes]:\n%s\n", len(rawServerData), hex.Dump(rawServerData))
|
||||
}
|
||||
|
||||
respType := "SV2"
|
||||
if config.ClientID <= _config.G32 {
|
||||
if config.GetConfig().ClientID <= config.G32 {
|
||||
respType = "SVR"
|
||||
}
|
||||
|
||||
@@ -144,16 +150,20 @@ func makeSv2Resp(config *_config.Config, server *Server, local bool) []byte {
|
||||
return bf.Data()
|
||||
}
|
||||
|
||||
func makeUsrResp(pkt []byte, server *Server) []byte {
|
||||
func makeUsrResp(pkt []byte, server *EntranceServer) []byte {
|
||||
bf := byteframe.NewByteFrameFromBytes(pkt)
|
||||
_ = bf.ReadUint32() // ALL+
|
||||
_ = bf.ReadUint8() // 0x00
|
||||
userEntries := bf.ReadUint16()
|
||||
resp := byteframe.NewByteFrame()
|
||||
database, err := db.GetDB()
|
||||
if err != nil {
|
||||
server.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
for i := 0; i < int(userEntries); i++ {
|
||||
cid := bf.ReadUint32()
|
||||
var sid uint16
|
||||
err := server.db.QueryRow("SELECT(SELECT server_id FROM sign_sessions WHERE char_id=$1) AS _", cid).Scan(&sid)
|
||||
err := database.QueryRow("SELECT(SELECT server_id FROM sign_sessions WHERE char_id=$1) AS _", cid).Scan(&sid)
|
||||
if err != nil {
|
||||
resp.WriteUint16(0)
|
||||
} else {
|
||||
@@ -162,7 +172,7 @@ func makeUsrResp(pkt []byte, server *Server) []byte {
|
||||
resp.WriteUint16(0)
|
||||
}
|
||||
|
||||
if server.erupeConfig.DebugOptions.LogOutboundMessages {
|
||||
if config.GetConfig().DebugOptions.LogOutboundMessages {
|
||||
fmt.Printf("[Server] -> [Client]\nData [%d bytes]:\n%s\n", len(resp.Data()), hex.Dump(resp.Data()))
|
||||
}
|
||||
|
||||
318
server/sign/dbutils.go
Normal file
318
server/sign/dbutils.go
Normal file
@@ -0,0 +1,318 @@
|
||||
package sign
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"erupe-ce/config"
|
||||
"erupe-ce/utils/db"
|
||||
"erupe-ce/utils/mhfcourse"
|
||||
"erupe-ce/utils/token"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"go.uber.org/zap"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
func (server *SignServer) newUserChara(uid uint32) error {
|
||||
var numNewChars int
|
||||
database, err := db.GetDB() // Capture both return values
|
||||
if err != nil {
|
||||
server.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
err = database.QueryRow("SELECT COUNT(*) FROM characters WHERE user_id = $1 AND is_new_character = true", uid).Scan(&numNewChars)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// prevent users with an uninitialised character from creating more
|
||||
if numNewChars >= 1 {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = database.Exec(`
|
||||
INSERT INTO characters (
|
||||
user_id, is_female, is_new_character, name, unk_desc_string,
|
||||
hr, gr, weapon_type, last_login)
|
||||
VALUES($1, False, True, '', '', 0, 0, 0, $2)`,
|
||||
uid,
|
||||
uint32(time.Now().Unix()),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (server *SignServer) registerDBAccount(username string, password string) (uint32, error) {
|
||||
var uid uint32
|
||||
server.logger.Info("Creating user", zap.String("User", username))
|
||||
database, err := db.GetDB() // Capture both return values
|
||||
if err != nil {
|
||||
server.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
// Create salted hash of user password
|
||||
passwordHash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
err = database.QueryRow("INSERT INTO users (username, password, return_expires) VALUES ($1, $2, $3) RETURNING id", username, string(passwordHash), time.Now().Add(time.Hour*24*30)).Scan(&uid)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return uid, nil
|
||||
}
|
||||
|
||||
type character struct {
|
||||
ID uint32 `db:"id"`
|
||||
IsFemale bool `db:"is_female"`
|
||||
IsNewCharacter bool `db:"is_new_character"`
|
||||
Name string `db:"name"`
|
||||
UnkDescString string `db:"unk_desc_string"`
|
||||
HR uint16 `db:"hr"`
|
||||
GR uint16 `db:"gr"`
|
||||
WeaponType uint16 `db:"weapon_type"`
|
||||
LastLogin uint32 `db:"last_login"`
|
||||
}
|
||||
|
||||
func (server *SignServer) getCharactersForUser(uid uint32) ([]character, error) {
|
||||
database, err := db.GetDB() // Capture both return values
|
||||
if err != nil {
|
||||
server.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
characters := make([]character, 0)
|
||||
err = database.Select(&characters, "SELECT id, is_female, is_new_character, name, unk_desc_string, hr, gr, weapon_type, last_login FROM characters WHERE user_id = $1 AND deleted = false ORDER BY id", uid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return characters, nil
|
||||
}
|
||||
|
||||
func (server *SignServer) getReturnExpiry(uid uint32) time.Time {
|
||||
database, err := db.GetDB() // Capture both return values
|
||||
if err != nil {
|
||||
server.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
var returnExpiry, lastLogin time.Time
|
||||
database.Get(&lastLogin, "SELECT COALESCE(last_login, now()) FROM users WHERE id=$1", uid)
|
||||
if time.Now().Add((time.Hour * 24) * -90).After(lastLogin) {
|
||||
returnExpiry = time.Now().Add(time.Hour * 24 * 30)
|
||||
database.Exec("UPDATE users SET return_expires=$1 WHERE id=$2", returnExpiry, uid)
|
||||
} else {
|
||||
err := database.Get(&returnExpiry, "SELECT return_expires FROM users WHERE id=$1", uid)
|
||||
if err != nil {
|
||||
returnExpiry = time.Now()
|
||||
database.Exec("UPDATE users SET return_expires=$1 WHERE id=$2", returnExpiry, uid)
|
||||
}
|
||||
}
|
||||
database.Exec("UPDATE users SET last_login=$1 WHERE id=$2", time.Now(), uid)
|
||||
return returnExpiry
|
||||
}
|
||||
|
||||
func (server *SignServer) getLastCID(uid uint32) uint32 {
|
||||
database, err := db.GetDB() // Capture both return values
|
||||
if err != nil {
|
||||
server.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
var lastPlayed uint32
|
||||
_ = database.QueryRow("SELECT last_character FROM users WHERE id=$1", uid).Scan(&lastPlayed)
|
||||
return lastPlayed
|
||||
}
|
||||
|
||||
func (server *SignServer) getUserRights(uid uint32) uint32 {
|
||||
database, err := db.GetDB() // Capture both return values
|
||||
if err != nil {
|
||||
server.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
var rights uint32
|
||||
if uid != 0 {
|
||||
_ = database.QueryRow("SELECT rights FROM users WHERE id=$1", uid).Scan(&rights)
|
||||
_, rights = mhfcourse.GetCourseStruct(rights)
|
||||
}
|
||||
return rights
|
||||
}
|
||||
|
||||
type members struct {
|
||||
CID uint32 // Local character ID
|
||||
ID uint32 `db:"id"`
|
||||
Name string `db:"name"`
|
||||
}
|
||||
|
||||
func (server *SignServer) getFriendsForCharacters(chars []character) []members {
|
||||
database, err := db.GetDB() // Capture both return values
|
||||
if err != nil {
|
||||
server.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
friends := make([]members, 0)
|
||||
for _, char := range chars {
|
||||
friendsCSV := ""
|
||||
err := database.QueryRow("SELECT friends FROM characters WHERE id=$1", char.ID).Scan(&friendsCSV)
|
||||
friendsSlice := strings.Split(friendsCSV, ",")
|
||||
friendQuery := "SELECT id, name FROM characters WHERE id="
|
||||
for i := 0; i < len(friendsSlice); i++ {
|
||||
friendQuery += friendsSlice[i]
|
||||
if i+1 != len(friendsSlice) {
|
||||
friendQuery += " OR id="
|
||||
}
|
||||
}
|
||||
charFriends := make([]members, 0)
|
||||
err = database.Select(&charFriends, friendQuery)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
for i := range charFriends {
|
||||
charFriends[i].CID = char.ID
|
||||
}
|
||||
friends = append(friends, charFriends...)
|
||||
}
|
||||
return friends
|
||||
}
|
||||
|
||||
func (server *SignServer) getGuildmatesForCharacters(chars []character) []members {
|
||||
database, err := db.GetDB() // Capture both return values
|
||||
if err != nil {
|
||||
server.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
guildmates := make([]members, 0)
|
||||
for _, char := range chars {
|
||||
var inGuild int
|
||||
_ = database.QueryRow("SELECT count(*) FROM guild_characters WHERE character_id=$1", char.ID).Scan(&inGuild)
|
||||
if inGuild > 0 {
|
||||
var guildID int
|
||||
err := database.QueryRow("SELECT guild_id FROM guild_characters WHERE character_id=$1", char.ID).Scan(&guildID)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
charGuildmates := make([]members, 0)
|
||||
err = database.Select(&charGuildmates, "SELECT character_id AS id, c.name FROM guild_characters gc JOIN characters c ON c.id = gc.character_id WHERE guild_id=$1 AND character_id!=$2", guildID, char.ID)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
for i := range charGuildmates {
|
||||
charGuildmates[i].CID = char.ID
|
||||
}
|
||||
guildmates = append(guildmates, charGuildmates...)
|
||||
}
|
||||
}
|
||||
return guildmates
|
||||
}
|
||||
|
||||
func (server *SignServer) deleteCharacter(cid int, token string, tokenID uint32) error {
|
||||
database, err := db.GetDB() // Capture both return values
|
||||
if err != nil {
|
||||
server.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
if !server.validateToken(token, tokenID) {
|
||||
return errors.New("invalid token")
|
||||
}
|
||||
var isNew bool
|
||||
err = database.QueryRow("SELECT is_new_character FROM characters WHERE id = $1", cid).Scan(&isNew)
|
||||
if isNew {
|
||||
_, err = database.Exec("DELETE FROM characters WHERE id = $1", cid)
|
||||
} else {
|
||||
_, err = database.Exec("UPDATE characters SET deleted = true WHERE id = $1", cid)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Unused
|
||||
func (server *SignServer) checkToken(uid uint32) (bool, error) {
|
||||
database, err := db.GetDB() // Capture both return values
|
||||
if err != nil {
|
||||
server.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
var exists int
|
||||
err = database.QueryRow("SELECT count(*) FROM sign_sessions WHERE user_id = $1", uid).Scan(&exists)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if exists > 0 {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (server *SignServer) registerUidToken(uid uint32) (uint32, string, error) {
|
||||
database, err := db.GetDB() // Capture both return values
|
||||
if err != nil {
|
||||
server.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
_token := token.Generate(16)
|
||||
var tid uint32
|
||||
err = database.QueryRow(`INSERT INTO sign_sessions (user_id, token) VALUES ($1, $2) RETURNING id`, uid, _token).Scan(&tid)
|
||||
return tid, _token, err
|
||||
}
|
||||
|
||||
func (server *SignServer) registerPsnToken(psn string) (uint32, string, error) {
|
||||
database, err := db.GetDB() // Capture both return values
|
||||
if err != nil {
|
||||
server.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
_token := token.Generate(16)
|
||||
var tid uint32
|
||||
err = database.QueryRow(`INSERT INTO sign_sessions (psn_id, token) VALUES ($1, $2) RETURNING id`, psn, _token).Scan(&tid)
|
||||
return tid, _token, err
|
||||
}
|
||||
|
||||
func (server *SignServer) validateToken(token string, tokenID uint32) bool {
|
||||
database, err := db.GetDB() // Capture both return values
|
||||
if err != nil {
|
||||
server.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
query := `SELECT count(*) FROM sign_sessions WHERE token = $1`
|
||||
if tokenID > 0 {
|
||||
query += ` AND id = $2`
|
||||
}
|
||||
var exists int
|
||||
err = database.QueryRow(query, token, tokenID).Scan(&exists)
|
||||
if err != nil || exists == 0 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (server *SignServer) validateLogin(user string, pass string) (uint32, RespID) {
|
||||
database, err := db.GetDB() // Capture both return values
|
||||
if err != nil {
|
||||
server.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
var uid uint32
|
||||
var passDB string
|
||||
err = database.QueryRow(`SELECT id, password FROM users WHERE username = $1`, user).Scan(&uid, &passDB)
|
||||
if err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
server.logger.Info("User not found", zap.String("User", user))
|
||||
if config.GetConfig().AutoCreateAccount {
|
||||
uid, err = server.registerDBAccount(user, pass)
|
||||
if err == nil {
|
||||
return uid, SIGN_SUCCESS
|
||||
} else {
|
||||
return 0, SIGN_EABORT
|
||||
}
|
||||
}
|
||||
return 0, SIGN_EAUTH
|
||||
}
|
||||
return 0, SIGN_EABORT
|
||||
} else {
|
||||
if bcrypt.CompareHashAndPassword([]byte(passDB), []byte(pass)) == nil {
|
||||
var bans int
|
||||
err = database.QueryRow(`SELECT count(*) FROM bans WHERE user_id=$1 AND expires IS NULL`, uid).Scan(&bans)
|
||||
if err == nil && bans > 0 {
|
||||
return uid, SIGN_EELIMINATE
|
||||
}
|
||||
err = database.QueryRow(`SELECT count(*) FROM bans WHERE user_id=$1 AND expires > now()`, uid).Scan(&bans)
|
||||
if err == nil && bans > 0 {
|
||||
return uid, SIGN_ESUSPEND
|
||||
}
|
||||
return uid, SIGN_SUCCESS
|
||||
}
|
||||
return 0, SIGN_EPASS
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,13 @@
|
||||
package signserver
|
||||
package sign
|
||||
|
||||
import (
|
||||
"erupe-ce/utils/byteframe"
|
||||
"erupe-ce/utils/db"
|
||||
"erupe-ce/utils/gametime"
|
||||
ps "erupe-ce/utils/pascalstring"
|
||||
"erupe-ce/utils/stringsupport"
|
||||
|
||||
_config "erupe-ce/config"
|
||||
"erupe-ce/config"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -40,7 +41,7 @@ func (s *Session) makeSignResponse(uid uint32) []byte {
|
||||
return bf.Data()
|
||||
}
|
||||
|
||||
if s.client == PS3 && (s.server.erupeConfig.PatchServerFile == "" || s.server.erupeConfig.PatchServerManifest == "") {
|
||||
if s.client == PS3 && (config.GetConfig().PatchServerFile == "" || config.GetConfig().PatchServerManifest == "") {
|
||||
bf.WriteUint8(uint8(SIGN_EABORT))
|
||||
return bf.Data()
|
||||
}
|
||||
@@ -53,16 +54,16 @@ func (s *Session) makeSignResponse(uid uint32) []byte {
|
||||
bf.WriteBytes([]byte(sessToken))
|
||||
bf.WriteUint32(uint32(gametime.TimeAdjusted().Unix()))
|
||||
if s.client == PS3 {
|
||||
ps.Uint8(bf, fmt.Sprintf("%s/ps3", s.server.erupeConfig.PatchServerManifest), false)
|
||||
ps.Uint8(bf, fmt.Sprintf("%s/ps3", s.server.erupeConfig.PatchServerFile), false)
|
||||
ps.Uint8(bf, fmt.Sprintf("%s/ps3", config.GetConfig().PatchServerManifest), false)
|
||||
ps.Uint8(bf, fmt.Sprintf("%s/ps3", config.GetConfig().PatchServerFile), false)
|
||||
} else {
|
||||
ps.Uint8(bf, s.server.erupeConfig.PatchServerManifest, false)
|
||||
ps.Uint8(bf, s.server.erupeConfig.PatchServerFile, false)
|
||||
ps.Uint8(bf, config.GetConfig().PatchServerManifest, false)
|
||||
ps.Uint8(bf, config.GetConfig().PatchServerFile, false)
|
||||
}
|
||||
if strings.Split(s.rawConn.RemoteAddr().String(), ":")[0] == "127.0.0.1" {
|
||||
ps.Uint8(bf, fmt.Sprintf("127.0.0.1:%d", s.server.erupeConfig.Entrance.Port), false)
|
||||
ps.Uint8(bf, fmt.Sprintf("127.0.0.1:%d", config.GetConfig().Entrance.Port), false)
|
||||
} else {
|
||||
ps.Uint8(bf, fmt.Sprintf("%s:%d", s.server.erupeConfig.Host, s.server.erupeConfig.Entrance.Port), false)
|
||||
ps.Uint8(bf, fmt.Sprintf("%s:%d", config.GetConfig().Host, config.GetConfig().Entrance.Port), false)
|
||||
}
|
||||
|
||||
lastPlayed := uint32(0)
|
||||
@@ -71,7 +72,7 @@ func (s *Session) makeSignResponse(uid uint32) []byte {
|
||||
lastPlayed = char.ID
|
||||
}
|
||||
bf.WriteUint32(char.ID)
|
||||
if s.server.erupeConfig.DebugOptions.MaxLauncherHR {
|
||||
if config.GetConfig().DebugOptions.MaxLauncherHR {
|
||||
bf.WriteUint16(999)
|
||||
} else {
|
||||
bf.WriteUint16(char.HR)
|
||||
@@ -84,7 +85,7 @@ func (s *Session) makeSignResponse(uid uint32) []byte {
|
||||
bf.WriteBool(true) // Use uint16 GR, no reason not to
|
||||
bf.WriteBytes(stringsupport.PaddedString(char.Name, 16, true)) // Character name
|
||||
bf.WriteBytes(stringsupport.PaddedString(char.UnkDescString, 32, false)) // unk str
|
||||
if s.server.erupeConfig.ClientID >= _config.G7 {
|
||||
if config.GetConfig().ClientID >= config.G7 {
|
||||
bf.WriteUint16(char.GR)
|
||||
bf.WriteUint8(0) // Unk
|
||||
bf.WriteUint8(0) // Unk
|
||||
@@ -125,13 +126,13 @@ func (s *Session) makeSignResponse(uid uint32) []byte {
|
||||
}
|
||||
}
|
||||
|
||||
if s.server.erupeConfig.HideLoginNotice {
|
||||
if config.GetConfig().HideLoginNotice {
|
||||
bf.WriteBool(false)
|
||||
} else {
|
||||
bf.WriteBool(true)
|
||||
bf.WriteUint8(0)
|
||||
bf.WriteUint8(0)
|
||||
ps.Uint16(bf, strings.Join(s.server.erupeConfig.LoginNotices[:], "<PAGE>"), true)
|
||||
ps.Uint16(bf, strings.Join(config.GetConfig().LoginNotices[:], "<PAGE>"), true)
|
||||
}
|
||||
|
||||
bf.WriteUint32(s.server.getLastCID(uid))
|
||||
@@ -332,18 +333,21 @@ func (s *Session) makeSignResponse(uid uint32) []byte {
|
||||
|
||||
bf.WriteUint16(uint16(len(filters.Data())))
|
||||
bf.WriteBytes(filters.Data())
|
||||
|
||||
database, err := db.GetDB() // Capture both return values
|
||||
if err != nil {
|
||||
s.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
if s.client == VITA || s.client == PS3 || s.client == PS4 {
|
||||
var psnUser string
|
||||
s.server.db.QueryRow("SELECT psn_id FROM users WHERE id = $1", uid).Scan(&psnUser)
|
||||
database.QueryRow("SELECT psn_id FROM users WHERE id = $1", uid).Scan(&psnUser)
|
||||
bf.WriteBytes(stringsupport.PaddedString(psnUser, 20, true))
|
||||
}
|
||||
|
||||
bf.WriteUint16(s.server.erupeConfig.DebugOptions.CapLink.Values[0])
|
||||
if s.server.erupeConfig.DebugOptions.CapLink.Values[0] == 51728 {
|
||||
bf.WriteUint16(s.server.erupeConfig.DebugOptions.CapLink.Values[1])
|
||||
if s.server.erupeConfig.DebugOptions.CapLink.Values[1] == 20000 || s.server.erupeConfig.DebugOptions.CapLink.Values[1] == 20002 {
|
||||
ps.Uint16(bf, s.server.erupeConfig.DebugOptions.CapLink.Key, false)
|
||||
bf.WriteUint16(config.GetConfig().DebugOptions.CapLink.Values[0])
|
||||
if config.GetConfig().DebugOptions.CapLink.Values[0] == 51728 {
|
||||
bf.WriteUint16(config.GetConfig().DebugOptions.CapLink.Values[1])
|
||||
if config.GetConfig().DebugOptions.CapLink.Values[1] == 20000 || config.GetConfig().DebugOptions.CapLink.Values[1] == 20002 {
|
||||
ps.Uint16(bf, config.GetConfig().DebugOptions.CapLink.Key, false)
|
||||
}
|
||||
}
|
||||
caStruct := []struct {
|
||||
@@ -357,31 +361,31 @@ func (s *Session) makeSignResponse(uid uint32) []byte {
|
||||
bf.WriteUint32(caStruct[i].Unk1)
|
||||
ps.Uint8(bf, caStruct[i].Unk2, false)
|
||||
}
|
||||
bf.WriteUint16(s.server.erupeConfig.DebugOptions.CapLink.Values[2])
|
||||
bf.WriteUint16(s.server.erupeConfig.DebugOptions.CapLink.Values[3])
|
||||
bf.WriteUint16(s.server.erupeConfig.DebugOptions.CapLink.Values[4])
|
||||
if s.server.erupeConfig.DebugOptions.CapLink.Values[2] == 51729 && s.server.erupeConfig.DebugOptions.CapLink.Values[3] == 1 && s.server.erupeConfig.DebugOptions.CapLink.Values[4] == 20000 {
|
||||
ps.Uint16(bf, fmt.Sprintf(`%s:%d`, s.server.erupeConfig.DebugOptions.CapLink.Host, s.server.erupeConfig.DebugOptions.CapLink.Port), false)
|
||||
bf.WriteUint16(config.GetConfig().DebugOptions.CapLink.Values[2])
|
||||
bf.WriteUint16(config.GetConfig().DebugOptions.CapLink.Values[3])
|
||||
bf.WriteUint16(config.GetConfig().DebugOptions.CapLink.Values[4])
|
||||
if config.GetConfig().DebugOptions.CapLink.Values[2] == 51729 && config.GetConfig().DebugOptions.CapLink.Values[3] == 1 && config.GetConfig().DebugOptions.CapLink.Values[4] == 20000 {
|
||||
ps.Uint16(bf, fmt.Sprintf(`%s:%d`, config.GetConfig().DebugOptions.CapLink.Host, config.GetConfig().DebugOptions.CapLink.Port), false)
|
||||
}
|
||||
|
||||
bf.WriteUint32(uint32(s.server.getReturnExpiry(uid).Unix()))
|
||||
bf.WriteUint32(0)
|
||||
|
||||
tickets := []uint32{
|
||||
s.server.erupeConfig.GameplayOptions.MezFesSoloTickets,
|
||||
s.server.erupeConfig.GameplayOptions.MezFesGroupTickets,
|
||||
config.GetConfig().GameplayOptions.MezFesSoloTickets,
|
||||
config.GetConfig().GameplayOptions.MezFesGroupTickets,
|
||||
}
|
||||
stalls := []uint8{
|
||||
10, 3, 6, 9, 4, 8, 5, 7,
|
||||
}
|
||||
if s.server.erupeConfig.GameplayOptions.MezFesSwitchMinigame {
|
||||
if config.GetConfig().GameplayOptions.MezFesSwitchMinigame {
|
||||
stalls[4] = 2
|
||||
}
|
||||
|
||||
// We can just use the start timestamp as the event ID
|
||||
bf.WriteUint32(uint32(gametime.TimeWeekStart().Unix()))
|
||||
// Start time
|
||||
bf.WriteUint32(uint32(gametime.TimeWeekNext().Add(-time.Duration(s.server.erupeConfig.GameplayOptions.MezFesDuration) * time.Second).Unix()))
|
||||
bf.WriteUint32(uint32(gametime.TimeWeekNext().Add(-time.Duration(config.GetConfig().GameplayOptions.MezFesDuration) * time.Second).Unix()))
|
||||
// End time
|
||||
bf.WriteUint32(uint32(gametime.TimeWeekNext().Unix()))
|
||||
bf.WriteUint8(uint8(len(tickets)))
|
||||
@@ -1,4 +1,4 @@
|
||||
package signserver
|
||||
package sign
|
||||
|
||||
type RespID uint8
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
package signserver
|
||||
package sign
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"encoding/hex"
|
||||
"erupe-ce/config"
|
||||
"erupe-ce/utils/db"
|
||||
"erupe-ce/utils/logger"
|
||||
|
||||
"erupe-ce/utils/stringsupport"
|
||||
"fmt"
|
||||
"net"
|
||||
@@ -30,7 +33,7 @@ const (
|
||||
type Session struct {
|
||||
sync.Mutex
|
||||
logger logger.Logger
|
||||
server *Server
|
||||
server *SignServer
|
||||
rawConn net.Conn
|
||||
cryptConn *network.CryptConn
|
||||
client client
|
||||
@@ -40,7 +43,7 @@ type Session struct {
|
||||
func (s *Session) work() {
|
||||
pkt, err := s.cryptConn.ReadPacket()
|
||||
|
||||
if s.server.erupeConfig.DebugOptions.LogInboundMessages {
|
||||
if config.GetConfig().DebugOptions.LogInboundMessages {
|
||||
fmt.Printf("\n[Client] -> [Server]\nData [%d bytes]:\n%s\n", len(pkt), hex.Dump(pkt))
|
||||
}
|
||||
|
||||
@@ -84,7 +87,7 @@ func (s *Session) handlePacket(pkt []byte) error {
|
||||
}
|
||||
default:
|
||||
s.logger.Warn("Unknown request", zap.String("reqType", reqType))
|
||||
if s.server.erupeConfig.DebugOptions.LogInboundMessages {
|
||||
if config.GetConfig().DebugOptions.LogInboundMessages {
|
||||
fmt.Printf("\n[Client] -> [Server]\nData [%d bytes]:\n%s\n", len(pkt), hex.Dump(pkt))
|
||||
}
|
||||
}
|
||||
@@ -108,7 +111,7 @@ func (s *Session) authenticate(username string, password string) {
|
||||
default:
|
||||
bf.WriteUint8(uint8(resp))
|
||||
}
|
||||
if s.server.erupeConfig.DebugOptions.LogOutboundMessages {
|
||||
if config.GetConfig().DebugOptions.LogOutboundMessages {
|
||||
fmt.Printf("\n[Server] -> [Client]\nData [%d bytes]:\n%s\n", len(bf.Data()), hex.Dump(bf.Data()))
|
||||
}
|
||||
_ = s.cryptConn.SendPacket(bf.Data())
|
||||
@@ -118,7 +121,11 @@ func (s *Session) handleWIIUSGN(bf *byteframe.ByteFrame) {
|
||||
_ = bf.ReadBytes(1)
|
||||
wiiuKey := string(bf.ReadBytes(64))
|
||||
var uid uint32
|
||||
err := s.server.db.QueryRow(`SELECT id FROM users WHERE wiiu_key = $1`, wiiuKey).Scan(&uid)
|
||||
database, err := db.GetDB() // Capture both return values
|
||||
if err != nil {
|
||||
s.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
err = database.QueryRow(`SELECT id FROM users WHERE wiiu_key = $1`, wiiuKey).Scan(&uid)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
s.logger.Info("Unlinked Wii U attempted to authenticate", zap.String("Key", wiiuKey))
|
||||
@@ -145,7 +152,11 @@ func (s *Session) handlePSSGN(bf *byteframe.ByteFrame) {
|
||||
}
|
||||
s.psn = string(bf.ReadNullTerminatedBytes())
|
||||
var uid uint32
|
||||
err := s.server.db.QueryRow(`SELECT id FROM users WHERE psn_id = $1`, s.psn).Scan(&uid)
|
||||
database, err := db.GetDB() // Capture both return values
|
||||
if err != nil {
|
||||
s.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
err = database.QueryRow(`SELECT id FROM users WHERE psn_id = $1`, s.psn).Scan(&uid)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
s.cryptConn.SendPacket(s.makeSignResponse(0))
|
||||
@@ -162,9 +173,13 @@ func (s *Session) handlePSNLink(bf *byteframe.ByteFrame) {
|
||||
credentials := strings.Split(stringsupport.SJISToUTF8(bf.ReadNullTerminatedBytes()), "\n")
|
||||
token := string(bf.ReadNullTerminatedBytes())
|
||||
uid, resp := s.server.validateLogin(credentials[0], credentials[1])
|
||||
database, err := db.GetDB() // Capture both return values
|
||||
if err != nil {
|
||||
s.logger.Fatal(fmt.Sprintf("Failed to get database instance: %s", err))
|
||||
}
|
||||
if resp == SIGN_SUCCESS && uid > 0 {
|
||||
var psn string
|
||||
err := s.server.db.QueryRow(`SELECT psn_id FROM sign_sessions WHERE token = $1`, token).Scan(&psn)
|
||||
err := database.QueryRow(`SELECT psn_id FROM sign_sessions WHERE token = $1`, token).Scan(&psn)
|
||||
if err != nil {
|
||||
s.sendCode(SIGN_ECOGLINK)
|
||||
return
|
||||
@@ -172,7 +187,7 @@ func (s *Session) handlePSNLink(bf *byteframe.ByteFrame) {
|
||||
|
||||
// Since we check for the psn_id, this will never run
|
||||
var exists int
|
||||
err = s.server.db.QueryRow(`SELECT count(*) FROM users WHERE psn_id = $1`, psn).Scan(&exists)
|
||||
err = database.QueryRow(`SELECT count(*) FROM users WHERE psn_id = $1`, psn).Scan(&exists)
|
||||
if err != nil {
|
||||
s.sendCode(SIGN_ECOGLINK)
|
||||
return
|
||||
@@ -182,7 +197,7 @@ func (s *Session) handlePSNLink(bf *byteframe.ByteFrame) {
|
||||
}
|
||||
|
||||
var currentPSN string
|
||||
err = s.server.db.QueryRow(`SELECT COALESCE(psn_id, '') FROM users WHERE username = $1`, credentials[0]).Scan(¤tPSN)
|
||||
err = database.QueryRow(`SELECT COALESCE(psn_id, '') FROM users WHERE username = $1`, credentials[0]).Scan(¤tPSN)
|
||||
if err != nil {
|
||||
s.sendCode(SIGN_ECOGLINK)
|
||||
return
|
||||
@@ -191,7 +206,7 @@ func (s *Session) handlePSNLink(bf *byteframe.ByteFrame) {
|
||||
return
|
||||
}
|
||||
|
||||
_, err = s.server.db.Exec(`UPDATE users SET psn_id = $1 WHERE username = $2`, psn, credentials[0])
|
||||
_, err = database.Exec(`UPDATE users SET psn_id = $1 WHERE username = $2`, psn, credentials[0])
|
||||
if err == nil {
|
||||
s.sendCode(SIGN_SUCCESS)
|
||||
return
|
||||
@@ -1,4 +1,4 @@
|
||||
package signserver
|
||||
package sign
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -6,44 +6,33 @@ import (
|
||||
"net"
|
||||
"sync"
|
||||
|
||||
_config "erupe-ce/config"
|
||||
"erupe-ce/config"
|
||||
"erupe-ce/network"
|
||||
"erupe-ce/utils/logger"
|
||||
|
||||
"github.com/jmoiron/sqlx"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// Config struct allows configuring the server.
|
||||
type Config struct {
|
||||
DB *sqlx.DB
|
||||
ErupeConfig *_config.Config
|
||||
}
|
||||
|
||||
// Server is a MHF sign server.
|
||||
type Server struct {
|
||||
// SignServer is a MHF sign server.
|
||||
type SignServer struct {
|
||||
sync.Mutex
|
||||
logger logger.Logger
|
||||
erupeConfig *_config.Config
|
||||
sessions map[int]*Session
|
||||
db *sqlx.DB
|
||||
listener net.Listener
|
||||
isShuttingDown bool
|
||||
}
|
||||
|
||||
// NewServer creates a new Server type.
|
||||
func NewServer(config *Config) *Server {
|
||||
s := &Server{
|
||||
logger: logger.Get().Named("sign"),
|
||||
erupeConfig: config.ErupeConfig,
|
||||
db: config.DB,
|
||||
func NewServer() *SignServer {
|
||||
s := &SignServer{
|
||||
logger: logger.Get().Named("sign"),
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// Start starts the server in a new goroutine.
|
||||
func (server *Server) Start() error {
|
||||
l, err := net.Listen("tcp", fmt.Sprintf(":%d", server.erupeConfig.Sign.Port))
|
||||
func (server *SignServer) Start() error {
|
||||
l, err := net.Listen("tcp", fmt.Sprintf(":%d", config.GetConfig().Sign.Port))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -55,7 +44,7 @@ func (server *Server) Start() error {
|
||||
}
|
||||
|
||||
// Shutdown exits the server gracefully.
|
||||
func (server *Server) Shutdown() {
|
||||
func (server *SignServer) Shutdown() {
|
||||
server.logger.Debug("Shutting down...")
|
||||
|
||||
server.Lock()
|
||||
@@ -66,7 +55,7 @@ func (server *Server) Shutdown() {
|
||||
server.listener.Close()
|
||||
}
|
||||
|
||||
func (server *Server) acceptClients() {
|
||||
func (server *SignServer) acceptClients() {
|
||||
for {
|
||||
conn, err := server.listener.Accept()
|
||||
if err != nil {
|
||||
@@ -86,7 +75,7 @@ func (server *Server) acceptClients() {
|
||||
}
|
||||
}
|
||||
|
||||
func (server *Server) handleConnection(conn net.Conn) {
|
||||
func (server *SignServer) handleConnection(conn net.Conn) {
|
||||
server.logger.Debug("New connection", zap.String("RemoteAddr", conn.RemoteAddr().String()))
|
||||
defer conn.Close()
|
||||
|
||||
@@ -1,260 +0,0 @@
|
||||
package signserver
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"erupe-ce/utils/mhfcourse"
|
||||
"erupe-ce/utils/token"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"go.uber.org/zap"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
func (server *Server) newUserChara(uid uint32) error {
|
||||
var numNewChars int
|
||||
err := server.db.QueryRow("SELECT COUNT(*) FROM characters WHERE user_id = $1 AND is_new_character = true", uid).Scan(&numNewChars)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// prevent users with an uninitialised character from creating more
|
||||
if numNewChars >= 1 {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = server.db.Exec(`
|
||||
INSERT INTO characters (
|
||||
user_id, is_female, is_new_character, name, unk_desc_string,
|
||||
hr, gr, weapon_type, last_login)
|
||||
VALUES($1, False, True, '', '', 0, 0, 0, $2)`,
|
||||
uid,
|
||||
uint32(time.Now().Unix()),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (server *Server) registerDBAccount(username string, password string) (uint32, error) {
|
||||
var uid uint32
|
||||
server.logger.Info("Creating user", zap.String("User", username))
|
||||
|
||||
// Create salted hash of user password
|
||||
passwordHash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
err = server.db.QueryRow("INSERT INTO users (username, password, return_expires) VALUES ($1, $2, $3) RETURNING id", username, string(passwordHash), time.Now().Add(time.Hour*24*30)).Scan(&uid)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return uid, nil
|
||||
}
|
||||
|
||||
type character struct {
|
||||
ID uint32 `db:"id"`
|
||||
IsFemale bool `db:"is_female"`
|
||||
IsNewCharacter bool `db:"is_new_character"`
|
||||
Name string `db:"name"`
|
||||
UnkDescString string `db:"unk_desc_string"`
|
||||
HR uint16 `db:"hr"`
|
||||
GR uint16 `db:"gr"`
|
||||
WeaponType uint16 `db:"weapon_type"`
|
||||
LastLogin uint32 `db:"last_login"`
|
||||
}
|
||||
|
||||
func (server *Server) getCharactersForUser(uid uint32) ([]character, error) {
|
||||
characters := make([]character, 0)
|
||||
err := server.db.Select(&characters, "SELECT id, is_female, is_new_character, name, unk_desc_string, hr, gr, weapon_type, last_login FROM characters WHERE user_id = $1 AND deleted = false ORDER BY id", uid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return characters, nil
|
||||
}
|
||||
|
||||
func (server *Server) getReturnExpiry(uid uint32) time.Time {
|
||||
var returnExpiry, lastLogin time.Time
|
||||
server.db.Get(&lastLogin, "SELECT COALESCE(last_login, now()) FROM users WHERE id=$1", uid)
|
||||
if time.Now().Add((time.Hour * 24) * -90).After(lastLogin) {
|
||||
returnExpiry = time.Now().Add(time.Hour * 24 * 30)
|
||||
server.db.Exec("UPDATE users SET return_expires=$1 WHERE id=$2", returnExpiry, uid)
|
||||
} else {
|
||||
err := server.db.Get(&returnExpiry, "SELECT return_expires FROM users WHERE id=$1", uid)
|
||||
if err != nil {
|
||||
returnExpiry = time.Now()
|
||||
server.db.Exec("UPDATE users SET return_expires=$1 WHERE id=$2", returnExpiry, uid)
|
||||
}
|
||||
}
|
||||
server.db.Exec("UPDATE users SET last_login=$1 WHERE id=$2", time.Now(), uid)
|
||||
return returnExpiry
|
||||
}
|
||||
|
||||
func (server *Server) getLastCID(uid uint32) uint32 {
|
||||
var lastPlayed uint32
|
||||
_ = server.db.QueryRow("SELECT last_character FROM users WHERE id=$1", uid).Scan(&lastPlayed)
|
||||
return lastPlayed
|
||||
}
|
||||
|
||||
func (server *Server) getUserRights(uid uint32) uint32 {
|
||||
var rights uint32
|
||||
if uid != 0 {
|
||||
_ = server.db.QueryRow("SELECT rights FROM users WHERE id=$1", uid).Scan(&rights)
|
||||
_, rights = mhfcourse.GetCourseStruct(rights)
|
||||
}
|
||||
return rights
|
||||
}
|
||||
|
||||
type members struct {
|
||||
CID uint32 // Local character ID
|
||||
ID uint32 `db:"id"`
|
||||
Name string `db:"name"`
|
||||
}
|
||||
|
||||
func (server *Server) getFriendsForCharacters(chars []character) []members {
|
||||
friends := make([]members, 0)
|
||||
for _, char := range chars {
|
||||
friendsCSV := ""
|
||||
err := server.db.QueryRow("SELECT friends FROM characters WHERE id=$1", char.ID).Scan(&friendsCSV)
|
||||
friendsSlice := strings.Split(friendsCSV, ",")
|
||||
friendQuery := "SELECT id, name FROM characters WHERE id="
|
||||
for i := 0; i < len(friendsSlice); i++ {
|
||||
friendQuery += friendsSlice[i]
|
||||
if i+1 != len(friendsSlice) {
|
||||
friendQuery += " OR id="
|
||||
}
|
||||
}
|
||||
charFriends := make([]members, 0)
|
||||
err = server.db.Select(&charFriends, friendQuery)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
for i := range charFriends {
|
||||
charFriends[i].CID = char.ID
|
||||
}
|
||||
friends = append(friends, charFriends...)
|
||||
}
|
||||
return friends
|
||||
}
|
||||
|
||||
func (server *Server) getGuildmatesForCharacters(chars []character) []members {
|
||||
guildmates := make([]members, 0)
|
||||
for _, char := range chars {
|
||||
var inGuild int
|
||||
_ = server.db.QueryRow("SELECT count(*) FROM guild_characters WHERE character_id=$1", char.ID).Scan(&inGuild)
|
||||
if inGuild > 0 {
|
||||
var guildID int
|
||||
err := server.db.QueryRow("SELECT guild_id FROM guild_characters WHERE character_id=$1", char.ID).Scan(&guildID)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
charGuildmates := make([]members, 0)
|
||||
err = server.db.Select(&charGuildmates, "SELECT character_id AS id, c.name FROM guild_characters gc JOIN characters c ON c.id = gc.character_id WHERE guild_id=$1 AND character_id!=$2", guildID, char.ID)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
for i := range charGuildmates {
|
||||
charGuildmates[i].CID = char.ID
|
||||
}
|
||||
guildmates = append(guildmates, charGuildmates...)
|
||||
}
|
||||
}
|
||||
return guildmates
|
||||
}
|
||||
|
||||
func (server *Server) deleteCharacter(cid int, token string, tokenID uint32) error {
|
||||
if !server.validateToken(token, tokenID) {
|
||||
return errors.New("invalid token")
|
||||
}
|
||||
var isNew bool
|
||||
err := server.db.QueryRow("SELECT is_new_character FROM characters WHERE id = $1", cid).Scan(&isNew)
|
||||
if isNew {
|
||||
_, err = server.db.Exec("DELETE FROM characters WHERE id = $1", cid)
|
||||
} else {
|
||||
_, err = server.db.Exec("UPDATE characters SET deleted = true WHERE id = $1", cid)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Unused
|
||||
func (server *Server) checkToken(uid uint32) (bool, error) {
|
||||
var exists int
|
||||
err := server.db.QueryRow("SELECT count(*) FROM sign_sessions WHERE user_id = $1", uid).Scan(&exists)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if exists > 0 {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (server *Server) registerUidToken(uid uint32) (uint32, string, error) {
|
||||
_token := token.Generate(16)
|
||||
var tid uint32
|
||||
err := server.db.QueryRow(`INSERT INTO sign_sessions (user_id, token) VALUES ($1, $2) RETURNING id`, uid, _token).Scan(&tid)
|
||||
return tid, _token, err
|
||||
}
|
||||
|
||||
func (server *Server) registerPsnToken(psn string) (uint32, string, error) {
|
||||
_token := token.Generate(16)
|
||||
var tid uint32
|
||||
err := server.db.QueryRow(`INSERT INTO sign_sessions (psn_id, token) VALUES ($1, $2) RETURNING id`, psn, _token).Scan(&tid)
|
||||
return tid, _token, err
|
||||
}
|
||||
|
||||
func (server *Server) validateToken(token string, tokenID uint32) bool {
|
||||
query := `SELECT count(*) FROM sign_sessions WHERE token = $1`
|
||||
if tokenID > 0 {
|
||||
query += ` AND id = $2`
|
||||
}
|
||||
var exists int
|
||||
err := server.db.QueryRow(query, token, tokenID).Scan(&exists)
|
||||
if err != nil || exists == 0 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (server *Server) validateLogin(user string, pass string) (uint32, RespID) {
|
||||
var uid uint32
|
||||
var passDB string
|
||||
err := server.db.QueryRow(`SELECT id, password FROM users WHERE username = $1`, user).Scan(&uid, &passDB)
|
||||
if err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
server.logger.Info("User not found", zap.String("User", user))
|
||||
if server.erupeConfig.AutoCreateAccount {
|
||||
uid, err = server.registerDBAccount(user, pass)
|
||||
if err == nil {
|
||||
return uid, SIGN_SUCCESS
|
||||
} else {
|
||||
return 0, SIGN_EABORT
|
||||
}
|
||||
}
|
||||
return 0, SIGN_EAUTH
|
||||
}
|
||||
return 0, SIGN_EABORT
|
||||
} else {
|
||||
if bcrypt.CompareHashAndPassword([]byte(passDB), []byte(pass)) == nil {
|
||||
var bans int
|
||||
err = server.db.QueryRow(`SELECT count(*) FROM bans WHERE user_id=$1 AND expires IS NULL`, uid).Scan(&bans)
|
||||
if err == nil && bans > 0 {
|
||||
return uid, SIGN_EELIMINATE
|
||||
}
|
||||
err = server.db.QueryRow(`SELECT count(*) FROM bans WHERE user_id=$1 AND expires > now()`, uid).Scan(&bans)
|
||||
if err == nil && bans > 0 {
|
||||
return uid, SIGN_ESUSPEND
|
||||
}
|
||||
return uid, SIGN_SUCCESS
|
||||
}
|
||||
return 0, SIGN_EPASS
|
||||
}
|
||||
}
|
||||
77
utils/db/db.go
Normal file
77
utils/db/db.go
Normal file
@@ -0,0 +1,77 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"erupe-ce/config"
|
||||
"erupe-ce/utils/logger"
|
||||
|
||||
"github.com/jmoiron/sqlx"
|
||||
_ "github.com/lib/pq" // Postgres driver
|
||||
)
|
||||
|
||||
var (
|
||||
instance *sqlx.DB
|
||||
once sync.Once
|
||||
dbLogger logger.Logger
|
||||
)
|
||||
|
||||
// InitDB initializes the database connection pool as a singleton
|
||||
func InitDB(config *config.Config) (*sqlx.DB, error) {
|
||||
dbLogger = logger.Get().Named("database")
|
||||
var err error
|
||||
once.Do(func() {
|
||||
// Create the postgres DB pool.
|
||||
connectString := fmt.Sprintf(
|
||||
"host='%s' port='%d' user='%s' password='%s' dbname='%s' sslmode=disable",
|
||||
config.Database.Host,
|
||||
config.Database.Port,
|
||||
config.Database.User,
|
||||
config.Database.Password,
|
||||
config.Database.Database,
|
||||
)
|
||||
|
||||
instance, err = sqlx.Open("postgres", connectString)
|
||||
if err != nil {
|
||||
return // Stop here if there's an error opening the database
|
||||
}
|
||||
|
||||
// Test the DB connection.
|
||||
err = instance.Ping()
|
||||
if err != nil {
|
||||
return // Stop here if there's an error pinging the database
|
||||
}
|
||||
dbLogger.Info("Database: Started successfully")
|
||||
|
||||
// Clear stale data
|
||||
if config.DebugOptions.ProxyPort == 0 {
|
||||
_ = instance.MustExec("DELETE FROM sign_sessions")
|
||||
}
|
||||
_ = instance.MustExec("DELETE FROM servers")
|
||||
_ = instance.MustExec(`UPDATE guild_characters SET treasure_hunt=NULL`)
|
||||
|
||||
// Clean the DB if the option is on.
|
||||
if config.DebugOptions.CleanDB {
|
||||
dbLogger.Info("Database: Started clearing...")
|
||||
cleanDB(instance)
|
||||
dbLogger.Info("Database: Finished clearing")
|
||||
}
|
||||
})
|
||||
return instance, err
|
||||
}
|
||||
|
||||
func GetDB() (*sqlx.DB, error) {
|
||||
if instance == nil {
|
||||
return nil, fmt.Errorf("database not initialized")
|
||||
}
|
||||
return instance, nil
|
||||
}
|
||||
|
||||
// Temporary DB auto clean on startup for quick development & testing.
|
||||
func cleanDB(db *sqlx.DB) {
|
||||
_ = db.MustExec("DELETE FROM guild_characters")
|
||||
_ = db.MustExec("DELETE FROM guilds")
|
||||
_ = db.MustExec("DELETE FROM characters")
|
||||
_ = db.MustExec("DELETE FROM users")
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package mhfcourse
|
||||
|
||||
import (
|
||||
_config "erupe-ce/config"
|
||||
"erupe-ce/config"
|
||||
"math"
|
||||
"sort"
|
||||
"time"
|
||||
@@ -68,7 +68,7 @@ func CourseExists(ID uint16, c []Course) bool {
|
||||
// GetCourseStruct returns a slice of Course(s) from a rights integer
|
||||
func GetCourseStruct(rights uint32) ([]Course, uint32) {
|
||||
var resp []Course
|
||||
for _, c := range _config.ErupeConfig.DefaultCourses {
|
||||
for _, c := range config.GetConfig().DefaultCourses {
|
||||
resp = append(resp, Course{ID: c})
|
||||
}
|
||||
s := Courses()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package mhfitem
|
||||
|
||||
import (
|
||||
_config "erupe-ce/config"
|
||||
"erupe-ce/config"
|
||||
"erupe-ce/utils/byteframe"
|
||||
"erupe-ce/utils/token"
|
||||
)
|
||||
@@ -114,7 +114,7 @@ func ReadWarehouseEquipment(bf *byteframe.ByteFrame) MHFEquipment {
|
||||
for i := 0; i < 3; i++ {
|
||||
equipment.Decorations[i].ItemID = bf.ReadUint16()
|
||||
}
|
||||
if _config.ErupeConfig.ClientID >= _config.G1 {
|
||||
if config.GetConfig().ClientID >= config.G1 {
|
||||
for i := 0; i < 3; i++ {
|
||||
for j := 0; j < 3; j++ {
|
||||
equipment.Sigils[i].Effects[j].ID = bf.ReadUint16()
|
||||
@@ -128,7 +128,7 @@ func ReadWarehouseEquipment(bf *byteframe.ByteFrame) MHFEquipment {
|
||||
equipment.Sigils[i].Unk3 = bf.ReadUint8()
|
||||
}
|
||||
}
|
||||
if _config.ErupeConfig.ClientID >= _config.Z1 {
|
||||
if config.GetConfig().ClientID >= config.Z1 {
|
||||
equipment.Unk1 = bf.ReadUint16()
|
||||
}
|
||||
return equipment
|
||||
@@ -144,7 +144,7 @@ func (e MHFEquipment) ToBytes() []byte {
|
||||
for i := 0; i < 3; i++ {
|
||||
bf.WriteUint16(e.Decorations[i].ItemID)
|
||||
}
|
||||
if _config.ErupeConfig.ClientID >= _config.G1 {
|
||||
if config.GetConfig().ClientID >= config.G1 {
|
||||
for i := 0; i < 3; i++ {
|
||||
for j := 0; j < 3; j++ {
|
||||
bf.WriteUint16(e.Sigils[i].Effects[j].ID)
|
||||
@@ -158,7 +158,7 @@ func (e MHFEquipment) ToBytes() []byte {
|
||||
bf.WriteUint8(e.Sigils[i].Unk3)
|
||||
}
|
||||
}
|
||||
if _config.ErupeConfig.ClientID >= _config.Z1 {
|
||||
if config.GetConfig().ClientID >= config.Z1 {
|
||||
bf.WriteUint16(e.Unk1)
|
||||
}
|
||||
return bf.Data()
|
||||
|
||||
Reference in New Issue
Block a user