mirror of
https://github.com/Mezeporta/Erupe.git
synced 2026-05-07 06:44:31 +02:00
fix(handlers): honor DisableLoginBoost and DisableBoostTime fully (#187)
GetBoostTimeLimit and GetBoostRight now respect DisableBoostTime, and
UseKeepLoginBoost now respects DisableLoginBoost. Also fix a latent
zero-time.Time wraparound in GetBoostTimeLimit that caused the
"Boost Time" overlay to appear on fresh characters regardless of
config, since time.Time{}.Unix() cast to uint32 yields a large value
the client interprets as an active timestamp.
This commit is contained in:
@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
- Fixed `DisableLoginBoost` and `DisableBoostTime` config flags not fully honored ([#187](https://github.com/Mezeporta/Erupe/issues/187)): `GetBoostTimeLimit`/`GetBoostRight` now respect `DisableBoostTime` and `UseKeepLoginBoost` now respects `DisableLoginBoost`. Also fixes a zero-`time.Time` wraparound in `GetBoostTimeLimit` that made the "Boost Time" overlay appear on fresh characters.
|
||||||
- Fixed playtime regression across sessions: `updateSaveDataWithStruct` now writes the accumulated playtime back into the binary save blob, preventing each reconnect from loading a stale in-game counter and rolling back progress.
|
- Fixed playtime regression across sessions: `updateSaveDataWithStruct` now writes the accumulated playtime back into the binary save blob, preventing each reconnect from loading a stale in-game counter and rolling back progress.
|
||||||
- Fixed player softlock when buying items at the forge: `MSG_CA_EXCHANGE_ITEM` `Parse()` was returning `NOT IMPLEMENTED`, causing the dispatch loop to drop the packet without sending an ACK. Now parses the `AckHandle` and responds with `doAckBufFail` so the client's error branch exits cleanly.
|
- Fixed player softlock when buying items at the forge: `MSG_CA_EXCHANGE_ITEM` `Parse()` was returning `NOT IMPLEMENTED`, causing the dispatch loop to drop the packet without sending an ACK. Now parses the `AckHandle` and responds with `doAckBufFail` so the client's error branch exits cleanly.
|
||||||
- Fixed player softlock on N-points (Hunting Road) interactions: same root cause for `MSG_MHF_USE_UD_SHOP_COIN` — `Parse()` now reads the `AckHandle` and responds with `doAckBufFail`.
|
- Fixed player softlock on N-points (Hunting Road) interactions: same root cause for `MSG_MHF_USE_UD_SHOP_COIN` — `Parse()` now reads the `AckHandle` and responds with `doAckBufFail`.
|
||||||
|
|||||||
@@ -219,7 +219,9 @@ func handleMsgMhfGetBoostTimeLimit(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
pkt := p.(*mhfpacket.MsgMhfGetBoostTimeLimit)
|
pkt := p.(*mhfpacket.MsgMhfGetBoostTimeLimit)
|
||||||
bf := byteframe.NewByteFrame()
|
bf := byteframe.NewByteFrame()
|
||||||
boostLimit, err := s.server.charRepo.ReadTime(s.charID, "boost_time", time.Time{})
|
boostLimit, err := s.server.charRepo.ReadTime(s.charID, "boost_time", time.Time{})
|
||||||
if err != nil {
|
// Return 0 when disabled, on read error, or when boost_time is unset
|
||||||
|
// (zero time.Time.Unix() wraps to a large uint32 the client interprets as active).
|
||||||
|
if err != nil || s.server.erupeConfig.GameplayOptions.DisableBoostTime || boostLimit.IsZero() {
|
||||||
bf.WriteUint32(0)
|
bf.WriteUint32(0)
|
||||||
} else {
|
} else {
|
||||||
bf.WriteUint32(uint32(boostLimit.Unix()))
|
bf.WriteUint32(uint32(boostLimit.Unix()))
|
||||||
@@ -230,6 +232,10 @@ func handleMsgMhfGetBoostTimeLimit(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
|
|
||||||
func handleMsgMhfGetBoostRight(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgMhfGetBoostRight(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgMhfGetBoostRight)
|
pkt := p.(*mhfpacket.MsgMhfGetBoostRight)
|
||||||
|
if s.server.erupeConfig.GameplayOptions.DisableBoostTime {
|
||||||
|
doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||||
|
return
|
||||||
|
}
|
||||||
boostLimit, err := s.server.charRepo.ReadTime(s.charID, "boost_time", time.Time{})
|
boostLimit, err := s.server.charRepo.ReadTime(s.charID, "boost_time", time.Time{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00})
|
||||||
|
|||||||
@@ -195,6 +195,10 @@ func handleMsgMhfGetKeepLoginBoostStatus(s *Session, p mhfpacket.MHFPacket) {
|
|||||||
|
|
||||||
func handleMsgMhfUseKeepLoginBoost(s *Session, p mhfpacket.MHFPacket) {
|
func handleMsgMhfUseKeepLoginBoost(s *Session, p mhfpacket.MHFPacket) {
|
||||||
pkt := p.(*mhfpacket.MsgMhfUseKeepLoginBoost)
|
pkt := p.(*mhfpacket.MsgMhfUseKeepLoginBoost)
|
||||||
|
if s.server.erupeConfig.GameplayOptions.DisableLoginBoost {
|
||||||
|
doAckBufSucceed(s, pkt.AckHandle, make([]byte, 5))
|
||||||
|
return
|
||||||
|
}
|
||||||
var expiration time.Time
|
var expiration time.Time
|
||||||
bf := byteframe.NewByteFrame()
|
bf := byteframe.NewByteFrame()
|
||||||
bf.WriteUint8(0)
|
bf.WriteUint8(0)
|
||||||
|
|||||||
Reference in New Issue
Block a user