mirror of
https://github.com/Mezeporta/Erupe.git
synced 2025-12-13 15:34:38 +01:00
Merge branch 'main' into feature/discord-login
This commit is contained in:
@@ -992,10 +992,17 @@ func handleMsgMhfGetEarthStatus(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint32(uint32(TimeWeekNext().Unix())) // End
|
||||
bf.WriteInt32(s.server.erupeConfig.DevModeOptions.EarthStatusOverride)
|
||||
bf.WriteInt32(s.server.erupeConfig.DevModeOptions.EarthIDOverride)
|
||||
bf.WriteInt32(s.server.erupeConfig.DevModeOptions.EarthMonsterOverride)
|
||||
bf.WriteInt32(0)
|
||||
bf.WriteInt32(0)
|
||||
bf.WriteInt32(0)
|
||||
for i, m := range s.server.erupeConfig.DevModeOptions.EarthMonsterOverride {
|
||||
if _config.ErupeConfig.RealClientMode <= _config.G9 {
|
||||
if i == 3 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if i == 4 {
|
||||
break
|
||||
}
|
||||
bf.WriteInt32(m)
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
@@ -1195,7 +1202,10 @@ func handleMsgMhfGetSeibattle(s *Session, p mhfpacket.MHFPacket) {
|
||||
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) {}
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ func sendServerChatMessage(s *Session, message string) {
|
||||
}
|
||||
|
||||
func parseChatCommand(s *Session, command string) {
|
||||
args := strings.Split(command[1:], " ")
|
||||
args := strings.Split(command[len(s.server.erupeConfig.CommandPrefix):], " ")
|
||||
switch args[0] {
|
||||
case commands["PSN"].Prefix:
|
||||
if commands["PSN"].Enabled {
|
||||
@@ -344,6 +344,15 @@ func parseChatCommand(s *Session, command string) {
|
||||
sendServerChatMessage(s, fmt.Sprintf(s.server.dict["commandDiscordSuccess"], discordToken))
|
||||
} else {
|
||||
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()
|
||||
chatMessage := &binpacket.MsgBinChat{}
|
||||
chatMessage.Parse(bf)
|
||||
if strings.HasPrefix(chatMessage.Message, "!") {
|
||||
if strings.HasPrefix(chatMessage.Message, s.server.erupeConfig.CommandPrefix) {
|
||||
parseChatCommand(s, chatMessage.Message)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ func handleMsgMhfGetUdSchedule(s *Session, p mhfpacket.MHFPacket) {
|
||||
var timestamps []uint32
|
||||
if s.server.erupeConfig.DevMode && 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))
|
||||
} else {
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 36))
|
||||
@@ -84,7 +84,7 @@ func handleMsgMhfGetUdSchedule(s *Session, p mhfpacket.MHFPacket) {
|
||||
timestamps = generateDivaTimestamps(s, start, false)
|
||||
}
|
||||
|
||||
if s.server.erupeConfig.RealClientMode <= _config.Z1 {
|
||||
if s.server.erupeConfig.RealClientMode >= _config.Z2 {
|
||||
bf.WriteUint32(id)
|
||||
}
|
||||
for i := range timestamps {
|
||||
|
||||
@@ -262,66 +262,55 @@ func handleMsgMhfLoadDecoMyset(s *Session, p mhfpacket.MHFPacket) {
|
||||
|
||||
func handleMsgMhfSaveDecoMyset(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfSaveDecoMyset)
|
||||
// TODO: Backwards compatibility for DecoMyset
|
||||
if s.server.erupeConfig.RealClientMode < _config.ZZ {
|
||||
var temp []byte
|
||||
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))
|
||||
return
|
||||
}
|
||||
// https://gist.github.com/Andoryuuta/9c524da7285e4b5ca7e52e0fc1ca1daf
|
||||
var loadData []byte
|
||||
bf := byteframe.NewByteFrameFromBytes(pkt.RawDataPayload[1:]) // skip first unk byte
|
||||
err := s.server.db.QueryRow("SELECT decomyset FROM characters WHERE id = $1", s.charID).Scan(&loadData)
|
||||
if err != nil {
|
||||
s.logger.Error("Failed to load decomyset", zap.Error(err))
|
||||
} else {
|
||||
numSets := bf.ReadUint8() // sets being written
|
||||
// empty save
|
||||
if len(loadData) == 0 {
|
||||
loadData = []byte{0x01, 0x00}
|
||||
}
|
||||
|
||||
savedSets := loadData[1] // existing saved sets
|
||||
// no sets, new slice with just first 2 bytes for appends later
|
||||
if savedSets == 0 {
|
||||
loadData = []byte{0x01, 0x00}
|
||||
}
|
||||
for i := 0; i < int(numSets); i++ {
|
||||
writeSet := bf.ReadUint16()
|
||||
dataChunk := bf.ReadBytes(76)
|
||||
setBytes := append([]byte{uint8(writeSet >> 8), uint8(writeSet & 0xff)}, dataChunk...)
|
||||
for x := 0; true; x++ {
|
||||
if x == int(savedSets) {
|
||||
// appending set
|
||||
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
|
||||
}
|
||||
currentSet := loadData[3+(x*78)]
|
||||
if int(currentSet) == int(writeSet) {
|
||||
// replacing a set
|
||||
loadData = append(loadData[:2+(x*78)], append(setBytes, loadData[2+((x+1)*78):]...)...)
|
||||
break
|
||||
} else if int(currentSet) > int(writeSet) {
|
||||
// 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, loadData, "decomyset")
|
||||
_, 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))
|
||||
}
|
||||
// Version handling
|
||||
bf := byteframe.NewByteFrame()
|
||||
var size uint
|
||||
if s.server.erupeConfig.RealClientMode >= _config.G10 {
|
||||
size = 76
|
||||
bf.WriteUint8(1)
|
||||
} else {
|
||||
size = 68
|
||||
bf.WriteUint8(0)
|
||||
}
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
|
||||
// Handle nil data
|
||||
if len(temp) == 0 {
|
||||
temp = append(bf.Data(), uint8(0))
|
||||
}
|
||||
|
||||
// Build a map of set data
|
||||
sets := make(map[uint16][]byte)
|
||||
oldSets := byteframe.NewByteFrameFromBytes(temp[2:])
|
||||
for i := uint8(0); i < temp[1]; i++ {
|
||||
index := oldSets.ReadUint16()
|
||||
sets[index] = oldSets.ReadBytes(size)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// Serialise the set data
|
||||
bf.WriteUint8(uint8(len(sets)))
|
||||
for u, b := range sets {
|
||||
bf.WriteUint16(u)
|
||||
bf.WriteBytes(b)
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
|
||||
type Title struct {
|
||||
|
||||
@@ -10,13 +10,13 @@ import (
|
||||
|
||||
type ShopItem struct {
|
||||
ID uint32 `db:"id"`
|
||||
ItemID uint16 `db:"item_id"`
|
||||
ItemID uint32 `db:"item_id"`
|
||||
Cost uint32 `db:"cost"`
|
||||
Quantity uint16 `db:"quantity"`
|
||||
MinHR uint16 `db:"min_hr"`
|
||||
MinSR uint16 `db:"min_sr"`
|
||||
MinGR uint16 `db:"min_gr"`
|
||||
StoreLevel uint16 `db:"store_level"`
|
||||
StoreLevel uint8 `db:"store_level"`
|
||||
MaxQuantity uint16 `db:"max_quantity"`
|
||||
UsedQuantity uint16 `db:"used_quantity"`
|
||||
RoadFloors uint16 `db:"road_floors"`
|
||||
@@ -61,19 +61,30 @@ func writeShopItems(bf *byteframe.ByteFrame, items []ShopItem) {
|
||||
bf.WriteUint16(uint16(len(items)))
|
||||
bf.WriteUint16(uint16(len(items)))
|
||||
for _, item := range items {
|
||||
bf.WriteUint32(item.ID)
|
||||
bf.WriteUint16(0)
|
||||
bf.WriteUint16(item.ItemID)
|
||||
if _config.ErupeConfig.RealClientMode >= _config.Z2 {
|
||||
bf.WriteUint32(item.ID)
|
||||
}
|
||||
bf.WriteUint32(item.ItemID)
|
||||
bf.WriteUint32(item.Cost)
|
||||
bf.WriteUint16(item.Quantity)
|
||||
bf.WriteUint16(item.MinHR)
|
||||
bf.WriteUint16(item.MinSR)
|
||||
bf.WriteUint16(item.MinGR)
|
||||
bf.WriteUint16(item.StoreLevel)
|
||||
bf.WriteUint16(item.MaxQuantity)
|
||||
bf.WriteUint16(item.UsedQuantity)
|
||||
bf.WriteUint16(item.RoadFloors)
|
||||
bf.WriteUint16(item.RoadFatalis)
|
||||
if _config.ErupeConfig.RealClientMode >= _config.Z2 {
|
||||
bf.WriteUint16(item.MinGR)
|
||||
}
|
||||
bf.WriteUint8(0) // Unk
|
||||
bf.WriteUint8(item.StoreLevel)
|
||||
if _config.ErupeConfig.RealClientMode >= _config.Z2 {
|
||||
bf.WriteUint16(item.MaxQuantity)
|
||||
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.RoadFatalis)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -241,6 +252,9 @@ func handleMsgMhfEnumerateShop(s *Session, p mhfpacket.MHFPacket) {
|
||||
case 10: // Item shop, 0-8
|
||||
bf := byteframe.NewByteFrame()
|
||||
items := getShopItems(s, pkt.ShopType, pkt.ShopID)
|
||||
if len(items) > int(pkt.Limit) {
|
||||
items = items[:pkt.Limit]
|
||||
}
|
||||
writeShopItems(bf, items)
|
||||
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.
|
||||
backStage, err := s.stageMoveStack.Pop()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
if backStage == "" || err != nil {
|
||||
backStage = "sl1Ns200p0a0u0"
|
||||
}
|
||||
|
||||
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"
|
||||
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)
|
||||
case 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)
|
||||
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)
|
||||
}
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user