mirror of
https://github.com/Mezeporta/Erupe.git
synced 2025-12-14 16:04:38 +01:00
Compare commits
2 Commits
feature/ev
...
feature/ea
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2d0cce719b | ||
|
|
c6fdf47779 |
@@ -1 +0,0 @@
|
||||
bin/
|
||||
9
.github/workflows/go.yml
vendored
9
.github/workflows/go.yml
vendored
@@ -10,17 +10,16 @@ on:
|
||||
- 'go.mod'
|
||||
- 'go.sum'
|
||||
- 'main.go'
|
||||
- '.github/workflows/go.yml'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.21'
|
||||
|
||||
@@ -28,7 +27,7 @@ jobs:
|
||||
run: env GOOS=linux GOARCH=amd64 go build -v
|
||||
|
||||
- name: Upload Linux-amd64 artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: Linux-amd64
|
||||
path: |
|
||||
@@ -43,7 +42,7 @@ jobs:
|
||||
run: env GOOS=windows GOARCH=amd64 go build -v
|
||||
|
||||
- name: Upload Windows-amd64 artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: Windows-amd64
|
||||
path: |
|
||||
|
||||
11
config.json
11
config.json
@@ -21,11 +21,9 @@
|
||||
"QuestCacheExpiry": 300,
|
||||
"CommandPrefix": "!",
|
||||
"AutoCreateAccount": true,
|
||||
"LoopDelay": 50,
|
||||
"DefaultCourses": [1, 23, 24],
|
||||
"EarthStatus": 0,
|
||||
"EarthID": 0,
|
||||
"EarthMonsters": [0, 0, 0, 0],
|
||||
"EarthDebug": false,
|
||||
"EarthMonsters": [116, 107, 2, 36],
|
||||
"SaveDumps": {
|
||||
"Enabled": true,
|
||||
"RawEnabled": false,
|
||||
@@ -170,11 +168,6 @@
|
||||
"Enabled": true,
|
||||
"Description": "Toggle the Quest timer",
|
||||
"Prefix": "timer"
|
||||
}, {
|
||||
"Name": "Playtime",
|
||||
"Enabled": true,
|
||||
"Description": "Show your playtime",
|
||||
"Prefix": "playtime"
|
||||
}
|
||||
],
|
||||
"Courses": [
|
||||
|
||||
@@ -81,10 +81,8 @@ type Config struct {
|
||||
QuestCacheExpiry int // Number of seconds to keep quest data cached
|
||||
CommandPrefix string // The prefix for commands
|
||||
AutoCreateAccount bool // Automatically create accounts if they don't exist
|
||||
LoopDelay int // Delay in milliseconds between each loop iteration
|
||||
DefaultCourses []uint16
|
||||
EarthStatus int32
|
||||
EarthID int32
|
||||
EarthDebug bool
|
||||
EarthMonsters []int32
|
||||
SaveDumps SaveDumpOptions
|
||||
Screenshots ScreenshotsOptions
|
||||
|
||||
@@ -64,7 +64,3 @@ if you want all the logs and you want it to be in an attached state
|
||||
```bash
|
||||
docker-compose up
|
||||
```
|
||||
|
||||
|
||||
# Troubleshooting
|
||||
Q: My Postgres will not populate. A: You're setup.sh is maybe saved as CRLF it needs to be saved as LF.
|
||||
BIN
erupe.ico
BIN
erupe.ico
Binary file not shown.
|
Before Width: | Height: | Size: 88 KiB After Width: | Height: | Size: 97 KiB |
8
go.mod
8
go.mod
@@ -10,9 +10,9 @@ require (
|
||||
github.com/lib/pq v1.10.9
|
||||
github.com/spf13/viper v1.17.0
|
||||
go.uber.org/zap v1.26.0
|
||||
golang.org/x/crypto v0.31.0
|
||||
golang.org/x/crypto v0.17.0
|
||||
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa
|
||||
golang.org/x/text v0.21.0
|
||||
golang.org/x/text v0.14.0
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -31,8 +31,8 @@ require (
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/net v0.33.0 // indirect
|
||||
golang.org/x/sys v0.28.0 // indirect
|
||||
golang.org/x/net v0.18.0 // indirect
|
||||
golang.org/x/sys v0.15.0 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
16
go.sum
16
go.sum
@@ -220,8 +220,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
|
||||
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
|
||||
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
@@ -289,8 +289,8 @@ golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v
|
||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
|
||||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||
golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg=
|
||||
golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@@ -345,8 +345,8 @@ golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@@ -356,8 +356,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
|
||||
@@ -11,7 +11,9 @@ import (
|
||||
// MsgMhfAcquireItem represents the MSG_MHF_ACQUIRE_ITEM
|
||||
type MsgMhfAcquireItem struct {
|
||||
AckHandle uint32
|
||||
RewardIDs []uint32
|
||||
Unk0 uint16
|
||||
Length uint16
|
||||
Unk1 []uint32
|
||||
}
|
||||
|
||||
// Opcode returns the ID associated with this packet type.
|
||||
@@ -22,10 +24,10 @@ func (m *MsgMhfAcquireItem) Opcode() network.PacketID {
|
||||
// Parse parses the packet from binary
|
||||
func (m *MsgMhfAcquireItem) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
bf.ReadUint16() // Zeroed
|
||||
ids := bf.ReadUint16()
|
||||
for i := uint16(0); i < ids; i++ {
|
||||
m.RewardIDs = append(m.RewardIDs, bf.ReadUint32())
|
||||
m.Unk0 = bf.ReadUint16()
|
||||
m.Length = bf.ReadUint16()
|
||||
for i := 0; i < int(m.Length); i++ {
|
||||
m.Unk1 = append(m.Unk1, bf.ReadUint32())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package mhfpacket
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"erupe-ce/common/bfutil"
|
||||
"erupe-ce/common/byteframe"
|
||||
"erupe-ce/network"
|
||||
"erupe-ce/network/clientctx"
|
||||
@@ -10,9 +9,10 @@ import (
|
||||
|
||||
// MsgMhfApplyCampaign represents the MSG_MHF_APPLY_CAMPAIGN
|
||||
type MsgMhfApplyCampaign struct {
|
||||
AckHandle uint32
|
||||
CampaignID uint32
|
||||
Code string
|
||||
AckHandle uint32
|
||||
Unk0 uint32
|
||||
Unk1 uint16
|
||||
Unk2 []byte
|
||||
}
|
||||
|
||||
// Opcode returns the ID associated with this packet type.
|
||||
@@ -23,9 +23,9 @@ func (m *MsgMhfApplyCampaign) Opcode() network.PacketID {
|
||||
// Parse parses the packet from binary
|
||||
func (m *MsgMhfApplyCampaign) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
m.CampaignID = bf.ReadUint32()
|
||||
bf.ReadUint16() // Zeroed
|
||||
m.Code = string(bfutil.UpToNull(bf.ReadBytes(16)))
|
||||
m.Unk0 = bf.ReadUint32()
|
||||
m.Unk1 = bf.ReadUint16()
|
||||
m.Unk2 = bf.ReadBytes(16)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -8,9 +8,9 @@ import (
|
||||
|
||||
// MsgMhfEnumerateCampaign represents the MSG_MHF_ENUMERATE_CAMPAIGN
|
||||
type MsgMhfEnumerateCampaign struct {
|
||||
AckHandle uint32
|
||||
NullPadding1 uint16 // 0 in z2
|
||||
NullPadding2 uint16 // 0 in z2
|
||||
AckHandle uint32
|
||||
Unk0 uint16
|
||||
Unk1 uint16
|
||||
}
|
||||
|
||||
// Opcode returns the ID associated with this packet type.
|
||||
@@ -21,15 +21,15 @@ func (m *MsgMhfEnumerateCampaign) Opcode() network.PacketID {
|
||||
// Parse parses the packet from binary
|
||||
func (m *MsgMhfEnumerateCampaign) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
m.NullPadding1 = bf.ReadUint16()
|
||||
m.NullPadding2 = bf.ReadUint16()
|
||||
m.Unk0 = bf.ReadUint16()
|
||||
m.Unk1 = bf.ReadUint16()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Build builds a binary packet from the current data.
|
||||
func (m *MsgMhfEnumerateCampaign) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||
bf.WriteUint32(m.AckHandle)
|
||||
bf.WriteUint16(m.NullPadding1)
|
||||
bf.WriteUint16(m.NullPadding2)
|
||||
bf.WriteUint16(m.Unk0)
|
||||
bf.WriteUint16(m.Unk1)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@ import (
|
||||
// MsgMhfEnumerateItem represents the MSG_MHF_ENUMERATE_ITEM
|
||||
type MsgMhfEnumerateItem struct {
|
||||
AckHandle uint32
|
||||
Unk0 uint16
|
||||
Unk1 uint16
|
||||
CampaignID uint32
|
||||
}
|
||||
|
||||
@@ -22,8 +24,8 @@ func (m *MsgMhfEnumerateItem) Opcode() network.PacketID {
|
||||
// Parse parses the packet from binary
|
||||
func (m *MsgMhfEnumerateItem) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
bf.ReadUint16() // Zeroed
|
||||
bf.ReadUint16() // Always 2
|
||||
m.Unk0 = bf.ReadUint16()
|
||||
m.Unk1 = bf.ReadUint16()
|
||||
m.CampaignID = bf.ReadUint32()
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package mhfpacket
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"erupe-ce/common/byteframe"
|
||||
"erupe-ce/network"
|
||||
@@ -10,11 +11,11 @@ import (
|
||||
|
||||
// MsgMhfGetWeeklySeibatuRankingReward represents the MSG_MHF_GET_WEEKLY_SEIBATU_RANKING_REWARD
|
||||
type MsgMhfGetWeeklySeibatuRankingReward struct {
|
||||
AckHandle uint32
|
||||
Unk0 uint32
|
||||
Unk1 uint32
|
||||
Unk2 uint32
|
||||
Unk3 uint32
|
||||
AckHandle uint32
|
||||
Unk0 uint32
|
||||
Operation uint32
|
||||
ID uint32
|
||||
EarthMonster uint32
|
||||
}
|
||||
|
||||
// Opcode returns the ID associated with this packet type.
|
||||
@@ -26,9 +27,10 @@ func (m *MsgMhfGetWeeklySeibatuRankingReward) Opcode() network.PacketID {
|
||||
func (m *MsgMhfGetWeeklySeibatuRankingReward) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
m.Unk0 = bf.ReadUint32()
|
||||
m.Unk1 = bf.ReadUint32()
|
||||
m.Unk2 = bf.ReadUint32()
|
||||
m.Unk3 = bf.ReadUint32()
|
||||
m.Operation = bf.ReadUint32()
|
||||
m.ID = bf.ReadUint32()
|
||||
m.EarthMonster = bf.ReadUint32()
|
||||
fmt.Printf("MsgMhfGetWeeklySeibatuRankingReward: Unk0:[%d] Operation:[%d] ID:[%d] EarthMonster:[%d]\n\n", m.Unk0, m.Operation, m.ID, m.EarthMonster)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -10,9 +10,9 @@ import (
|
||||
|
||||
// MsgMhfStateCampaign represents the MSG_MHF_STATE_CAMPAIGN
|
||||
type MsgMhfStateCampaign struct {
|
||||
AckHandle uint32
|
||||
CampaignID uint32
|
||||
NullPadding uint16
|
||||
AckHandle uint32
|
||||
CampaignID uint32
|
||||
Unk1 uint16
|
||||
}
|
||||
|
||||
// Opcode returns the ID associated with this packet type.
|
||||
@@ -24,7 +24,7 @@ func (m *MsgMhfStateCampaign) Opcode() network.PacketID {
|
||||
func (m *MsgMhfStateCampaign) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
m.CampaignID = bf.ReadUint32()
|
||||
m.NullPadding = bf.ReadUint16() //0 in Z2
|
||||
m.Unk1 = bf.ReadUint16()
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -11,9 +11,12 @@ import (
|
||||
// MsgMhfTransferItem represents the MSG_MHF_TRANSFER_ITEM
|
||||
type MsgMhfTransferItem struct {
|
||||
AckHandle uint32
|
||||
QuestID uint32
|
||||
ItemType uint8
|
||||
Quantity uint16
|
||||
// looking at packets, these were static across sessions and did not actually
|
||||
// correlate with any item IDs that would make sense to get after quests so
|
||||
// I have no idea what this actually does
|
||||
Unk0 uint32
|
||||
Unk1 uint8
|
||||
Unk2 uint16
|
||||
}
|
||||
|
||||
// Opcode returns the ID associated with this packet type.
|
||||
@@ -24,10 +27,10 @@ func (m *MsgMhfTransferItem) Opcode() network.PacketID {
|
||||
// Parse parses the packet from binary
|
||||
func (m *MsgMhfTransferItem) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
m.QuestID = bf.ReadUint32()
|
||||
m.ItemType = bf.ReadUint8()
|
||||
m.Unk0 = bf.ReadUint32()
|
||||
m.Unk1 = bf.ReadUint8()
|
||||
bf.ReadUint8() // Zeroed
|
||||
m.Quantity = bf.ReadUint16()
|
||||
m.Unk2 = bf.ReadUint16()
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -1,15 +1,13 @@
|
||||
BEGIN;
|
||||
|
||||
TRUNCATE public.cafebonus;
|
||||
|
||||
INSERT INTO public.cafebonus (time_req, item_type, item_id, quantity)
|
||||
VALUES
|
||||
(1800, 17, 0, 50),
|
||||
(3600, 17, 0, 100),
|
||||
(7200, 17, 0, 200),
|
||||
(10800, 17, 0, 300),
|
||||
(18000, 17, 0, 350),
|
||||
(28800, 17, 0, 500),
|
||||
(43200, 17, 0, 500);
|
||||
(1800, 17, 0, 250),
|
||||
(3600, 17, 0, 500),
|
||||
(7200, 17, 0, 1000),
|
||||
(10800, 17, 0, 1500),
|
||||
(18000, 17, 0, 1750),
|
||||
(28800, 17, 0, 3000),
|
||||
(43200, 17, 0, 4000);
|
||||
|
||||
END;
|
||||
@@ -1,66 +0,0 @@
|
||||
BEGIN;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS public.campaigns (
|
||||
id SERIAL PRIMARY KEY,
|
||||
min_hr INTEGER,
|
||||
max_hr INTEGER,
|
||||
min_sr INTEGER,
|
||||
max_sr INTEGER,
|
||||
min_gr INTEGER,
|
||||
max_gr INTEGER,
|
||||
reward_type INTEGER,
|
||||
stamps INTEGER,
|
||||
unk INTEGER,
|
||||
background_id INTEGER,
|
||||
start_time TIMESTAMP WITH TIME ZONE,
|
||||
end_time TIMESTAMP WITH TIME ZONE,
|
||||
title TEXT,
|
||||
reward TEXT,
|
||||
link TEXT,
|
||||
code_prefix TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS public.campaign_categories (
|
||||
id SERIAL PRIMARY KEY,
|
||||
type INTEGER,
|
||||
title TEXT,
|
||||
description TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS public.campaign_category_links (
|
||||
id SERIAL PRIMARY KEY,
|
||||
campaign_id INTEGER,
|
||||
category_id INTEGER
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS public.campaign_rewards (
|
||||
id SERIAL PRIMARY KEY,
|
||||
campaign_id INTEGER,
|
||||
item_type INTEGER,
|
||||
quantity INTEGER,
|
||||
item_id INTEGER
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS public.campaign_rewards_claimed (
|
||||
character_id INTEGER,
|
||||
reward_id INTEGER
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS public.campaign_state (
|
||||
id SERIAL PRIMARY KEY,
|
||||
campaign_id INTEGER,
|
||||
character_id INTEGER,
|
||||
code TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS public.campaign_codes (
|
||||
code TEXT,
|
||||
multi BOOLEAN
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS public.campaign_quest (
|
||||
campaign_id INTEGER,
|
||||
character_id INTEGER
|
||||
);
|
||||
|
||||
END;
|
||||
6
schemas/patch-schema/23-earth.sql
Normal file
6
schemas/patch-schema/23-earth.sql
Normal file
@@ -0,0 +1,6 @@
|
||||
BEGIN;
|
||||
|
||||
-- Add 'earth' to the event_type ENUM type
|
||||
ALTER TYPE event_type ADD VALUE 'earth';
|
||||
|
||||
END;
|
||||
@@ -1,6 +0,0 @@
|
||||
BEGIN;
|
||||
|
||||
ALTER TABLE distribution ADD COLUMN rights INTEGER;
|
||||
ALTER TABLE distribution ADD COLUMN selection BOOLEAN;
|
||||
|
||||
END;
|
||||
@@ -30,18 +30,6 @@ func stubEnumerateNoResults(s *Session, ackHandle uint32) {
|
||||
doAckBufSucceed(s, ackHandle, enumBf.Data())
|
||||
}
|
||||
|
||||
func doAckEarthSucceed(s *Session, ackHandle uint32, data []*byteframe.ByteFrame) {
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint32(uint32(s.server.erupeConfig.EarthID))
|
||||
bf.WriteUint32(0)
|
||||
bf.WriteUint32(0)
|
||||
bf.WriteUint32(uint32(len(data)))
|
||||
for i := range data {
|
||||
bf.WriteBytes(data[i].Data())
|
||||
}
|
||||
doAckBufSucceed(s, ackHandle, bf.Data())
|
||||
}
|
||||
|
||||
func doAckBufSucceed(s *Session, ackHandle uint32, data []byte) {
|
||||
s.QueueSendMHF(&mhfpacket.MsgSysAck{
|
||||
AckHandle: ackHandle,
|
||||
@@ -88,7 +76,7 @@ func updateRights(s *Session) {
|
||||
Rights: s.courses,
|
||||
UnkSize: 0,
|
||||
}
|
||||
s.QueueSendMHFNonBlocking(update)
|
||||
s.QueueSendMHF(update)
|
||||
}
|
||||
|
||||
func handleMsgHead(s *Session, p mhfpacket.MHFPacket) {}
|
||||
@@ -143,6 +131,7 @@ func handleMsgSysLogin(s *Session, p mhfpacket.MHFPacket) {
|
||||
s.token = pkt.LoginTokenString
|
||||
s.Unlock()
|
||||
|
||||
updateRights(s)
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint32(uint32(TimeAdjusted().Unix())) // Unix timestamp
|
||||
|
||||
@@ -192,7 +181,7 @@ func logoutPlayer(s *Session) {
|
||||
for _, sess := range s.server.sessions {
|
||||
for rSlot := range stage.reservedClientSlots {
|
||||
if sess.charID == rSlot && sess.stage != nil && sess.stage.id[3:5] != "Qs" {
|
||||
sess.QueueSendMHFNonBlocking(&mhfpacket.MsgSysStageDestruct{})
|
||||
sess.QueueSendMHF(&mhfpacket.MsgSysStageDestruct{})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -640,6 +629,11 @@ func handleMsgSysInfokyserver(s *Session, p mhfpacket.MHFPacket) {}
|
||||
|
||||
func handleMsgMhfGetCaUniqueID(s *Session, p mhfpacket.MHFPacket) {}
|
||||
|
||||
func handleMsgMhfTransferItem(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfTransferItem)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
}
|
||||
|
||||
func handleMsgMhfEnumeratePrice(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfEnumeratePrice)
|
||||
bf := byteframe.NewByteFrame()
|
||||
@@ -1109,66 +1103,8 @@ func handleMsgMhfUnreserveSrg(s *Session, p mhfpacket.MHFPacket) {
|
||||
|
||||
func handleMsgMhfKickExportForce(s *Session, p mhfpacket.MHFPacket) {}
|
||||
|
||||
func handleMsgMhfGetEarthStatus(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetEarthStatus)
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint32(uint32(TimeWeekStart().Unix())) // Start
|
||||
bf.WriteUint32(uint32(TimeWeekNext().Unix())) // End
|
||||
bf.WriteInt32(s.server.erupeConfig.EarthStatus)
|
||||
bf.WriteInt32(s.server.erupeConfig.EarthID)
|
||||
for i, m := range s.server.erupeConfig.EarthMonsters {
|
||||
if _config.ErupeConfig.RealClientMode <= _config.G9 {
|
||||
if i == 3 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if i == 4 {
|
||||
break
|
||||
}
|
||||
bf.WriteInt32(m)
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfRegistSpabiTime(s *Session, p mhfpacket.MHFPacket) {}
|
||||
|
||||
func handleMsgMhfGetEarthValue(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetEarthValue)
|
||||
type EarthValues struct {
|
||||
Value []uint32
|
||||
}
|
||||
|
||||
var earthValues []EarthValues
|
||||
switch pkt.ReqType {
|
||||
case 1:
|
||||
earthValues = []EarthValues{
|
||||
{[]uint32{1, 312, 0, 0, 0, 0}},
|
||||
{[]uint32{2, 99, 0, 0, 0, 0}},
|
||||
}
|
||||
case 2:
|
||||
earthValues = []EarthValues{
|
||||
{[]uint32{1, 5771, 0, 0, 0, 0}},
|
||||
{[]uint32{2, 1847, 0, 0, 0, 0}},
|
||||
}
|
||||
case 3:
|
||||
earthValues = []EarthValues{
|
||||
{[]uint32{1001, 36, 0, 0, 0, 0}},
|
||||
{[]uint32{9001, 3, 0, 0, 0, 0}},
|
||||
{[]uint32{9002, 10, 300, 0, 0, 0}},
|
||||
}
|
||||
}
|
||||
|
||||
var data []*byteframe.ByteFrame
|
||||
for _, i := range earthValues {
|
||||
bf := byteframe.NewByteFrame()
|
||||
for _, j := range i.Value {
|
||||
bf.WriteUint32(j)
|
||||
}
|
||||
data = append(data, bf)
|
||||
}
|
||||
doAckEarthSucceed(s, pkt.AckHandle, data)
|
||||
}
|
||||
|
||||
func handleMsgMhfDebugPostValue(s *Session, p mhfpacket.MHFPacket) {}
|
||||
|
||||
func handleMsgMhfGetRandFromTable(s *Session, p mhfpacket.MHFPacket) {
|
||||
|
||||
@@ -166,7 +166,7 @@ func handleMsgMhfReceiveCafeDurationBonus(s *Session, p mhfpacket.MHFPacket) {
|
||||
FROM characters ch
|
||||
WHERE ch.id = $1
|
||||
) >= time_req`, s.charID, TimeAdjusted().Unix()-s.sessionStart)
|
||||
if err != nil || !mhfcourse.CourseExists(30, s.courses) {
|
||||
if err != nil {
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
} else {
|
||||
for rows.Next() {
|
||||
|
||||
@@ -10,68 +10,51 @@ import (
|
||||
)
|
||||
|
||||
type CampaignEvent struct {
|
||||
ID uint32 `db:"id"`
|
||||
MinHR int16 `db:"min_hr"`
|
||||
MaxHR int16 `db:"max_hr"`
|
||||
MinSR int16 `db:"min_sr"`
|
||||
MaxSR int16 `db:"max_sr"`
|
||||
MinGR int16 `db:"min_gr"`
|
||||
MaxGR int16 `db:"max_gr"`
|
||||
RewardType uint16 `db:"reward_type"`
|
||||
Stamps uint8 `db:"stamps"`
|
||||
Unk uint8 `db:"unk"`
|
||||
BackgroundID uint16 `db:"background_id"`
|
||||
Start time.Time `db:"start_time"`
|
||||
End time.Time `db:"end_time"`
|
||||
Title string `db:"title"`
|
||||
Reward string `db:"reward"`
|
||||
Link string `db:"link"`
|
||||
Prefix string `db:"code_prefix"`
|
||||
ID uint32
|
||||
Unk0 uint32
|
||||
MinHR int16
|
||||
MaxHR int16
|
||||
MinSR int16
|
||||
MaxSR int16
|
||||
MinGR int16
|
||||
MaxGR int16
|
||||
Unk1 uint16
|
||||
Unk2 uint8
|
||||
Unk3 uint8
|
||||
Unk4 uint16
|
||||
Unk5 uint16
|
||||
Start time.Time
|
||||
End time.Time
|
||||
Unk6 uint8
|
||||
String0 string
|
||||
String1 string
|
||||
String2 string
|
||||
String3 string
|
||||
Link string
|
||||
Prefix string
|
||||
Categories []uint16
|
||||
}
|
||||
|
||||
type CampaignCategory struct {
|
||||
ID uint16 `db:"id"`
|
||||
Type uint8 `db:"type"`
|
||||
Title string `db:"title"`
|
||||
Description string `db:"description"`
|
||||
ID uint16
|
||||
Type uint8
|
||||
Title string
|
||||
Description string
|
||||
}
|
||||
|
||||
type CampaignLink struct {
|
||||
CategoryID uint16 `db:"category_id"`
|
||||
CampaignID uint32 `db:"campaign_id"`
|
||||
}
|
||||
|
||||
type CampaignReward struct {
|
||||
ID uint32 `db:"id"`
|
||||
ItemType uint16 `db:"item_type"`
|
||||
Quantity uint16 `db:"quantity"`
|
||||
ItemID uint16 `db:"item_id"`
|
||||
Deadline time.Time `db:"deadline"`
|
||||
CategoryID uint16
|
||||
CampaignID uint32
|
||||
}
|
||||
|
||||
func handleMsgMhfEnumerateCampaign(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfEnumerateCampaign)
|
||||
bf := byteframe.NewByteFrame()
|
||||
|
||||
var events []CampaignEvent
|
||||
var categories []CampaignCategory
|
||||
events := []CampaignEvent{}
|
||||
categories := []CampaignCategory{}
|
||||
var campaignLinks []CampaignLink
|
||||
|
||||
err := s.server.db.Select(&events, "SELECT id,min_hr,max_hr,min_sr,max_sr,min_gr,max_gr,reward_type,stamps,unk,background_id,start_time,end_time,title,reward,link,code_prefix FROM campaigns")
|
||||
if err != nil {
|
||||
doAckBufFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
err = s.server.db.Select(&categories, "SELECT id, type, title, description FROM campaign_categories")
|
||||
if err != nil {
|
||||
doAckBufFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
err = s.server.db.Select(&campaignLinks, "SELECT campaign_id, category_id FROM campaign_category_links")
|
||||
if err != nil {
|
||||
doAckBufFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
if len(events) > 255 {
|
||||
bf.WriteUint8(255)
|
||||
bf.WriteUint16(uint16(len(events)))
|
||||
@@ -80,7 +63,7 @@ func handleMsgMhfEnumerateCampaign(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
for _, event := range events {
|
||||
bf.WriteUint32(event.ID)
|
||||
bf.WriteUint32(0)
|
||||
bf.WriteUint32(event.Unk0)
|
||||
bf.WriteInt16(event.MinHR)
|
||||
bf.WriteInt16(event.MaxHR)
|
||||
bf.WriteInt16(event.MinSR)
|
||||
@@ -89,23 +72,22 @@ func handleMsgMhfEnumerateCampaign(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteInt16(event.MinGR)
|
||||
bf.WriteInt16(event.MaxGR)
|
||||
}
|
||||
bf.WriteUint16(event.RewardType)
|
||||
bf.WriteUint8(event.Stamps)
|
||||
bf.WriteUint8(event.Unk) // Related to stamp count
|
||||
bf.WriteUint16(event.BackgroundID)
|
||||
bf.WriteUint16(0)
|
||||
bf.WriteUint16(event.Unk1)
|
||||
bf.WriteUint8(event.Unk2)
|
||||
bf.WriteUint8(event.Unk3)
|
||||
bf.WriteUint16(event.Unk4)
|
||||
bf.WriteUint16(event.Unk5)
|
||||
bf.WriteUint32(uint32(event.Start.Unix()))
|
||||
bf.WriteUint32(uint32(event.End.Unix()))
|
||||
if event.End.After(time.Now()) {
|
||||
bf.WriteBool(true)
|
||||
} else {
|
||||
bf.WriteBool(false)
|
||||
}
|
||||
ps.Uint8(bf, event.Title, true)
|
||||
ps.Uint8(bf, event.Reward, true)
|
||||
ps.Uint8(bf, "", false)
|
||||
ps.Uint8(bf, "", false)
|
||||
bf.WriteUint8(event.Unk6)
|
||||
ps.Uint8(bf, event.String0, true)
|
||||
ps.Uint8(bf, event.String1, true)
|
||||
ps.Uint8(bf, event.String2, true)
|
||||
ps.Uint8(bf, event.String3, true)
|
||||
ps.Uint8(bf, event.Link, true)
|
||||
for i := range event.Categories {
|
||||
campaignLinks = append(campaignLinks, CampaignLink{event.Categories[i], event.ID})
|
||||
}
|
||||
}
|
||||
|
||||
if len(events) > 255 {
|
||||
@@ -116,7 +98,7 @@ func handleMsgMhfEnumerateCampaign(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
for _, event := range events {
|
||||
bf.WriteUint32(event.ID)
|
||||
bf.WriteUint8(1) // Related to stamp count
|
||||
bf.WriteUint8(1) // Always 1?
|
||||
bf.WriteBytes([]byte(event.Prefix))
|
||||
}
|
||||
|
||||
@@ -153,156 +135,42 @@ func handleMsgMhfEnumerateCampaign(s *Session, p mhfpacket.MHFPacket) {
|
||||
func handleMsgMhfStateCampaign(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfStateCampaign)
|
||||
bf := byteframe.NewByteFrame()
|
||||
var required int
|
||||
var deadline time.Time
|
||||
var stamps []uint32
|
||||
|
||||
err := s.server.db.Select(&stamps, "SELECT id FROM campaign_state WHERE campaign_id = $1 AND character_id = $2", pkt.CampaignID, s.charID)
|
||||
if err != nil {
|
||||
doAckBufFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
err = s.server.db.QueryRow(`SELECT stamps, end_time FROM campaigns WHERE id = $1`, pkt.CampaignID).Scan(&required, &deadline)
|
||||
if err != nil {
|
||||
doAckBufFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
bf.WriteUint16(uint16(len(stamps) + 1))
|
||||
|
||||
if required == 0 {
|
||||
required = 1 // TODO: I don't understand how this is supposed to work
|
||||
}
|
||||
|
||||
if len(stamps) < required {
|
||||
bf.WriteUint16(0)
|
||||
} else if len(stamps) >= required || deadline.After(time.Now()) {
|
||||
bf.WriteUint16(2)
|
||||
}
|
||||
|
||||
for _, v := range stamps {
|
||||
bf.WriteUint32(v)
|
||||
}
|
||||
|
||||
bf.WriteUint16(1)
|
||||
bf.WriteUint16(0)
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfApplyCampaign(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfApplyCampaign)
|
||||
|
||||
// Check if the code exists and check if it's a multi-code
|
||||
var multi bool
|
||||
err := s.server.db.QueryRow(`SELECT multi FROM public.campaign_codes WHERE code = $1 GROUP BY multi`, pkt.Code).Scan(&multi)
|
||||
if err != nil {
|
||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
|
||||
// Check if the code is already used
|
||||
var exists bool
|
||||
if multi {
|
||||
s.server.db.QueryRow(`SELECT COUNT(*) FROM public.campaign_state WHERE code = $1 AND character_id = $2`, pkt.Code, s.charID).Scan(&exists)
|
||||
} else {
|
||||
s.server.db.QueryRow(`SELECT COUNT(*) FROM public.campaign_state WHERE code = $1`, pkt.Code).Scan(&exists)
|
||||
}
|
||||
if exists {
|
||||
doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
|
||||
s.server.db.Exec(`INSERT INTO public.campaign_state (code, campaign_id, character_id) VALUES ($1, $2, $3)`, pkt.Code, pkt.CampaignID, s.charID)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint32(1)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfEnumerateItem(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfEnumerateItem)
|
||||
items := []struct {
|
||||
Unk0 uint32
|
||||
Unk1 uint16
|
||||
Unk2 uint16
|
||||
Unk3 uint16
|
||||
Unk4 uint32
|
||||
Unk5 uint32
|
||||
}{}
|
||||
bf := byteframe.NewByteFrame()
|
||||
|
||||
var stamps, required, rewardType uint16
|
||||
var deadline time.Time
|
||||
err := s.server.db.QueryRow(`SELECT COUNT(*) FROM campaign_state WHERE campaign_id = $1 AND character_id = $2`, pkt.CampaignID, s.charID).Scan(&stamps)
|
||||
if err != nil {
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
err = s.server.db.QueryRow(`SELECT stamps, reward_type, end_time FROM campaigns WHERE id = $1`, pkt.CampaignID).Scan(&required, &rewardType, &deadline)
|
||||
if err != nil {
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
|
||||
if required == 0 {
|
||||
required = 1 // TODO: I don't understand how this is supposed to work
|
||||
}
|
||||
|
||||
if stamps >= required {
|
||||
var items []CampaignReward
|
||||
if rewardType == 2 {
|
||||
var exists int
|
||||
s.server.db.QueryRow(`SELECT COUNT(*) FROM campaign_quest WHERE campaign_id = $1 AND character_id = $2`, pkt.CampaignID, s.charID).Scan(&exists)
|
||||
if exists > 0 {
|
||||
err = s.server.db.Select(&items, `
|
||||
SELECT id, item_type, quantity, item_id, TO_TIMESTAMP(0) AS deadline FROM campaign_rewards
|
||||
WHERE campaign_id = $1 AND item_type != 9
|
||||
AND NOT EXISTS (SELECT 1 FROM campaign_rewards_claimed WHERE reward_id = campaign_rewards.id AND character_id = $2)
|
||||
`, pkt.CampaignID, s.charID)
|
||||
} else {
|
||||
err = s.server.db.Select(&items, `
|
||||
SELECT cr.id, cr.item_type, cr.quantity, cr.item_id, COALESCE(c.end_time, TO_TIMESTAMP(0)) AS deadline FROM campaign_rewards cr
|
||||
JOIN campaigns c ON cr.campaign_id = c.id
|
||||
WHERE campaign_id = $1 AND item_type = 9`, pkt.CampaignID)
|
||||
}
|
||||
} else {
|
||||
err = s.server.db.Select(&items, `
|
||||
SELECT id, item_type, quantity, item_id, TO_TIMESTAMP(0) AS deadline FROM campaign_rewards
|
||||
WHERE campaign_id = $1
|
||||
AND NOT EXISTS (SELECT 1 FROM campaign_rewards_claimed WHERE reward_id = campaign_rewards.id AND character_id = $2)
|
||||
`, pkt.CampaignID, s.charID)
|
||||
}
|
||||
if err != nil {
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
return
|
||||
}
|
||||
|
||||
bf.WriteUint16(uint16(len(items)))
|
||||
for _, item := range items {
|
||||
bf.WriteUint32(item.ID)
|
||||
bf.WriteUint16(item.ItemType)
|
||||
bf.WriteUint16(item.Quantity)
|
||||
bf.WriteUint16(item.ItemID) //HACK:placed quest id in this field to fit with Item No pattern. however it could be another field... possibly the other unks.
|
||||
bf.WriteUint16(0) //Unk4, gets cast to uint8
|
||||
bf.WriteUint32(0) //Unk5
|
||||
bf.WriteUint32(uint32(deadline.Unix()))
|
||||
}
|
||||
if len(items) == 0 {
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
} else {
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
} else {
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
bf.WriteUint16(uint16(len(items)))
|
||||
for _, item := range items {
|
||||
bf.WriteUint32(item.Unk0)
|
||||
bf.WriteUint16(item.Unk1)
|
||||
bf.WriteUint16(item.Unk2)
|
||||
bf.WriteUint16(item.Unk3)
|
||||
bf.WriteUint32(item.Unk4)
|
||||
bf.WriteUint32(item.Unk5)
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfAcquireItem(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfAcquireItem)
|
||||
for _, id := range pkt.RewardIDs {
|
||||
s.server.db.Exec(`INSERT INTO campaign_rewards_claimed (reward_id, character_id) VALUES ($1, $2)`, id, s.charID)
|
||||
}
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func handleMsgMhfTransferItem(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfTransferItem)
|
||||
if pkt.ItemType == 9 {
|
||||
var campaignID uint32
|
||||
err := s.server.db.QueryRow(`
|
||||
SELECT ce.campaign_id FROM campaign_rewards ce
|
||||
JOIN event_quests eq ON ce.item_id = eq.quest_id
|
||||
WHERE eq.id = $1
|
||||
`, pkt.QuestID).Scan(&campaignID)
|
||||
if err == nil {
|
||||
s.server.db.Exec(`INSERT INTO campaign_quest (campaign_id, character_id) VALUES ($1, $2)`, campaignID, s.charID)
|
||||
}
|
||||
}
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ func sendServerChatMessage(s *Session, message string) {
|
||||
RawDataPayload: bf.Data(),
|
||||
}
|
||||
|
||||
s.QueueSendMHFNonBlocking(castedBin)
|
||||
s.QueueSendMHF(castedBin)
|
||||
}
|
||||
|
||||
func parseChatCommand(s *Session, command string) {
|
||||
@@ -198,7 +198,7 @@ func parseChatCommand(s *Session, command string) {
|
||||
temp.Build(deleteNotif, s.clientContext)
|
||||
}
|
||||
deleteNotif.WriteUint16(uint16(network.MSG_SYS_END))
|
||||
s.QueueSendNonBlocking(deleteNotif.Data())
|
||||
s.QueueSend(deleteNotif.Data())
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
reloadNotif := byteframe.NewByteFrame()
|
||||
for _, session := range s.server.sessions {
|
||||
@@ -233,7 +233,7 @@ func parseChatCommand(s *Session, command string) {
|
||||
temp.Build(reloadNotif, s.clientContext)
|
||||
}
|
||||
reloadNotif.WriteUint16(uint16(network.MSG_SYS_END))
|
||||
s.QueueSendNonBlocking(reloadNotif.Data())
|
||||
s.QueueSend(reloadNotif.Data())
|
||||
} else {
|
||||
sendDisabledCommandMessage(s, commands["Reload"])
|
||||
}
|
||||
@@ -381,7 +381,7 @@ func parseChatCommand(s *Session, command string) {
|
||||
payload.WriteInt16(int16(x)) // X
|
||||
payload.WriteInt16(int16(y)) // Y
|
||||
payloadBytes := payload.Data()
|
||||
s.QueueSendMHFNonBlocking(&mhfpacket.MsgSysCastedBinary{
|
||||
s.QueueSendMHF(&mhfpacket.MsgSysCastedBinary{
|
||||
CharID: s.charID,
|
||||
MessageType: BinaryMessageTypeState,
|
||||
RawDataPayload: payloadBytes,
|
||||
@@ -407,13 +407,6 @@ func parseChatCommand(s *Session, command string) {
|
||||
} else {
|
||||
sendDisabledCommandMessage(s, commands["Discord"])
|
||||
}
|
||||
case commands["Playtime"].Prefix:
|
||||
if commands["Playtime"].Enabled || s.isOp() {
|
||||
playtime := s.playtime + uint32(time.Now().Sub(s.playtimeTime).Seconds())
|
||||
sendServerChatMessage(s, fmt.Sprintf(s.server.i18n.commands.playtime, playtime/60/60, playtime/60%60, playtime%60))
|
||||
} else {
|
||||
sendDisabledCommandMessage(s, commands["Playtime"])
|
||||
}
|
||||
case commands["Help"].Prefix:
|
||||
if commands["Help"].Enabled || s.isOp() {
|
||||
for _, command := range commands {
|
||||
@@ -539,7 +532,7 @@ func handleMsgSysCastBinary(s *Session, p mhfpacket.MHFPacket) {
|
||||
char := s.server.FindSessionByCharID(targetID)
|
||||
|
||||
if char != nil {
|
||||
char.QueueSendMHFNonBlocking(resp)
|
||||
char.QueueSendMHF(resp)
|
||||
}
|
||||
}
|
||||
default:
|
||||
|
||||
@@ -23,7 +23,6 @@ const (
|
||||
pGalleryData // +1748
|
||||
pToreData // +240
|
||||
pGardenData // +68
|
||||
pPlaytime // +4
|
||||
pWeaponType // +1
|
||||
pWeaponID // +2
|
||||
pHR // +2
|
||||
@@ -46,7 +45,6 @@ type CharacterSaveData struct {
|
||||
GalleryData []byte
|
||||
ToreData []byte
|
||||
GardenData []byte
|
||||
Playtime uint32
|
||||
WeaponType uint8
|
||||
WeaponID uint16
|
||||
HR uint16
|
||||
@@ -61,7 +59,6 @@ func getPointers() map[SavePointer]int {
|
||||
pointers := map[SavePointer]int{pGender: 81, lBookshelfData: 5576}
|
||||
switch _config.ErupeConfig.RealClientMode {
|
||||
case _config.ZZ:
|
||||
pointers[pPlaytime] = 128356
|
||||
pointers[pWeaponID] = 128522
|
||||
pointers[pWeaponType] = 128789
|
||||
pointers[pHouseTier] = 129900
|
||||
@@ -77,7 +74,6 @@ func getPointers() map[SavePointer]int {
|
||||
case _config.Z2, _config.Z1, _config.G101, _config.G10, _config.G91, _config.G9, _config.G81, _config.G8,
|
||||
_config.G7, _config.G61, _config.G6, _config.G52, _config.G51, _config.G5, _config.GG, _config.G32, _config.G31,
|
||||
_config.G3, _config.G2, _config.G1:
|
||||
pointers[pPlaytime] = 92356
|
||||
pointers[pWeaponID] = 92522
|
||||
pointers[pWeaponType] = 92789
|
||||
pointers[pHouseTier] = 93900
|
||||
@@ -91,7 +87,6 @@ func getPointers() map[SavePointer]int {
|
||||
pointers[pRP] = 106614
|
||||
pointers[pKQF] = 110720
|
||||
case _config.F5, _config.F4:
|
||||
pointers[pPlaytime] = 60356
|
||||
pointers[pWeaponID] = 60522
|
||||
pointers[pWeaponType] = 60789
|
||||
pointers[pHouseTier] = 61900
|
||||
@@ -103,7 +98,6 @@ func getPointers() map[SavePointer]int {
|
||||
pointers[pGardenData] = 74424
|
||||
pointers[pRP] = 74614
|
||||
case _config.S6:
|
||||
pointers[pPlaytime] = 12356
|
||||
pointers[pWeaponID] = 12522
|
||||
pointers[pWeaponType] = 12789
|
||||
pointers[pHouseTier] = 13900
|
||||
@@ -237,7 +231,6 @@ func (save *CharacterSaveData) updateStructWithSaveData() {
|
||||
save.GalleryData = save.decompSave[save.Pointers[pGalleryData] : save.Pointers[pGalleryData]+1748]
|
||||
save.ToreData = save.decompSave[save.Pointers[pToreData] : save.Pointers[pToreData]+240]
|
||||
save.GardenData = save.decompSave[save.Pointers[pGardenData] : save.Pointers[pGardenData]+68]
|
||||
save.Playtime = binary.LittleEndian.Uint32(save.decompSave[save.Pointers[pPlaytime] : save.Pointers[pPlaytime]+4])
|
||||
save.WeaponType = save.decompSave[save.Pointers[pWeaponType]]
|
||||
save.WeaponID = binary.LittleEndian.Uint16(save.decompSave[save.Pointers[pWeaponID] : save.Pointers[pWeaponID]+2])
|
||||
save.HR = binary.LittleEndian.Uint16(save.decompSave[save.Pointers[pHR] : save.Pointers[pHR]+2])
|
||||
|
||||
@@ -54,9 +54,6 @@ func handleMsgMhfSavedata(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
characterSaveData.updateStructWithSaveData()
|
||||
|
||||
s.playtime = characterSaveData.Playtime
|
||||
s.playtimeTime = time.Now()
|
||||
|
||||
// Bypass name-checker if new
|
||||
if characterSaveData.IsNewCharacter == true {
|
||||
s.Name = characterSaveData.Name
|
||||
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
type Distribution struct {
|
||||
ID uint32 `db:"id"`
|
||||
Deadline time.Time `db:"deadline"`
|
||||
Rights uint32 `db:"rights"`
|
||||
TimesAcceptable uint16 `db:"times_acceptable"`
|
||||
TimesAccepted uint16 `db:"times_accepted"`
|
||||
MinHR int16 `db:"min_hr"`
|
||||
@@ -24,7 +23,7 @@ type Distribution struct {
|
||||
MaxGR int16 `db:"max_gr"`
|
||||
EventName string `db:"event_name"`
|
||||
Description string `db:"description"`
|
||||
Selection bool `db:"selection"`
|
||||
Data []byte `db:"data"`
|
||||
}
|
||||
|
||||
func handleMsgMhfEnumerateDistItem(s *Session, p mhfpacket.MHFPacket) {
|
||||
@@ -33,7 +32,7 @@ func handleMsgMhfEnumerateDistItem(s *Session, p mhfpacket.MHFPacket) {
|
||||
var itemDists []Distribution
|
||||
bf := byteframe.NewByteFrame()
|
||||
rows, err := s.server.db.Queryx(`
|
||||
SELECT d.id, event_name, description, COALESCE(rights, 0) AS rights, COALESCE(selection, false) AS selection, times_acceptable,
|
||||
SELECT d.id, event_name, description, times_acceptable,
|
||||
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,
|
||||
@@ -61,7 +60,7 @@ func handleMsgMhfEnumerateDistItem(s *Session, p mhfpacket.MHFPacket) {
|
||||
for _, dist := range itemDists {
|
||||
bf.WriteUint32(dist.ID)
|
||||
bf.WriteUint32(uint32(dist.Deadline.Unix()))
|
||||
bf.WriteUint32(dist.Rights)
|
||||
bf.WriteUint32(0) // Unk
|
||||
bf.WriteUint16(dist.TimesAcceptable)
|
||||
bf.WriteUint16(dist.TimesAccepted)
|
||||
if _config.ErupeConfig.RealClientMode >= _config.G9 {
|
||||
@@ -80,11 +79,7 @@ func handleMsgMhfEnumerateDistItem(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint16(0) // Unk
|
||||
}
|
||||
if _config.ErupeConfig.RealClientMode >= _config.G8 {
|
||||
if dist.Selection {
|
||||
bf.WriteUint8(2) // Selection
|
||||
} else {
|
||||
bf.WriteUint8(0)
|
||||
}
|
||||
bf.WriteUint8(0) // Unk
|
||||
}
|
||||
if _config.ErupeConfig.RealClientMode >= _config.G7 {
|
||||
bf.WriteUint16(0) // Unk
|
||||
|
||||
172
server/channelserver/handlers_earth.go
Normal file
172
server/channelserver/handlers_earth.go
Normal file
@@ -0,0 +1,172 @@
|
||||
package channelserver
|
||||
|
||||
import (
|
||||
"erupe-ce/common/byteframe"
|
||||
_config "erupe-ce/config"
|
||||
"erupe-ce/network/mhfpacket"
|
||||
"log"
|
||||
"time"
|
||||
)
|
||||
|
||||
func doAckEarthSucceed(s *Session, ackHandle uint32, data []*byteframe.ByteFrame) {
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint32(0)
|
||||
bf.WriteUint32(0)
|
||||
bf.WriteUint32(0)
|
||||
bf.WriteUint32(uint32(len(data)))
|
||||
for i := range data {
|
||||
bf.WriteBytes(data[i].Data())
|
||||
}
|
||||
doAckBufSucceed(s, ackHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfGetEarthValue(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetEarthValue)
|
||||
type EarthValues struct {
|
||||
Value []uint32
|
||||
}
|
||||
|
||||
var earthValues []EarthValues
|
||||
switch pkt.ReqType {
|
||||
case 1:
|
||||
earthValues = []EarthValues{
|
||||
// {Block, DureSlays, Unk, Unk, Unk, Unk}
|
||||
{[]uint32{1, 100, 0, 0, 0, 0}},
|
||||
{[]uint32{2, 100, 0, 0, 0, 0}},
|
||||
}
|
||||
case 2:
|
||||
earthValues = []EarthValues{
|
||||
// {Block, Floors?, Unk, Unk, Unk, Unk}
|
||||
{[]uint32{1, 5771, 0, 0, 0, 0}},
|
||||
{[]uint32{2, 1847, 0, 0, 0, 0}},
|
||||
}
|
||||
case 3:
|
||||
earthValues = []EarthValues{
|
||||
{[]uint32{1001, 36, 0, 0, 0, 0}}, //getTouhaHistory
|
||||
{[]uint32{9001, 3, 0, 0, 0, 0}}, //getKohouhinDropStopFlag // something to do with ttcSetDisableFlag?
|
||||
{[]uint32{9002, 10, 300, 0, 0, 0}}, //getKohouhinForceValue
|
||||
}
|
||||
}
|
||||
|
||||
var data []*byteframe.ByteFrame
|
||||
for _, i := range earthValues {
|
||||
bf := byteframe.NewByteFrame()
|
||||
for _, j := range i.Value {
|
||||
bf.WriteUint32(j)
|
||||
}
|
||||
data = append(data, bf)
|
||||
}
|
||||
doAckEarthSucceed(s, pkt.AckHandle, data)
|
||||
}
|
||||
func cleanupEarthStatus(s *Session) {
|
||||
s.server.db.Exec(`DELETE FROM events WHERE event_type='earth'`)
|
||||
}
|
||||
|
||||
func generateEarthStatusTimestamps(s *Session, start uint32, debug bool) []uint32 {
|
||||
timestamps := make([]uint32, 4)
|
||||
midnight := TimeMidnight()
|
||||
if start == 0 || TimeAdjusted().Unix() > int64(start)+1814400 {
|
||||
cleanupEarthStatus(s)
|
||||
start = uint32(midnight.Add(24 * time.Hour).Unix())
|
||||
s.server.db.Exec("INSERT INTO events (event_type, start_time) VALUES ('earth', to_timestamp($1)::timestamp without time zone)", start)
|
||||
}
|
||||
if debug {
|
||||
timestamps[0] = uint32(TimeWeekStart().Unix())
|
||||
timestamps[1] = uint32(TimeWeekNext().Unix())
|
||||
timestamps[2] = uint32(TimeWeekNext().Add(time.Duration(7) * time.Hour * 24).Unix())
|
||||
timestamps[3] = uint32(TimeWeekNext().Add(time.Duration(14) * time.Hour * 24).Unix())
|
||||
} else {
|
||||
timestamps[0] = start
|
||||
timestamps[1] = timestamps[0] + 604800
|
||||
timestamps[2] = timestamps[1] + 604800
|
||||
timestamps[3] = timestamps[2] + 604800
|
||||
}
|
||||
return timestamps
|
||||
}
|
||||
func handleMsgMhfGetEarthStatus(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetEarthStatus)
|
||||
bf := byteframe.NewByteFrame()
|
||||
|
||||
var earthTimestamps []uint32
|
||||
var debug = s.server.erupeConfig.EarthDebug
|
||||
earthId, earthStart := int32(0x01BEEFEE), uint32(0)
|
||||
rows, _ := s.server.db.Queryx("SELECT id, (EXTRACT(epoch FROM start_time)::int) as start_time FROM events WHERE event_type='earth'")
|
||||
if rows == nil {
|
||||
log.Println("No rows found")
|
||||
} else {
|
||||
for rows.Next() {
|
||||
rows.Scan(&earthId, &earthStart)
|
||||
}
|
||||
}
|
||||
earthTimestamps = generateEarthStatusTimestamps(s, earthStart, debug)
|
||||
|
||||
// Conquest
|
||||
if uint32(TimeAdjusted().Unix()) > earthTimestamps[0] {
|
||||
bf.WriteUint32(earthTimestamps[0]) // Start
|
||||
bf.WriteUint32(earthTimestamps[1]) // End
|
||||
bf.WriteInt32(1) //Conquest Earth Status ID //1 and 2 UNK the difference
|
||||
bf.WriteInt32(earthId) //ID
|
||||
} else {
|
||||
bf.WriteUint32(earthTimestamps[1]) // Start
|
||||
bf.WriteUint32(earthTimestamps[2]) // End
|
||||
bf.WriteInt32(2) //Conquest Earth Status ID //1 and 2 UNK the difference
|
||||
bf.WriteInt32(earthId) //ID
|
||||
}
|
||||
for i, m := range s.server.erupeConfig.EarthMonsters {
|
||||
//Changed from G9 to G8 to get conquest working in g9.1
|
||||
if _config.ErupeConfig.RealClientMode <= _config.G8 {
|
||||
if i == 3 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if i == 4 {
|
||||
break
|
||||
}
|
||||
bf.WriteInt32(m)
|
||||
}
|
||||
|
||||
// Pallone
|
||||
if uint32(TimeAdjusted().Unix()) > earthTimestamps[1] {
|
||||
bf.WriteUint32(earthTimestamps[1]) // Start
|
||||
bf.WriteUint32(earthTimestamps[2]) // End
|
||||
bf.WriteInt32(11) //Pallone Earth Status ID //11 is Fest //12 is Reward
|
||||
bf.WriteInt32(earthId + 1) //ID
|
||||
} else {
|
||||
bf.WriteUint32(earthTimestamps[2]) // Start
|
||||
bf.WriteUint32(earthTimestamps[3]) // End
|
||||
bf.WriteInt32(12) //Pallone Earth Status ID //11 is Fest //12 is Reward
|
||||
bf.WriteInt32(earthId + 1) //ID
|
||||
}
|
||||
for i, m := range s.server.erupeConfig.EarthMonsters {
|
||||
//Changed from G9 to G8 to get conquest working in g9.1
|
||||
if _config.ErupeConfig.RealClientMode <= _config.G8 {
|
||||
if i == 3 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if i == 4 {
|
||||
break
|
||||
}
|
||||
bf.WriteInt32(m)
|
||||
}
|
||||
|
||||
// Tower
|
||||
if uint32(TimeAdjusted().Unix()) > earthTimestamps[2] {
|
||||
bf.WriteUint32(earthTimestamps[2]) // Start
|
||||
bf.WriteUint32(earthTimestamps[3]) // End
|
||||
bf.WriteInt32(21) //Tower Earth Status ID
|
||||
bf.WriteInt32(earthId + 2) //ID
|
||||
for i, m := range s.server.erupeConfig.EarthMonsters {
|
||||
if _config.ErupeConfig.RealClientMode <= _config.G8 {
|
||||
if i == 3 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if i == 4 {
|
||||
break
|
||||
}
|
||||
bf.WriteInt32(m)
|
||||
}
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
@@ -292,7 +292,7 @@ func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) {
|
||||
} else {
|
||||
bf.WriteUint32(s.server.erupeConfig.GameplayOptions.MaximumFP)
|
||||
}
|
||||
bf.WriteUint16(100) // Reward multiplier (%)
|
||||
bf.WriteUint16(500)
|
||||
|
||||
var temp uint32
|
||||
bf.WriteUint16(4)
|
||||
|
||||
@@ -971,21 +971,14 @@ func handleMsgMhfInfoGuild(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint8(0)
|
||||
bf.WriteUint8(0)
|
||||
|
||||
flags := uint8(0)
|
||||
if !guild.Recruiting {
|
||||
flags |= 0x01
|
||||
}
|
||||
//if guild.Suspended {
|
||||
// flags |= 0x02
|
||||
//}
|
||||
bf.WriteUint8(flags)
|
||||
bf.WriteBool(!guild.Recruiting)
|
||||
|
||||
if characterGuildData == nil || characterGuildData.IsApplicant {
|
||||
bf.WriteUint16(0)
|
||||
bf.WriteUint16(0x00)
|
||||
} else if guild.LeaderCharID == s.charID {
|
||||
bf.WriteUint16(1)
|
||||
bf.WriteUint16(0x01)
|
||||
} else {
|
||||
bf.WriteUint16(2)
|
||||
bf.WriteUint16(0x02)
|
||||
}
|
||||
|
||||
bf.WriteUint32(uint32(guild.CreatedAt.Unix()))
|
||||
@@ -1105,25 +1098,20 @@ func handleMsgMhfInfoGuild(s *Session, p mhfpacket.MHFPacket) {
|
||||
bf.WriteUint32(applicant.CharID)
|
||||
bf.WriteUint32(0)
|
||||
bf.WriteUint16(applicant.HR)
|
||||
if s.server.erupeConfig.RealClientMode >= _config.G10 {
|
||||
bf.WriteUint16(applicant.GR)
|
||||
}
|
||||
bf.WriteUint16(applicant.GR)
|
||||
ps.Uint8(bf, applicant.Name, true)
|
||||
}
|
||||
}
|
||||
|
||||
type Activity struct {
|
||||
Pass uint8
|
||||
type UnkGuildInfo struct {
|
||||
Unk0 uint8
|
||||
Unk1 uint8
|
||||
Unk2 uint8
|
||||
}
|
||||
activity := []Activity{
|
||||
// 1,0,0 = ok
|
||||
// 0,0,0 = ng
|
||||
}
|
||||
bf.WriteUint8(uint8(len(activity)))
|
||||
for _, info := range activity {
|
||||
bf.WriteUint8(info.Pass)
|
||||
unkGuildInfo := []UnkGuildInfo{}
|
||||
bf.WriteUint8(uint8(len(unkGuildInfo)))
|
||||
for _, info := range unkGuildInfo {
|
||||
bf.WriteUint8(info.Unk0)
|
||||
bf.WriteUint8(info.Unk1)
|
||||
bf.WriteUint8(info.Unk2)
|
||||
}
|
||||
@@ -1171,7 +1159,7 @@ func handleMsgMhfInfoGuild(s *Session, p mhfpacket.MHFPacket) {
|
||||
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
} else {
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 5))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1538,7 +1526,7 @@ func handleMsgMhfGetGuildManageRight(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetGuildManageRight)
|
||||
|
||||
guild, err := GetGuildInfoByCharacterId(s, s.charID)
|
||||
if guild == nil || s.prevGuildID != 0 {
|
||||
if guild == nil && s.prevGuildID != 0 {
|
||||
guild, err = GetGuildInfoByID(s, s.prevGuildID)
|
||||
s.prevGuildID = 0
|
||||
if guild == nil || err != nil {
|
||||
|
||||
@@ -61,41 +61,35 @@ func (gm *GuildMember) Save(s *Session) error {
|
||||
}
|
||||
|
||||
const guildMembersSelectSQL = `
|
||||
SELECT
|
||||
COALESCE(g.id, 0) AS guild_id,
|
||||
joined_at,
|
||||
COALESCE((SELECT SUM(souls) FROM festa_submissions fs WHERE fs.character_id=c.id), 0) AS souls,
|
||||
COALESCE(rp_today, 0) AS rp_today,
|
||||
COALESCE(rp_yesterday, 0) AS rp_yesterday,
|
||||
c.name,
|
||||
c.id AS character_id,
|
||||
COALESCE(order_index, 0) AS order_index,
|
||||
c.last_login,
|
||||
COALESCE(recruiter, false) AS recruiter,
|
||||
COALESCE(avoid_leadership, false) AS avoid_leadership,
|
||||
c.hr,
|
||||
c.gr,
|
||||
c.weapon_id,
|
||||
c.weapon_type,
|
||||
CASE WHEN g.leader_id = c.id THEN true ELSE false END AS is_leader,
|
||||
character.is_applicant
|
||||
FROM (
|
||||
SELECT character_id, true as is_applicant, guild_id
|
||||
FROM guild_applications ga
|
||||
WHERE ga.application_type = 'applied'
|
||||
UNION
|
||||
SELECT character_id, false as is_applicant, guild_id
|
||||
SELECT * FROM (
|
||||
SELECT
|
||||
g.id AS guild_id,
|
||||
joined_at,
|
||||
COALESCE((SELECT SUM(souls) FROM festa_submissions fs WHERE fs.character_id=c.id), 0) AS souls,
|
||||
COALESCE(rp_today, 0) AS rp_today,
|
||||
COALESCE(rp_yesterday, 0) AS rp_yesterday,
|
||||
c.name,
|
||||
c.id AS character_id,
|
||||
COALESCE(order_index, 0) AS order_index,
|
||||
c.last_login,
|
||||
COALESCE(recruiter, false) AS recruiter,
|
||||
COALESCE(avoid_leadership, false) AS avoid_leadership,
|
||||
c.hr,
|
||||
c.gr,
|
||||
c.weapon_id,
|
||||
c.weapon_type,
|
||||
EXISTS(SELECT 1 FROM guild_applications ga WHERE ga.character_id=c.id AND application_type='applied') AS is_applicant,
|
||||
CASE WHEN g.leader_id = c.id THEN true ELSE false END AS is_leader
|
||||
FROM guild_characters gc
|
||||
) character
|
||||
JOIN characters c on character.character_id = c.id
|
||||
LEFT JOIN guild_characters gc ON gc.character_id = character.character_id
|
||||
LEFT JOIN guilds g ON g.id = gc.guild_id
|
||||
LEFT JOIN characters c ON c.id = gc.character_id
|
||||
LEFT JOIN guilds g ON g.id = gc.guild_id
|
||||
) AS subquery
|
||||
`
|
||||
|
||||
func GetGuildMembers(s *Session, guildID uint32, applicants bool) ([]*GuildMember, error) {
|
||||
rows, err := s.server.db.Queryx(fmt.Sprintf(`
|
||||
%s
|
||||
WHERE character.guild_id = $1 AND is_applicant = $2
|
||||
WHERE guild_id = $1 AND is_applicant = $2
|
||||
`, guildMembersSelectSQL), guildID, applicants)
|
||||
|
||||
if err != nil {
|
||||
@@ -121,7 +115,7 @@ func GetGuildMembers(s *Session, guildID uint32, applicants bool) ([]*GuildMembe
|
||||
}
|
||||
|
||||
func GetCharacterGuildData(s *Session, charID uint32) (*GuildMember, error) {
|
||||
rows, err := s.server.db.Queryx(fmt.Sprintf("%s WHERE character.character_id=$1", guildMembersSelectSQL), charID)
|
||||
rows, err := s.server.db.Queryx(fmt.Sprintf("%s WHERE character_id=$1", guildMembersSelectSQL), charID)
|
||||
|
||||
if err != nil {
|
||||
s.logger.Error(fmt.Sprintf("failed to retrieve membership data for character '%d'", charID))
|
||||
|
||||
@@ -185,7 +185,7 @@ func SendMailNotification(s *Session, m *Mail, recipient *Session) {
|
||||
|
||||
castedBinary.Build(bf, s.clientContext)
|
||||
|
||||
recipient.QueueSendMHFNonBlocking(castedBinary)
|
||||
recipient.QueueSendMHF(castedBinary)
|
||||
}
|
||||
|
||||
func getCharacterName(s *Session, charID uint32) string {
|
||||
|
||||
@@ -21,6 +21,7 @@ func handleMsgMhfLoadPartner(s *Session, p mhfpacket.MHFPacket) {
|
||||
data = make([]byte, 9)
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, data)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
}
|
||||
|
||||
func handleMsgMhfSavePartner(s *Session, p mhfpacket.MHFPacket) {
|
||||
@@ -156,60 +157,60 @@ func handleMsgMhfSaveMercenary(s *Session, p mhfpacket.MHFPacket) {
|
||||
|
||||
func handleMsgMhfReadMercenaryW(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfReadMercenaryW)
|
||||
bf := byteframe.NewByteFrame()
|
||||
if pkt.Op > 0 {
|
||||
bf := byteframe.NewByteFrame()
|
||||
var pactID uint32
|
||||
var name string
|
||||
var cid uint32
|
||||
|
||||
var pactID, cid uint32
|
||||
var name string
|
||||
s.server.db.QueryRow("SELECT pact_id FROM characters WHERE id=$1", s.charID).Scan(&pactID)
|
||||
if pactID > 0 {
|
||||
s.server.db.QueryRow("SELECT name, id FROM characters WHERE rasta_id = $1", pactID).Scan(&name, &cid)
|
||||
bf.WriteUint8(1) // numLends
|
||||
bf.WriteUint32(pactID)
|
||||
bf.WriteUint32(cid)
|
||||
bf.WriteBool(true) // Escort enabled
|
||||
bf.WriteUint32(uint32(TimeAdjusted().Unix()))
|
||||
bf.WriteUint32(uint32(TimeAdjusted().Add(time.Hour * 24 * 7).Unix()))
|
||||
bf.WriteBytes(stringsupport.PaddedString(name, 18, true))
|
||||
s.server.db.QueryRow("SELECT pact_id FROM characters WHERE id=$1", s.charID).Scan(&pactID)
|
||||
if pactID > 0 {
|
||||
s.server.db.QueryRow("SELECT name, id FROM characters WHERE rasta_id = $1", pactID).Scan(&name, &cid)
|
||||
bf.WriteUint8(1) // numLends
|
||||
bf.WriteUint32(pactID)
|
||||
bf.WriteUint32(cid)
|
||||
bf.WriteBool(false) // ?
|
||||
bf.WriteUint32(uint32(TimeAdjusted().Add(time.Hour * 24 * -8).Unix()))
|
||||
bf.WriteUint32(uint32(TimeAdjusted().Add(time.Hour * 24 * -1).Unix()))
|
||||
bf.WriteBytes(stringsupport.PaddedString(name, 18, true))
|
||||
} else {
|
||||
bf.WriteUint8(0)
|
||||
}
|
||||
|
||||
if pkt.Op < 2 {
|
||||
var loans uint8
|
||||
temp := byteframe.NewByteFrame()
|
||||
rows, _ := s.server.db.Query("SELECT name, id, pact_id FROM characters WHERE pact_id=(SELECT rasta_id FROM characters WHERE id=$1)", s.charID)
|
||||
for rows.Next() {
|
||||
loans++
|
||||
rows.Scan(&name, &cid, &pactID)
|
||||
temp.WriteUint32(pactID)
|
||||
temp.WriteUint32(cid)
|
||||
temp.WriteUint32(uint32(TimeAdjusted().Add(time.Hour * 24 * -8).Unix()))
|
||||
temp.WriteUint32(uint32(TimeAdjusted().Add(time.Hour * 24 * -1).Unix()))
|
||||
temp.WriteBytes(stringsupport.PaddedString(name, 18, true))
|
||||
}
|
||||
bf.WriteUint8(loans)
|
||||
bf.WriteBytes(temp.Data())
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
return
|
||||
}
|
||||
var data []byte
|
||||
var gcp uint32
|
||||
s.server.db.QueryRow("SELECT savemercenary FROM characters WHERE id=$1", s.charID).Scan(&data)
|
||||
s.server.db.QueryRow("SELECT COALESCE(gcp, 0) FROM characters WHERE id=$1", s.charID).Scan(&gcp)
|
||||
|
||||
resp := byteframe.NewByteFrame()
|
||||
resp.WriteUint16(0)
|
||||
if len(data) == 0 {
|
||||
resp.WriteBool(false)
|
||||
} else {
|
||||
bf.WriteUint8(0)
|
||||
resp.WriteBool(true)
|
||||
resp.WriteBytes(data)
|
||||
}
|
||||
|
||||
if pkt.Op != 2 && pkt.Op != 5 {
|
||||
var loans uint8
|
||||
temp := byteframe.NewByteFrame()
|
||||
rows, _ := s.server.db.Query("SELECT name, id, pact_id FROM characters WHERE pact_id=(SELECT rasta_id FROM characters WHERE id=$1)", s.charID)
|
||||
for rows.Next() {
|
||||
err := rows.Scan(&name, &cid, &pactID)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
loans++
|
||||
temp.WriteUint32(pactID)
|
||||
temp.WriteUint32(cid)
|
||||
temp.WriteUint32(uint32(TimeAdjusted().Unix()))
|
||||
temp.WriteUint32(uint32(TimeAdjusted().Add(time.Hour * 24 * 7).Unix()))
|
||||
temp.WriteBytes(stringsupport.PaddedString(name, 18, true))
|
||||
}
|
||||
bf.WriteUint8(loans)
|
||||
bf.WriteBytes(temp.Data())
|
||||
|
||||
if pkt.Op != 1 && pkt.Op != 4 {
|
||||
var data []byte
|
||||
var gcp uint32
|
||||
s.server.db.QueryRow("SELECT savemercenary FROM characters WHERE id=$1", s.charID).Scan(&data)
|
||||
s.server.db.QueryRow("SELECT COALESCE(gcp, 0) FROM characters WHERE id=$1", s.charID).Scan(&gcp)
|
||||
|
||||
if len(data) == 0 {
|
||||
bf.WriteBool(false)
|
||||
} else {
|
||||
bf.WriteBool(true)
|
||||
bf.WriteBytes(data)
|
||||
}
|
||||
bf.WriteUint32(gcp)
|
||||
}
|
||||
}
|
||||
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
resp.WriteUint32(gcp)
|
||||
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfReadMercenaryM(s *Session, p mhfpacket.MHFPacket) {
|
||||
|
||||
@@ -238,10 +238,8 @@ func loadQuestFile(s *Session, questId int) []byte {
|
||||
}
|
||||
questBody.WriteBytes(newStrings.Data())
|
||||
|
||||
s.server.questCacheLock.Lock()
|
||||
s.server.questCacheData[questId] = questBody.Data()
|
||||
s.server.questCacheTime[questId] = time.Now()
|
||||
s.server.questCacheLock.Unlock()
|
||||
return questBody.Data()
|
||||
}
|
||||
|
||||
@@ -277,33 +275,7 @@ func makeEventQuest(s *Session, rows *sql.Rows) ([]byte, error) {
|
||||
}
|
||||
bf.WriteUint8(questType)
|
||||
if questType == 9 {
|
||||
var stamps, required int
|
||||
var deadline time.Time
|
||||
err := s.server.db.QueryRow(`SELECT COUNT(*) FROM campaign_state WHERE campaign_id = (
|
||||
SELECT campaign_id
|
||||
FROM campaign_rewards
|
||||
WHERE item_type = 9
|
||||
AND item_id = $1
|
||||
) AND character_id = $2`, questId, s.charID).Scan(&stamps)
|
||||
err2 := s.server.db.QueryRow(`SELECT stamps, end_time
|
||||
FROM campaigns
|
||||
WHERE id = (
|
||||
SELECT campaign_id
|
||||
FROM campaign_rewards
|
||||
WHERE item_type = 9
|
||||
AND item_id = $1
|
||||
)`, questId).Scan(&required, &deadline)
|
||||
|
||||
if required == 0 {
|
||||
required = 1 // TODO: I don't understand how this is supposed to work
|
||||
}
|
||||
|
||||
// Check if there are enough stamps to activate the quest, the deadline hasn't passed, and there are no errors
|
||||
if stamps >= required && deadline.After(time.Now()) && err == nil && err2 == nil {
|
||||
bf.WriteBool(true)
|
||||
} else {
|
||||
bf.WriteBool(false)
|
||||
}
|
||||
bf.WriteBool(false)
|
||||
} else {
|
||||
bf.WriteBool(true)
|
||||
}
|
||||
|
||||
@@ -129,12 +129,12 @@ func (s *Session) notifyRavi() {
|
||||
raviNotif.WriteUint16(0x0010) // End it.
|
||||
if s.server.erupeConfig.GameplayOptions.LowLatencyRaviente {
|
||||
for session := range sema.clients {
|
||||
session.QueueSendNonBlocking(raviNotif.Data())
|
||||
session.QueueSend(raviNotif.Data())
|
||||
}
|
||||
} else {
|
||||
for session := range sema.clients {
|
||||
if session.charID == s.charID {
|
||||
session.QueueSendNonBlocking(raviNotif.Data())
|
||||
session.QueueSend(raviNotif.Data())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,31 +15,546 @@ func handleMsgMhfGetBreakSeibatuLevelReward(s *Session, p mhfpacket.MHFPacket) {
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
type WeeklySeibatuRankingReward struct {
|
||||
Unk0 int32
|
||||
Unk1 int32
|
||||
Unk2 uint32
|
||||
Unk3 int32
|
||||
Unk4 int32
|
||||
Unk5 int32
|
||||
type WeeklySeibatuRankingRewardData struct {
|
||||
Index0 int32 //Place Start
|
||||
Index1 int32 //Place Finish
|
||||
Index2 uint32 // UNK
|
||||
DistributionType int32 //Type 7201:Item 7202:N Points 7203:Guild Contribution Points
|
||||
ItemID int32
|
||||
Amount int32
|
||||
}
|
||||
type WeeklySeibatuRankingRewards struct {
|
||||
Unk0 int32
|
||||
ItemID int32
|
||||
Amount uint32
|
||||
PlaceFrom int32
|
||||
PlaceTo int32
|
||||
}
|
||||
|
||||
func handleMsgMhfGetWeeklySeibatuRankingReward(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetWeeklySeibatuRankingReward)
|
||||
var data []*byteframe.ByteFrame
|
||||
weeklySeibatuRankingRewards := []WeeklySeibatuRankingReward{
|
||||
{0, 0, 0, 0, 0, 0},
|
||||
var weeklySeibatuRankingRewards []WeeklySeibatuRankingRewards
|
||||
var weeklySeibatuRankingRewardsData []WeeklySeibatuRankingRewardData
|
||||
|
||||
switch pkt.Operation {
|
||||
case 1:
|
||||
//Conquest Data
|
||||
switch pkt.ID { // Seems to align with EarthStatus 1 and 2 for Conquest
|
||||
case 1:
|
||||
switch pkt.EarthMonster {
|
||||
case 116:
|
||||
weeklySeibatuRankingRewards = []WeeklySeibatuRankingRewards{
|
||||
{0, 2, 3, 1, 100},
|
||||
{0, 2, 6, 1, 100},
|
||||
{0, 2, 6, 1, 100},
|
||||
{0, 2, 6, 1, 100},
|
||||
{0, 2, 15, 1, 100},
|
||||
{0, 2, 15, 1, 100},
|
||||
{0, 2, 25, 1, 100},
|
||||
|
||||
{0, 2, 2, 101, 1000},
|
||||
{0, 2, 4, 101, 1000},
|
||||
{0, 2, 4, 101, 1000},
|
||||
{0, 2, 4, 101, 1000},
|
||||
{0, 2, 9, 101, 1000},
|
||||
{0, 2, 9, 101, 1000},
|
||||
{0, 2, 30, 101, 1000},
|
||||
|
||||
{0, 2, 2, 1000, 1001},
|
||||
{0, 2, 4, 1000, 1001},
|
||||
{0, 2, 4, 1000, 1001},
|
||||
{0, 2, 4, 1000, 1001},
|
||||
{0, 2, 6, 1000, 1001},
|
||||
{0, 2, 6, 1000, 1001},
|
||||
}
|
||||
case 107:
|
||||
weeklySeibatuRankingRewards = []WeeklySeibatuRankingRewards{
|
||||
{0, 2, 3, 1, 100},
|
||||
{0, 2, 6, 1, 100},
|
||||
{0, 2, 6, 1, 100},
|
||||
{0, 2, 6, 1, 100},
|
||||
{0, 2, 15, 1, 100},
|
||||
{0, 2, 15, 1, 100},
|
||||
{0, 2, 25, 1, 100},
|
||||
|
||||
{0, 2, 2, 101, 1000},
|
||||
{0, 2, 4, 101, 1000},
|
||||
{0, 2, 4, 101, 1000},
|
||||
{0, 2, 4, 101, 1000},
|
||||
{0, 2, 9, 101, 1000},
|
||||
{0, 2, 9, 101, 1000},
|
||||
{0, 2, 30, 101, 1000},
|
||||
|
||||
{0, 2, 2, 1000, 1001},
|
||||
{0, 2, 4, 1000, 1001},
|
||||
{0, 2, 4, 1000, 1001},
|
||||
{0, 2, 4, 1000, 1001},
|
||||
{0, 2, 6, 1000, 1001},
|
||||
{0, 2, 6, 1000, 1001},
|
||||
}
|
||||
case 2:
|
||||
weeklySeibatuRankingRewards = []WeeklySeibatuRankingRewards{
|
||||
{0, 2, 3, 1, 100},
|
||||
{0, 2, 6, 1, 100},
|
||||
{0, 2, 6, 1, 100},
|
||||
{0, 2, 6, 1, 100},
|
||||
{0, 2, 15, 1, 100},
|
||||
{0, 2, 15, 1, 100},
|
||||
{0, 2, 25, 1, 100},
|
||||
|
||||
{0, 2, 2, 101, 1000},
|
||||
{0, 2, 4, 101, 1000},
|
||||
{0, 2, 4, 101, 1000},
|
||||
{0, 2, 4, 101, 1000},
|
||||
{0, 2, 9, 101, 1000},
|
||||
{0, 2, 9, 101, 1000},
|
||||
{0, 2, 30, 101, 1000},
|
||||
|
||||
{0, 2, 2, 1000, 1001},
|
||||
{0, 2, 4, 1000, 1001},
|
||||
{0, 2, 4, 1000, 1001},
|
||||
{0, 2, 4, 1000, 1001},
|
||||
{0, 2, 6, 1000, 1001},
|
||||
{0, 2, 6, 1000, 1001},
|
||||
}
|
||||
case 36:
|
||||
weeklySeibatuRankingRewards = []WeeklySeibatuRankingRewards{
|
||||
{0, 2, 3, 1, 100},
|
||||
{0, 2, 6, 1, 100},
|
||||
{0, 2, 6, 1, 100},
|
||||
{0, 2, 6, 1, 100},
|
||||
{0, 2, 15, 1, 100},
|
||||
{0, 2, 15, 1, 100},
|
||||
{0, 2, 25, 1, 100},
|
||||
|
||||
{0, 2, 2, 101, 1000},
|
||||
{0, 2, 4, 101, 1000},
|
||||
{0, 2, 4, 101, 1000},
|
||||
{0, 2, 4, 101, 1000},
|
||||
{0, 2, 9, 101, 1000},
|
||||
{0, 2, 9, 101, 1000},
|
||||
{0, 2, 30, 101, 1000},
|
||||
|
||||
{0, 2, 2, 1000, 1001},
|
||||
{0, 2, 4, 1000, 1001},
|
||||
{0, 2, 4, 1000, 1001},
|
||||
{0, 2, 4, 1000, 1001},
|
||||
{0, 2, 6, 1000, 1001},
|
||||
{0, 2, 6, 1000, 1001},
|
||||
}
|
||||
}
|
||||
|
||||
case 2:
|
||||
switch pkt.EarthMonster {
|
||||
case 116:
|
||||
weeklySeibatuRankingRewards = []WeeklySeibatuRankingRewards{
|
||||
{0, 2, 3, 1, 100},
|
||||
{0, 2, 6, 1, 100},
|
||||
{0, 2, 6, 1, 100},
|
||||
{0, 2, 6, 1, 100},
|
||||
{0, 2, 15, 1, 100},
|
||||
{0, 2, 15, 1, 100},
|
||||
{0, 2, 25, 1, 100},
|
||||
|
||||
{0, 2, 2, 101, 1000},
|
||||
{0, 2, 4, 101, 1000},
|
||||
{0, 2, 4, 101, 1000},
|
||||
{0, 2, 4, 101, 1000},
|
||||
{0, 2, 9, 101, 1000},
|
||||
{0, 2, 9, 101, 1000},
|
||||
{0, 2, 30, 101, 1000},
|
||||
|
||||
{0, 2, 2, 1000, 1001},
|
||||
{0, 2, 4, 1000, 1001},
|
||||
{0, 2, 4, 1000, 1001},
|
||||
{0, 2, 4, 1000, 1001},
|
||||
{0, 2, 6, 1000, 1001},
|
||||
{0, 2, 6, 1000, 1001},
|
||||
}
|
||||
case 107:
|
||||
weeklySeibatuRankingRewards = []WeeklySeibatuRankingRewards{
|
||||
{0, 2, 3, 1, 100},
|
||||
{0, 2, 6, 1, 100},
|
||||
{0, 2, 6, 1, 100},
|
||||
{0, 2, 6, 1, 100},
|
||||
{0, 2, 15, 1, 100},
|
||||
{0, 2, 15, 1, 100},
|
||||
{0, 2, 25, 1, 100},
|
||||
|
||||
{0, 2, 2, 101, 1000},
|
||||
{0, 2, 4, 101, 1000},
|
||||
{0, 2, 4, 101, 1000},
|
||||
{0, 2, 4, 101, 1000},
|
||||
{0, 2, 9, 101, 1000},
|
||||
{0, 2, 9, 101, 1000},
|
||||
{0, 2, 30, 101, 1000},
|
||||
|
||||
{0, 2, 2, 1000, 1001},
|
||||
{0, 2, 4, 1000, 1001},
|
||||
{0, 2, 4, 1000, 1001},
|
||||
{0, 2, 4, 1000, 1001},
|
||||
{0, 2, 6, 1000, 1001},
|
||||
{0, 2, 6, 1000, 1001},
|
||||
}
|
||||
case 2:
|
||||
weeklySeibatuRankingRewards = []WeeklySeibatuRankingRewards{
|
||||
{0, 2, 3, 1, 100},
|
||||
{0, 2, 6, 1, 100},
|
||||
{0, 2, 6, 1, 100},
|
||||
{0, 2, 6, 1, 100},
|
||||
{0, 2, 15, 1, 100},
|
||||
{0, 2, 15, 1, 100},
|
||||
{0, 2, 25, 1, 100},
|
||||
|
||||
{0, 2, 2, 101, 1000},
|
||||
{0, 2, 4, 101, 1000},
|
||||
{0, 2, 4, 101, 1000},
|
||||
{0, 2, 4, 101, 1000},
|
||||
{0, 2, 9, 101, 1000},
|
||||
{0, 2, 9, 101, 1000},
|
||||
{0, 2, 30, 101, 1000},
|
||||
|
||||
{0, 2, 2, 1000, 1001},
|
||||
{0, 2, 4, 1000, 1001},
|
||||
{0, 2, 4, 1000, 1001},
|
||||
{0, 2, 4, 1000, 1001},
|
||||
{0, 2, 6, 1000, 1001},
|
||||
{0, 2, 6, 1000, 1001},
|
||||
}
|
||||
case 36:
|
||||
weeklySeibatuRankingRewards = []WeeklySeibatuRankingRewards{
|
||||
{0, 2, 3, 1, 100},
|
||||
{0, 2, 6, 1, 100},
|
||||
{0, 2, 6, 1, 100},
|
||||
{0, 2, 6, 1, 100},
|
||||
{0, 2, 15, 1, 100},
|
||||
{0, 2, 15, 1, 100},
|
||||
{0, 2, 25, 1, 100},
|
||||
|
||||
{0, 2, 2, 101, 1000},
|
||||
{0, 2, 4, 101, 1000},
|
||||
{0, 2, 4, 101, 1000},
|
||||
{0, 2, 4, 101, 1000},
|
||||
{0, 2, 9, 101, 1000},
|
||||
{0, 2, 9, 101, 1000},
|
||||
{0, 2, 30, 101, 1000},
|
||||
|
||||
{0, 2, 2, 1000, 1001},
|
||||
{0, 2, 4, 1000, 1001},
|
||||
{0, 2, 4, 1000, 1001},
|
||||
{0, 2, 4, 1000, 1001},
|
||||
{0, 2, 6, 1000, 1001},
|
||||
{0, 2, 6, 1000, 1001},
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
case 3:
|
||||
//Pallone Festival Data
|
||||
weeklySeibatuRankingRewardsData = []WeeklySeibatuRankingRewardData{
|
||||
|
||||
//Unk0
|
||||
//Unk1
|
||||
//Unk2
|
||||
//Unk3,
|
||||
//ROUTE, (Crashes if it doesnt exist be careful with values )
|
||||
//Status 1 = Only Now ! 2= Unk 3= Disabled}
|
||||
|
||||
//Route 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, 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},
|
||||
//Route 1
|
||||
{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, 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},
|
||||
//Route 2
|
||||
{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, 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},
|
||||
//Route 3
|
||||
{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, 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},
|
||||
//Route 4
|
||||
{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, 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},
|
||||
//Route 5
|
||||
{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, 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},
|
||||
//Route 6
|
||||
{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, 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},
|
||||
//Route 7
|
||||
{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, 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},
|
||||
//Route 8
|
||||
{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, 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},
|
||||
//Route 9
|
||||
{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, 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},
|
||||
//Route 10
|
||||
{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, 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 = Max 7 Routes so value 6
|
||||
//ZZ looks like it only works up to Route 2
|
||||
|
||||
case 5:
|
||||
//Event Reward Data
|
||||
switch pkt.ID {
|
||||
//243400 = Route 0
|
||||
//243401 = Route 1
|
||||
//I have a sneaky suspicion that the above massive array is feeding into this somehow....
|
||||
case 240031:
|
||||
weeklySeibatuRankingRewardsData = []WeeklySeibatuRankingRewardData{
|
||||
{1, 1, 1, 7201, 12068, 1}}
|
||||
case 240041:
|
||||
weeklySeibatuRankingRewardsData = []WeeklySeibatuRankingRewardData{
|
||||
{0, 0, 1, 7201, 12068, 1}}
|
||||
case 240042:
|
||||
weeklySeibatuRankingRewardsData = []WeeklySeibatuRankingRewardData{
|
||||
{0, 0, 2, 7201, 12068, 1}}
|
||||
case 240051:
|
||||
weeklySeibatuRankingRewardsData = []WeeklySeibatuRankingRewardData{
|
||||
{0, 0, 1, 7201, 12068, 1}}
|
||||
case 240052:
|
||||
weeklySeibatuRankingRewardsData = []WeeklySeibatuRankingRewardData{
|
||||
{1, 1, 1, 7201, 12068, 1},
|
||||
}
|
||||
case 260001:
|
||||
//Tower Dure Kill Reward
|
||||
weeklySeibatuRankingRewardsData = []WeeklySeibatuRankingRewardData{
|
||||
|
||||
//Can only have 10 in each dist (It disapears otherwise) Looks like up to dist 4 is implemented
|
||||
//This is claimable for every Dure Kill, Make cliamable in bulk or mandatory claim per kill
|
||||
//{unk,unk,dist,seiabtuType,ItemID,Value}
|
||||
{0, 0, 1, 7201, 11463, 1},
|
||||
{0, 0, 1, 7201, 11464, 1},
|
||||
{0, 0, 1, 7201, 11163, 1},
|
||||
{0, 0, 1, 7201, 11159, 5},
|
||||
{0, 0, 1, 7201, 11160, 5},
|
||||
{0, 0, 1, 7201, 11161, 5},
|
||||
|
||||
{0, 0, 2, 7201, 12506, 1},
|
||||
{0, 0, 2, 7201, 10355, 1},
|
||||
{0, 0, 2, 7201, 11163, 1},
|
||||
{0, 0, 2, 7201, 11159, 5},
|
||||
{0, 0, 2, 7201, 11160, 5},
|
||||
{0, 0, 2, 7201, 11161, 5},
|
||||
}
|
||||
case 260003:
|
||||
//Tower Floor Reward
|
||||
weeklySeibatuRankingRewardsData = []WeeklySeibatuRankingRewardData{
|
||||
//Adjust Floors done in database to make blue
|
||||
//This is claimable for every Floor Climbed across dist 1 and 2
|
||||
//{Floor,unk,unk,seiabtuType,ItemID,Value}
|
||||
|
||||
{1, 0, 0, 7201, 11158, 1},
|
||||
{2, 0, 0, 7201, 11173, 1},
|
||||
{3, 0, 0, 7201, 10813, 3},
|
||||
{4, 0, 0, 7201, 11163, 1},
|
||||
{5, 0, 0, 7201, 11164, 1},
|
||||
{6, 0, 0, 7201, 11389, 3},
|
||||
{6, 0, 0, 7201, 11381, 1},
|
||||
{7, 0, 0, 7201, 11384, 1},
|
||||
{8, 0, 0, 7201, 11159, 10},
|
||||
{9, 0, 0, 7201, 11160, 10},
|
||||
{10, 0, 0, 7201, 11161, 10},
|
||||
{11, 0, 0, 7201, 11265, 2},
|
||||
{11, 0, 0, 7201, 7279, 2},
|
||||
{12, 0, 0, 7201, 11381, 1},
|
||||
{13, 0, 0, 7201, 11384, 1},
|
||||
{14, 0, 0, 7201, 11381, 1},
|
||||
{15, 0, 0, 7201, 11384, 1},
|
||||
{15, 0, 0, 7201, 11464, 1},
|
||||
{16, 0, 0, 7201, 11381, 1},
|
||||
{17, 0, 0, 7201, 11384, 1},
|
||||
{18, 0, 0, 7201, 11381, 1},
|
||||
{19, 0, 0, 7201, 11384, 1},
|
||||
{20, 0, 0, 7201, 10778, 3},
|
||||
{21, 0, 0, 7201, 11265, 2},
|
||||
{21, 0, 0, 7201, 7279, 2},
|
||||
{22, 0, 0, 7201, 11381, 1},
|
||||
{23, 0, 0, 7201, 11384, 1},
|
||||
{24, 0, 0, 7201, 11381, 1},
|
||||
{25, 0, 0, 7201, 11389, 3},
|
||||
{25, 0, 0, 7201, 11286, 4},
|
||||
{26, 0, 0, 7201, 11384, 1},
|
||||
{27, 0, 0, 7201, 11381, 1},
|
||||
{28, 0, 0, 7201, 11384, 1},
|
||||
{29, 0, 0, 7201, 11381, 1},
|
||||
{30, 0, 0, 7201, 11209, 3},
|
||||
{31, 0, 0, 7201, 11265, 2},
|
||||
{31, 0, 0, 7201, 7279, 2},
|
||||
{32, 0, 0, 7201, 11159, 10},
|
||||
{33, 0, 0, 7201, 11463, 1},
|
||||
{34, 0, 0, 7201, 11160, 10},
|
||||
{35, 0, 0, 7201, 11286, 4},
|
||||
{36, 0, 0, 7201, 11161, 10},
|
||||
{38, 0, 0, 7201, 11384, 1},
|
||||
{39, 0, 0, 7201, 11164, 1},
|
||||
{40, 0, 0, 7201, 10813, 3},
|
||||
{41, 0, 0, 7201, 11265, 2},
|
||||
{41, 0, 0, 7201, 7280, 2},
|
||||
{43, 0, 0, 7201, 11381, 1},
|
||||
{45, 0, 0, 7201, 11286, 4},
|
||||
{47, 0, 0, 7201, 11384, 1},
|
||||
{48, 0, 0, 7201, 11358, 1},
|
||||
{50, 0, 0, 7201, 11356, 1},
|
||||
{51, 0, 0, 7201, 11265, 2},
|
||||
{51, 0, 0, 7201, 7280, 2},
|
||||
{53, 0, 0, 7201, 11381, 2},
|
||||
{55, 0, 0, 7201, 11357, 1},
|
||||
{57, 0, 0, 7201, 11384, 1},
|
||||
{60, 0, 0, 7201, 11286, 4},
|
||||
{61, 0, 0, 7201, 11265, 2},
|
||||
{61, 0, 0, 7201, 7280, 2},
|
||||
{63, 0, 0, 7201, 11381, 2},
|
||||
{66, 0, 0, 7201, 11463, 1},
|
||||
{67, 0, 0, 7201, 11384, 1},
|
||||
{70, 0, 0, 7201, 11286, 4},
|
||||
{71, 0, 0, 7201, 11265, 2},
|
||||
{71, 0, 0, 7201, 7280, 2},
|
||||
{73, 0, 0, 7201, 11381, 2},
|
||||
{77, 0, 0, 7201, 11384, 1},
|
||||
{79, 0, 0, 7201, 11164, 1},
|
||||
{80, 0, 0, 7201, 11286, 6},
|
||||
{81, 0, 0, 7201, 11265, 2},
|
||||
{81, 0, 0, 7201, 7281, 1},
|
||||
{83, 0, 0, 7201, 11381, 2},
|
||||
{85, 0, 0, 7201, 11464, 1},
|
||||
{87, 0, 0, 7201, 11384, 1},
|
||||
{90, 0, 0, 7201, 11286, 6},
|
||||
{91, 0, 0, 7201, 11265, 2},
|
||||
{91, 0, 0, 7201, 7281, 1},
|
||||
{93, 0, 0, 7201, 11381, 2},
|
||||
{95, 0, 0, 7201, 10778, 3},
|
||||
{97, 0, 0, 7201, 11384, 1},
|
||||
{99, 0, 0, 7201, 11463, 1},
|
||||
{100, 0, 0, 7201, 11286, 6},
|
||||
{101, 0, 0, 7201, 11265, 2},
|
||||
{101, 0, 0, 7201, 7281, 1},
|
||||
{103, 0, 0, 7201, 11381, 2},
|
||||
{107, 0, 0, 7201, 11384, 1},
|
||||
{110, 0, 0, 7201, 11286, 6},
|
||||
{113, 0, 0, 7201, 11381, 2},
|
||||
{115, 0, 0, 7201, 11164, 1},
|
||||
{117, 0, 0, 7201, 11384, 1},
|
||||
{120, 0, 0, 7201, 11286, 12},
|
||||
{123, 0, 0, 7201, 11381, 2},
|
||||
{127, 0, 0, 7201, 11384, 1},
|
||||
{130, 0, 0, 7201, 11286, 12},
|
||||
{132, 0, 0, 7201, 11381, 2},
|
||||
{134, 0, 0, 7201, 11384, 1},
|
||||
{136, 0, 0, 7201, 11381, 2},
|
||||
{138, 0, 0, 7201, 11384, 1},
|
||||
{140, 0, 0, 7201, 11286, 12},
|
||||
{142, 0, 0, 7201, 11382, 1},
|
||||
{144, 0, 0, 7201, 11385, 1},
|
||||
{145, 0, 0, 7201, 11464, 1},
|
||||
{146, 0, 0, 7201, 11382, 1},
|
||||
{148, 0, 0, 7201, 11385, 1},
|
||||
{150, 0, 0, 7201, 11164, 1},
|
||||
{155, 0, 0, 7201, 11382, 1},
|
||||
{160, 0, 0, 7201, 11209, 3},
|
||||
{165, 0, 0, 7201, 11385, 1},
|
||||
{170, 0, 0, 7201, 11159, 10},
|
||||
{175, 0, 0, 7201, 11382, 1},
|
||||
{180, 0, 0, 7201, 11160, 10},
|
||||
{185, 0, 0, 7201, 11385, 1},
|
||||
{190, 0, 0, 7201, 11161, 10},
|
||||
{195, 0, 0, 7201, 11382, 1},
|
||||
{200, 0, 0, 7201, 11159, 15},
|
||||
{210, 0, 0, 7201, 11160, 15},
|
||||
{220, 0, 0, 7201, 11385, 1},
|
||||
{235, 0, 0, 7201, 11382, 2},
|
||||
{250, 0, 0, 7201, 11161, 15},
|
||||
{265, 0, 0, 7201, 11159, 20},
|
||||
{280, 0, 0, 7201, 11385, 1},
|
||||
{300, 0, 0, 7201, 11160, 20},
|
||||
{315, 0, 0, 7201, 11382, 2},
|
||||
{330, 0, 0, 7201, 11385, 1},
|
||||
{350, 0, 0, 7201, 11161, 20},
|
||||
{365, 0, 0, 7201, 11382, 2},
|
||||
{380, 0, 0, 7201, 11385, 1},
|
||||
{400, 0, 0, 7201, 11159, 25},
|
||||
{415, 0, 0, 7201, 11382, 2},
|
||||
{430, 0, 0, 7201, 11385, 1},
|
||||
{450, 0, 0, 7201, 11160, 25},
|
||||
{465, 0, 0, 7201, 11382, 2},
|
||||
{480, 0, 0, 7201, 11385, 1},
|
||||
{500, 0, 0, 7201, 11161, 25},
|
||||
{525, 0, 0, 7201, 11382, 2},
|
||||
{550, 0, 0, 7201, 11385, 1},
|
||||
{575, 0, 0, 7201, 11159, 25},
|
||||
{600, 0, 0, 7201, 11382, 2},
|
||||
{625, 0, 0, 7201, 11385, 1},
|
||||
{650, 0, 0, 7201, 11160, 25},
|
||||
{675, 0, 0, 7201, 11382, 2},
|
||||
{700, 0, 0, 7201, 11385, 1},
|
||||
{725, 0, 0, 7201, 11161, 25},
|
||||
{750, 0, 0, 7201, 11382, 2},
|
||||
{775, 0, 0, 7201, 11385, 1},
|
||||
{800, 0, 0, 7201, 11159, 25},
|
||||
{825, 0, 0, 7201, 11382, 2},
|
||||
{850, 0, 0, 7201, 11385, 1},
|
||||
{875, 0, 0, 7201, 11160, 25},
|
||||
{900, 0, 0, 7201, 11382, 2},
|
||||
{925, 0, 0, 7201, 11385, 1},
|
||||
{950, 0, 0, 7201, 11161, 25},
|
||||
{975, 0, 0, 7201, 11382, 2},
|
||||
{1000, 0, 0, 7201, 11385, 1},
|
||||
{1025, 0, 0, 7201, 11159, 25},
|
||||
{1050, 0, 0, 7201, 11382, 2},
|
||||
{1075, 0, 0, 7201, 11385, 1},
|
||||
{1100, 0, 0, 7201, 11160, 25},
|
||||
{1125, 0, 0, 7201, 11382, 2},
|
||||
{1150, 0, 0, 7201, 11385, 1},
|
||||
{1200, 0, 0, 7201, 11161, 25},
|
||||
{1235, 0, 0, 7201, 11382, 2},
|
||||
{1270, 0, 0, 7201, 11385, 1},
|
||||
{1305, 0, 0, 7201, 11159, 25},
|
||||
{1340, 0, 0, 7201, 11382, 2},
|
||||
{1375, 0, 0, 7201, 11385, 1},
|
||||
{1410, 0, 0, 7201, 11160, 25},
|
||||
{1445, 0, 0, 7201, 11382, 2},
|
||||
{1480, 0, 0, 7201, 11385, 1},
|
||||
{1500, 0, 0, 7201, 11161, 25},
|
||||
}
|
||||
default:
|
||||
//Covers all Pallone Requests... for now
|
||||
weeklySeibatuRankingRewardsData = []WeeklySeibatuRankingRewardData{
|
||||
//1st
|
||||
{1, 0, 0, 7202, 10, 10000},
|
||||
{1, 1, 0, 7201, 10, 30},
|
||||
{1, 1, 0, 7201, 10, 18},
|
||||
{1, 1, 0, 7201, 10, 18},
|
||||
//2nd - 3rd
|
||||
{2, 3, 0, 7202, 10, 6000},
|
||||
{2, 3, 0, 7201, 10, 15},
|
||||
{2, 3, 0, 7201, 10, 9},
|
||||
{2, 3, 0, 7201, 10, 9},
|
||||
//4th -10th
|
||||
{4, 10, 0, 7202, 10, 5500},
|
||||
{4, 10, 0, 7201, 10, 12},
|
||||
{4, 10, 0, 7201, 10, 9},
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
for _, reward := range weeklySeibatuRankingRewards {
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteInt32(reward.Unk0)
|
||||
bf.WriteInt32(reward.Unk1)
|
||||
bf.WriteUint32(reward.Unk2)
|
||||
bf.WriteInt32(reward.Unk3)
|
||||
bf.WriteInt32(reward.Unk4)
|
||||
bf.WriteInt32(reward.Unk5)
|
||||
data = append(data, bf)
|
||||
if pkt.Operation == 1 {
|
||||
for _, seibatuData := range weeklySeibatuRankingRewards {
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteInt32(seibatuData.Unk0)
|
||||
bf.WriteInt32(seibatuData.ItemID)
|
||||
bf.WriteUint32(seibatuData.Amount)
|
||||
bf.WriteInt32(seibatuData.PlaceFrom)
|
||||
bf.WriteInt32(seibatuData.PlaceTo)
|
||||
data = append(data, bf)
|
||||
}
|
||||
} else {
|
||||
for _, seibatuData := range weeklySeibatuRankingRewardsData {
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteInt32(seibatuData.Index0)
|
||||
bf.WriteInt32(seibatuData.Index1)
|
||||
bf.WriteUint32(seibatuData.Index2)
|
||||
bf.WriteInt32(seibatuData.DistributionType)
|
||||
bf.WriteInt32(seibatuData.ItemID)
|
||||
bf.WriteInt32(seibatuData.Amount)
|
||||
data = append(data, bf)
|
||||
}
|
||||
}
|
||||
|
||||
doAckEarthSucceed(s, pkt.AckHandle, data)
|
||||
}
|
||||
|
||||
|
||||
@@ -65,15 +65,6 @@ func handleMsgSysCreateAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgSysCreateAcquireSemaphore)
|
||||
SemaphoreID := pkt.SemaphoreID
|
||||
|
||||
if s.server.HasSemaphore(s) {
|
||||
s.semaphoreMode = !s.semaphoreMode
|
||||
}
|
||||
if s.semaphoreMode {
|
||||
s.semaphoreID[1]++
|
||||
} else {
|
||||
s.semaphoreID[0]++
|
||||
}
|
||||
|
||||
newSemaphore, exists := s.server.semaphore[SemaphoreID]
|
||||
if !exists {
|
||||
s.server.semaphoreLock.Lock()
|
||||
@@ -86,7 +77,7 @@ func handleMsgSysCreateAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
||||
maxPlayers: 127,
|
||||
}
|
||||
} else {
|
||||
s.server.semaphore[SemaphoreID] = NewSemaphore(s, SemaphoreID, 1)
|
||||
s.server.semaphore[SemaphoreID] = NewSemaphore(s.server, SemaphoreID, 1)
|
||||
}
|
||||
newSemaphore = s.server.semaphore[SemaphoreID]
|
||||
s.server.semaphoreLock.Unlock()
|
||||
@@ -112,7 +103,7 @@ func handleMsgSysCreateAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
||||
func handleMsgSysAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgSysAcquireSemaphore)
|
||||
if sema, exists := s.server.semaphore[pkt.SemaphoreID]; exists {
|
||||
sema.host = s
|
||||
sema.clients[s] = s.charID
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint32(sema.id)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
|
||||
|
||||
@@ -59,7 +59,7 @@ func doStageTransfer(s *Session, ackHandle uint32, stageID string) {
|
||||
s.Unlock()
|
||||
|
||||
// Tell the client to cleanup its current stage objects.
|
||||
s.QueueSendMHFNonBlocking(&mhfpacket.MsgSysCleanupObject{})
|
||||
s.QueueSendMHF(&mhfpacket.MsgSysCleanupObject{})
|
||||
|
||||
// Confirm the stage entry.
|
||||
doAckSimpleSucceed(s, ackHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
@@ -112,8 +112,9 @@ func doStageTransfer(s *Session, ackHandle uint32, stageID string) {
|
||||
s.stage.RUnlock()
|
||||
}
|
||||
|
||||
newNotif.WriteUint16(0x0010) // End it.
|
||||
if len(newNotif.Data()) > 2 {
|
||||
s.QueueSendNonBlocking(newNotif.Data())
|
||||
s.QueueSend(newNotif.Data())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,7 +238,7 @@ func handleMsgSysUnlockStage(s *Session, p mhfpacket.MHFPacket) {
|
||||
for charID := range s.reservationStage.reservedClientSlots {
|
||||
session := s.server.FindSessionByCharID(charID)
|
||||
if session != nil {
|
||||
session.QueueSendMHFNonBlocking(&mhfpacket.MsgSysStageDestruct{})
|
||||
session.QueueSendMHF(&mhfpacket.MsgSysStageDestruct{})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -361,7 +362,7 @@ func handleMsgSysWaitStageBinary(s *Session, p mhfpacket.MHFPacket) {
|
||||
doAckBufSucceed(s, pkt.AckHandle, []byte{0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})
|
||||
return
|
||||
}
|
||||
for i := 0; i < 10; i++ {
|
||||
for {
|
||||
s.logger.Debug("MsgSysWaitStageBinary before lock and get stage")
|
||||
stage.Lock()
|
||||
stageBinary, gotBinary := stage.rawBinaryData[stageBinaryKey{pkt.BinaryType0, pkt.BinaryType1}]
|
||||
@@ -369,15 +370,13 @@ func handleMsgSysWaitStageBinary(s *Session, p mhfpacket.MHFPacket) {
|
||||
s.logger.Debug("MsgSysWaitStageBinary after lock and get stage")
|
||||
if gotBinary {
|
||||
doAckBufSucceed(s, pkt.AckHandle, stageBinary)
|
||||
return
|
||||
break
|
||||
} else {
|
||||
s.logger.Debug("Waiting stage binary", zap.Uint8("BinaryType0", pkt.BinaryType0), zap.Uint8("pkt.BinaryType1", pkt.BinaryType1))
|
||||
time.Sleep(1 * time.Second)
|
||||
continue
|
||||
}
|
||||
}
|
||||
s.logger.Warn("MsgSysWaitStageBinary stage binary timeout")
|
||||
doAckBufSucceed(s, pkt.AckHandle, []byte{})
|
||||
} else {
|
||||
s.logger.Warn("Failed to get stage", zap.String("StageID", pkt.StageID))
|
||||
}
|
||||
|
||||
@@ -75,7 +75,6 @@ type Server struct {
|
||||
|
||||
raviente *Raviente
|
||||
|
||||
questCacheLock sync.RWMutex
|
||||
questCacheData map[int][]byte
|
||||
questCacheTime map[int]time.Time
|
||||
}
|
||||
@@ -208,7 +207,6 @@ func (s *Server) Start() error {
|
||||
|
||||
go s.acceptClients()
|
||||
go s.manageSessions()
|
||||
go s.invalidateSessions()
|
||||
|
||||
// Start the discord bot for chat integration.
|
||||
if s.erupeConfig.Discord.Enabled && s.discordBot != nil {
|
||||
@@ -280,21 +278,6 @@ func (s *Server) manageSessions() {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) invalidateSessions() {
|
||||
for {
|
||||
if s.isShuttingDown {
|
||||
break
|
||||
}
|
||||
for _, sess := range s.sessions {
|
||||
if time.Now().Sub(sess.lastPacket) > time.Second*time.Duration(30) {
|
||||
s.logger.Info("session timeout", zap.String("Name", sess.Name))
|
||||
logoutPlayer(sess)
|
||||
}
|
||||
}
|
||||
time.Sleep(time.Second * 10)
|
||||
}
|
||||
}
|
||||
|
||||
// BroadcastMHF queues a MHFPacket to be sent to all sessions.
|
||||
func (s *Server) BroadcastMHF(pkt mhfpacket.MHFPacket, ignoredSession *Session) {
|
||||
// Broadcast the data.
|
||||
@@ -441,13 +424,24 @@ func (s *Server) FindObjectByChar(charID uint32) *Object {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) HasSemaphore(ses *Session) bool {
|
||||
for _, semaphore := range s.semaphore {
|
||||
if semaphore.host == ses {
|
||||
return true
|
||||
func (s *Server) NextSemaphoreID() uint32 {
|
||||
for {
|
||||
exists := false
|
||||
s.semaphoreIndex = s.semaphoreIndex + 1
|
||||
if s.semaphoreIndex > 0xFFFF {
|
||||
s.semaphoreIndex = 1
|
||||
}
|
||||
for _, semaphore := range s.semaphore {
|
||||
if semaphore.id == s.semaphoreIndex {
|
||||
exists = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !exists {
|
||||
break
|
||||
}
|
||||
}
|
||||
return false
|
||||
return s.semaphoreIndex
|
||||
}
|
||||
|
||||
func (s *Server) Season() uint8 {
|
||||
|
||||
@@ -10,7 +10,6 @@ type i18n struct {
|
||||
noOp string
|
||||
disabled string
|
||||
reload string
|
||||
playtime string
|
||||
kqf struct {
|
||||
get string
|
||||
set struct {
|
||||
@@ -176,8 +175,6 @@ func getLangStrings(s *Server) i18n {
|
||||
i.commands.noOp = "You don't have permission to use this command"
|
||||
i.commands.disabled = "%s command is disabled"
|
||||
i.commands.reload = "Reloading players..."
|
||||
i.commands.playtime = "Playtime: %d hours %d minutes %d seconds"
|
||||
|
||||
i.commands.kqf.get = "KQF: %x"
|
||||
i.commands.kqf.set.error = "Error in command. Format: %s set xxxxxxxxxxxxxxxx"
|
||||
i.commands.kqf.set.success = "KQF set, please switch Land/World"
|
||||
|
||||
@@ -22,18 +22,15 @@ type Semaphore struct {
|
||||
|
||||
// Max Players for Semaphore
|
||||
maxPlayers uint16
|
||||
|
||||
host *Session
|
||||
}
|
||||
|
||||
// NewSemaphore creates a new Semaphore with intialized values
|
||||
func NewSemaphore(s *Session, ID string, MaxPlayers uint16) *Semaphore {
|
||||
func NewSemaphore(s *Server, ID string, MaxPlayers uint16) *Semaphore {
|
||||
sema := &Semaphore{
|
||||
name: ID,
|
||||
id: s.GetSemaphoreID(),
|
||||
id: s.NextSemaphoreID(),
|
||||
clients: make(map[*Session]uint32),
|
||||
maxPlayers: MaxPlayers,
|
||||
host: s,
|
||||
}
|
||||
return sema
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"erupe-ce/common/mhfcourse"
|
||||
_config "erupe-ce/config"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
@@ -16,7 +15,6 @@ import (
|
||||
"erupe-ce/network"
|
||||
"erupe-ce/network/clientctx"
|
||||
"erupe-ce/network/mhfpacket"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
@@ -50,12 +48,7 @@ type Session struct {
|
||||
kqf []byte
|
||||
kqfOverride bool
|
||||
|
||||
playtime uint32
|
||||
playtimeTime time.Time
|
||||
|
||||
semaphore *Semaphore // Required for the stateful MsgSysUnreserveStage packet.
|
||||
semaphoreMode bool
|
||||
semaphoreID []uint16
|
||||
semaphore *Semaphore // Required for the stateful MsgSysUnreserveStage packet.
|
||||
|
||||
// A stack containing the stage movement history (push on enter/move, pop on back)
|
||||
stageMoveStack *stringstack.StringStack
|
||||
@@ -86,7 +79,6 @@ func NewSession(server *Server, conn net.Conn) *Session {
|
||||
sessionStart: TimeAdjusted().Unix(),
|
||||
stageMoveStack: stringstack.New(),
|
||||
ackStart: make(map[uint32]time.Time),
|
||||
semaphoreID: make([]uint16, 2),
|
||||
}
|
||||
s.SetObjectID()
|
||||
return s
|
||||
@@ -104,9 +96,22 @@ func (s *Session) Start() {
|
||||
// QueueSend queues a packet (raw []byte) to be sent.
|
||||
func (s *Session) QueueSend(data []byte) {
|
||||
s.logMessage(binary.BigEndian.Uint16(data[0:2]), data, "Server", s.Name)
|
||||
err := s.cryptConn.SendPacket(append(data, []byte{0x00, 0x10}...))
|
||||
if err != nil {
|
||||
s.logger.Warn("Failed to send packet")
|
||||
select {
|
||||
case s.sendPackets <- packet{data, false}:
|
||||
// Enqueued data
|
||||
default:
|
||||
s.logger.Warn("Packet queue too full, flushing!")
|
||||
var tempPackets []packet
|
||||
for len(s.sendPackets) > 0 {
|
||||
tempPacket := <-s.sendPackets
|
||||
if !tempPacket.nonBlocking {
|
||||
tempPackets = append(tempPackets, tempPacket)
|
||||
}
|
||||
}
|
||||
for _, tempPacket := range tempPackets {
|
||||
s.sendPackets <- tempPacket
|
||||
}
|
||||
s.sendPackets <- packet{data, false}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,19 +138,6 @@ func (s *Session) QueueSendMHF(pkt mhfpacket.MHFPacket) {
|
||||
s.QueueSend(bf.Data())
|
||||
}
|
||||
|
||||
// QueueSendMHFNonBlocking queues a MHFPacket to be sent, dropping the packet entirely if the queue is full.
|
||||
func (s *Session) QueueSendMHFNonBlocking(pkt mhfpacket.MHFPacket) {
|
||||
// Make the header
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint16(uint16(pkt.Opcode()))
|
||||
|
||||
// Build the packet onto the byteframe.
|
||||
pkt.Build(bf, s.clientContext)
|
||||
|
||||
// Queue it.
|
||||
s.QueueSendNonBlocking(bf.Data())
|
||||
}
|
||||
|
||||
// QueueAck is a helper function to queue an MSG_SYS_ACK with the given ack handle and data.
|
||||
func (s *Session) QueueAck(ackHandle uint32, data []byte) {
|
||||
bf := byteframe.NewByteFrame()
|
||||
@@ -158,26 +150,26 @@ func (s *Session) QueueAck(ackHandle uint32, data []byte) {
|
||||
func (s *Session) sendLoop() {
|
||||
var pkt packet
|
||||
for {
|
||||
var buf []byte
|
||||
if s.closed {
|
||||
return
|
||||
}
|
||||
for len(s.sendPackets) > 0 {
|
||||
pkt = <-s.sendPackets
|
||||
buf = append(buf, pkt.data...)
|
||||
}
|
||||
if len(buf) > 0 {
|
||||
err := s.cryptConn.SendPacket(append(buf, []byte{0x00, 0x10}...))
|
||||
err := s.cryptConn.SendPacket(append(pkt.data, []byte{0x00, 0x10}...))
|
||||
if err != nil {
|
||||
s.logger.Warn("Failed to send packet")
|
||||
}
|
||||
}
|
||||
time.Sleep(time.Duration(_config.ErupeConfig.LoopDelay) * time.Millisecond)
|
||||
time.Sleep(5 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Session) recvLoop() {
|
||||
for {
|
||||
if time.Now().Add(-30 * time.Second).After(s.lastPacket) {
|
||||
logoutPlayer(s)
|
||||
return
|
||||
}
|
||||
if s.closed {
|
||||
logoutPlayer(s)
|
||||
return
|
||||
@@ -193,7 +185,7 @@ func (s *Session) recvLoop() {
|
||||
return
|
||||
}
|
||||
s.handlePacketGroup(pkt)
|
||||
time.Sleep(time.Duration(_config.ErupeConfig.LoopDelay) * time.Millisecond)
|
||||
time.Sleep(5 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -280,7 +272,7 @@ func (s *Session) logMessage(opcode uint16, data []byte, sender string, recipien
|
||||
} else {
|
||||
fmt.Printf("[%s] -> [%s]\n", sender, recipient)
|
||||
}
|
||||
fmt.Printf("Opcode: (Dec: %d Hex: 0x%04X Name: %s) \n", opcode, opcode, opcodePID)
|
||||
fmt.Printf("Opcode: %s\n", opcodePID)
|
||||
if s.server.erupeConfig.DebugOptions.LogMessageData {
|
||||
if len(data) <= s.server.erupeConfig.DebugOptions.MaxHexdumpLength {
|
||||
fmt.Printf("Data [%d bytes]:\n%s\n", len(data), hex.Dump(data))
|
||||
@@ -318,14 +310,6 @@ func (s *Session) NextObjectID() uint32 {
|
||||
return bf.ReadUint32()
|
||||
}
|
||||
|
||||
func (s *Session) GetSemaphoreID() uint32 {
|
||||
if s.semaphoreMode {
|
||||
return 0x000E0000 + uint32(s.semaphoreID[1])
|
||||
} else {
|
||||
return 0x000F0000 + uint32(s.semaphoreID[0])
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Session) isOp() bool {
|
||||
var op bool
|
||||
err := s.server.db.QueryRow(`SELECT op FROM users u WHERE u.id=(SELECT c.user_id FROM characters c WHERE c.id=$1)`, s.charID).Scan(&op)
|
||||
|
||||
@@ -86,7 +86,7 @@ func encodeServerInfo(config *_config.Config, s *Server, local bool) []byte {
|
||||
}
|
||||
}
|
||||
bf.WriteUint32(uint32(channelserver.TimeAdjusted().Unix()))
|
||||
bf.WriteUint32(uint32(s.erupeConfig.GameplayOptions.ClanMemberLimits[len(s.erupeConfig.GameplayOptions.ClanMemberLimits)-1][1]))
|
||||
bf.WriteUint32(60)
|
||||
return bf.Data()
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user