implement hunt data logging (partial #82)

This commit is contained in:
wish
2023-10-08 19:25:48 +11:00
parent f37915bcae
commit 641032f862
5 changed files with 445 additions and 21 deletions

366
common/mhfmon/mhfmon.go Normal file
View File

@@ -0,0 +1,366 @@
package mhfmon
const (
Mon0 = iota
Rathian
Fatalis
Kelbi
Mosswine
Bullfango
YianKutKu
LaoShanLung
Cephadrome
Felyne
VeggieElder
Rathalos
Aptonoth
Genprey
Diablos
Khezu
Velociprey
Gravios
Mon18
Vespoid
Gypceros
Plesioth
Basarios
Melynx
Hornetaur
Apceros
Monoblos
Velocidrome
Gendrome
Mon29
Ioprey
Iodrome
Mon32
Kirin
Cephalos
Giaprey
CrimsonFatalis
PinkRathian
BlueYianKutKu
PurpleGypceros
YianGaruga
SilverRathalos
GoldRathian
BlackDiablos
WhiteMonoblos
RedKhezu
GreenPlesioth
BlackGravios
DaimyoHermitaur
AzureRathalos
AshenLaoShanLung
Blangonga
Congalala
Rajang
KushalaDaora
ShenGaoren
GreatThunderbug
Shakalaka
YamaTsukami
Chameleos
RustedKushalaDaora
Blango
Conga
Remobra
Lunastra
Teostra
Hermitaur
ShogunCeanataur
Bulldrome
Anteka
Popo
WhiteFatalis
Mon72
Ceanataur
Hypnocatrice
Lavasioth
Tigrex
Akantor
BrightHypnoc
RedLavasioth
Espinas
OrangeEspinas
WhiteHypnoc
AqraVashimu
AqraJebia
Berukyurosu
Mon86
Mon87
Mon88
Pariapuria
WhiteEspinas
KamuOrugaron
NonoOrugaron
Raviente
Dyuragaua
Doragyurosu
Gurenzeburu
Burukku
Erupe
Rukodiora
Unknown
Gogomoa
Kokomoa
TaikunZamuza
Abiorugu
Kuarusepusu
Odibatorasu
Disufiroa
Rebidiora
Anorupatisu
Hyujikiki
Midogaron
Giaorugu
MiRu
Farunokku
Pokaradon
Shantien
Pokara
Mon118
Goruganosu
Aruganosu
Baruragaru
Zerureusu
Gougarf
Uruki
Forokururu
Meraginasu
Diorex
GarubaDaora
Inagami
Varusaburosu
Poborubarumu
Block1Duremudira
Mon133
Mon134
Mon135
Mon136
Mon137
Mon138
Gureadomosu
Harudomerugu
Toridcless
Gasurabazura
Kusubami
YamaKurai
Block2Duremudira
Zinogre
Deviljho
Brachydios
BerserkRaviente
ToaTesukatora
Barioth
Uragaan
StygianZinogre
Guanzorumu
SavageDeviljho
Mon156
Egyurasu
Voljang
Nargacuga
Keoaruboru
Zenaserisu
GoreMagala
BlinkingNargacuga
ShagaruMagala
Amatsu
Eruzerion
MusouDuremudira
Mon168
Seregios
Bogabadorumu
Mon171
MusouBogabadorumu
CostumedUruki
MusouZerureusu
Rappy
KingShakalaka
)
type Monster struct {
Name string
Large bool
}
var Monsters = []Monster{
{"Mon0", false},
{"Rathian", true},
{"Fatalis", true},
{"Kelbi", false},
{"Mosswine", false},
{"Bullfango", false},
{"Yian Kut-Ku", true},
{"Lao-Shan Lung", true},
{"Cephadrome", true},
{"Felyne", false},
{"Veggie Elder", false},
{"Rathalos", true},
{"Aptonoth", false},
{"Genprey", false},
{"Diablos", true},
{"Khezu", true},
{"Velociprey", false},
{"Gravios", true},
{"Mon18", false},
{"Vespoid", false},
{"Gypceros", true},
{"Plesioth", true},
{"Basarios", true},
{"Melynx", false},
{"Hornetaur", false},
{"Apceros", false},
{"Monoblos", true},
{"Velocidrome", true},
{"Gendrome", true},
{"Mon29", false},
{"Ioprey", false},
{"Iodrome", true},
{"Mon32", false},
{"Kirin", true},
{"Cephalos", false},
{"Giaprey", false},
{"Crimson Fatalis", true},
{"Pink Rathian", true},
{"Blue Yian Kut-Ku", true},
{"Purple Gypceros", true},
{"Yian Garuga", true},
{"Silver Rathalos", true},
{"Gold Rathian", true},
{"Black Diablos", true},
{"White Monoblos", true},
{"Red Khezu", true},
{"Green Plesioth", true},
{"Black Gravios", true},
{"Daimyo Hermitaur", true},
{"Azure Rathalos", true},
{"Ashen Lao-Shan Lung", true},
{"Blangonga", true},
{"Congalala", true},
{"Rajang", true},
{"Kushala Daora", true},
{"Shen Gaoren", true},
{"Great Thunderbug", false},
{"Shakalaka", false},
{"Yama Tsukami", true},
{"Chameleos", true},
{"Rusted Kushala Daora", true},
{"Blango", false},
{"Conga", false},
{"Remobra", false},
{"Lunastra", true},
{"Teostra", true},
{"Hermitaur", false},
{"Shogun Ceanataur", true},
{"Bulldrome", true},
{"Anteka", false},
{"Popo", false},
{"White Fatalis", true},
{"Mon72", false},
{"Ceanataur", false},
{"Hypnocatrice", true},
{"Lavasioth", true},
{"Tigrex", true},
{"Akantor", true},
{"Bright Hypnocatrice", true},
{"Red Lavasioth", true},
{"Espinas", true},
{"Orange Espinas", true},
{"White Hypnocatrice", true},
{"Aqra Vashimu", true},
{"Aqra Jebia", true},
{"Berukyurosu", true},
{"Mon86", false},
{"Mon87", false},
{"Mon88", false},
{"Pariapuria", true},
{"White Espinas", true},
{"Kamu Orugaron", true},
{"Nono Orugaron", true},
{"Raviente", true}, // + Violent
{"Dyuragaua", true},
{"Doragyurosu", true},
{"Gurenzeburu", true},
{"Burukku", false},
{"Erupe", false},
{"Rukodiora", true},
{"Unknown", true},
{"Gogomoa", true},
{"Kokomoa", false},
{"Taikun Zamuza", true},
{"Abiorugu", true},
{"Kuarusepusu", true},
{"Odibatorasu", true},
{"Disufiroa", true},
{"Rebidiora", true},
{"Anorupatisu", true},
{"Hyujikiki", true},
{"Midogaron", true},
{"Giaorugu", true},
{"Mi-Ru", true}, // + Musou
{"Farunokku", true},
{"Pokaradon", true},
{"Shantien", true},
{"Pokara", false},
{"Mon118", false},
{"Goruganosu", true},
{"Aruganosu", true},
{"Baruragaru", true},
{"Zerureusu", true},
{"Gougarf", true}, // Both
{"Uruki", false},
{"Forokururu", true},
{"Meraginasu", true},
{"Diorex", true},
{"Garuba Daora", true},
{"Inagami", true},
{"Varusablos", true},
{"Poborubarumu", true},
{"1st Block Duremudira", true},
{"Mon133", false},
{"Mon134", false},
{"Mon135", false},
{"Mon136", false},
{"Mon137", false},
{"Mon138", false},
{"Gureadomosu", true},
{"Harudomerugu", true},
{"Toridcless", true},
{"Gasurabazura", true},
{"Kusubami", false},
{"Yama Kurai", true},
{"2nd Block Duremudira", true},
{"Zinogre", true},
{"Deviljho", true},
{"Brachydios", true},
{"Berserk Raviente", true},
{"Toa Tesukatora", true},
{"Barioth", true},
{"Uragaan", true},
{"Stygian Zinogre", true},
{"Guanzorumu", true},
{"Savage Deviljho", true}, // + Starving/Heavenly
{"Mon156", false},
{"Egyurasu", false},
{"Voljang", true},
{"Nargacuga", true},
{"Keoaruboru", true},
{"Zenaserisu", true},
{"Gore Magala", true},
{"Blinking Nargacuga", true},
{"Shagaru Magala", true},
{"Amatsu", true},
{"Eruzerion", true}, // + Musou
{"Musou Duremudira", true},
{"Mon168", false},
{"Seregios", true},
{"Bogabadorumu", true},
{"Mon171", false},
{"Musou Bogabadorumu", true},
{"Costumed Uruki", false},
{"Musou Zerureusu", true},
{"Rappy", false},
{"King Shakalaka", false},
}

View File

@@ -1,21 +1,19 @@
package mhfpacket
import (
"errors"
import (
"errors"
"erupe-ce/network/clientctx"
"erupe-ce/network"
"erupe-ce/common/byteframe"
"erupe-ce/network"
"erupe-ce/network/clientctx"
)
// MsgSysRecordLog represents the MSG_SYS_RECORD_LOG
type MsgSysRecordLog struct {
AckHandle uint32
Unk0 uint32
Unk1 uint16 // Hardcoded 0
HardcodedDataSize uint16 // Hardcoded 0x4AC
Unk3 uint32 // Some shared ID with MSG_MHF_GET_SEIBATTLE. World ID??
DataBuf []byte
AckHandle uint32
Unk0 uint32
Unk1 uint32
Data []byte
}
// Opcode returns the ID associated with this packet type.
@@ -27,10 +25,10 @@ func (m *MsgSysRecordLog) Opcode() network.PacketID {
func (m *MsgSysRecordLog) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
m.AckHandle = bf.ReadUint32()
m.Unk0 = bf.ReadUint32()
m.Unk1 = bf.ReadUint16()
m.HardcodedDataSize = bf.ReadUint16()
m.Unk3 = bf.ReadUint32()
m.DataBuf = bf.ReadBytes(uint(m.HardcodedDataSize))
bf.ReadUint16() // Zeroed
size := bf.ReadUint16()
m.Unk1 = bf.ReadUint32()
m.Data = bf.ReadBytes(uint(size))
return nil
}

View File

@@ -0,0 +1,12 @@
CREATE TABLE public.kill_logs
(
id serial,
character_id integer NOT NULL,
monster integer NOT NULL,
quantity integer NOT NULL,
timestamp timestamp with time zone NOT NULL,
PRIMARY KEY (id)
);
ALTER TABLE IF EXISTS public.guild_characters
ADD COLUMN box_claimed timestamp with time zone DEFAULT now();

View File

@@ -4,6 +4,7 @@ import (
"encoding/binary"
"encoding/hex"
"erupe-ce/common/mhfcourse"
"erupe-ce/common/mhfmon"
ps "erupe-ce/common/pascalstring"
"erupe-ce/common/stringsupport"
_config "erupe-ce/config"
@@ -305,9 +306,20 @@ func handleMsgSysIssueLogkey(s *Session, p mhfpacket.MHFPacket) {
func handleMsgSysRecordLog(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgSysRecordLog)
if _config.ErupeConfig.RealClientMode == _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, 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, []byte{0x00, 0x00, 0x00, 0x00})
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
}
func handleMsgSysEcho(s *Session, p mhfpacket.MHFPacket) {}

View File

@@ -1867,15 +1867,51 @@ func handleMsgMhfGuildHuntdata(s *Session, p mhfpacket.MHFPacket) {
bf := byteframe.NewByteFrame()
switch pkt.Operation {
case 0: // Acquire
// Probably mark everything as claimed
s.server.db.Exec(`UPDATE guild_characters SET box_claimed=$1 WHERE character_id=$2`, TimeAdjusted(), s.charID)
case 1: // Enumerate
bf.WriteUint8(0) // Entries
/* Entry format
uint32 UnkID
uint32 MonID
*/
rows, err := s.server.db.Query(`SELECT kl.id, kl.monster FROM kill_logs kl
INNER JOIN guild_characters gc ON kl.character_id = gc.character_id
WHERE gc.guild_id=$1
AND kl.timestamp >= (SELECT box_claimed FROM guild_characters WHERE character_id=$2)
`, pkt.GuildID, s.charID)
if err == nil {
var count uint8
var huntID, monID uint32
for rows.Next() {
err = rows.Scan(&huntID, &monID)
if err != nil {
continue
}
count++
if count > 255 {
count = 255
rows.Close()
break
}
bf.WriteUint32(huntID)
bf.WriteUint32(monID)
}
bf.Seek(0, 0)
bf.WriteUint8(count)
}
case 2: // Check
bf.WriteBool(false)
guild, err := GetGuildInfoByCharacterId(s, s.charID)
if err == nil {
var count uint8
err = s.server.db.QueryRow(`SELECT COUNT(*) FROM kill_logs kl
INNER JOIN guild_characters gc ON kl.character_id = gc.character_id
WHERE gc.guild_id=$1
AND kl.timestamp >= (SELECT box_claimed FROM guild_characters WHERE character_id=$2)
`, guild.ID, s.charID).Scan(&count)
if err == nil && count > 0 {
bf.WriteBool(true)
} else {
bf.WriteBool(false)
}
} else {
bf.WriteBool(false)
}
}
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
}