mirror of
https://github.com/Mezeporta/Erupe.git
synced 2026-02-04 09:15:08 +01:00
Merge branch 'main' into feature/discord-login
This commit is contained in:
@@ -5,6 +5,42 @@ INSERT INTO public.shop_items
|
|||||||
VALUES
|
VALUES
|
||||||
(5,5,16516,100,1,0,0,1,0,0,0,0),
|
(5,5,16516,100,1,0,0,1,0,0,0,0),
|
||||||
(5,5,16517,100,1,0,0,1,0,0,0,0),
|
(5,5,16517,100,1,0,0,1,0,0,0,0),
|
||||||
|
(6,5,9958,3,3,1,0,0,0,0,0,0),
|
||||||
|
(6,5,1897,3,1,1,0,0,0,0,0,0),
|
||||||
|
(6,5,8889,3,1,0,0,1,0,0,0,0),
|
||||||
|
(6,5,6176,3,6,1,0,0,0,0,0,0),
|
||||||
|
(6,5,1472,3,10,1,0,0,0,0,0,0),
|
||||||
|
(6,5,7280,3,3,0,0,1,0,0,0,0),
|
||||||
|
(6,5,8027,3,30,1,0,0,0,0,0,0),
|
||||||
|
(6,5,8028,3,30,1,0,0,0,0,0,0),
|
||||||
|
(6,5,8029,3,30,1,0,0,0,0,0,0),
|
||||||
|
(6,5,8026,3,30,1,0,0,0,0,0,0),
|
||||||
|
(6,5,8030,3,30,1,0,0,0,0,0,0),
|
||||||
|
(6,5,4353,3,30,1,0,0,0,0,0,0),
|
||||||
|
(6,5,4354,3,30,1,0,0,0,0,0,0),
|
||||||
|
(6,5,4355,3,30,1,0,0,0,0,0,0),
|
||||||
|
(6,5,4356,3,30,1,0,0,0,0,0,0),
|
||||||
|
(6,5,4357,3,30,1,0,0,0,0,0,0),
|
||||||
|
(6,5,4745,3,30,1,0,0,0,0,0,0),
|
||||||
|
(6,5,4746,3,30,1,0,0,0,0,0,0),
|
||||||
|
(6,5,4747,3,30,1,0,0,0,0,0,0),
|
||||||
|
(6,5,4748,3,30,1,0,0,0,0,0,0),
|
||||||
|
(6,5,4749,3,30,1,0,0,0,0,0,0),
|
||||||
|
(6,5,5122,3,30,1,0,0,0,0,0,0),
|
||||||
|
(6,5,5123,3,30,1,0,0,0,0,0,0),
|
||||||
|
(6,5,5124,3,30,1,0,0,0,0,0,0),
|
||||||
|
(6,5,5125,3,30,1,0,0,0,0,0,0),
|
||||||
|
(6,5,5126,3,30,1,0,0,0,0,0,0),
|
||||||
|
(6,5,5795,3,30,1,0,0,0,0,0,0),
|
||||||
|
(6,5,5796,3,30,1,0,0,0,0,0,0),
|
||||||
|
(6,5,5797,3,30,1,0,0,0,0,0,0),
|
||||||
|
(6,5,5798,3,30,1,0,0,0,0,0,0),
|
||||||
|
(6,5,5799,3,30,1,0,0,0,0,0,0),
|
||||||
|
(6,5,6168,3,30,1,0,0,0,0,0,0),
|
||||||
|
(6,5,6169,3,30,1,0,0,0,0,0,0),
|
||||||
|
(6,5,6170,3,30,1,0,0,0,0,0,0),
|
||||||
|
(6,5,6171,3,30,1,0,0,0,0,0,0),
|
||||||
|
(6,5,6172,3,30,1,0,0,0,0,0,0),
|
||||||
(7,0,13190,10,1,0,0,0,0,0,0,0),
|
(7,0,13190,10,1,0,0,0,0,0,0,0),
|
||||||
(7,0,1662,10,1,0,0,0,0,0,0,0),
|
(7,0,1662,10,1,0,0,0,0,0,0,0),
|
||||||
(7,0,10179,100,1,0,0,0,0,0,0,0);
|
(7,0,10179,100,1,0,0,0,0,0,0,0);
|
||||||
|
|||||||
15
config.json
15
config.json
@@ -14,6 +14,7 @@
|
|||||||
"ClientMode": "ZZ",
|
"ClientMode": "ZZ",
|
||||||
"QuestCacheExpiry": 300,
|
"QuestCacheExpiry": 300,
|
||||||
"ProxyPort": 0,
|
"ProxyPort": 0,
|
||||||
|
"CommandPrefix": "!",
|
||||||
"DevMode": true,
|
"DevMode": true,
|
||||||
"DevModeOptions": {
|
"DevModeOptions": {
|
||||||
"AutoCreateAccount": true,
|
"AutoCreateAccount": true,
|
||||||
@@ -30,7 +31,7 @@
|
|||||||
"QuestDebugTools": false,
|
"QuestDebugTools": false,
|
||||||
"EarthStatusOverride": 0,
|
"EarthStatusOverride": 0,
|
||||||
"EarthIDOverride": 0,
|
"EarthIDOverride": 0,
|
||||||
"EarthMonsterOverride": 0,
|
"EarthMonsterOverride": [0, 0, 0, 0],
|
||||||
"SaveDumps": {
|
"SaveDumps": {
|
||||||
"Enabled": true,
|
"Enabled": true,
|
||||||
"OutputDir": "save-backups"
|
"OutputDir": "save-backups"
|
||||||
@@ -82,32 +83,44 @@
|
|||||||
},
|
},
|
||||||
"Commands": [
|
"Commands": [
|
||||||
{
|
{
|
||||||
|
"Name": "Help",
|
||||||
|
"Enabled": true,
|
||||||
|
"Description": "Show enabled chat commands",
|
||||||
|
"Prefix": "help"
|
||||||
|
}, {
|
||||||
"Name": "Rights",
|
"Name": "Rights",
|
||||||
"Enabled": false,
|
"Enabled": false,
|
||||||
|
"Description": "Overwrite the Rights value on your account",
|
||||||
"Prefix": "rights"
|
"Prefix": "rights"
|
||||||
}, {
|
}, {
|
||||||
"Name": "Raviente",
|
"Name": "Raviente",
|
||||||
"Enabled": true,
|
"Enabled": true,
|
||||||
|
"Description": "Various Raviente siege commands",
|
||||||
"Prefix": "ravi"
|
"Prefix": "ravi"
|
||||||
}, {
|
}, {
|
||||||
"Name": "Teleport",
|
"Name": "Teleport",
|
||||||
"Enabled": false,
|
"Enabled": false,
|
||||||
|
"Description": "Teleport to specified coordinates",
|
||||||
"Prefix": "tele"
|
"Prefix": "tele"
|
||||||
}, {
|
}, {
|
||||||
"Name": "Reload",
|
"Name": "Reload",
|
||||||
"Enabled": true,
|
"Enabled": true,
|
||||||
|
"Description": "Reload all players in your Land",
|
||||||
"Prefix": "reload"
|
"Prefix": "reload"
|
||||||
}, {
|
}, {
|
||||||
"Name": "KeyQuest",
|
"Name": "KeyQuest",
|
||||||
"Enabled": false,
|
"Enabled": false,
|
||||||
|
"Description": "Overwrite your HR Key Quest progress",
|
||||||
"Prefix": "kqf"
|
"Prefix": "kqf"
|
||||||
}, {
|
}, {
|
||||||
"Name": "Course",
|
"Name": "Course",
|
||||||
"Enabled": true,
|
"Enabled": true,
|
||||||
|
"Description": "Toggle Courses on your account",
|
||||||
"Prefix": "course"
|
"Prefix": "course"
|
||||||
}, {
|
}, {
|
||||||
"Name": "PSN",
|
"Name": "PSN",
|
||||||
"Enabled": true,
|
"Enabled": true,
|
||||||
|
"Description": "Link a PlayStation Network ID to your account",
|
||||||
"Prefix": "psn"
|
"Prefix": "psn"
|
||||||
}, {
|
}, {
|
||||||
"Name": "Discord",
|
"Name": "Discord",
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ type Config struct {
|
|||||||
RealClientMode Mode
|
RealClientMode Mode
|
||||||
QuestCacheExpiry int // Number of seconds to keep quest data cached
|
QuestCacheExpiry int // Number of seconds to keep quest data cached
|
||||||
ProxyPort uint16 // Forces the game to connect to a channel server proxy
|
ProxyPort uint16 // Forces the game to connect to a channel server proxy
|
||||||
|
CommandPrefix string // The prefix for commands
|
||||||
DevMode bool
|
DevMode bool
|
||||||
|
|
||||||
DevModeOptions DevModeOptions
|
DevModeOptions DevModeOptions
|
||||||
@@ -111,7 +112,7 @@ type DevModeOptions struct {
|
|||||||
QuestDebugTools bool // Enable various quest debug logs
|
QuestDebugTools bool // Enable various quest debug logs
|
||||||
EarthStatusOverride int32
|
EarthStatusOverride int32
|
||||||
EarthIDOverride int32
|
EarthIDOverride int32
|
||||||
EarthMonsterOverride int32
|
EarthMonsterOverride []int32
|
||||||
SaveDumps SaveDumpOptions
|
SaveDumps SaveDumpOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,6 +176,7 @@ type DiscordRealTime struct {
|
|||||||
type Command struct {
|
type Command struct {
|
||||||
Name string
|
Name string
|
||||||
Enabled bool
|
Enabled bool
|
||||||
|
Description string
|
||||||
Prefix string
|
Prefix string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ type MsgMhfEnumerateShop struct {
|
|||||||
AckHandle uint32
|
AckHandle uint32
|
||||||
ShopType uint8 // 1 running gachas, 10 normal shop extensions, 8 Diva Defense shop
|
ShopType uint8 // 1 running gachas, 10 normal shop extensions, 8 Diva Defense shop
|
||||||
ShopID uint32
|
ShopID uint32
|
||||||
Unk2 uint16 // 00 80 running gachas, 00 20 normal shop
|
Limit uint16
|
||||||
Unk3 uint8
|
Unk3 uint8
|
||||||
Unk4 uint8
|
Unk4 uint8
|
||||||
Unk5 uint32
|
Unk5 uint32
|
||||||
@@ -30,7 +30,7 @@ func (m *MsgMhfEnumerateShop) Parse(bf *byteframe.ByteFrame, ctx *clientctx.Clie
|
|||||||
m.AckHandle = bf.ReadUint32()
|
m.AckHandle = bf.ReadUint32()
|
||||||
m.ShopType = bf.ReadUint8()
|
m.ShopType = bf.ReadUint8()
|
||||||
m.ShopID = bf.ReadUint32()
|
m.ShopID = bf.ReadUint32()
|
||||||
m.Unk2 = bf.ReadUint16()
|
m.Limit = bf.ReadUint16()
|
||||||
m.Unk3 = bf.ReadUint8()
|
m.Unk3 = bf.ReadUint8()
|
||||||
if _config.ErupeConfig.RealClientMode >= _config.G2 {
|
if _config.ErupeConfig.RealClientMode >= _config.G2 {
|
||||||
m.Unk4 = bf.ReadUint8()
|
m.Unk4 = bf.ReadUint8()
|
||||||
|
|||||||
@@ -3,13 +3,22 @@ package mhfpacket
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"erupe-ce/network/clientctx"
|
|
||||||
"erupe-ce/network"
|
|
||||||
"erupe-ce/common/byteframe"
|
"erupe-ce/common/byteframe"
|
||||||
|
"erupe-ce/network"
|
||||||
|
"erupe-ce/network/clientctx"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MsgMhfPostSeibattle represents the MSG_MHF_POST_SEIBATTLE
|
// MsgMhfPostSeibattle represents the MSG_MHF_POST_SEIBATTLE
|
||||||
type MsgMhfPostSeibattle struct{}
|
type MsgMhfPostSeibattle struct {
|
||||||
|
AckHandle uint32
|
||||||
|
Unk0 uint8
|
||||||
|
Unk1 uint8
|
||||||
|
Unk2 uint32
|
||||||
|
Unk3 uint8
|
||||||
|
Unk4 uint16
|
||||||
|
Unk5 uint16
|
||||||
|
Unk6 uint8
|
||||||
|
}
|
||||||
|
|
||||||
// Opcode returns the ID associated with this packet type.
|
// Opcode returns the ID associated with this packet type.
|
||||||
func (m *MsgMhfPostSeibattle) Opcode() network.PacketID {
|
func (m *MsgMhfPostSeibattle) Opcode() network.PacketID {
|
||||||
@@ -18,7 +27,15 @@ func (m *MsgMhfPostSeibattle) Opcode() network.PacketID {
|
|||||||
|
|
||||||
// Parse parses the packet from binary
|
// Parse parses the packet from binary
|
||||||
func (m *MsgMhfPostSeibattle) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
func (m *MsgMhfPostSeibattle) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||||
return errors.New("NOT IMPLEMENTED")
|
m.AckHandle = bf.ReadUint32()
|
||||||
|
m.Unk0 = bf.ReadUint8()
|
||||||
|
m.Unk1 = bf.ReadUint8()
|
||||||
|
m.Unk2 = bf.ReadUint32()
|
||||||
|
m.Unk3 = bf.ReadUint8()
|
||||||
|
m.Unk4 = bf.ReadUint16()
|
||||||
|
m.Unk5 = bf.ReadUint16()
|
||||||
|
m.Unk6 = bf.ReadUint8()
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build builds a binary packet from the current data.
|
// Build builds a binary packet from the current data.
|
||||||
|
|||||||
@@ -992,10 +992,17 @@ func handleMsgMhfGetEarthStatus(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
bf.WriteUint32(uint32(TimeWeekNext().Unix())) // End
|
bf.WriteUint32(uint32(TimeWeekNext().Unix())) // End
|
||||||
bf.WriteInt32(s.server.erupeConfig.DevModeOptions.EarthStatusOverride)
|
bf.WriteInt32(s.server.erupeConfig.DevModeOptions.EarthStatusOverride)
|
||||||
bf.WriteInt32(s.server.erupeConfig.DevModeOptions.EarthIDOverride)
|
bf.WriteInt32(s.server.erupeConfig.DevModeOptions.EarthIDOverride)
|
||||||
bf.WriteInt32(s.server.erupeConfig.DevModeOptions.EarthMonsterOverride)
|
for i, m := range s.server.erupeConfig.DevModeOptions.EarthMonsterOverride {
|
||||||
bf.WriteInt32(0)
|
if _config.ErupeConfig.RealClientMode <= _config.G9 {
|
||||||
bf.WriteInt32(0)
|
if i == 3 {
|
||||||
bf.WriteInt32(0)
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if i == 4 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
bf.WriteInt32(m)
|
||||||
|
}
|
||||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1195,7 +1202,10 @@ func handleMsgMhfGetSeibattle(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
doAckEarthSucceed(s, pkt.AckHandle, data)
|
doAckEarthSucceed(s, pkt.AckHandle, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleMsgMhfPostSeibattle(s *Session, p mhfpacket.MHFPacket) {}
|
func handleMsgMhfPostSeibattle(s *Session, p mhfpacket.MHFPacket) {
|
||||||
|
pkt := p.(*mhfpacket.MsgMhfPostSeibattle)
|
||||||
|
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||||
|
}
|
||||||
|
|
||||||
func handleMsgMhfGetDailyMissionMaster(s *Session, p mhfpacket.MHFPacket) {}
|
func handleMsgMhfGetDailyMissionMaster(s *Session, p mhfpacket.MHFPacket) {}
|
||||||
|
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ func sendServerChatMessage(s *Session, message string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func parseChatCommand(s *Session, command string) {
|
func parseChatCommand(s *Session, command string) {
|
||||||
args := strings.Split(command[1:], " ")
|
args := strings.Split(command[len(s.server.erupeConfig.CommandPrefix):], " ")
|
||||||
switch args[0] {
|
switch args[0] {
|
||||||
case commands["PSN"].Prefix:
|
case commands["PSN"].Prefix:
|
||||||
if commands["PSN"].Enabled {
|
if commands["PSN"].Enabled {
|
||||||
@@ -344,6 +344,15 @@ func parseChatCommand(s *Session, command string) {
|
|||||||
sendServerChatMessage(s, fmt.Sprintf(s.server.dict["commandDiscordSuccess"], discordToken))
|
sendServerChatMessage(s, fmt.Sprintf(s.server.dict["commandDiscordSuccess"], discordToken))
|
||||||
} else {
|
} else {
|
||||||
sendDisabledCommandMessage(s, commands["Discord"])
|
sendDisabledCommandMessage(s, commands["Discord"])
|
||||||
|
case commands["Help"].Prefix:
|
||||||
|
if commands["Help"].Enabled {
|
||||||
|
for _, command := range commands {
|
||||||
|
if command.Enabled {
|
||||||
|
sendServerChatMessage(s, fmt.Sprintf("%s%s: %s", s.server.erupeConfig.CommandPrefix, command.Prefix, command.Description))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sendDisabledCommandMessage(s, commands["Help"])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -418,7 +427,7 @@ func handleMsgSysCastBinary(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
bf.SetLE()
|
bf.SetLE()
|
||||||
chatMessage := &binpacket.MsgBinChat{}
|
chatMessage := &binpacket.MsgBinChat{}
|
||||||
chatMessage.Parse(bf)
|
chatMessage.Parse(bf)
|
||||||
if strings.HasPrefix(chatMessage.Message, "!") {
|
if strings.HasPrefix(chatMessage.Message, s.server.erupeConfig.CommandPrefix) {
|
||||||
parseChatCommand(s, chatMessage.Message)
|
parseChatCommand(s, chatMessage.Message)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ func handleMsgMhfGetUdSchedule(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
var timestamps []uint32
|
var timestamps []uint32
|
||||||
if s.server.erupeConfig.DevMode && s.server.erupeConfig.DevModeOptions.DivaEvent >= 0 {
|
if s.server.erupeConfig.DevMode && s.server.erupeConfig.DevModeOptions.DivaEvent >= 0 {
|
||||||
if s.server.erupeConfig.DevModeOptions.DivaEvent == 0 {
|
if s.server.erupeConfig.DevModeOptions.DivaEvent == 0 {
|
||||||
if s.server.erupeConfig.RealClientMode <= _config.Z1 {
|
if s.server.erupeConfig.RealClientMode >= _config.Z2 {
|
||||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 32))
|
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 32))
|
||||||
} else {
|
} else {
|
||||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 36))
|
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 36))
|
||||||
@@ -84,7 +84,7 @@ func handleMsgMhfGetUdSchedule(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
timestamps = generateDivaTimestamps(s, start, false)
|
timestamps = generateDivaTimestamps(s, start, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.server.erupeConfig.RealClientMode <= _config.Z1 {
|
if s.server.erupeConfig.RealClientMode >= _config.Z2 {
|
||||||
bf.WriteUint32(id)
|
bf.WriteUint32(id)
|
||||||
}
|
}
|
||||||
for i := range timestamps {
|
for i := range timestamps {
|
||||||
|
|||||||
@@ -262,66 +262,55 @@ func handleMsgMhfLoadDecoMyset(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
|
|
||||||
func handleMsgMhfSaveDecoMyset(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgMhfSaveDecoMyset(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgMhfSaveDecoMyset)
|
pkt := p.(*mhfpacket.MsgMhfSaveDecoMyset)
|
||||||
// TODO: Backwards compatibility for DecoMyset
|
var temp []byte
|
||||||
if s.server.erupeConfig.RealClientMode < _config.ZZ {
|
err := s.server.db.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))
|
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// https://gist.github.com/Andoryuuta/9c524da7285e4b5ca7e52e0fc1ca1daf
|
|
||||||
var loadData []byte
|
// Version handling
|
||||||
bf := byteframe.NewByteFrameFromBytes(pkt.RawDataPayload[1:]) // skip first unk byte
|
bf := byteframe.NewByteFrame()
|
||||||
err := s.server.db.QueryRow("SELECT decomyset FROM characters WHERE id = $1", s.charID).Scan(&loadData)
|
var size uint
|
||||||
if err != nil {
|
if s.server.erupeConfig.RealClientMode >= _config.G10 {
|
||||||
s.logger.Error("Failed to load decomyset", zap.Error(err))
|
size = 76
|
||||||
|
bf.WriteUint8(1)
|
||||||
} else {
|
} else {
|
||||||
numSets := bf.ReadUint8() // sets being written
|
size = 68
|
||||||
// empty save
|
bf.WriteUint8(0)
|
||||||
if len(loadData) == 0 {
|
|
||||||
loadData = []byte{0x01, 0x00}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
savedSets := loadData[1] // existing saved sets
|
// Handle nil data
|
||||||
// no sets, new slice with just first 2 bytes for appends later
|
if len(temp) == 0 {
|
||||||
if savedSets == 0 {
|
temp = append(bf.Data(), uint8(0))
|
||||||
loadData = []byte{0x01, 0x00}
|
|
||||||
}
|
}
|
||||||
for i := 0; i < int(numSets); i++ {
|
|
||||||
writeSet := bf.ReadUint16()
|
// Build a map of set data
|
||||||
dataChunk := bf.ReadBytes(76)
|
sets := make(map[uint16][]byte)
|
||||||
setBytes := append([]byte{uint8(writeSet >> 8), uint8(writeSet & 0xff)}, dataChunk...)
|
oldSets := byteframe.NewByteFrameFromBytes(temp[2:])
|
||||||
for x := 0; true; x++ {
|
for i := uint8(0); i < temp[1]; i++ {
|
||||||
if x == int(savedSets) {
|
index := oldSets.ReadUint16()
|
||||||
// appending set
|
sets[index] = oldSets.ReadBytes(size)
|
||||||
if loadData[len(loadData)-1] == 0x10 {
|
|
||||||
// sanity check for if there was a messy manual import
|
|
||||||
loadData = append(loadData[:len(loadData)-2], setBytes...)
|
|
||||||
} else {
|
|
||||||
loadData = append(loadData, setBytes...)
|
|
||||||
}
|
}
|
||||||
savedSets++
|
|
||||||
break
|
// Overwrite existing sets
|
||||||
|
newSets := byteframe.NewByteFrameFromBytes(pkt.RawDataPayload[2:])
|
||||||
|
for i := uint8(0); i < pkt.RawDataPayload[1]; i++ {
|
||||||
|
index := newSets.ReadUint16()
|
||||||
|
sets[index] = newSets.ReadBytes(size)
|
||||||
}
|
}
|
||||||
currentSet := loadData[3+(x*78)]
|
|
||||||
if int(currentSet) == int(writeSet) {
|
// Serialise the set data
|
||||||
// replacing a set
|
bf.WriteUint8(uint8(len(sets)))
|
||||||
loadData = append(loadData[:2+(x*78)], append(setBytes, loadData[2+((x+1)*78):]...)...)
|
for u, b := range sets {
|
||||||
break
|
bf.WriteUint16(u)
|
||||||
} else if int(currentSet) > int(writeSet) {
|
bf.WriteBytes(b)
|
||||||
// inserting before current set
|
|
||||||
loadData = append(loadData[:2+((x)*78)], append(setBytes, loadData[2+((x)*78):]...)...)
|
|
||||||
savedSets++
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
loadData[1] = savedSets // update set count
|
dumpSaveData(s, bf.Data(), "decomyset")
|
||||||
}
|
s.server.db.Exec("UPDATE characters SET decomyset=$1 WHERE id=$2", bf.Data(), s.charID)
|
||||||
dumpSaveData(s, loadData, "decomyset")
|
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||||
_, err := s.server.db.Exec("UPDATE characters SET decomyset=$1 WHERE id=$2", loadData, s.charID)
|
|
||||||
if err != nil {
|
|
||||||
s.logger.Error("Failed to save decomyset", zap.Error(err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Title struct {
|
type Title struct {
|
||||||
|
|||||||
@@ -10,13 +10,13 @@ import (
|
|||||||
|
|
||||||
type ShopItem struct {
|
type ShopItem struct {
|
||||||
ID uint32 `db:"id"`
|
ID uint32 `db:"id"`
|
||||||
ItemID uint16 `db:"item_id"`
|
ItemID uint32 `db:"item_id"`
|
||||||
Cost uint32 `db:"cost"`
|
Cost uint32 `db:"cost"`
|
||||||
Quantity uint16 `db:"quantity"`
|
Quantity uint16 `db:"quantity"`
|
||||||
MinHR uint16 `db:"min_hr"`
|
MinHR uint16 `db:"min_hr"`
|
||||||
MinSR uint16 `db:"min_sr"`
|
MinSR uint16 `db:"min_sr"`
|
||||||
MinGR uint16 `db:"min_gr"`
|
MinGR uint16 `db:"min_gr"`
|
||||||
StoreLevel uint16 `db:"store_level"`
|
StoreLevel uint8 `db:"store_level"`
|
||||||
MaxQuantity uint16 `db:"max_quantity"`
|
MaxQuantity uint16 `db:"max_quantity"`
|
||||||
UsedQuantity uint16 `db:"used_quantity"`
|
UsedQuantity uint16 `db:"used_quantity"`
|
||||||
RoadFloors uint16 `db:"road_floors"`
|
RoadFloors uint16 `db:"road_floors"`
|
||||||
@@ -61,21 +61,32 @@ func writeShopItems(bf *byteframe.ByteFrame, items []ShopItem) {
|
|||||||
bf.WriteUint16(uint16(len(items)))
|
bf.WriteUint16(uint16(len(items)))
|
||||||
bf.WriteUint16(uint16(len(items)))
|
bf.WriteUint16(uint16(len(items)))
|
||||||
for _, item := range items {
|
for _, item := range items {
|
||||||
|
if _config.ErupeConfig.RealClientMode >= _config.Z2 {
|
||||||
bf.WriteUint32(item.ID)
|
bf.WriteUint32(item.ID)
|
||||||
bf.WriteUint16(0)
|
}
|
||||||
bf.WriteUint16(item.ItemID)
|
bf.WriteUint32(item.ItemID)
|
||||||
bf.WriteUint32(item.Cost)
|
bf.WriteUint32(item.Cost)
|
||||||
bf.WriteUint16(item.Quantity)
|
bf.WriteUint16(item.Quantity)
|
||||||
bf.WriteUint16(item.MinHR)
|
bf.WriteUint16(item.MinHR)
|
||||||
bf.WriteUint16(item.MinSR)
|
bf.WriteUint16(item.MinSR)
|
||||||
|
if _config.ErupeConfig.RealClientMode >= _config.Z2 {
|
||||||
bf.WriteUint16(item.MinGR)
|
bf.WriteUint16(item.MinGR)
|
||||||
bf.WriteUint16(item.StoreLevel)
|
}
|
||||||
|
bf.WriteUint8(0) // Unk
|
||||||
|
bf.WriteUint8(item.StoreLevel)
|
||||||
|
if _config.ErupeConfig.RealClientMode >= _config.Z2 {
|
||||||
bf.WriteUint16(item.MaxQuantity)
|
bf.WriteUint16(item.MaxQuantity)
|
||||||
bf.WriteUint16(item.UsedQuantity)
|
bf.WriteUint16(item.UsedQuantity)
|
||||||
|
}
|
||||||
|
if _config.ErupeConfig.RealClientMode == _config.Z1 {
|
||||||
|
bf.WriteUint8(uint8(item.RoadFloors))
|
||||||
|
bf.WriteUint8(uint8(item.RoadFatalis))
|
||||||
|
} else if _config.ErupeConfig.RealClientMode >= _config.Z2 {
|
||||||
bf.WriteUint16(item.RoadFloors)
|
bf.WriteUint16(item.RoadFloors)
|
||||||
bf.WriteUint16(item.RoadFatalis)
|
bf.WriteUint16(item.RoadFatalis)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func getShopItems(s *Session, shopType uint8, shopID uint32) []ShopItem {
|
func getShopItems(s *Session, shopType uint8, shopID uint32) []ShopItem {
|
||||||
var items []ShopItem
|
var items []ShopItem
|
||||||
@@ -241,6 +252,9 @@ func handleMsgMhfEnumerateShop(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
case 10: // Item shop, 0-8
|
case 10: // Item shop, 0-8
|
||||||
bf := byteframe.NewByteFrame()
|
bf := byteframe.NewByteFrame()
|
||||||
items := getShopItems(s, pkt.ShopType, pkt.ShopID)
|
items := getShopItems(s, pkt.ShopType, pkt.ShopID)
|
||||||
|
if len(items) > int(pkt.Limit) {
|
||||||
|
items = items[:pkt.Limit]
|
||||||
|
}
|
||||||
writeShopItems(bf, items)
|
writeShopItems(bf, items)
|
||||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -171,8 +171,8 @@ func handleMsgSysBackStage(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
|
|
||||||
// Transfer back to the saved stage ID before the previous move or enter.
|
// Transfer back to the saved stage ID before the previous move or enter.
|
||||||
backStage, err := s.stageMoveStack.Pop()
|
backStage, err := s.stageMoveStack.Pop()
|
||||||
if err != nil {
|
if backStage == "" || err != nil {
|
||||||
panic(err)
|
backStage = "sl1Ns200p0a0u0"
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, exists := s.stage.reservedClientSlots[s.charID]; exists {
|
if _, exists := s.stage.reservedClientSlots[s.charID]; exists {
|
||||||
|
|||||||
@@ -126,8 +126,9 @@ func handleMsgMhfPostTowerInfo(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
skills := "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0"
|
skills := "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0"
|
||||||
s.server.db.QueryRow(`SELECT skills FROM tower WHERE char_id=$1`, s.charID).Scan(&skills)
|
s.server.db.QueryRow(`SELECT skills FROM tower WHERE char_id=$1`, 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)
|
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)
|
||||||
case 7:
|
case 1, 7:
|
||||||
s.server.db.Exec(`UPDATE tower SET tr=$1, trp=trp+$2, block1=block1+$3 WHERE char_id=$4`, pkt.TR, pkt.TRP, pkt.Block1, s.charID)
|
// 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)
|
||||||
}
|
}
|
||||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user