mirror of
https://github.com/Mezeporta/Erupe.git
synced 2025-12-12 15:04:38 +01:00
implement hunt data logging (partial #82)
This commit is contained in:
366
common/mhfmon/mhfmon.go
Normal file
366
common/mhfmon/mhfmon.go
Normal 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},
|
||||
}
|
||||
@@ -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
|
||||
|
||||
}
|
||||
|
||||
12
patch-schema/08-kill-counts.sql
Normal file
12
patch-schema/08-kill-counts.sql
Normal 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();
|
||||
@@ -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) {}
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user