mirror of
https://github.com/Mezeporta/Erupe.git
synced 2025-12-14 16:04:38 +01:00
Merge pull request #97 from ZeruLight/fix/rework-distributions
fix/rework-distributions
This commit is contained in:
11
bundled-schema/DistributionDemo.sql
Normal file
11
bundled-schema/DistributionDemo.sql
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
BEGIN;
|
||||||
|
|
||||||
|
-- Adds a Distribution that can be accepted up to 20 times that gives one of Item Type 30 (Item Box extra page)
|
||||||
|
INSERT INTO distribution (type, event_name, description, times_acceptable) VALUES (1, 'Extra Item Storage', '~C05Adds one new page to your Item Box.', 20);
|
||||||
|
INSERT INTO distribution_items (distribution_id, item_type, quantity) VALUES ((SELECT id FROM distribution ORDER BY id DESC LIMIT 1), 30, 1);
|
||||||
|
|
||||||
|
-- Adds a Distribution that can be accepted up to 20 times that gives one of Item Type 31 (Equipment Box extra page)
|
||||||
|
INSERT INTO distribution (type, event_name, description, times_acceptable) VALUES (1, 'Extra Equipment Storage', '~C05Adds one new page to your Equipment Box.', 20);
|
||||||
|
INSERT INTO distribution_items (distribution_id, item_type, quantity) VALUES ((SELECT id FROM distribution ORDER BY id DESC LIMIT 1), 31, 1);
|
||||||
|
|
||||||
|
END;
|
||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
// MsgMhfEnumerateDistItem represents the MSG_MHF_ENUMERATE_DIST_ITEM
|
// MsgMhfEnumerateDistItem represents the MSG_MHF_ENUMERATE_DIST_ITEM
|
||||||
type MsgMhfEnumerateDistItem struct {
|
type MsgMhfEnumerateDistItem struct {
|
||||||
AckHandle uint32
|
AckHandle uint32
|
||||||
Unk0 uint8
|
DistType uint8
|
||||||
Unk1 uint8
|
Unk1 uint8
|
||||||
Unk2 uint16
|
Unk2 uint16
|
||||||
Unk3 []byte
|
Unk3 []byte
|
||||||
@@ -24,9 +24,9 @@ func (m *MsgMhfEnumerateDistItem) Opcode() network.PacketID {
|
|||||||
// Parse parses the packet from binary
|
// Parse parses the packet from binary
|
||||||
func (m *MsgMhfEnumerateDistItem) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
func (m *MsgMhfEnumerateDistItem) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||||
m.AckHandle = bf.ReadUint32()
|
m.AckHandle = bf.ReadUint32()
|
||||||
m.Unk0 = bf.ReadUint8()
|
m.DistType = bf.ReadUint8()
|
||||||
m.Unk1 = bf.ReadUint8()
|
m.Unk1 = bf.ReadUint8()
|
||||||
m.Unk2 = bf.ReadUint16()
|
m.Unk2 = bf.ReadUint16() // Maximum? Hardcoded to 256
|
||||||
m.Unk3 = bf.ReadBytes(uint(bf.ReadUint8()))
|
m.Unk3 = bf.ReadBytes(uint(bf.ReadUint8()))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
36
patch-schema/10-rework-distributions.sql
Normal file
36
patch-schema/10-rework-distributions.sql
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
BEGIN;
|
||||||
|
|
||||||
|
-- This will delete all of your old distribution data!
|
||||||
|
--ALTER TABLE IF EXISTS public.distribution DROP COLUMN IF EXISTS data;
|
||||||
|
|
||||||
|
CREATE TABLE public.distribution_items
|
||||||
|
(
|
||||||
|
id serial PRIMARY KEY,
|
||||||
|
distribution_id integer NOT NULL,
|
||||||
|
item_type integer NOT NULL,
|
||||||
|
item_id integer,
|
||||||
|
quantity integer
|
||||||
|
);
|
||||||
|
|
||||||
|
ALTER TABLE IF EXISTS public.distribution ALTER COLUMN min_hr DROP DEFAULT;
|
||||||
|
ALTER TABLE IF EXISTS public.distribution ALTER COLUMN max_hr DROP DEFAULT;
|
||||||
|
ALTER TABLE IF EXISTS public.distribution ALTER COLUMN min_sr DROP DEFAULT;
|
||||||
|
ALTER TABLE IF EXISTS public.distribution ALTER COLUMN max_sr DROP DEFAULT;
|
||||||
|
ALTER TABLE IF EXISTS public.distribution ALTER COLUMN min_gr DROP DEFAULT;
|
||||||
|
ALTER TABLE IF EXISTS public.distribution ALTER COLUMN max_gr DROP DEFAULT;
|
||||||
|
|
||||||
|
ALTER TABLE IF EXISTS public.distribution ALTER COLUMN min_hr DROP NOT NULL;
|
||||||
|
ALTER TABLE IF EXISTS public.distribution ALTER COLUMN max_hr DROP NOT NULL;
|
||||||
|
ALTER TABLE IF EXISTS public.distribution ALTER COLUMN min_sr DROP NOT NULL;
|
||||||
|
ALTER TABLE IF EXISTS public.distribution ALTER COLUMN max_sr DROP NOT NULL;
|
||||||
|
ALTER TABLE IF EXISTS public.distribution ALTER COLUMN min_gr DROP NOT NULL;
|
||||||
|
ALTER TABLE IF EXISTS public.distribution ALTER COLUMN max_gr DROP NOT NULL;
|
||||||
|
|
||||||
|
UPDATE distribution SET min_hr=NULL WHERE min_hr=65535;
|
||||||
|
UPDATE distribution SET max_hr=NULL WHERE max_hr=65535;
|
||||||
|
UPDATE distribution SET min_sr=NULL WHERE min_sr=65535;
|
||||||
|
UPDATE distribution SET max_sr=NULL WHERE max_sr=65535;
|
||||||
|
UPDATE distribution SET min_gr=NULL WHERE min_gr=65535;
|
||||||
|
UPDATE distribution SET max_gr=NULL WHERE max_gr=65535;
|
||||||
|
|
||||||
|
END;
|
||||||
@@ -4,21 +4,22 @@ import (
|
|||||||
"erupe-ce/common/byteframe"
|
"erupe-ce/common/byteframe"
|
||||||
ps "erupe-ce/common/pascalstring"
|
ps "erupe-ce/common/pascalstring"
|
||||||
"erupe-ce/network/mhfpacket"
|
"erupe-ce/network/mhfpacket"
|
||||||
|
"time"
|
||||||
|
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ItemDist struct {
|
type Distribution struct {
|
||||||
ID uint32 `db:"id"`
|
ID uint32 `db:"id"`
|
||||||
Deadline uint32 `db:"deadline"`
|
Deadline time.Time `db:"deadline"`
|
||||||
TimesAcceptable uint16 `db:"times_acceptable"`
|
TimesAcceptable uint16 `db:"times_acceptable"`
|
||||||
TimesAccepted uint16 `db:"times_accepted"`
|
TimesAccepted uint16 `db:"times_accepted"`
|
||||||
MinHR uint16 `db:"min_hr"`
|
MinHR int16 `db:"min_hr"`
|
||||||
MaxHR uint16 `db:"max_hr"`
|
MaxHR int16 `db:"max_hr"`
|
||||||
MinSR uint16 `db:"min_sr"`
|
MinSR int16 `db:"min_sr"`
|
||||||
MaxSR uint16 `db:"max_sr"`
|
MaxSR int16 `db:"max_sr"`
|
||||||
MinGR uint16 `db:"min_gr"`
|
MinGR int16 `db:"min_gr"`
|
||||||
MaxGR uint16 `db:"max_gr"`
|
MaxGR int16 `db:"max_gr"`
|
||||||
EventName string `db:"event_name"`
|
EventName string `db:"event_name"`
|
||||||
Description string `db:"description"`
|
Description string `db:"description"`
|
||||||
Data []byte `db:"data"`
|
Data []byte `db:"data"`
|
||||||
@@ -26,54 +27,55 @@ type ItemDist struct {
|
|||||||
|
|
||||||
func handleMsgMhfEnumerateDistItem(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgMhfEnumerateDistItem(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgMhfEnumerateDistItem)
|
pkt := p.(*mhfpacket.MsgMhfEnumerateDistItem)
|
||||||
|
|
||||||
|
var itemDists []Distribution
|
||||||
bf := byteframe.NewByteFrame()
|
bf := byteframe.NewByteFrame()
|
||||||
distCount := 0
|
rows, err := s.server.db.Queryx(`
|
||||||
dists, err := s.server.db.Queryx(`
|
|
||||||
SELECT d.id, event_name, description, times_acceptable,
|
SELECT d.id, event_name, description, times_acceptable,
|
||||||
min_hr, max_hr, min_sr, max_sr, min_gr, max_gr,
|
COALESCE(min_hr, -1) AS min_hr, COALESCE(max_hr, -1) AS max_hr,
|
||||||
|
COALESCE(min_sr, -1) AS min_sr, COALESCE(max_sr, -1) AS max_sr,
|
||||||
|
COALESCE(min_gr, -1) AS min_gr, COALESCE(max_gr, -1) AS max_gr,
|
||||||
(
|
(
|
||||||
SELECT count(*)
|
SELECT count(*) FROM distributions_accepted da
|
||||||
FROM distributions_accepted da
|
WHERE d.id = da.distribution_id AND da.character_id = $1
|
||||||
WHERE d.id = da.distribution_id
|
|
||||||
AND da.character_id = $1
|
|
||||||
) AS times_accepted,
|
) AS times_accepted,
|
||||||
CASE
|
COALESCE(deadline, TO_TIMESTAMP(0)) AS deadline
|
||||||
WHEN (EXTRACT(epoch FROM deadline)::int) IS NULL THEN 0
|
|
||||||
ELSE (EXTRACT(epoch FROM deadline)::int)
|
|
||||||
END deadline
|
|
||||||
FROM distribution d
|
FROM distribution d
|
||||||
WHERE character_id = $1 AND type = $2 OR character_id IS NULL AND type = $2 ORDER BY id DESC;
|
WHERE character_id = $1 AND type = $2 OR character_id IS NULL AND type = $2 ORDER BY id DESC
|
||||||
`, s.charID, pkt.Unk0)
|
`, s.charID, pkt.DistType)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
var itemDist Distribution
|
||||||
|
for rows.Next() {
|
||||||
|
err = rows.StructScan(&itemDist)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.logger.Error("Error getting distribution data from db", zap.Error(err))
|
continue
|
||||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
|
|
||||||
} else {
|
|
||||||
for dists.Next() {
|
|
||||||
distCount++
|
|
||||||
distData := &ItemDist{}
|
|
||||||
err = dists.StructScan(&distData)
|
|
||||||
if err != nil {
|
|
||||||
s.logger.Error("Error parsing item distribution data", zap.Error(err))
|
|
||||||
}
|
}
|
||||||
bf.WriteUint32(distData.ID)
|
itemDists = append(itemDists, itemDist)
|
||||||
bf.WriteUint32(distData.Deadline)
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bf.WriteUint16(uint16(len(itemDists)))
|
||||||
|
for _, dist := range itemDists {
|
||||||
|
bf.WriteUint32(dist.ID)
|
||||||
|
bf.WriteUint32(uint32(dist.Deadline.Unix()))
|
||||||
bf.WriteUint32(0) // Unk
|
bf.WriteUint32(0) // Unk
|
||||||
bf.WriteUint16(distData.TimesAcceptable)
|
bf.WriteUint16(dist.TimesAcceptable)
|
||||||
bf.WriteUint16(distData.TimesAccepted)
|
bf.WriteUint16(dist.TimesAccepted)
|
||||||
bf.WriteUint16(0) // Unk
|
bf.WriteUint16(0) // Unk
|
||||||
bf.WriteUint16(distData.MinHR)
|
bf.WriteInt16(dist.MinHR)
|
||||||
bf.WriteUint16(distData.MaxHR)
|
bf.WriteInt16(dist.MaxHR)
|
||||||
bf.WriteUint16(distData.MinSR)
|
bf.WriteInt16(dist.MinSR)
|
||||||
bf.WriteUint16(distData.MaxSR)
|
bf.WriteInt16(dist.MaxSR)
|
||||||
bf.WriteUint16(distData.MinGR)
|
bf.WriteInt16(dist.MinGR)
|
||||||
bf.WriteUint16(distData.MaxGR)
|
bf.WriteInt16(dist.MaxGR)
|
||||||
bf.WriteUint8(0)
|
bf.WriteUint8(0)
|
||||||
bf.WriteUint16(0)
|
bf.WriteUint16(0)
|
||||||
bf.WriteUint8(0)
|
bf.WriteUint8(0)
|
||||||
bf.WriteUint16(0)
|
bf.WriteUint16(0)
|
||||||
bf.WriteUint16(0)
|
bf.WriteUint16(0)
|
||||||
bf.WriteUint8(0)
|
bf.WriteUint8(0)
|
||||||
ps.Uint8(bf, distData.EventName, true)
|
ps.Uint8(bf, dist.EventName, true)
|
||||||
for i := 0; i < 6; i++ {
|
for i := 0; i < 6; i++ {
|
||||||
for j := 0; j < 13; j++ {
|
for j := 0; j < 13; j++ {
|
||||||
bf.WriteUint8(0)
|
bf.WriteUint8(0)
|
||||||
@@ -90,75 +92,73 @@ func handleMsgMhfEnumerateDistItem(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
resp := byteframe.NewByteFrame()
|
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||||
resp.WriteUint16(uint16(distCount))
|
}
|
||||||
resp.WriteBytes(bf.Data())
|
|
||||||
resp.WriteUint8(0)
|
type DistributionItem struct {
|
||||||
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
ItemType uint8 `db:"item_type"`
|
||||||
|
ID uint32 `db:"id"`
|
||||||
|
ItemID uint32 `db:"item_id"`
|
||||||
|
Quantity uint32 `db:"quantity"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func getDistributionItems(s *Session, i uint32) []DistributionItem {
|
||||||
|
var distItems []DistributionItem
|
||||||
|
rows, err := s.server.db.Queryx(`SELECT id, item_type, COALESCE(item_id, 0) AS item_id, COALESCE(quantity, 0) AS quantity FROM distribution_items WHERE distribution_id=$1`, i)
|
||||||
|
if err == nil {
|
||||||
|
var distItem DistributionItem
|
||||||
|
for rows.Next() {
|
||||||
|
err = rows.StructScan(&distItem)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
distItems = append(distItems, distItem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return distItems
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleMsgMhfApplyDistItem(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgMhfApplyDistItem(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgMhfApplyDistItem)
|
pkt := p.(*mhfpacket.MsgMhfApplyDistItem)
|
||||||
|
bf := byteframe.NewByteFrame()
|
||||||
if pkt.DistributionID == 0 {
|
bf.WriteUint32(pkt.DistributionID)
|
||||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 6))
|
distItems := getDistributionItems(s, pkt.DistributionID)
|
||||||
} else {
|
bf.WriteUint16(uint16(len(distItems)))
|
||||||
row := s.server.db.QueryRowx("SELECT data FROM distribution WHERE id = $1", pkt.DistributionID)
|
for _, item := range distItems {
|
||||||
dist := &ItemDist{}
|
bf.WriteUint8(item.ItemType)
|
||||||
err := row.StructScan(dist)
|
bf.WriteUint32(item.ItemID)
|
||||||
if err != nil {
|
bf.WriteUint32(item.Quantity)
|
||||||
s.logger.Error("Error parsing item distribution data", zap.Error(err))
|
bf.WriteUint32(item.ID)
|
||||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 6))
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||||
|
}
|
||||||
|
|
||||||
if len(dist.Data) >= 2 {
|
func handleMsgMhfAcquireDistItem(s *Session, p mhfpacket.MHFPacket) {
|
||||||
distData := byteframe.NewByteFrameFromBytes(dist.Data)
|
pkt := p.(*mhfpacket.MsgMhfAcquireDistItem)
|
||||||
distItems := int(distData.ReadUint16())
|
if pkt.DistributionID > 0 {
|
||||||
for i := 0; i < distItems; i++ {
|
_, err := s.server.db.Exec(`INSERT INTO public.distributions_accepted VALUES ($1, $2)`, pkt.DistributionID, s.charID)
|
||||||
if len(dist.Data) >= 2+(i*13) {
|
if err == nil {
|
||||||
itemType := distData.ReadUint8()
|
distItems := getDistributionItems(s, pkt.DistributionID)
|
||||||
_ = distData.ReadBytes(6)
|
for _, item := range distItems {
|
||||||
quantity := int(distData.ReadUint16())
|
switch item.ItemType {
|
||||||
_ = distData.ReadBytes(4)
|
|
||||||
switch itemType {
|
|
||||||
case 17:
|
case 17:
|
||||||
_ = addPointNetcafe(s, quantity)
|
_ = addPointNetcafe(s, int(item.Quantity))
|
||||||
case 19:
|
case 19:
|
||||||
s.server.db.Exec("UPDATE users u SET gacha_premium=gacha_premium+$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)", quantity, s.charID)
|
s.server.db.Exec("UPDATE users u SET gacha_premium=gacha_premium+$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)", item.Quantity, s.charID)
|
||||||
case 20:
|
case 20:
|
||||||
s.server.db.Exec("UPDATE users u SET gacha_trial=gacha_trial+$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)", quantity, s.charID)
|
s.server.db.Exec("UPDATE users u SET gacha_trial=gacha_trial+$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)", item.Quantity, s.charID)
|
||||||
case 21:
|
case 21:
|
||||||
s.server.db.Exec("UPDATE users u SET frontier_points=frontier_points+$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)", quantity, s.charID)
|
s.server.db.Exec("UPDATE users u SET frontier_points=frontier_points+$1 WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$2)", item.Quantity, s.charID)
|
||||||
case 23:
|
case 23:
|
||||||
saveData, err := GetCharacterSaveData(s, s.charID)
|
saveData, err := GetCharacterSaveData(s, s.charID)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
saveData.RP += uint16(quantity)
|
saveData.RP += uint16(item.Quantity)
|
||||||
saveData.Save(s)
|
saveData.Save(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bf := byteframe.NewByteFrame()
|
|
||||||
bf.WriteUint32(pkt.DistributionID)
|
|
||||||
bf.WriteBytes(dist.Data)
|
|
||||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
|
||||||
|
|
||||||
_, err = s.server.db.Exec(`
|
|
||||||
INSERT INTO public.distributions_accepted
|
|
||||||
VALUES ($1, $2)
|
|
||||||
`, pkt.DistributionID, s.charID)
|
|
||||||
if err != nil {
|
|
||||||
s.logger.Error("Error updating accepted dist count", zap.Error(err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleMsgMhfAcquireDistItem(s *Session, p mhfpacket.MHFPacket) {
|
|
||||||
pkt := p.(*mhfpacket.MsgMhfAcquireDistItem)
|
|
||||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user