mirror of
https://github.com/Mezeporta/Erupe.git
synced 2025-12-16 17:05:03 +01:00
Merge branch 'main' into feature/diva
This commit is contained in:
@@ -36,6 +36,7 @@
|
|||||||
"TournamentOverride": 0,
|
"TournamentOverride": 0,
|
||||||
"DisableTokenCheck": false,
|
"DisableTokenCheck": false,
|
||||||
"QuestTools": false,
|
"QuestTools": false,
|
||||||
|
"AutoQuestBackport": true,
|
||||||
"ProxyPort": 0,
|
"ProxyPort": 0,
|
||||||
"CapLink": {
|
"CapLink": {
|
||||||
"Values": [51728, 20000, 51729, 1, 20000],
|
"Values": [51728, 20000, 51729, 1, 20000],
|
||||||
|
|||||||
@@ -118,6 +118,7 @@ type DebugOptions struct {
|
|||||||
TournamentOverride int // VS Tournament event status
|
TournamentOverride int // VS Tournament event status
|
||||||
DisableTokenCheck bool // Disables checking login token exists in the DB (security risk!)
|
DisableTokenCheck bool // Disables checking login token exists in the DB (security risk!)
|
||||||
QuestTools bool // Enable various quest debug logs
|
QuestTools bool // Enable various quest debug logs
|
||||||
|
AutoQuestBackport bool // Automatically backport quest files
|
||||||
ProxyPort uint16 // Forces the game to connect to a channel server proxy
|
ProxyPort uint16 // Forces the game to connect to a channel server proxy
|
||||||
CapLink CapLinkOptions
|
CapLink CapLinkOptions
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ CREATE TABLE IF NOT EXISTS tower (
|
|||||||
tsp INT,
|
tsp INT,
|
||||||
block1 INT,
|
block1 INT,
|
||||||
block2 INT,
|
block2 INT,
|
||||||
skills TEXT DEFAULT '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 TEXT,
|
||||||
gems TEXT DEFAULT '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'
|
gems TEXT
|
||||||
);
|
);
|
||||||
|
|
||||||
ALTER TABLE IF EXISTS guild_characters
|
ALTER TABLE IF EXISTS guild_characters
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package channelserver
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"encoding/binary"
|
||||||
"erupe-ce/common/byteframe"
|
"erupe-ce/common/byteframe"
|
||||||
"erupe-ce/common/decryption"
|
"erupe-ce/common/decryption"
|
||||||
ps "erupe-ce/common/pascalstring"
|
ps "erupe-ce/common/pascalstring"
|
||||||
@@ -21,6 +22,20 @@ type tuneValue struct {
|
|||||||
Value uint16
|
Value uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BackportQuest(data []byte) []byte {
|
||||||
|
wp := binary.LittleEndian.Uint32(data[0:4]) + 96
|
||||||
|
rp := wp + 4
|
||||||
|
for i := uint32(0); i < 6; i++ {
|
||||||
|
if i != 0 {
|
||||||
|
wp += 4
|
||||||
|
rp += 8
|
||||||
|
}
|
||||||
|
copy(data[wp:wp+4], data[rp:rp+4])
|
||||||
|
}
|
||||||
|
copy(data[wp:wp+180], data[rp:rp+180])
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
func handleMsgSysGetFile(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgSysGetFile(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgSysGetFile)
|
pkt := p.(*mhfpacket.MsgSysGetFile)
|
||||||
|
|
||||||
@@ -63,6 +78,9 @@ func handleMsgSysGetFile(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
doAckBufSucceed(s, pkt.AckHandle, data)
|
doAckBufSucceed(s, pkt.AckHandle, data)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if _config.ErupeConfig.RealClientMode <= _config.Z1 && s.server.erupeConfig.DebugOptions.AutoQuestBackport {
|
||||||
|
data = BackportQuest(decryption.UnpackSimple(data))
|
||||||
|
}
|
||||||
doAckBufSucceed(s, pkt.AckHandle, data)
|
doAckBufSucceed(s, pkt.AckHandle, data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -124,6 +142,9 @@ func loadQuestFile(s *Session, questId int) []byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
decrypted := decryption.UnpackSimple(file)
|
decrypted := decryption.UnpackSimple(file)
|
||||||
|
if _config.ErupeConfig.RealClientMode <= _config.Z1 && s.server.erupeConfig.DebugOptions.AutoQuestBackport {
|
||||||
|
decrypted = BackportQuest(decrypted)
|
||||||
|
}
|
||||||
fileBytes := byteframe.NewByteFrameFromBytes(decrypted)
|
fileBytes := byteframe.NewByteFrameFromBytes(decrypted)
|
||||||
fileBytes.SetLE()
|
fileBytes.SetLE()
|
||||||
fileBytes.Seek(int64(fileBytes.ReadUint32()), 0)
|
fileBytes.Seek(int64(fileBytes.ReadUint32()), 0)
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
package channelserver
|
package channelserver
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
_config "erupe-ce/config"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"erupe-ce/common/byteframe"
|
"erupe-ce/common/byteframe"
|
||||||
@@ -16,8 +18,8 @@ type TowerInfoTRP struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type TowerInfoSkill struct {
|
type TowerInfoSkill struct {
|
||||||
TSP int32
|
TSP int32
|
||||||
Unk1 []int16 // 40
|
Skills []int16 // 64
|
||||||
}
|
}
|
||||||
|
|
||||||
type TowerInfoHistory struct {
|
type TowerInfoHistory struct {
|
||||||
@@ -32,6 +34,14 @@ type TowerInfoLevel struct {
|
|||||||
Unk3 int32
|
Unk3 int32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func EmptyTowerCSV(len int) string {
|
||||||
|
temp := make([]string, len)
|
||||||
|
for i := range temp {
|
||||||
|
temp[i] = "0"
|
||||||
|
}
|
||||||
|
return strings.Join(temp, ",")
|
||||||
|
}
|
||||||
|
|
||||||
func handleMsgMhfGetTowerInfo(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgMhfGetTowerInfo(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgMhfGetTowerInfo)
|
pkt := p.(*mhfpacket.MsgMhfGetTowerInfo)
|
||||||
var data []*byteframe.ByteFrame
|
var data []*byteframe.ByteFrame
|
||||||
@@ -44,21 +54,24 @@ func handleMsgMhfGetTowerInfo(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
|
|
||||||
towerInfo := TowerInfo{
|
towerInfo := TowerInfo{
|
||||||
TRP: []TowerInfoTRP{{0, 0}},
|
TRP: []TowerInfoTRP{{0, 0}},
|
||||||
Skill: []TowerInfoSkill{{0, make([]int16, 40)}},
|
Skill: []TowerInfoSkill{{0, make([]int16, 64)}},
|
||||||
History: []TowerInfoHistory{{make([]int16, 5), make([]int16, 5)}},
|
History: []TowerInfoHistory{{make([]int16, 5), make([]int16, 5)}},
|
||||||
Level: []TowerInfoLevel{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
Level: []TowerInfoLevel{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
||||||
}
|
}
|
||||||
|
|
||||||
tempSkills := "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"
|
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
|
||||||
err := s.server.db.QueryRow(`SELECT COALESCE(tr, 0), COALESCE(trp, 0), COALESCE(tsp, 0), COALESCE(block1, 0), COALESCE(block2, 0), skills FROM tower WHERE char_id=$1
|
`, 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)
|
||||||
`, 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 {
|
if err != nil {
|
||||||
s.server.db.Exec(`INSERT INTO tower (char_id) VALUES ($1)`, s.charID)
|
s.server.db.Exec(`INSERT INTO tower (char_id) VALUES ($1)`, s.charID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if _config.ErupeConfig.RealClientMode <= _config.G7 {
|
||||||
|
towerInfo.Level = towerInfo.Level[:1]
|
||||||
|
}
|
||||||
|
|
||||||
for i, skill := range stringsupport.CSVElems(tempSkills) {
|
for i, skill := range stringsupport.CSVElems(tempSkills) {
|
||||||
towerInfo.Skill[0].Unk1[i] = int16(skill)
|
towerInfo.Skill[0].Skills[i] = int16(skill)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch pkt.InfoType {
|
switch pkt.InfoType {
|
||||||
@@ -73,8 +86,8 @@ func handleMsgMhfGetTowerInfo(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
for _, skills := range towerInfo.Skill {
|
for _, skills := range towerInfo.Skill {
|
||||||
bf := byteframe.NewByteFrame()
|
bf := byteframe.NewByteFrame()
|
||||||
bf.WriteInt32(skills.TSP)
|
bf.WriteInt32(skills.TSP)
|
||||||
for i := range skills.Unk1 {
|
for i := range skills.Skills {
|
||||||
bf.WriteInt16(skills.Unk1[i])
|
bf.WriteInt16(skills.Skills[i])
|
||||||
}
|
}
|
||||||
data = append(data, bf)
|
data = append(data, bf)
|
||||||
}
|
}
|
||||||
@@ -89,7 +102,7 @@ func handleMsgMhfGetTowerInfo(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
}
|
}
|
||||||
data = append(data, bf)
|
data = append(data, bf)
|
||||||
}
|
}
|
||||||
case 5:
|
case 3, 5:
|
||||||
for _, level := range towerInfo.Level {
|
for _, level := range towerInfo.Level {
|
||||||
bf := byteframe.NewByteFrame()
|
bf := byteframe.NewByteFrame()
|
||||||
bf.WriteInt32(level.Floors)
|
bf.WriteInt32(level.Floors)
|
||||||
@@ -123,8 +136,8 @@ func handleMsgMhfPostTowerInfo(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
|
|
||||||
switch pkt.InfoType {
|
switch pkt.InfoType {
|
||||||
case 2:
|
case 2:
|
||||||
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"
|
var skills string
|
||||||
s.server.db.QueryRow(`SELECT skills FROM tower WHERE char_id=$1`, s.charID).Scan(&skills)
|
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)
|
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 1, 7:
|
case 1, 7:
|
||||||
// This might give too much TSP? No idea what the rate is supposed to be
|
// This might give too much TSP? No idea what the rate is supposed to be
|
||||||
@@ -412,10 +425,10 @@ func handleMsgMhfGetGemInfo(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
gemInfo := []GemInfo{}
|
gemInfo := []GemInfo{}
|
||||||
gemHistory := []GemHistory{}
|
gemHistory := []GemHistory{}
|
||||||
|
|
||||||
tempGems := "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"
|
var tempGems string
|
||||||
s.server.db.QueryRow(`SELECT gems FROM tower WHERE char_id=$1`, s.charID).Scan(&tempGems)
|
s.server.db.QueryRow(`SELECT COALESCE(gems, $1) FROM tower WHERE char_id=$2`, EmptyTowerCSV(30), s.charID).Scan(&tempGems)
|
||||||
for i, v := range stringsupport.CSVElems(tempGems) {
|
for i, v := range stringsupport.CSVElems(tempGems) {
|
||||||
gemInfo = append(gemInfo, GemInfo{uint16(((i / 5) * 256) + ((i % 5) + 1)), uint16(v)})
|
gemInfo = append(gemInfo, GemInfo{uint16((i / 5 << 8) + (i%5 + 1)), uint16(v)})
|
||||||
}
|
}
|
||||||
|
|
||||||
switch pkt.Unk0 {
|
switch pkt.Unk0 {
|
||||||
@@ -455,11 +468,11 @@ func handleMsgMhfPostGemInfo(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
gems := "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"
|
var gems string
|
||||||
s.server.db.QueryRow(`SELECT gems FROM tower WHERE char_id=$1`, s.charID).Scan(&gems)
|
s.server.db.QueryRow(`SELECT COALESCE(gems, $1) FROM tower WHERE char_id=$2`, EmptyTowerCSV(30), s.charID).Scan(&gems)
|
||||||
switch pkt.Op {
|
switch pkt.Op {
|
||||||
case 1: // Add gem
|
case 1: // Add gem
|
||||||
i := int(((pkt.Gem / 256) * 5) + (((pkt.Gem - ((pkt.Gem / 256) * 256)) - 1) % 5))
|
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)
|
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)
|
||||||
case 2: // Transfer gem
|
case 2: // Transfer gem
|
||||||
// no way im doing this for now
|
// no way im doing this for now
|
||||||
|
|||||||
Reference in New Issue
Block a user