mirror of
https://github.com/Mezeporta/Erupe.git
synced 2025-12-17 09:24:50 +01:00
Raviente Patch
This commit is contained in:
@@ -9,11 +9,22 @@ import (
|
||||
)
|
||||
|
||||
// MsgMhfAcquireUdItem represents the MSG_MHF_ACQUIRE_UD_ITEM
|
||||
type MsgMhfAcquireUdItem struct{
|
||||
type MsgMhfAcquireUdItem struct {
|
||||
AckHandle uint32
|
||||
// Valid field size(s), not sure about the types.
|
||||
Unk0 uint8
|
||||
Unk1 uint32
|
||||
// from gal
|
||||
// daily = 0
|
||||
// personal = 1
|
||||
// personal rank = 2
|
||||
// guild rank = 3
|
||||
// gcp = 4
|
||||
// from cat
|
||||
// treasure achievement = 5
|
||||
// personal achievement = 6
|
||||
// guild achievement = 7
|
||||
RewardType uint8
|
||||
Unk2 uint8 // Number of uint32s to read?
|
||||
Unk3 []byte
|
||||
}
|
||||
|
||||
// Opcode returns the ID associated with this packet type.
|
||||
@@ -25,9 +36,12 @@ func (m *MsgMhfAcquireUdItem) Opcode() network.PacketID {
|
||||
func (m *MsgMhfAcquireUdItem) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
m.Unk0 = bf.ReadUint8()
|
||||
m.Unk1 = bf.ReadUint32()
|
||||
m.RewardType = bf.ReadUint8()
|
||||
m.Unk2 = bf.ReadUint8()
|
||||
for i := uint8(0); i < m.Unk2; i++ {
|
||||
bf.ReadUint32()
|
||||
}
|
||||
return nil
|
||||
//return errors.New("NOT IMPLEMENTED")
|
||||
}
|
||||
|
||||
// Build builds a binary packet from the current data.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package mhfpacket
|
||||
|
||||
import (
|
||||
"errors"
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/Solenataris/Erupe/network/clientctx"
|
||||
"github.com/Solenataris/Erupe/network"
|
||||
@@ -9,7 +9,10 @@ import (
|
||||
)
|
||||
|
||||
// MsgMhfAddGuildWeeklyBonusExceptionalUser represents the MSG_MHF_ADD_GUILD_WEEKLY_BONUS_EXCEPTIONAL_USER
|
||||
type MsgMhfAddGuildWeeklyBonusExceptionalUser struct{}
|
||||
type MsgMhfAddGuildWeeklyBonusExceptionalUser struct {
|
||||
AckHandle uint32
|
||||
NumUsers uint8
|
||||
}
|
||||
|
||||
// Opcode returns the ID associated with this packet type.
|
||||
func (m *MsgMhfAddGuildWeeklyBonusExceptionalUser) Opcode() network.PacketID {
|
||||
@@ -18,7 +21,9 @@ func (m *MsgMhfAddGuildWeeklyBonusExceptionalUser) Opcode() network.PacketID {
|
||||
|
||||
// Parse parses the packet from binary
|
||||
func (m *MsgMhfAddGuildWeeklyBonusExceptionalUser) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||
return errors.New("NOT IMPLEMENTED")
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
m.NumUsers = bf.ReadUint8()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Build builds a binary packet from the current data.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package mhfpacket
|
||||
|
||||
import (
|
||||
"errors"
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/Solenataris/Erupe/network/clientctx"
|
||||
"github.com/Solenataris/Erupe/network"
|
||||
@@ -11,22 +11,25 @@ import (
|
||||
type EnumerateGuildType uint8
|
||||
|
||||
const (
|
||||
_ = iota
|
||||
ENUMERATE_GUILD_TYPE_NAME
|
||||
//Numbers correspond to order in guild search menu
|
||||
ENUMERATE_GUILD_TYPE_6
|
||||
ENUMERATE_GUILD_TYPE_LEADER_ID
|
||||
ENUMERATE_GUILD_TYPE_3
|
||||
ENUMERATE_GUILD_TYPE_2
|
||||
ENUMERATE_GUILD_TYPE_7
|
||||
ENUMERATE_GUILD_TYPE_8
|
||||
ENUMERATE_GUILD_TYPE_NEW
|
||||
ENUMERATE_GUILD_TYPE_GUILD_NAME = 0x01
|
||||
ENUMERATE_GUILD_TYPE_LEADER_NAME = 0x02
|
||||
ENUMERATE_GUILD_TYPE_LEADER_ID = 0x03
|
||||
ENUMERATE_GUILD_TYPE_ORDER_MEMBERS = 0x04
|
||||
ENUMERATE_GUILD_TYPE_ORDER_REGISTRATION = 0x05
|
||||
ENUMERATE_GUILD_TYPE_ORDER_RANK = 0x06
|
||||
ENUMERATE_GUILD_TYPE_MOTTO = 0x07
|
||||
ENUMERATE_GUILD_TYPE_RECRUITING = 0x08
|
||||
ENUMERATE_ALLIANCE_TYPE_ALLIANCE_NAME = 0x09
|
||||
ENUMERATE_ALLIANCE_TYPE_LEADER_NAME = 0x0A
|
||||
ENUMERATE_ALLIANCE_TYPE_LEADER_ID = 0x0B
|
||||
ENUMERATE_ALLIANCE_TYPE_ORDER_MEMBERS = 0x0C
|
||||
ENUMERATE_ALLIANCE_TYPE_ORDER_REGISTRATION = 0x0D
|
||||
)
|
||||
|
||||
// MsgMhfEnumerateGuild represents the MSG_MHF_ENUMERATE_GUILD
|
||||
type MsgMhfEnumerateGuild struct {
|
||||
AckHandle uint32
|
||||
Type uint8
|
||||
Type EnumerateGuildType
|
||||
RawDataPayload []byte
|
||||
}
|
||||
|
||||
@@ -38,9 +41,9 @@ func (m *MsgMhfEnumerateGuild) Opcode() network.PacketID {
|
||||
// Parse parses the packet from binary
|
||||
func (m *MsgMhfEnumerateGuild) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
m.Type = bf.ReadUint8()
|
||||
m.Type = EnumerateGuildType(bf.ReadUint8())
|
||||
m.RawDataPayload = bf.DataFromCurrent()
|
||||
|
||||
bf.Seek(int64(len(bf.Data()) - 2), 0)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package mhfpacket
|
||||
|
||||
import (
|
||||
"errors"
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/Solenataris/Erupe/network/clientctx"
|
||||
"github.com/Solenataris/Erupe/network"
|
||||
@@ -11,6 +11,8 @@ import (
|
||||
// MsgMhfEnumerateGuildItem represents the MSG_MHF_ENUMERATE_GUILD_ITEM
|
||||
type MsgMhfEnumerateGuildItem struct {
|
||||
AckHandle uint32
|
||||
GuildId uint32
|
||||
Unk0 uint16
|
||||
}
|
||||
|
||||
// Opcode returns the ID associated with this packet type.
|
||||
@@ -20,8 +22,9 @@ func (m *MsgMhfEnumerateGuildItem) Opcode() network.PacketID {
|
||||
|
||||
// Parse parses the packet from binary
|
||||
func (m *MsgMhfEnumerateGuildItem) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
m.GuildId = bf.ReadUint32()
|
||||
m.Unk0 = bf.ReadUint16()
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package mhfpacket
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/Solenataris/Erupe/network/clientctx"
|
||||
"github.com/Solenataris/Erupe/network"
|
||||
"github.com/Andoryuuta/byteframe"
|
||||
)
|
||||
|
||||
// MsgMhfEnumerateGuildMessageBoard represents the MSG_MHF_ENUMERATE_GUILD_MESSAGE_BOARD
|
||||
type MsgMhfEnumerateGuildMessageBoard struct{
|
||||
AckHandle uint32
|
||||
Unk0 uint32
|
||||
MaxPosts uint32 // always 100, even on news (00000064)
|
||||
// returning more than 4 news posts WILL softlock
|
||||
BoardType uint32 // 0 => message, 1 => news
|
||||
}
|
||||
|
||||
// Opcode returns the ID associated with this packet type.
|
||||
func (m *MsgMhfEnumerateGuildMessageBoard) Opcode() network.PacketID {
|
||||
return network.MSG_MHF_ENUMERATE_GUILD_MESSAGE_BOARD
|
||||
}
|
||||
|
||||
// Parse parses the packet from binary
|
||||
func (m *MsgMhfEnumerateGuildMessageBoard) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
m.Unk0 = bf.ReadUint32()
|
||||
m.MaxPosts = bf.ReadUint32()
|
||||
m.BoardType = bf.ReadUint32()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Build builds a binary packet from the current data.
|
||||
func (m *MsgMhfEnumerateGuildMessageBoard) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||
return errors.New("NOT IMPLEMENTED")
|
||||
}
|
||||
@@ -9,7 +9,10 @@ import (
|
||||
)
|
||||
|
||||
// MsgMhfEnumerateUnionItem represents the MSG_MHF_ENUMERATE_UNION_ITEM
|
||||
type MsgMhfEnumerateUnionItem struct{}
|
||||
type MsgMhfEnumerateUnionItem struct {
|
||||
AckHandle uint32
|
||||
Unk0 uint16
|
||||
}
|
||||
|
||||
// Opcode returns the ID associated with this packet type.
|
||||
func (m *MsgMhfEnumerateUnionItem) Opcode() network.PacketID {
|
||||
@@ -18,7 +21,10 @@ func (m *MsgMhfEnumerateUnionItem) Opcode() network.PacketID {
|
||||
|
||||
// Parse parses the packet from binary
|
||||
func (m *MsgMhfEnumerateUnionItem) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||
return errors.New("NOT IMPLEMENTED")
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
m.Unk0 = bf.ReadUint16()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Build builds a binary packet from the current data.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package mhfpacket
|
||||
|
||||
import (
|
||||
"errors"
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/Solenataris/Erupe/network/clientctx"
|
||||
"github.com/Solenataris/Erupe/network"
|
||||
@@ -10,10 +10,9 @@ import (
|
||||
|
||||
// MsgMhfGetAchievement represents the MSG_MHF_GET_ACHIEVEMENT
|
||||
type MsgMhfGetAchievement struct{
|
||||
AckHandle uint32
|
||||
Unk0 uint16 // id?
|
||||
AckHandle uint32
|
||||
Unk0 uint32 // id?
|
||||
Unk1 uint32 // char?
|
||||
Unk2 uint32 // pad?
|
||||
}
|
||||
|
||||
// Opcode returns the ID associated with this packet type.
|
||||
@@ -23,10 +22,9 @@ func (m *MsgMhfGetAchievement) Opcode() network.PacketID {
|
||||
|
||||
// Parse parses the packet from binary
|
||||
func (m *MsgMhfGetAchievement) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
m.Unk0 = bf.ReadUint16()
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
m.Unk0 = bf.ReadUint32()
|
||||
m.Unk1 = bf.ReadUint32()
|
||||
m.Unk2 = bf.ReadUint32()
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package mhfpacket
|
||||
|
||||
import (
|
||||
"errors"
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/Solenataris/Erupe/network/clientctx"
|
||||
"github.com/Solenataris/Erupe/network"
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
// MsgMhfGetUdRanking represents the MSG_MHF_GET_UD_RANKING
|
||||
type MsgMhfGetUdRanking struct{
|
||||
AckHandle uint32
|
||||
Unk0 uint8
|
||||
}
|
||||
|
||||
// Opcode returns the ID associated with this packet type.
|
||||
@@ -20,8 +21,9 @@ func (m *MsgMhfGetUdRanking) Opcode() network.PacketID {
|
||||
|
||||
// Parse parses the packet from binary
|
||||
func (m *MsgMhfGetUdRanking) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
return nil
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
m.Unk0 = bf.ReadUint8()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Build builds a binary packet from the current data.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package mhfpacket
|
||||
|
||||
import (
|
||||
"errors"
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/Solenataris/Erupe/network/clientctx"
|
||||
"github.com/Solenataris/Erupe/network"
|
||||
@@ -9,7 +9,10 @@ import (
|
||||
)
|
||||
|
||||
// MsgMhfGetUdTacticsRanking represents the MSG_MHF_GET_UD_TACTICS_RANKING
|
||||
type MsgMhfGetUdTacticsRanking struct{}
|
||||
type MsgMhfGetUdTacticsRanking struct {
|
||||
AckHandle uint32
|
||||
GuildID uint32
|
||||
}
|
||||
|
||||
// Opcode returns the ID associated with this packet type.
|
||||
func (m *MsgMhfGetUdTacticsRanking) Opcode() network.PacketID {
|
||||
@@ -18,7 +21,9 @@ func (m *MsgMhfGetUdTacticsRanking) Opcode() network.PacketID {
|
||||
|
||||
// Parse parses the packet from binary
|
||||
func (m *MsgMhfGetUdTacticsRanking) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||
return errors.New("NOT IMPLEMENTED")
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
m.GuildID = bf.ReadUint32()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Build builds a binary packet from the current data.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package mhfpacket
|
||||
|
||||
import (
|
||||
"errors"
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/Solenataris/Erupe/network/clientctx"
|
||||
"github.com/Solenataris/Erupe/network"
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
// MsgMhfListMail represents the MSG_MHF_LIST_MAIL
|
||||
type MsgMhfListMail struct {
|
||||
AckHandle uint32
|
||||
Unk0 uint32
|
||||
}
|
||||
|
||||
// Opcode returns the ID associated with this packet type.
|
||||
@@ -21,6 +22,7 @@ func (m *MsgMhfListMail) Opcode() network.PacketID {
|
||||
// Parse parses the packet from binary
|
||||
func (m *MsgMhfListMail) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
m.Unk0 = bf.ReadUint32()
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package mhfpacket
|
||||
|
||||
import (
|
||||
"errors"
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/Solenataris/Erupe/network/clientctx"
|
||||
"github.com/Solenataris/Erupe/network"
|
||||
@@ -11,14 +11,29 @@ import (
|
||||
type OperateGuildAction uint8
|
||||
|
||||
const (
|
||||
OPERATE_GUILD_ACTION_DISBAND = 0x01
|
||||
OPERATE_GUILD_ACTION_APPLY = 0x02
|
||||
OPERATE_GUILD_ACTION_LEAVE = 0x03
|
||||
OPERATE_GUILD_SET_AVOID_LEADERSHIP_TRUE = 0x07
|
||||
OPERATE_GUILD_SET_AVOID_LEADERSHIP_FALSE = 0x08
|
||||
OPERATE_GUILD_ACTION_UPDATE_COMMENT = 0x09
|
||||
OPERATE_GUILD_ACTION_DONATE = 0x0a
|
||||
OPERATE_GUILD_ACTION_UPDATE_MOTTO = 0x0b
|
||||
OPERATE_GUILD_DISBAND = 0x01
|
||||
OPERATE_GUILD_APPLY = 0x02
|
||||
OPERATE_GUILD_LEAVE = 0x03
|
||||
OPERATE_GUILD_RESIGN = 0x04
|
||||
OPERATE_GUILD_SET_APPLICATION_DENY = 0x05
|
||||
OPERATE_GUILD_SET_APPLICATION_ALLOW = 0x06
|
||||
OPERATE_GUILD_SET_AVOID_LEADERSHIP_TRUE = 0x07
|
||||
OPERATE_GUILD_SET_AVOID_LEADERSHIP_FALSE = 0x08
|
||||
OPERATE_GUILD_UPDATE_COMMENT = 0x09
|
||||
OPERATE_GUILD_DONATE_RANK = 0x0a
|
||||
OPERATE_GUILD_UPDATE_MOTTO = 0x0b
|
||||
OPERATE_GUILD_RENAME_PUGI_1 = 0x0c
|
||||
OPERATE_GUILD_RENAME_PUGI_2 = 0x0d
|
||||
OPERATE_GUILD_RENAME_PUGI_3 = 0x0e
|
||||
OPERATE_GUILD_CHANGE_PUGI_1 = 0x0f
|
||||
OPERATE_GUILD_CHANGE_PUGI_2 = 0x10
|
||||
OPERATE_GUILD_CHANGE_PUGI_3 = 0x11
|
||||
// pugi something
|
||||
OPERATE_GUILD_DONATE_EVENT = 0x15
|
||||
// pugi something
|
||||
OPERATE_GUILD_CHANGE_DIVA_PUGI_1 = 0x19
|
||||
OPERATE_GUILD_CHANGE_DIVA_PUGI_2 = 0x1a
|
||||
OPERATE_GUILD_CHANGE_DIVA_PUGI_3 = 0x1b
|
||||
)
|
||||
|
||||
// MsgMhfOperateGuild represents the MSG_MHF_OPERATE_GUILD
|
||||
@@ -40,7 +55,7 @@ func (m *MsgMhfOperateGuild) Parse(bf *byteframe.ByteFrame, ctx *clientctx.Clien
|
||||
m.GuildID = bf.ReadUint32()
|
||||
m.Action = OperateGuildAction(bf.ReadUint8())
|
||||
m.UnkData = bf.DataFromCurrent()
|
||||
|
||||
bf.Seek(int64(len(bf.Data()) - 2), 0)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,15 +1,29 @@
|
||||
package mhfpacket
|
||||
|
||||
import (
|
||||
"errors"
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/Solenataris/Erupe/network/clientctx"
|
||||
"github.com/Solenataris/Erupe/network"
|
||||
"github.com/Andoryuuta/byteframe"
|
||||
)
|
||||
|
||||
type OperateJointAction uint8
|
||||
|
||||
const (
|
||||
OPERATE_JOINT_DISBAND = 0x01
|
||||
OPERATE_JOINT_LEAVE = 0x03
|
||||
OPERATE_JOINT_KICK = 0x09
|
||||
)
|
||||
|
||||
// MsgMhfOperateJoint represents the MSG_MHF_OPERATE_JOINT
|
||||
type MsgMhfOperateJoint struct{}
|
||||
type MsgMhfOperateJoint struct {
|
||||
AckHandle uint32
|
||||
AllianceID uint32
|
||||
GuildID uint32
|
||||
Action OperateJointAction
|
||||
UnkData []byte
|
||||
}
|
||||
|
||||
// Opcode returns the ID associated with this packet type.
|
||||
func (m *MsgMhfOperateJoint) Opcode() network.PacketID {
|
||||
@@ -18,7 +32,13 @@ func (m *MsgMhfOperateJoint) Opcode() network.PacketID {
|
||||
|
||||
// Parse parses the packet from binary
|
||||
func (m *MsgMhfOperateJoint) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||
return errors.New("NOT IMPLEMENTED")
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
m.AllianceID = bf.ReadUint32()
|
||||
m.GuildID = bf.ReadUint32()
|
||||
m.Action = OperateJointAction(bf.ReadUint8())
|
||||
m.UnkData = bf.DataFromCurrent()
|
||||
bf.Seek(int64(len(bf.Data()) - 2), 0)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Build builds a binary packet from the current data.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package mhfpacket
|
||||
|
||||
import (
|
||||
"errors"
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/Solenataris/Erupe/network/clientctx"
|
||||
"github.com/Solenataris/Erupe/network"
|
||||
@@ -11,15 +11,20 @@ import (
|
||||
type OperateMailOperation uint8
|
||||
|
||||
const (
|
||||
OperateMailOperationDelete OperateMailOperation = 0x01
|
||||
OPERATE_MAIL_DELETE = 0x01
|
||||
OPERATE_MAIL_ACQUIRE_ITEM = 0x05
|
||||
)
|
||||
|
||||
// MsgMhfOprtMail represents the MSG_MHF_OPRT_MAIL
|
||||
type MsgMhfOprtMail struct {
|
||||
AckHandle uint32
|
||||
AckHandle uint32
|
||||
AccIndex uint8
|
||||
Index uint8
|
||||
Operation uint8
|
||||
Operation OperateMailOperation
|
||||
Unk0 uint8
|
||||
Data []byte
|
||||
Amount uint16
|
||||
ItemID uint16
|
||||
}
|
||||
|
||||
// Opcode returns the ID associated with this packet type.
|
||||
@@ -29,10 +34,16 @@ func (m *MsgMhfOprtMail) Opcode() network.PacketID {
|
||||
|
||||
// Parse parses the packet from binary
|
||||
func (m *MsgMhfOprtMail) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
m.AccIndex = bf.ReadUint8()
|
||||
m.Index = bf.ReadUint8()
|
||||
m.Operation = bf.ReadUint8()
|
||||
m.Operation = OperateMailOperation(bf.ReadUint8())
|
||||
m.Unk0 = bf.ReadUint8()
|
||||
switch m.Operation {
|
||||
case OPERATE_MAIL_ACQUIRE_ITEM:
|
||||
m.Amount = bf.ReadUint16()
|
||||
m.ItemID = bf.ReadUint16()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package mhfpacket
|
||||
|
||||
import (
|
||||
"errors"
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/Solenataris/Erupe/network/clientctx"
|
||||
"github.com/Solenataris/Erupe/network"
|
||||
@@ -19,6 +19,7 @@ type MsgMhfReadMail struct {
|
||||
|
||||
// This is the index within the current mail list
|
||||
Index uint8
|
||||
Unk0 uint16
|
||||
}
|
||||
|
||||
// Opcode returns the ID associated with this packet type.
|
||||
@@ -31,6 +32,7 @@ func (m *MsgMhfReadMail) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientCon
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
m.AccIndex = bf.ReadUint8()
|
||||
m.Index = bf.ReadUint8()
|
||||
m.Unk0 = bf.ReadUint16()
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package mhfpacket
|
||||
|
||||
import (
|
||||
"errors"
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/Solenataris/Erupe/network/clientctx"
|
||||
"github.com/Solenataris/Erupe/network"
|
||||
@@ -9,7 +9,16 @@ import (
|
||||
)
|
||||
|
||||
// MsgMhfSendMail represents the MSG_MHF_SEND_MAIL
|
||||
type MsgMhfSendMail struct{}
|
||||
type MsgMhfSendMail struct {
|
||||
AckHandle uint32
|
||||
RecipientID uint32
|
||||
SubjectLength uint16
|
||||
BodyLength uint16
|
||||
Quantity uint32
|
||||
ItemID uint16
|
||||
Subject []byte
|
||||
Body []byte
|
||||
}
|
||||
|
||||
// Opcode returns the ID associated with this packet type.
|
||||
func (m *MsgMhfSendMail) Opcode() network.PacketID {
|
||||
@@ -18,7 +27,15 @@ func (m *MsgMhfSendMail) Opcode() network.PacketID {
|
||||
|
||||
// Parse parses the packet from binary
|
||||
func (m *MsgMhfSendMail) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||
return errors.New("NOT IMPLEMENTED")
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
m.RecipientID = bf.ReadUint32()
|
||||
m.SubjectLength = bf.ReadUint16()
|
||||
m.BodyLength = bf.ReadUint16()
|
||||
m.Quantity = bf.ReadUint32()
|
||||
m.ItemID = bf.ReadUint16()
|
||||
m.Subject = bf.ReadNullTerminatedBytes()
|
||||
m.Body = bf.ReadNullTerminatedBytes()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Build builds a binary packet from the current data.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package mhfpacket
|
||||
|
||||
import (
|
||||
"errors"
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/Solenataris/Erupe/network/clientctx"
|
||||
"github.com/Solenataris/Erupe/network"
|
||||
@@ -9,7 +9,10 @@ import (
|
||||
)
|
||||
|
||||
// MsgMhfSetGuildMissionTarget represents the MSG_MHF_SET_GUILD_MISSION_TARGET
|
||||
type MsgMhfSetGuildMissionTarget struct{}
|
||||
type MsgMhfSetGuildMissionTarget struct {
|
||||
AckHandle uint32
|
||||
MissionID uint32
|
||||
}
|
||||
|
||||
// Opcode returns the ID associated with this packet type.
|
||||
func (m *MsgMhfSetGuildMissionTarget) Opcode() network.PacketID {
|
||||
@@ -18,7 +21,9 @@ func (m *MsgMhfSetGuildMissionTarget) Opcode() network.PacketID {
|
||||
|
||||
// Parse parses the packet from binary
|
||||
func (m *MsgMhfSetGuildMissionTarget) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||
return errors.New("NOT IMPLEMENTED")
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
m.MissionID = bf.ReadUint32()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Build builds a binary packet from the current data.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package mhfpacket
|
||||
|
||||
import (
|
||||
"errors"
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/Solenataris/Erupe/network/clientctx"
|
||||
"github.com/Solenataris/Erupe/network"
|
||||
@@ -11,11 +11,12 @@ import (
|
||||
type GuildIconMsgPart struct {
|
||||
Index uint16
|
||||
ID uint16
|
||||
Unk0 uint8
|
||||
Page uint8
|
||||
Size uint8
|
||||
Rotation uint8
|
||||
Unk1 uint8
|
||||
Unk2 uint16
|
||||
Red uint8
|
||||
Green uint8
|
||||
Blue uint8
|
||||
PosX uint16
|
||||
PosY uint16
|
||||
}
|
||||
@@ -47,11 +48,12 @@ func (m *MsgMhfUpdateGuildIcon) Parse(bf *byteframe.ByteFrame, ctx *clientctx.Cl
|
||||
m.IconParts[i] = GuildIconMsgPart{
|
||||
Index: bf.ReadUint16(),
|
||||
ID: bf.ReadUint16(),
|
||||
Unk0: bf.ReadUint8(),
|
||||
Page: bf.ReadUint8(),
|
||||
Size: bf.ReadUint8(),
|
||||
Rotation: bf.ReadUint8(),
|
||||
Unk1: bf.ReadUint8(),
|
||||
Unk2: bf.ReadUint16(),
|
||||
Red: bf.ReadUint8(),
|
||||
Green: bf.ReadUint8(),
|
||||
Blue: bf.ReadUint8(),
|
||||
PosX: bf.ReadUint16(),
|
||||
PosY: bf.ReadUint16(),
|
||||
}
|
||||
|
||||
@@ -1,15 +1,28 @@
|
||||
package mhfpacket
|
||||
|
||||
import (
|
||||
"errors"
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/Solenataris/Erupe/network/clientctx"
|
||||
"github.com/Solenataris/Erupe/network"
|
||||
"github.com/Andoryuuta/byteframe"
|
||||
)
|
||||
|
||||
type Item struct{
|
||||
Unk0 uint32
|
||||
ItemId uint16
|
||||
Amount uint16
|
||||
Unk1 uint32
|
||||
}
|
||||
|
||||
// MsgMhfUpdateGuildItem represents the MSG_MHF_UPDATE_GUILD_ITEM
|
||||
type MsgMhfUpdateGuildItem struct{}
|
||||
type MsgMhfUpdateGuildItem struct{
|
||||
AckHandle uint32
|
||||
GuildId uint32
|
||||
Amount uint16
|
||||
Unk1 uint16 // 0x00 0x00
|
||||
Items []Item // Array of updated item IDs
|
||||
}
|
||||
|
||||
// Opcode returns the ID associated with this packet type.
|
||||
func (m *MsgMhfUpdateGuildItem) Opcode() network.PacketID {
|
||||
@@ -18,7 +31,20 @@ func (m *MsgMhfUpdateGuildItem) Opcode() network.PacketID {
|
||||
|
||||
// Parse parses the packet from binary
|
||||
func (m *MsgMhfUpdateGuildItem) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||
return errors.New("NOT IMPLEMENTED")
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
m.GuildId = bf.ReadUint32()
|
||||
m.Amount = bf.ReadUint16()
|
||||
m.Unk1 = bf.ReadUint16()
|
||||
m.Items = make([]Item, int(m.Amount))
|
||||
|
||||
for i := 0; i < int(m.Amount); i++ {
|
||||
m.Items[i].Unk0 = bf.ReadUint32()
|
||||
m.Items[i].ItemId = bf.ReadUint16()
|
||||
m.Items[i].Amount = bf.ReadUint16()
|
||||
m.Items[i].Unk1 = bf.ReadUint32()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Build builds a binary packet from the current data.
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package mhfpacket
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/Solenataris/Erupe/network/clientctx"
|
||||
"github.com/Solenataris/Erupe/network"
|
||||
"github.com/Andoryuuta/byteframe"
|
||||
)
|
||||
|
||||
// MsgMhfUpdateGuildMessageBoard represents the MSG_MHF_UPDATE_GUILD_MESSAGE_BOARD
|
||||
type MsgMhfUpdateGuildMessageBoard struct {
|
||||
AckHandle uint32
|
||||
MessageOp uint32
|
||||
Request []byte
|
||||
}
|
||||
|
||||
// Opcode returns the ID associated with this packet type.
|
||||
func (m *MsgMhfUpdateGuildMessageBoard) Opcode() network.PacketID {
|
||||
return network.MSG_MHF_UPDATE_GUILD_MESSAGE_BOARD
|
||||
}
|
||||
|
||||
// Parse parses the packet from binary
|
||||
func (m *MsgMhfUpdateGuildMessageBoard) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
m.MessageOp = bf.ReadUint32()
|
||||
if m.MessageOp != 5 {
|
||||
m.Request = bf.DataFromCurrent()
|
||||
bf.Seek(int64(len(bf.Data()) - 2), 0)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Build builds a binary packet from the current data.
|
||||
func (m *MsgMhfUpdateGuildMessageBoard) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||
return errors.New("NOT IMPLEMENTED")
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package mhfpacket
|
||||
|
||||
import (
|
||||
"errors"
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/Solenataris/Erupe/network/clientctx"
|
||||
"github.com/Solenataris/Erupe/network"
|
||||
@@ -9,7 +9,12 @@ import (
|
||||
)
|
||||
|
||||
// MsgMhfUpdateUnionItem represents the MSG_MHF_UPDATE_UNION_ITEM
|
||||
type MsgMhfUpdateUnionItem struct{}
|
||||
type MsgMhfUpdateUnionItem struct {
|
||||
AckHandle uint32
|
||||
Amount uint16
|
||||
Unk1 uint16 // 0x00 0x00
|
||||
Items []Item // Array of updated item IDs
|
||||
}
|
||||
|
||||
// Opcode returns the ID associated with this packet type.
|
||||
func (m *MsgMhfUpdateUnionItem) Opcode() network.PacketID {
|
||||
@@ -18,7 +23,19 @@ func (m *MsgMhfUpdateUnionItem) Opcode() network.PacketID {
|
||||
|
||||
// Parse parses the packet from binary
|
||||
func (m *MsgMhfUpdateUnionItem) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||
return errors.New("NOT IMPLEMENTED")
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
m.Amount = bf.ReadUint16()
|
||||
m.Unk1 = bf.ReadUint16()
|
||||
m.Items = make([]Item, int(m.Amount))
|
||||
|
||||
for i := 0; i < int(m.Amount); i++ {
|
||||
m.Items[i].Unk0 = bf.ReadUint32()
|
||||
m.Items[i].ItemId = bf.ReadUint16()
|
||||
m.Items[i].Amount = bf.ReadUint16()
|
||||
m.Items[i].Unk1 = bf.ReadUint32()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Build builds a binary packet from the current data.
|
||||
|
||||
@@ -1,27 +1 @@
|
||||
package mhfpacket
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/Solenataris/Erupe/network/clientctx"
|
||||
"github.com/Solenataris/Erupe/network"
|
||||
"github.com/Andoryuuta/byteframe"
|
||||
)
|
||||
|
||||
// MsgSysReserve202 represents the MSG_SYS_reserve202
|
||||
type MsgSysReserve202 struct{}
|
||||
|
||||
// Opcode returns the ID associated with this packet type.
|
||||
func (m *MsgSysReserve202) Opcode() network.PacketID {
|
||||
return network.MSG_SYS_reserve202
|
||||
}
|
||||
|
||||
// Parse parses the packet from binary
|
||||
func (m *MsgSysReserve202) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||
return errors.New("NOT IMPLEMENTED")
|
||||
}
|
||||
|
||||
// Build builds a binary packet from the current data.
|
||||
func (m *MsgSysReserve202) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||
return errors.New("NOT IMPLEMENTED")
|
||||
}
|
||||
package mhfpacket
|
||||
@@ -1,36 +1 @@
|
||||
package mhfpacket
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/Solenataris/Erupe/network/clientctx"
|
||||
"github.com/Solenataris/Erupe/network"
|
||||
"github.com/Andoryuuta/byteframe"
|
||||
)
|
||||
|
||||
// TODO(Andoryuuta): Make up a name for this packet, not reserved anymore. Called "Is_update_guild_msg_board"
|
||||
|
||||
// MsgSysReserve203 represents the MSG_SYS_reserve203
|
||||
type MsgSysReserve203 struct {
|
||||
AckHandle uint32
|
||||
Unk0 uint16 // Hardcoded 0x0000 in the binary
|
||||
Unk1 uint16 // Hardcoded 0x0500 in the binary.
|
||||
}
|
||||
|
||||
// Opcode returns the ID associated with this packet type.
|
||||
func (m *MsgSysReserve203) Opcode() network.PacketID {
|
||||
return network.MSG_SYS_reserve203
|
||||
}
|
||||
|
||||
// Parse parses the packet from binary
|
||||
func (m *MsgSysReserve203) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
m.Unk0 = bf.ReadUint16()
|
||||
m.Unk1 = bf.ReadUint16()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Build builds a binary packet from the current data.
|
||||
func (m *MsgSysReserve203) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||
return errors.New("NOT IMPLEMENTED")
|
||||
}
|
||||
package mhfpacket
|
||||
@@ -1,7 +1,7 @@
|
||||
package mhfpacket
|
||||
|
||||
import (
|
||||
"errors"
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/Solenataris/Erupe/network/clientctx"
|
||||
"github.com/Solenataris/Erupe/network"
|
||||
@@ -9,7 +9,12 @@ import (
|
||||
)
|
||||
|
||||
// MsgSysReserve205 represents the MSG_SYS_reserve205
|
||||
type MsgSysReserve205 struct{}
|
||||
type MsgSysReserve205 struct {
|
||||
AckHandle uint32
|
||||
Unk0 uint32
|
||||
Unk1 uint32
|
||||
Unk2 uint32
|
||||
}
|
||||
|
||||
// Opcode returns the ID associated with this packet type.
|
||||
func (m *MsgSysReserve205) Opcode() network.PacketID {
|
||||
@@ -18,7 +23,11 @@ func (m *MsgSysReserve205) Opcode() network.PacketID {
|
||||
|
||||
// Parse parses the packet from binary
|
||||
func (m *MsgSysReserve205) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
|
||||
return errors.New("NOT IMPLEMENTED")
|
||||
m.AckHandle = bf.ReadUint32()
|
||||
m.Unk0 = bf.ReadUint32()
|
||||
m.Unk1 = bf.ReadUint32()
|
||||
m.Unk2 = bf.ReadUint32()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Build builds a binary packet from the current data.
|
||||
|
||||
@@ -841,10 +841,10 @@ func FromOpcode(opcode network.PacketID) MHFPacket {
|
||||
return &MsgMhfUpdateForceGuildRank{}
|
||||
case network.MSG_MHF_RESET_TITLE:
|
||||
return &MsgMhfResetTitle{}
|
||||
case network.MSG_SYS_reserve202:
|
||||
return &MsgSysReserve202{}
|
||||
case network.MSG_SYS_reserve203:
|
||||
return &MsgSysReserve203{}
|
||||
case network.MSG_MHF_ENUMERATE_GUILD_MESSAGE_BOARD:
|
||||
return &MsgMhfEnumerateGuildMessageBoard{}
|
||||
case network.MSG_MHF_UPDATE_GUILD_MESSAGE_BOARD:
|
||||
return &MsgMhfUpdateGuildMessageBoard{}
|
||||
case network.MSG_SYS_reserve204:
|
||||
return &MsgSysReserve204{}
|
||||
case network.MSG_SYS_reserve205:
|
||||
|
||||
@@ -423,8 +423,8 @@ const (
|
||||
MSG_SYS_reserve19F
|
||||
MSG_MHF_UPDATE_FORCE_GUILD_RANK
|
||||
MSG_MHF_RESET_TITLE
|
||||
MSG_SYS_reserve202
|
||||
MSG_SYS_reserve203
|
||||
MSG_MHF_ENUMERATE_GUILD_MESSAGE_BOARD
|
||||
MSG_MHF_UPDATE_GUILD_MESSAGE_BOARD
|
||||
MSG_SYS_reserve204
|
||||
MSG_SYS_reserve205
|
||||
MSG_SYS_reserve206
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -3,6 +3,7 @@ package channelserver
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"encoding/binary"
|
||||
"io/ioutil"
|
||||
"math/bits"
|
||||
"math/rand"
|
||||
@@ -74,16 +75,7 @@ func doAckSimpleFail(s *Session, ackHandle uint32, data []byte) {
|
||||
func updateRights(s *Session) {
|
||||
update := &mhfpacket.MsgSysUpdateRight{
|
||||
ClientRespAckHandle: 0,
|
||||
Unk1: 0x0E, //0e with normal sub 4e when having premium it's probably a bitfield?
|
||||
// 01 = Character can take quests at allows
|
||||
// 02 = Hunter Life, normal quests core sub
|
||||
// 03 = Extra Course, extra quests, town boxes, QOL course, core sub
|
||||
// 06 = Premium Course, standard 'premium' which makes ranking etc. faster
|
||||
// some connection to unk1 above for these maybe?
|
||||
// 06 0A 0B = Boost Course, just actually 3 subs combined
|
||||
// 08 09 1E = N Course, gives you the benefits of being in a netcafe (extra quests, N Points, daily freebies etc.) minimal and pointless
|
||||
// no timestamp after 08 or 1E while active
|
||||
// 0C = N Boost course, ultra luxury course that ruins the game if in use but also gives a
|
||||
Unk1: s.rights,
|
||||
Rights: []mhfpacket.ClientRight{
|
||||
{
|
||||
ID: 1,
|
||||
@@ -143,10 +135,25 @@ func handleMsgSysLogin(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgSysLogin)
|
||||
name := ""
|
||||
|
||||
rights := uint32(0x0E)
|
||||
// 0e with normal sub 4e when having premium
|
||||
// 01 = Character can take quests at allows
|
||||
// 02 = Hunter Life, normal quests core sub
|
||||
// 03 = Extra Course, extra quests, town boxes, QOL course, core sub
|
||||
// 06 = Premium Course, standard 'premium' which makes ranking etc. faster
|
||||
// 06 0A 0B = Boost Course, just actually 3 subs combined
|
||||
// 08 09 1E = N Course, gives you the benefits of being in a netcafe (extra quests, N Points, daily freebies etc.) minimal and pointless
|
||||
// 0C = N Boost course, ultra luxury course that ruins the game if in use
|
||||
err := s.server.db.QueryRow("SELECT rights FROM users u INNER JOIN characters c ON u.id = c.user_id WHERE c.id = $1", pkt.CharID0).Scan(&rights)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
s.server.db.QueryRow("SELECT name FROM characters WHERE id = $1", pkt.CharID0).Scan(&name)
|
||||
s.Lock()
|
||||
s.Name = name
|
||||
s.charID = pkt.CharID0
|
||||
s.rights = rights
|
||||
s.Unlock()
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint32(uint32(Time_Current_Adjusted().Unix())) // Unix timestamp
|
||||
@@ -158,11 +165,11 @@ func handleMsgSysLogin(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
}
|
||||
|
||||
_, err := s.server.db.Exec("UPDATE characters SET last_login=$1 WHERE id=$2", Time_Current().Unix(), s.charID)
|
||||
_, err = s.server.db.Exec("UPDATE characters SET last_login=$1 WHERE id=$2", Time_Current().Unix(), s.charID)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
@@ -191,6 +198,46 @@ func logoutPlayer(s *Session) {
|
||||
}
|
||||
|
||||
removeSessionFromStage(s)
|
||||
|
||||
if _, exists := s.server.semaphore["hs_l0u3B51J9k3"]; exists {
|
||||
if _, ok := s.server.semaphore["hs_l0u3B51J9k3"].reservedClientSlots[s.charID]; ok {
|
||||
removeSessionFromSemaphore(s)
|
||||
}
|
||||
}
|
||||
|
||||
var timePlayed int
|
||||
err := s.server.db.QueryRow("SELECT time_played FROM characters WHERE id = $1", s.charID).Scan(&timePlayed)
|
||||
|
||||
timePlayed = (int(Time_Current_Adjusted().Unix()) - int(s.sessionStart)) + timePlayed
|
||||
|
||||
var rpGained int
|
||||
|
||||
if s.rights == 0x08091e4e || s.rights == 0x08091e0e { // N Course
|
||||
rpGained = timePlayed / 900
|
||||
timePlayed = timePlayed % 900
|
||||
} else {
|
||||
rpGained = timePlayed / 1800
|
||||
timePlayed = timePlayed % 1800
|
||||
}
|
||||
|
||||
_, err = s.server.db.Exec("UPDATE characters SET time_played = $1 WHERE id = $2", timePlayed, s.charID)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
saveData, err := GetCharacterSaveData(s, s.charID)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
saveData.RP += uint16(rpGained)
|
||||
transaction, err := s.server.db.Begin()
|
||||
err = saveData.Save(s, transaction)
|
||||
if err != nil {
|
||||
transaction.Rollback()
|
||||
panic(err)
|
||||
} else {
|
||||
transaction.Commit()
|
||||
}
|
||||
}
|
||||
|
||||
func handleMsgSysSetStatus(s *Session, p mhfpacket.MHFPacket) {}
|
||||
@@ -208,6 +255,8 @@ func handleMsgSysTime(s *Session, p mhfpacket.MHFPacket) {
|
||||
Timestamp: uint32(Time_Current_Adjusted().Unix()), // JP timezone
|
||||
}
|
||||
s.QueueSendMHF(resp)
|
||||
|
||||
s.notifyticker()
|
||||
}
|
||||
|
||||
func handleMsgSysIssueLogkey(s *Session, p mhfpacket.MHFPacket) {
|
||||
@@ -356,15 +405,92 @@ func handleMsgMhfAcquireTitle(s *Session, p mhfpacket.MHFPacket) {}
|
||||
|
||||
func handleMsgMhfEnumerateTitle(s *Session, p mhfpacket.MHFPacket) {}
|
||||
|
||||
func handleMsgMhfEnumerateUnionItem(s *Session, p mhfpacket.MHFPacket) {}
|
||||
func handleMsgMhfEnumerateUnionItem(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfEnumerateUnionItem)
|
||||
var boxContents []byte
|
||||
bf := byteframe.NewByteFrame()
|
||||
err := s.server.db.QueryRow("SELECT item_box FROM users, characters WHERE characters.id = $1 AND users.id = characters.user_id", int(s.charID)).Scan(&boxContents)
|
||||
if err != nil {
|
||||
s.logger.Fatal("Failed to get shared item box contents from db", zap.Error(err))
|
||||
} else {
|
||||
if len(boxContents) == 0 {
|
||||
bf.WriteUint32(0x00)
|
||||
} else {
|
||||
amount := len(boxContents) / 4
|
||||
bf.WriteUint16(uint16(amount))
|
||||
bf.WriteUint32(0x00)
|
||||
bf.WriteUint16(0x00)
|
||||
for i := 0; i < amount; i++ {
|
||||
bf.WriteUint32(binary.BigEndian.Uint32(boxContents[i*4 : i*4+4]))
|
||||
if i+1 != amount {
|
||||
bf.WriteUint64(0x00)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfUpdateUnionItem(s *Session, p mhfpacket.MHFPacket) {}
|
||||
func handleMsgMhfUpdateUnionItem(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfUpdateUnionItem)
|
||||
// Get item cache from DB
|
||||
var boxContents []byte
|
||||
var oldItems []Item
|
||||
|
||||
func handleMsgMhfCreateJoint(s *Session, p mhfpacket.MHFPacket) {}
|
||||
err := s.server.db.QueryRow("SELECT item_box FROM users, characters WHERE characters.id = $1 AND users.id = characters.user_id", int(s.charID)).Scan(&boxContents)
|
||||
if err != nil {
|
||||
s.logger.Fatal("Failed to get shared item box contents from db", zap.Error(err))
|
||||
} else {
|
||||
amount := len(boxContents) / 4
|
||||
oldItems = make([]Item, amount)
|
||||
for i := 0; i < amount; i++ {
|
||||
oldItems[i].ItemId = binary.BigEndian.Uint16(boxContents[i*4 : i*4+2])
|
||||
oldItems[i].Amount = binary.BigEndian.Uint16(boxContents[i*4+2 : i*4+4])
|
||||
}
|
||||
}
|
||||
|
||||
func handleMsgMhfOperateJoint(s *Session, p mhfpacket.MHFPacket) {}
|
||||
// Update item stacks
|
||||
newItems := make([]Item, len(oldItems))
|
||||
copy(newItems, oldItems)
|
||||
for i := 0; i < int(pkt.Amount); i++ {
|
||||
for j := 0; j <= len(oldItems); j++ {
|
||||
if j == len(oldItems) {
|
||||
var newItem Item
|
||||
newItem.ItemId = pkt.Items[i].ItemId
|
||||
newItem.Amount = pkt.Items[i].Amount
|
||||
newItems = append(newItems, newItem)
|
||||
break
|
||||
}
|
||||
if pkt.Items[i].ItemId == oldItems[j].ItemId {
|
||||
newItems[j].Amount = pkt.Items[i].Amount
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func handleMsgMhfInfoJoint(s *Session, p mhfpacket.MHFPacket) {}
|
||||
// Delete empty item stacks
|
||||
for i := len(newItems) - 1; i >= 0; i-- {
|
||||
if int(newItems[i].Amount) == 0 {
|
||||
copy(newItems[i:], newItems[i+1:])
|
||||
newItems[len(newItems)-1] = make([]Item, 1)[0]
|
||||
newItems = newItems[:len(newItems)-1]
|
||||
}
|
||||
}
|
||||
|
||||
// Create new item cache
|
||||
bf := byteframe.NewByteFrame()
|
||||
for i := 0; i < len(newItems); i++ {
|
||||
bf.WriteUint16(newItems[i].ItemId)
|
||||
bf.WriteUint16(newItems[i].Amount)
|
||||
}
|
||||
|
||||
// Upload new item cache
|
||||
_, err = s.server.db.Exec("UPDATE users SET item_box = $1 FROM characters WHERE users.id = characters.user_id AND characters.id = $2", bf.Data(), int(s.charID))
|
||||
if err != nil {
|
||||
s.logger.Fatal("Failed to update shared item box contents in db", zap.Error(err))
|
||||
}
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
}
|
||||
|
||||
func handleMsgMhfAcquireCafeItem(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfAcquireCafeItem)
|
||||
|
||||
@@ -2,8 +2,8 @@ package channelserver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"strings"
|
||||
"math"
|
||||
|
||||
"github.com/Andoryuuta/byteframe"
|
||||
"github.com/Solenataris/Erupe/network/binpacket"
|
||||
@@ -22,6 +22,7 @@ const (
|
||||
const (
|
||||
BroadcastTypeTargeted = 0x01
|
||||
BroadcastTypeStage = 0x03
|
||||
BroadcastTypeRavi = 0x06
|
||||
BroadcastTypeWorld = 0x0a
|
||||
)
|
||||
|
||||
@@ -51,15 +52,14 @@ func handleMsgSysCastBinary(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgSysCastBinary)
|
||||
|
||||
if pkt.BroadcastType == 0x03 && pkt.MessageType == 0x03 && len(pkt.RawDataPayload) == 0x10 {
|
||||
tmp := byteframe.NewByteFrameFromBytes(pkt.RawDataPayload)
|
||||
|
||||
if tmp.ReadUint16() == 0x0002 && tmp.ReadUint8() == 0x18 {
|
||||
_ = tmp.ReadBytes(9)
|
||||
tmp.SetLE()
|
||||
frame := tmp.ReadUint32()
|
||||
sendServerChatMessage(s, fmt.Sprintf("TIME : %d'%d.%03d (%dframe)", frame/30/60, frame/30%60, int(math.Round(float64(frame%30*100)/3)), frame))
|
||||
}
|
||||
tmp := byteframe.NewByteFrameFromBytes(pkt.RawDataPayload)
|
||||
if tmp.ReadUint16() == 0x0002 && tmp.ReadUint8() == 0x18 {
|
||||
_ = tmp.ReadBytes(9)
|
||||
tmp.SetLE()
|
||||
frame := tmp.ReadUint32()
|
||||
sendServerChatMessage(s, fmt.Sprintf("TIME : %d'%d.%03d (%dframe)", frame/30/60, frame/30%60, int(math.Round(float64(frame%30*100)/3)), frame))
|
||||
}
|
||||
}
|
||||
|
||||
// Parse out the real casted binary payload
|
||||
var realPayload []byte
|
||||
@@ -93,6 +93,11 @@ func handleMsgSysCastBinary(s *Session, p mhfpacket.MHFPacket) {
|
||||
s.server.BroadcastMHF(resp, s)
|
||||
case BroadcastTypeStage:
|
||||
s.stage.BroadcastMHF(resp, s)
|
||||
case BroadcastTypeRavi:
|
||||
if pkt.MessageType == 1 {
|
||||
session := s.server.semaphore["hs_l0u3B51J9k3"]
|
||||
(*session).BroadcastMHF(resp, s)
|
||||
}
|
||||
case BroadcastTypeTargeted:
|
||||
for _, targetID := range (*msgBinTargeted).TargetCharIDs {
|
||||
char := s.server.FindSessionByCharID(targetID)
|
||||
@@ -129,6 +134,114 @@ func handleMsgSysCastBinary(s *Session, p mhfpacket.MHFPacket) {
|
||||
s.server.discordSession.ChannelMessageSend(s.server.erupeConfig.Discord.ChannelID, message)
|
||||
}
|
||||
|
||||
// RAVI COMMANDS
|
||||
if _, exists := s.server.semaphore["hs_l0u3B51J9k3"]; exists {
|
||||
s.server.semaphoreLock.Lock()
|
||||
getSemaphore := s.server.semaphore["hs_l0u3B51J9k3"]
|
||||
s.server.semaphoreLock.Unlock()
|
||||
if _, exists := getSemaphore.reservedClientSlots[s.charID]; exists {
|
||||
if strings.HasPrefix(chatMessage.Message, "!ravistart") {
|
||||
row := s.server.db.QueryRow("SELECT raviposttime, ravistarted FROM raviregister WHERE refid = 12")
|
||||
var raviPosted, raviStarted uint32
|
||||
err := row.Scan(&raviPosted, &raviStarted)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return
|
||||
}
|
||||
if raviStarted == 0 {
|
||||
sendServerChatMessage(s, fmt.Sprintf("Raviente will start in less than 10 seconds"))
|
||||
s.server.db.Exec("UPDATE raviregister SET ravistarted = $1", raviPosted)
|
||||
} else {
|
||||
sendServerChatMessage(s, fmt.Sprintf("Raviente has already started"))
|
||||
}
|
||||
}
|
||||
if strings.HasPrefix(chatMessage.Message, "!bressend") {
|
||||
row := s.server.db.QueryRow("SELECT unknown20 FROM ravistate WHERE refid = 29")
|
||||
var berserkRes uint32
|
||||
err := row.Scan(&berserkRes)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return
|
||||
}
|
||||
if berserkRes > 0 {
|
||||
sendServerChatMessage(s, fmt.Sprintf("Sending ressurection support"))
|
||||
s.server.db.Exec("UPDATE ravistate SET unknown20 = $1", 0)
|
||||
} else {
|
||||
sendServerChatMessage(s, fmt.Sprintf("Ressurection support has not been requested"))
|
||||
}
|
||||
}
|
||||
if strings.HasPrefix(chatMessage.Message, "!bsedsend") {
|
||||
hprow := s.server.db.QueryRow("SELECT phase1hp, phase2hp, phase3hp, phase4hp, phase5hp FROM ravistate WHERE refid = 29")
|
||||
var phase1HP, phase2HP, phase3HP, phase4HP, phase5HP uint32
|
||||
hperr := hprow.Scan(&phase1HP, &phase2HP, &phase3HP, &phase4HP, &phase5HP)
|
||||
if hperr != nil {
|
||||
panic(hperr)
|
||||
return
|
||||
}
|
||||
row := s.server.db.QueryRow("SELECT support2 FROM ravisupport WHERE refid = 25")
|
||||
var berserkTranq uint32
|
||||
err := row.Scan(&berserkTranq)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return
|
||||
}
|
||||
sendServerChatMessage(s, fmt.Sprintf("Sending sedation support if requested"))
|
||||
s.server.db.Exec("UPDATE ravisupport SET support2 = $1", (phase1HP + phase2HP + phase3HP + phase4HP + phase5HP))
|
||||
}
|
||||
if strings.HasPrefix(chatMessage.Message, "!bsedreq") {
|
||||
hprow := s.server.db.QueryRow("SELECT phase1hp, phase2hp, phase3hp, phase4hp, phase5hp FROM ravistate WHERE refid = 29")
|
||||
var phase1HP, phase2HP, phase3HP, phase4HP, phase5HP uint32
|
||||
hperr := hprow.Scan(&phase1HP, &phase2HP, &phase3HP, &phase4HP, &phase5HP)
|
||||
if hperr != nil {
|
||||
panic(hperr)
|
||||
return
|
||||
}
|
||||
row := s.server.db.QueryRow("SELECT support2 FROM ravisupport WHERE refid = 25")
|
||||
var berserkTranq uint32
|
||||
err := row.Scan(&berserkTranq)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return
|
||||
}
|
||||
sendServerChatMessage(s, fmt.Sprintf("Requesting sedation support"))
|
||||
s.server.db.Exec("UPDATE ravisupport SET support2 = $1", ((phase1HP + phase2HP + phase3HP + phase4HP + phase5HP) + 12))
|
||||
}
|
||||
if strings.HasPrefix(chatMessage.Message, "!setmultiplier ") {
|
||||
var num uint8
|
||||
n, numerr := fmt.Sscanf(chatMessage.Message, "!setmultiplier %d", &num)
|
||||
row := s.server.db.QueryRow("SELECT damagemultiplier FROM ravistate WHERE refid = 29")
|
||||
var damageMultiplier uint32
|
||||
err := row.Scan(&damageMultiplier)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return
|
||||
}
|
||||
if numerr != nil || n != 1 {
|
||||
sendServerChatMessage(s, fmt.Sprintf("Please use the format !setmultiplier x"))
|
||||
} else if damageMultiplier == 1 {
|
||||
if num > 20 {
|
||||
sendServerChatMessage(s, fmt.Sprintf("Max multiplier for Ravi is 20, setting to this value"))
|
||||
s.server.db.Exec("UPDATE ravistate SET damagemultiplier = $1", 20)
|
||||
} else {
|
||||
sendServerChatMessage(s, fmt.Sprintf("Setting Ravi damage multiplier to %d", num))
|
||||
s.server.db.Exec("UPDATE ravistate SET damagemultiplier = $1", num)
|
||||
}
|
||||
} else {
|
||||
sendServerChatMessage(s, fmt.Sprintf("Multiplier can only be set once, please restart Ravi to set again"))
|
||||
}
|
||||
}
|
||||
if strings.HasPrefix(chatMessage.Message, "!checkmultiplier") {
|
||||
var damageMultiplier uint32
|
||||
row := s.server.db.QueryRow("SELECT damagemultiplier FROM ravistate WHERE refid = 29").Scan(&damageMultiplier)
|
||||
if row != nil {
|
||||
return
|
||||
}
|
||||
sendServerChatMessage(s, fmt.Sprintf("Ravi's current damage multiplier is %d", damageMultiplier))
|
||||
}
|
||||
}
|
||||
}
|
||||
// END OF RAVI COMMANDS
|
||||
|
||||
if strings.HasPrefix(chatMessage.Message, "!tele ") {
|
||||
var x, y int16
|
||||
n, err := fmt.Sscanf(chatMessage.Message, "!tele %d %d", &x, &y)
|
||||
|
||||
@@ -59,7 +59,11 @@ func handleMsgMhfListMember(s *Session, p mhfpacket.MHFPacket) {
|
||||
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfOprMember(s *Session, p mhfpacket.MHFPacket) {}
|
||||
func handleMsgMhfOprMember(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfListMember)
|
||||
// TODO: add targetid(uint32) to charid(uint32)'s database under new field
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
func handleMsgMhfShutClient(s *Session, p mhfpacket.MHFPacket) {}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package channelserver
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
@@ -54,21 +55,46 @@ func handleMsgMhfSavedata(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
s.logger.Info("Wrote recompressed savedata back to DB.")
|
||||
dumpSaveData(s, pkt.RawDataPayload, "")
|
||||
// Temporary server launcher response stuff
|
||||
// 0x1F715 Weapon Class
|
||||
// 0x1FDF6 HR (small_gr_level)
|
||||
// 0x88 Character Name
|
||||
_, err = s.server.db.Exec("UPDATE characters SET weapon=$1 WHERE id=$2", uint16(decompressedData[128789]), s.charID)
|
||||
|
||||
_, err = s.server.db.Exec("UPDATE characters SET weapon_type=$1 WHERE id=$2", uint16(decompressedData[128789]), s.charID)
|
||||
if err != nil {
|
||||
s.logger.Fatal("Failed to character weapon in db", zap.Error(err))
|
||||
s.logger.Fatal("Failed to character weapon type in db", zap.Error(err))
|
||||
}
|
||||
|
||||
isMale := uint8(decompressedData[80]) // 0x50
|
||||
if isMale == 1 {
|
||||
_, err = s.server.db.Exec("UPDATE characters SET is_female=true WHERE id=$1", s.charID)
|
||||
} else {
|
||||
_, err = s.server.db.Exec("UPDATE characters SET is_female=false WHERE id=$1", s.charID)
|
||||
}
|
||||
gr := uint16(decompressedData[130550])<<8 | uint16(decompressedData[130551])
|
||||
s.logger.Info("Setting db field", zap.Uint16("gr_override_level", gr))
|
||||
// We have to use `gr_override_level` (uint16), not `small_gr_level` (uint8) to store this.
|
||||
_, err = s.server.db.Exec("UPDATE characters SET gr_override_mode=true, gr_override_level=$1 WHERE id=$2", gr, s.charID)
|
||||
if err != nil {
|
||||
s.logger.Fatal("Failed to update character gr_override_level in db", zap.Error(err))
|
||||
s.logger.Fatal("Failed to character gender in db", zap.Error(err))
|
||||
}
|
||||
|
||||
weaponId := binary.LittleEndian.Uint16(decompressedData[128522:128524]) // 0x1F60A
|
||||
_, err = s.server.db.Exec("UPDATE characters SET weapon_id=$1 WHERE id=$2", weaponId, s.charID)
|
||||
if err != nil {
|
||||
s.logger.Fatal("Failed to update character weapon id in db", zap.Error(err))
|
||||
}
|
||||
|
||||
hrp := binary.LittleEndian.Uint16(decompressedData[130550:130552]) // 0x1FDF6
|
||||
_, err = s.server.db.Exec("UPDATE characters SET hrp=$1 WHERE id=$2", hrp, s.charID)
|
||||
if err != nil {
|
||||
s.logger.Fatal("Failed to update character hrp in db", zap.Error(err))
|
||||
}
|
||||
|
||||
grp := binary.LittleEndian.Uint32(decompressedData[130556:130560]) // 0x1FDFC
|
||||
var gr uint16
|
||||
if grp > 0 {
|
||||
gr = grpToGR(grp)
|
||||
} else {
|
||||
gr = 0
|
||||
}
|
||||
_, err = s.server.db.Exec("UPDATE characters SET gr=$1 WHERE id=$2", gr, s.charID)
|
||||
if err != nil {
|
||||
s.logger.Fatal("Failed to update character gr in db", zap.Error(err))
|
||||
}
|
||||
|
||||
characterName := s.clientContext.StrConv.MustDecode(bfutil.UpToNull(decompressedData[88:100]))
|
||||
_, err = s.server.db.Exec("UPDATE characters SET name=$1 WHERE id=$2", characterName, s.charID)
|
||||
if err != nil {
|
||||
@@ -77,6 +103,53 @@ func handleMsgMhfSavedata(s *Session, p mhfpacket.MHFPacket) {
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
}
|
||||
|
||||
func grpToGR(n uint32) uint16 {
|
||||
var gr uint16
|
||||
gr = 1
|
||||
switch grp := int(n); {
|
||||
case grp < 208750: // Up to 50
|
||||
i := 0
|
||||
for {
|
||||
grp -= 500
|
||||
if grp <= 500 {
|
||||
if grp < 0 {
|
||||
i--
|
||||
}
|
||||
break
|
||||
} else {
|
||||
i++
|
||||
for j := 0; j < i; j++ {
|
||||
grp -= 150
|
||||
}
|
||||
}
|
||||
}
|
||||
gr = uint16(i + 2); break
|
||||
case grp < 593400: // 51-99
|
||||
grp -= 208750; i := 51; for { if grp < 7850 {break}; i++; grp -= 7850 }; gr = uint16(i); break
|
||||
case grp < 993400: // 100-149
|
||||
grp -= 593400; i := 100; for { if grp < 8000 {break}; i++; grp -= 8000 }; gr = uint16(i); break
|
||||
case grp < 1400900: // 150-199
|
||||
grp -= 993400; i := 150; for { if grp < 8150 {break}; i++; grp -= 8150 }; gr = uint16(i); break
|
||||
case grp < 2315900: // 200-299
|
||||
grp -= 1400900; i := 200; for { if grp < 9150 {break}; i++; grp -= 9150 }; gr = uint16(i); break
|
||||
case grp < 3340900: // 300-399
|
||||
grp -= 2315900; i := 300; for { if grp < 10250 {break}; i++; grp -= 10250 }; gr = uint16(i); break
|
||||
case grp < 4505900: // 400-499
|
||||
grp -= 3340900; i := 400; for { if grp < 11650 {break}; i++; grp -= 11650 }; gr = uint16(i); break
|
||||
case grp < 5850900: // 500-599
|
||||
grp -= 4505900; i := 500; for { if grp < 13450 {break}; i++; grp -= 13450 }; gr = uint16(i); break
|
||||
case grp < 7415900: // 600-699
|
||||
grp -= 5850900; i := 600; for { if grp < 15650 {break}; i++; grp -= 15650 }; gr = uint16(i); break
|
||||
case grp < 9230900: // 700-799
|
||||
grp -= 7415900; i := 700; for { if grp < 18150 {break}; i++; grp -= 18150 }; gr = uint16(i); break
|
||||
case grp < 11345900: // 800-899
|
||||
grp -= 9230900; i := 800; for { if grp < 21150 {break}; i++; grp -= 21150 }; gr = uint16(i); break
|
||||
default: // 900+
|
||||
grp -= 11345900; i := 900; for { if grp < 23950 {break}; i++; grp -= 23950 }; gr = uint16(i); break
|
||||
}
|
||||
return gr
|
||||
}
|
||||
|
||||
func dumpSaveData(s *Session, data []byte, suffix string) {
|
||||
if !s.server.erupeConfig.DevModeOptions.SaveDumps.Enabled {
|
||||
return
|
||||
|
||||
@@ -196,7 +196,10 @@ func handleMsgMhfAcquireUdItem(s *Session, p mhfpacket.MHFPacket) {
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
}
|
||||
|
||||
func handleMsgMhfGetUdRanking(s *Session, p mhfpacket.MHFPacket) {}
|
||||
func handleMsgMhfGetUdRanking(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetUdRanking)
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
}
|
||||
|
||||
func handleMsgMhfGetUdMyRanking(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetUdMyRanking)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -18,7 +18,10 @@ type GuildMember struct {
|
||||
LastLogin uint32 `db:"last_login"`
|
||||
AvoidLeadership bool `db:"avoid_leadership"`
|
||||
IsLeader bool `db:"is_leader"`
|
||||
Exp uint16 `db:"exp"`
|
||||
HRP uint16 `db:"hrp"`
|
||||
GR uint16 `db:"gr"`
|
||||
WeaponID uint16 `db:"weapon_id"`
|
||||
WeaponType uint16 `db:"weapon_type"`
|
||||
}
|
||||
|
||||
func (gm *GuildMember) IsSubLeader() bool {
|
||||
@@ -53,7 +56,10 @@ SELECT g.id as guild_id,
|
||||
coalesce(gc.order_index, 0) as order_index,
|
||||
c.last_login,
|
||||
coalesce(gc.avoid_leadership, false) as avoid_leadership,
|
||||
c.exp,
|
||||
c.hrp,
|
||||
c.gr,
|
||||
c.weapon_id,
|
||||
c.weapon_type,
|
||||
character.is_applicant,
|
||||
CASE WHEN g.leader_id = c.id THEN 1 ELSE 0 END as is_leader
|
||||
FROM (
|
||||
|
||||
@@ -61,7 +61,7 @@ func (m *Mail) Send(s *Session, transaction *sql.Tx) error {
|
||||
|
||||
func (m *Mail) MarkRead(s *Session) error {
|
||||
_, err := s.server.db.Exec(`
|
||||
UPDATE mail SET read = true WHERE id = $1
|
||||
UPDATE mail SET read = true WHERE id = $1
|
||||
`, m.ID)
|
||||
|
||||
if err != nil {
|
||||
@@ -78,7 +78,7 @@ func (m *Mail) MarkRead(s *Session) error {
|
||||
|
||||
func (m *Mail) MarkDeleted(s *Session) error {
|
||||
_, err := s.server.db.Exec(`
|
||||
UPDATE mail SET deleted = true WHERE id = $1
|
||||
UPDATE mail SET deleted = true WHERE id = $1
|
||||
`, m.ID)
|
||||
|
||||
if err != nil {
|
||||
@@ -93,22 +93,40 @@ func (m *Mail) MarkDeleted(s *Session) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Mail) MarkAcquired(s *Session) error {
|
||||
_, err := s.server.db.Exec(`
|
||||
UPDATE mail SET attached_item_received = true WHERE id = $1
|
||||
`, m.ID)
|
||||
|
||||
if err != nil {
|
||||
s.logger.Error(
|
||||
"failed to mark mail item as claimed",
|
||||
zap.Error(err),
|
||||
zap.Int("mailID", m.ID),
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetMailListForCharacter(s *Session, charID uint32) ([]Mail, error) {
|
||||
rows, err := s.server.db.Queryx(`
|
||||
SELECT
|
||||
SELECT
|
||||
m.id,
|
||||
m.sender_id,
|
||||
m.recipient_id,
|
||||
m.subject,
|
||||
m.read,
|
||||
m.attached_item_received,
|
||||
m.attached_item,
|
||||
m.attached_item_amount,
|
||||
m.created_at,
|
||||
m.is_guild_invite,
|
||||
m.deleted,
|
||||
c.name as sender_name
|
||||
FROM mail m
|
||||
JOIN characters c ON c.id = m.sender_id
|
||||
FROM mail m
|
||||
JOIN characters c ON c.id = m.sender_id
|
||||
WHERE recipient_id = $1 AND deleted = false
|
||||
ORDER BY m.created_at DESC, id DESC
|
||||
LIMIT 32
|
||||
@@ -140,21 +158,22 @@ func GetMailListForCharacter(s *Session, charID uint32) ([]Mail, error) {
|
||||
|
||||
func GetMailByID(s *Session, ID int) (*Mail, error) {
|
||||
row := s.server.db.QueryRowx(`
|
||||
SELECT
|
||||
SELECT
|
||||
m.id,
|
||||
m.sender_id,
|
||||
m.recipient_id,
|
||||
m.subject,
|
||||
m.read,
|
||||
m.body,
|
||||
m.attached_item_received,
|
||||
m.attached_item,
|
||||
m.attached_item_amount,
|
||||
m.created_at,
|
||||
m.is_guild_invite,
|
||||
m.deleted,
|
||||
c.name as sender_name
|
||||
FROM mail m
|
||||
JOIN characters c ON c.id = m.sender_id
|
||||
FROM mail m
|
||||
JOIN characters c ON c.id = m.sender_id
|
||||
WHERE m.id = $1
|
||||
LIMIT 1
|
||||
`, ID)
|
||||
@@ -235,9 +254,11 @@ func handleMsgMhfReadMail(s *Session, p mhfpacket.MHFPacket) {
|
||||
|
||||
_ = mail.MarkRead(s)
|
||||
|
||||
bf := byteframe.NewByteFrame()
|
||||
bodyBytes, _ := stringsupport.ConvertUTF8ToShiftJIS(mail.Body)
|
||||
bf.WriteNullTerminatedBytes(bodyBytes)
|
||||
|
||||
doAckBufSucceed(s, pkt.AckHandle, bodyBytes)
|
||||
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
|
||||
}
|
||||
|
||||
func handleMsgMhfListMail(s *Session, p mhfpacket.MHFPacket) {
|
||||
@@ -295,10 +316,10 @@ func handleMsgMhfListMail(s *Session, p mhfpacket.MHFPacket) {
|
||||
|
||||
msg.WriteUint8(flags)
|
||||
msg.WriteBool(itemAttached)
|
||||
msg.WriteUint8(uint8(len(subjectBytes)))
|
||||
msg.WriteUint8(uint8(len(senderNameBytes)))
|
||||
msg.WriteBytes(subjectBytes)
|
||||
msg.WriteBytes(senderNameBytes)
|
||||
msg.WriteUint8(uint8(len(subjectBytes)+1))
|
||||
msg.WriteUint8(uint8(len(senderNameBytes)+1))
|
||||
msg.WriteNullTerminatedBytes(subjectBytes)
|
||||
msg.WriteNullTerminatedBytes(senderNameBytes)
|
||||
|
||||
if itemAttached {
|
||||
msg.WriteInt16(m.AttachedItemAmount)
|
||||
@@ -320,9 +341,14 @@ func handleMsgMhfOprtMail(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
|
||||
switch mhfpacket.OperateMailOperation(pkt.Operation) {
|
||||
case mhfpacket.OperateMailOperationDelete:
|
||||
case mhfpacket.OPERATE_MAIL_DELETE:
|
||||
err = mail.MarkDeleted(s)
|
||||
|
||||
if err != nil {
|
||||
doAckSimpleFail(s, pkt.AckHandle, nil)
|
||||
panic(err)
|
||||
}
|
||||
case mhfpacket.OPERATE_MAIL_ACQUIRE_ITEM:
|
||||
err = mail.MarkAcquired(s)
|
||||
if err != nil {
|
||||
doAckSimpleFail(s, pkt.AckHandle, nil)
|
||||
panic(err)
|
||||
@@ -332,4 +358,34 @@ func handleMsgMhfOprtMail(s *Session, p mhfpacket.MHFPacket) {
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, nil)
|
||||
}
|
||||
|
||||
func handleMsgMhfSendMail(s *Session, p mhfpacket.MHFPacket) {}
|
||||
func handleMsgMhfSendMail(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfSendMail)
|
||||
query := `
|
||||
INSERT INTO mail (sender_id, recipient_id, subject, body, attached_item, attached_item_amount, is_guild_invite)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
||||
`
|
||||
|
||||
if pkt.RecipientID == 0 { // Guild mail
|
||||
g, err := GetGuildInfoByCharacterId(s, s.charID)
|
||||
if err != nil {
|
||||
s.logger.Fatal("Failed to get guild info for mail")
|
||||
}
|
||||
gm, err := GetGuildMembers(s, g.ID, false)
|
||||
if err != nil {
|
||||
s.logger.Fatal("Failed to get guild members for mail")
|
||||
}
|
||||
for i := 0; i < len(gm); i++ {
|
||||
_, err := s.server.db.Exec(query, s.charID, gm[i].CharID, pkt.Subject, pkt.Body, 0, 0, false)
|
||||
if err != nil {
|
||||
s.logger.Fatal("Failed to send mail")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_, err := s.server.db.Exec(query, s.charID, pkt.RecipientID, pkt.Subject, pkt.Body, pkt.ItemID, pkt.Quantity, false)
|
||||
if err != nil {
|
||||
s.logger.Fatal("Failed to send mail")
|
||||
}
|
||||
}
|
||||
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4))
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -12,13 +12,35 @@ func handleMsgSysCreateSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
||||
}
|
||||
|
||||
func handleMsgSysDeleteSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
||||
//pkt := p.(*mhfpacket.MsgSysDeleteSemaphore)
|
||||
|
||||
s.semaphore.Lock()
|
||||
pkt := p.(*mhfpacket.MsgSysDeleteSemaphore)
|
||||
sem := pkt.AckHandle
|
||||
if s.server.semaphore != nil {
|
||||
s.server.semaphoreLock.Lock()
|
||||
for id := range s.server.semaphore {
|
||||
delete(s.server.semaphore[id].reservedClientSlots, s.charID)
|
||||
switch sem {
|
||||
case 917533:
|
||||
if s.server.semaphore[id].id_semaphore == "hs_l0u3B51J9k3" {
|
||||
delete(s.server.semaphore["hs_l0u3B51J9k3"].reservedClientSlots, s.charID)
|
||||
delete(s.server.semaphore["hs_l0u3B51J9k3"].clients, s)
|
||||
}
|
||||
case 851997:
|
||||
if s.server.semaphore[id].id_semaphore == "hs_l0u3B51J9k4" {
|
||||
delete(s.server.semaphore["hs_l0u3B51J9k4"].reservedClientSlots, s.charID)
|
||||
}
|
||||
case 786461:
|
||||
if s.server.semaphore[id].id_semaphore == "hs_l0u3B51J9k5" {
|
||||
delete(s.server.semaphore["hs_l0u3B51J9k5"].reservedClientSlots, s.charID)
|
||||
}
|
||||
default:
|
||||
if len(s.server.semaphore[id].reservedClientSlots) != 0 {
|
||||
if s.server.semaphore[id].id_semaphore != "hs_l0u3B51J9k3" && s.server.semaphore[id].id_semaphore != "hs_l0u3B51J9k4" && s.server.semaphore[id].id_semaphore != "hs_l0u3B51J9k5" {
|
||||
delete(s.server.semaphore[id].reservedClientSlots, s.charID)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
s.server.semaphoreLock.Unlock()
|
||||
}
|
||||
s.semaphore.Unlock()
|
||||
}
|
||||
|
||||
func handleMsgSysCreateAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
||||
@@ -49,11 +71,33 @@ func handleMsgSysCreateAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
||||
s.logger.Info("IS ALREADY EXIST !")
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x0F, 0x00, 0x1D})
|
||||
} else if uint16(len(newSemaphore.reservedClientSlots)) < newSemaphore.maxPlayers {
|
||||
newSemaphore.reservedClientSlots[s.charID] = nil
|
||||
s.Lock()
|
||||
s.semaphore = newSemaphore
|
||||
s.Unlock()
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x0F, 0x00, 0x1D})
|
||||
switch SemaphoreID {
|
||||
case "hs_l0u3B51J9k3":
|
||||
newSemaphore.reservedClientSlots[s.charID] = nil
|
||||
newSemaphore.clients[s] = s.charID
|
||||
s.Lock()
|
||||
s.semaphore = newSemaphore
|
||||
s.Unlock()
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x0E, 0x00, 0x1D})
|
||||
case "hs_l0u3B51J9k4":
|
||||
newSemaphore.reservedClientSlots[s.charID] = nil
|
||||
s.Lock()
|
||||
s.semaphore = newSemaphore
|
||||
s.Unlock()
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x0D, 0x00, 0x1D})
|
||||
case "hs_l0u3B51J9k5":
|
||||
newSemaphore.reservedClientSlots[s.charID] = nil
|
||||
s.Lock()
|
||||
s.semaphore = newSemaphore
|
||||
s.Unlock()
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x0C, 0x00, 0x1D})
|
||||
default:
|
||||
newSemaphore.reservedClientSlots[s.charID] = nil
|
||||
s.Lock()
|
||||
s.semaphore = newSemaphore
|
||||
s.Unlock()
|
||||
doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x0F, 0x00, 0x25})
|
||||
}
|
||||
} else {
|
||||
doAckSimpleFail(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||
}
|
||||
@@ -65,15 +109,26 @@ func handleMsgSysAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
||||
|
||||
func handleMsgSysReleaseSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
||||
//pkt := p.(*mhfpacket.MsgSysReleaseSemaphore)
|
||||
for _, session := range s.server.sessions {
|
||||
session.semaphore.Lock()
|
||||
for id := range session.server.semaphore {
|
||||
delete(s.server.semaphore[id].reservedClientSlots, s.charID)
|
||||
if _, exists := s.server.semaphore["hs_l0u3B51J9k3"]; exists {
|
||||
reset := len(s.server.semaphore["hs_l0u3B51J9k3"].reservedClientSlots)
|
||||
if reset == 0 {
|
||||
s.server.db.Exec("CALL ravireset($1)", 0)
|
||||
}
|
||||
session.semaphore.Unlock()
|
||||
}
|
||||
//data, _ := hex.DecodeString("000180e703000d443b37ff006d00131809000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010627426400a936a93600000100cf330600cc31cc31d431000025000000000000000000010218330600bd3cbd3cbd3c01032c280600ee3dee3da9360104f3300600d231a936a93601054a310600e23ae23ae23a00000d0000000000004d814c0000000003008501d723b7334001e7038b3fd437d516113505000000e7030001000002000203000000000000fafafafafafafafafafafafafafa000000000000ecb2000060da0000000000000000000000000000000000000000000000000000000000000000000000000000181818187e2d00003b31702d662d402e000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000")
|
||||
//doAckBufSucceed(s, pkt.AckHandle, data)
|
||||
}
|
||||
|
||||
func removeSessionFromSemaphore(s *Session) {
|
||||
|
||||
s.server.semaphoreLock.Lock()
|
||||
for id := range s.server.semaphore {
|
||||
delete(s.server.semaphore[id].reservedClientSlots, s.charID)
|
||||
if id == "hs_l0u3B51J9k3" {
|
||||
delete(s.server.semaphore[id].clients, s)
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
}
|
||||
s.server.semaphoreLock.Unlock()
|
||||
}
|
||||
|
||||
func handleMsgSysCheckSemaphore(s *Session, p mhfpacket.MHFPacket) {
|
||||
|
||||
@@ -429,8 +429,8 @@ func init() {
|
||||
handlerTable[network.MSG_SYS_reserve19F] = handleMsgSysReserve19F
|
||||
handlerTable[network.MSG_MHF_UPDATE_FORCE_GUILD_RANK] = handleMsgMhfUpdateForceGuildRank
|
||||
handlerTable[network.MSG_MHF_RESET_TITLE] = handleMsgMhfResetTitle
|
||||
handlerTable[network.MSG_SYS_reserve202] = handleMsgSysReserve202
|
||||
handlerTable[network.MSG_SYS_reserve203] = handleMsgSysReserve203
|
||||
handlerTable[network.MSG_MHF_ENUMERATE_GUILD_MESSAGE_BOARD] = handleMsgMhfEnumerateGuildMessageBoard
|
||||
handlerTable[network.MSG_MHF_UPDATE_GUILD_MESSAGE_BOARD] = handleMsgMhfUpdateGuildMessageBoard
|
||||
handlerTable[network.MSG_SYS_reserve204] = handleMsgSysReserve204
|
||||
handlerTable[network.MSG_SYS_reserve205] = handleMsgSysReserve205
|
||||
handlerTable[network.MSG_SYS_reserve206] = handleMsgSysReserve206
|
||||
|
||||
@@ -48,7 +48,12 @@ func handleMsgMhfGetUdTacticsFirstQuestBonus(s *Session, p mhfpacket.MHFPacket)
|
||||
|
||||
func handleMsgMhfGetUdTacticsRemainingPoint(s *Session, p mhfpacket.MHFPacket) {}
|
||||
|
||||
func handleMsgMhfGetUdTacticsRanking(s *Session, p mhfpacket.MHFPacket) {}
|
||||
func handleMsgMhfGetUdTacticsRanking(s *Session, p mhfpacket.MHFPacket) {
|
||||
pkt := p.(*mhfpacket.MsgMhfGetUdTacticsRanking)
|
||||
// Temporary canned response
|
||||
data, _ := hex.DecodeString("00000515000005150000CEB4000003CE000003CE0000CEB44D49444E494748542D414E47454C0000000000000000000000")
|
||||
doAckBufSucceed(s, pkt.AckHandle, data)
|
||||
}
|
||||
|
||||
func handleMsgMhfSetUdTacticsFollower(s *Session, p mhfpacket.MHFPacket) {}
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package channelserver
|
||||
|
||||
import (
|
||||
"github.com/Andoryuuta/byteframe"
|
||||
"github.com/Solenataris/Erupe/network/mhfpacket"
|
||||
|
||||
"sync"
|
||||
)
|
||||
|
||||
@@ -11,6 +14,10 @@ type Semaphore struct {
|
||||
// Stage ID string
|
||||
id_semaphore string
|
||||
|
||||
// Map of session -> charID.
|
||||
// These are clients that are CURRENTLY in the stage
|
||||
clients map[*Session]uint32
|
||||
|
||||
// Map of charID -> interface{}, only the key is used, value is always nil.
|
||||
reservedClientSlots map[uint32]interface{}
|
||||
|
||||
@@ -22,8 +29,46 @@ type Semaphore struct {
|
||||
func NewSemaphore(ID string, MaxPlayers uint16) *Semaphore {
|
||||
s := &Semaphore{
|
||||
id_semaphore: ID,
|
||||
clients: make(map[*Session]uint32),
|
||||
reservedClientSlots: make(map[uint32]interface{}),
|
||||
maxPlayers: MaxPlayers,
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *Semaphore) BroadcastRavi(pkt mhfpacket.MHFPacket) {
|
||||
// Broadcast the data.
|
||||
for session := range s.clients {
|
||||
|
||||
|
||||
// Make the header
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint16(uint16(pkt.Opcode()))
|
||||
|
||||
// Build the packet onto the byteframe.
|
||||
pkt.Build(bf, session.clientContext)
|
||||
|
||||
// Enqueue in a non-blocking way that drops the packet if the connections send buffer channel is full.
|
||||
session.QueueSendNonBlocking(bf.Data())
|
||||
}
|
||||
}
|
||||
|
||||
// BroadcastMHF queues a MHFPacket to be sent to all sessions in the stage.
|
||||
func (s *Semaphore) BroadcastMHF(pkt mhfpacket.MHFPacket, ignoredSession *Session) {
|
||||
// Broadcast the data.
|
||||
for session := range s.clients {
|
||||
if session == ignoredSession {
|
||||
continue
|
||||
}
|
||||
|
||||
// Make the header
|
||||
bf := byteframe.NewByteFrame()
|
||||
bf.WriteUint16(uint16(pkt.Opcode()))
|
||||
|
||||
// Build the packet onto the byteframe.
|
||||
pkt.Build(bf, session.clientContext)
|
||||
|
||||
// Enqueue in a non-blocking way that drops the packet if the connections send buffer channel is full.
|
||||
session.QueueSendNonBlocking(bf.Data())
|
||||
}
|
||||
}
|
||||
@@ -32,6 +32,8 @@ type Session struct {
|
||||
reservationStage *Stage // Required for the stateful MsgSysUnreserveStage packet.
|
||||
charID uint32
|
||||
logKey []byte
|
||||
sessionStart int64
|
||||
rights uint32
|
||||
|
||||
semaphore *Semaphore // Required for the stateful MsgSysUnreserveStage packet.
|
||||
|
||||
@@ -62,6 +64,7 @@ func NewSession(server *Server, conn net.Conn) *Session {
|
||||
Encoding: japanese.ShiftJIS,
|
||||
},
|
||||
},
|
||||
sessionStart: Time_Current_Adjusted().Unix(),
|
||||
stageMoveStack: stringstack.New(),
|
||||
}
|
||||
return s
|
||||
@@ -177,6 +180,7 @@ func (s *Session) handlePacketGroup(pktGroup []byte) {
|
||||
opcode != network.MSG_SYS_PING &&
|
||||
opcode != network.MSG_SYS_NOP &&
|
||||
opcode != network.MSG_SYS_TIME &&
|
||||
opcode != network.MSG_SYS_POSITION_OBJECT &&
|
||||
opcode != network.MSG_SYS_EXTEND_THRESHOLD {
|
||||
fmt.Printf("[%s] send to Server\n", s.Name)
|
||||
fmt.Printf("Opcode: %s\n", opcode)
|
||||
|
||||
@@ -26,9 +26,9 @@ func (s *Server) newUserChara(username string) error {
|
||||
|
||||
_, err = s.db.Exec(`
|
||||
INSERT INTO characters (
|
||||
user_id, is_female, is_new_character, small_gr_level, gr_override_mode, name, unk_desc_string,
|
||||
gr_override_level, gr_override_unk0, gr_override_unk1, exp, weapon, last_login)
|
||||
VALUES($1, False, True, 0, True, '', '', 0, 0, 0, 0, 0, $2)`,
|
||||
user_id, is_female, is_new_character, name, unk_desc_string,
|
||||
hrp, gr, weapon_type, last_login)
|
||||
VALUES($1, False, True, '', '', 1, 0, 0, $2)`,
|
||||
id,
|
||||
uint32(time.Now().Unix()),
|
||||
)
|
||||
@@ -60,9 +60,9 @@ func (s *Server) registerDBAccount(username string, password string) error {
|
||||
// Create a base new character.
|
||||
_, err = s.db.Exec(`
|
||||
INSERT INTO characters (
|
||||
user_id, is_female, is_new_character, small_gr_level, gr_override_mode, name, unk_desc_string,
|
||||
gr_override_level, gr_override_unk0, gr_override_unk1, exp, weapon, last_login)
|
||||
VALUES($1, False, True, 0, True, '', '', 0, 0, 0, 0, 0, $2)`,
|
||||
user_id, is_female, is_new_character, name, unk_desc_string,
|
||||
hrp, gr, weapon_type, last_login)
|
||||
VALUES($1, False, True, '', '', 1, 0, 0, $2)`,
|
||||
id,
|
||||
uint32(time.Now().Unix()),
|
||||
)
|
||||
@@ -77,21 +77,17 @@ type character struct {
|
||||
ID uint32 `db:"id"`
|
||||
IsFemale bool `db:"is_female"`
|
||||
IsNewCharacter bool `db:"is_new_character"`
|
||||
SmallGRLevel uint8 `db:"small_gr_level"`
|
||||
GROverrideMode bool `db:"gr_override_mode"`
|
||||
Name string `db:"name"`
|
||||
UnkDescString string `db:"unk_desc_string"`
|
||||
GROverrideLevel uint16 `db:"gr_override_level"`
|
||||
GROverrideUnk0 uint8 `db:"gr_override_unk0"`
|
||||
GROverrideUnk1 uint8 `db:"gr_override_unk1"`
|
||||
Exp uint16 `db:"exp"`
|
||||
Weapon uint16 `db:"weapon"`
|
||||
HRP uint16 `db:"hrp"`
|
||||
GR uint16 `db:"gr"`
|
||||
WeaponType uint16 `db:"weapon_type"`
|
||||
LastLogin uint32 `db:"last_login"`
|
||||
}
|
||||
|
||||
func (s *Server) getCharactersForUser(uid int) ([]character, error) {
|
||||
characters := []character{}
|
||||
err := s.db.Select(&characters, "SELECT id, is_female, is_new_character, small_gr_level, gr_override_mode, name, unk_desc_string, gr_override_level, gr_override_unk0, gr_override_unk1, exp, weapon, last_login FROM characters WHERE user_id = $1", uid)
|
||||
err := s.db.Select(&characters, "SELECT id, is_female, is_new_character, name, unk_desc_string, hrp, gr, weapon_type, last_login FROM characters WHERE user_id = $1", uid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ package signserver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"github.com/Andoryuuta/byteframe"
|
||||
"go.uber.org/zap"
|
||||
@@ -32,6 +34,15 @@ func makeSignInFailureResp(respID RespID) []byte {
|
||||
return bf.Data()
|
||||
}
|
||||
|
||||
func randSeq(n int) string {
|
||||
var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
|
||||
b := make([]rune, n)
|
||||
for i := range b {
|
||||
b[i] = letters[rand.Intn(len(letters))]
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func (s *Session) makeSignInResp(uid int) []byte {
|
||||
// Get the characters from the DB.
|
||||
chars, err := s.server.getCharactersForUser(uid)
|
||||
@@ -39,14 +50,18 @@ func (s *Session) makeSignInResp(uid int) []byte {
|
||||
s.logger.Warn("Error getting characters from DB", zap.Error(err))
|
||||
}
|
||||
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
token := randSeq(16)
|
||||
// TODO: register token to db, users table
|
||||
|
||||
bf := byteframe.NewByteFrame()
|
||||
|
||||
bf.WriteUint8(1) // resp_code
|
||||
bf.WriteUint8(0) // file/patch server count
|
||||
bf.WriteUint8(4) // entrance server count
|
||||
bf.WriteUint8(uint8(len(chars))) // character count
|
||||
bf.WriteUint32(0xFFFFFFFF) // login_token_number
|
||||
bf.WriteBytes(paddedString("logintokenstrng", 16)) // login_token (16 byte padded string)
|
||||
bf.WriteUint8(1) // resp_code
|
||||
bf.WriteUint8(0) // file/patch server count
|
||||
bf.WriteUint8(4) // entrance server count
|
||||
bf.WriteUint8(uint8(len(chars))) // character count
|
||||
bf.WriteUint32(0xFFFFFFFF) // login_token_number
|
||||
bf.WriteBytes(paddedString(token, 16)) // login_token (16 byte padded string)
|
||||
bf.WriteUint32(1576761190)
|
||||
uint8PascalString(bf, fmt.Sprintf("%s:%d", s.server.erupeConfig.HostIP, s.server.erupeConfig.Entrance.Port))
|
||||
uint8PascalString(bf, "")
|
||||
@@ -60,24 +75,18 @@ func (s *Session) makeSignInResp(uid int) []byte {
|
||||
if s.server.erupeConfig.DevMode && s.server.erupeConfig.DevModeOptions.MaxLauncherHR {
|
||||
bf.WriteUint16(999)
|
||||
} else {
|
||||
bf.WriteUint16(char.Exp)
|
||||
bf.WriteUint16(char.HRP)
|
||||
}
|
||||
|
||||
bf.WriteUint16(char.Weapon) // Weapon, 0-13.
|
||||
bf.WriteUint16(char.WeaponType) // Weapon, 0-13.
|
||||
bf.WriteUint32(char.LastLogin) // Last login date, unix timestamp in seconds.
|
||||
bf.WriteBool(char.IsFemale) // Sex, 0=male, 1=female.
|
||||
bf.WriteBool(char.IsNewCharacter) // Is new character, 1 replaces character name with ?????.
|
||||
bf.WriteUint8(char.SmallGRLevel) // GR level if grMode == 0
|
||||
bf.WriteBool(char.GROverrideMode) // GR mode.
|
||||
bf.WriteUint8(0) // Old GR
|
||||
bf.WriteBool(true) // Use uint16 GR, no reason not to
|
||||
bf.WriteBytes(paddedString(char.Name, 16)) // Character name
|
||||
bf.WriteBytes(paddedString(char.UnkDescString, 32)) // unk str
|
||||
if char.GROverrideMode {
|
||||
bf.SetLE()
|
||||
bf.WriteUint16(char.GROverrideLevel) // GR level override.
|
||||
bf.SetBE()
|
||||
bf.WriteUint8(char.GROverrideUnk0) // unk
|
||||
bf.WriteUint8(char.GROverrideUnk1) // unk
|
||||
}
|
||||
bf.WriteUint16(char.GR)
|
||||
bf.WriteUint16(0) // Unk
|
||||
}
|
||||
|
||||
bf.WriteUint8(0) // friends_list_count
|
||||
|
||||
@@ -71,12 +71,21 @@
|
||||
<p class="lbl">Important Updates</p>
|
||||
</div>
|
||||
<ul class="article">
|
||||
<li>
|
||||
<div class="date">2022-05-03</div>
|
||||
<div class="body">
|
||||
<a
|
||||
href="javascript:toggleModal('openLink',"https://discord.com/channels/368424389416583169/929509970624532511/969305400795078656");"
|
||||
onclick="soundOk()">Eng 2.0 & Ravi Patch Released!
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div class="date">2022-04-24</div>
|
||||
<div class="body">
|
||||
<a
|
||||
href="javascript:toggleModal('openLink',"https://discord.com/channels/368424389416583169/929509970624532511/964339905364918272");"
|
||||
onclick="soundOk()">Launcher Patch v1.0 Released!
|
||||
href="javascript:toggleModal('openLink',"https://discord.com/channels/368424389416583169/929509970624532511/969286397301248050");"
|
||||
onclick="soundOk()">Launcher Patch V1.0 Released!
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
@@ -92,7 +101,7 @@
|
||||
<div class="body">
|
||||
<a
|
||||
href="javascript:toggleModal('openLink',"https://discord.gg/CFnzbhQ");"
|
||||
onclick="soundOk()">Join the community discord for updates!
|
||||
onclick="soundOk()">Join the community Discord for updates!
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
@@ -108,7 +108,7 @@ function createCharItem(name, uid, weapon, hr, gr, date, sex) {
|
||||
icon = 'img/icons/ss.png';
|
||||
break;
|
||||
case '双剣':
|
||||
weapon = 'Dual Blades';
|
||||
weapon = 'Dual Swords';
|
||||
icon = 'img/icons/db.png';
|
||||
break;
|
||||
case '大剣':
|
||||
@@ -116,7 +116,7 @@ function createCharItem(name, uid, weapon, hr, gr, date, sex) {
|
||||
icon = 'img/icons/gs.png';
|
||||
break;
|
||||
case '太刀':
|
||||
weapon = 'Long Sword';
|
||||
weapon = 'Longsword';
|
||||
icon = 'img/icons/ls.png';
|
||||
break;
|
||||
case 'ハンマー':
|
||||
@@ -139,7 +139,7 @@ function createCharItem(name, uid, weapon, hr, gr, date, sex) {
|
||||
weapon = 'Tonfa';
|
||||
icon = 'img/icons/tf.png';
|
||||
break;
|
||||
case 'スラッシュアックスF':
|
||||
case 'スラッシュアックスF':
|
||||
weapon = 'Switch Axe F';
|
||||
icon = 'img/icons/sa.png';
|
||||
break;
|
||||
@@ -272,7 +272,7 @@ function doLogin(option) {
|
||||
addLog('Creating new character...', 'normal');
|
||||
window.external.loginCog(username+'+', password, password);
|
||||
} else {
|
||||
window.external.loginCog(username, password, password);
|
||||
window.external.loginCog(username, password, 'test');
|
||||
}
|
||||
} catch (e) {
|
||||
addLog('Error on loginCog: '+e, 'error');
|
||||
|
||||
Reference in New Issue
Block a user