108 lines
4.7 KiB
Go
108 lines
4.7 KiB
Go
package service
|
||
|
||
import (
|
||
"context"
|
||
"strings"
|
||
"time"
|
||
|
||
roomv1 "hyapp.local/api/proto/room/v1"
|
||
walletv1 "hyapp.local/api/proto/wallet/v1"
|
||
"hyapp/pkg/appcode"
|
||
"hyapp/pkg/xerr"
|
||
"hyapp/services/room-service/internal/room/command"
|
||
"hyapp/services/room-service/internal/room/outbox"
|
||
"hyapp/services/room-service/internal/room/rank"
|
||
"hyapp/services/room-service/internal/room/state"
|
||
)
|
||
|
||
// ApplyRoomRPSGift 把 room-rps 最终由败者支付的一份礼物应用到火箭。
|
||
// 钱包已由 game-service 结算,因此本入口只接受服务端锁定的 heat_value,并用 command_id 保证重试不重复充能。
|
||
func (s *Service) ApplyRoomRPSGift(ctx context.Context, req *roomv1.ApplyRoomRPSGiftRequest) (*roomv1.ApplyRoomRPSGiftResponse, error) {
|
||
ctx = contextFromMeta(ctx, req.GetMeta())
|
||
if req.GetSenderUserId() <= 0 || req.GetTargetUserId() <= 0 || strings.TrimSpace(req.GetGiftId()) == "" || req.GetHeatValue() <= 0 {
|
||
return nil, xerr.New(xerr.InvalidArgument, "room rps settled gift is incomplete")
|
||
}
|
||
cmd := command.ApplyRoomRPSGift{
|
||
Base: baseFromMeta(req.GetMeta()),
|
||
TargetUserID: req.GetTargetUserId(),
|
||
GiftID: strings.TrimSpace(req.GetGiftId()),
|
||
HeatValue: req.GetHeatValue(),
|
||
}
|
||
cmd.Base.Room = strings.TrimSpace(req.GetRoomId())
|
||
cmd.Base.ActorID = req.GetSenderUserId()
|
||
|
||
result, err := s.mutateRoom(ctx, cmd, true, func(now time.Time, current *state.RoomState, _ *rank.LocalRank) (mutationResult, []outbox.Record, error) {
|
||
roomMeta, exists, err := s.repository.GetRoomMeta(ctx, cmd.RoomID())
|
||
if err != nil {
|
||
return mutationResult{}, nil, err
|
||
}
|
||
if !exists {
|
||
return mutationResult{}, nil, xerr.New(xerr.NotFound, "room not found")
|
||
}
|
||
cfg, err := s.roomRocketConfig(ctx)
|
||
if err != nil {
|
||
return mutationResult{}, nil, err
|
||
}
|
||
// 复用普通送礼的唯一火箭规则实现,但不进入钱包、房间热度、礼物榜或 RoomGiftSent 链路。
|
||
giftCmd := command.SendGift{Base: cmd.Base, TargetUserID: cmd.TargetUserID, TargetUserIDs: []int64{cmd.TargetUserID}, GiftID: cmd.GiftID, GiftCount: 1, HeatValue: cmd.HeatValue}
|
||
settledGift := giftCmd
|
||
billing := &walletv1.DebitGiftResponse{HeatValue: cmd.HeatValue}
|
||
rocketApply, err := s.applyRoomRocketGift(now, current, cfg, giftCmd, &settledGift, billing, roomMeta)
|
||
if err != nil {
|
||
return mutationResult{}, nil, err
|
||
}
|
||
copyRoomRPSRocketSnapshot(&cmd, settledGift)
|
||
payload, err := command.Serialize(cmd)
|
||
if err != nil {
|
||
return mutationResult{}, nil, err
|
||
}
|
||
current.Version++
|
||
|
||
records := make([]outbox.Record, 0, 1)
|
||
var progress *roomRocketProgressPending
|
||
if rocketApply.progressEvent != nil {
|
||
progressRecord, err := outbox.Build(current.RoomID, "RoomRocketFuelChanged", current.Version, now, rocketApply.progressEvent)
|
||
if err != nil {
|
||
return mutationResult{}, nil, err
|
||
}
|
||
progressRecord.AppCode = appcode.FromContext(ctx)
|
||
if progressRecord.Envelope != nil {
|
||
progressRecord.Envelope.AppCode = progressRecord.AppCode
|
||
}
|
||
progress = &roomRocketProgressPending{record: progressRecord, rocketID: rocketApply.progressEvent.GetRocketId(), level: rocketApply.progressEvent.GetLevel(), currentFuel: rocketApply.progressEvent.GetCurrentFuel(), roomVersion: current.Version}
|
||
}
|
||
if rocketApply.ignited != nil {
|
||
ignitedRecord, err := outbox.Build(current.RoomID, "RoomRocketIgnited", current.Version, now, rocketApply.ignited)
|
||
if err != nil {
|
||
return mutationResult{}, nil, err
|
||
}
|
||
records = append(records, ignitedRecord)
|
||
}
|
||
return mutationResult{snapshot: current.ToProto(), commandPayload: payload, roomRocketProgress: progress}, records, nil
|
||
})
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
return &roomv1.ApplyRoomRPSGiftResponse{Result: commandResult(result.applied, result.snapshot.GetVersion(), s.clock.Now()), Rocket: result.snapshot.GetRocket()}, nil
|
||
}
|
||
|
||
func copyRoomRPSRocketSnapshot(target *command.ApplyRoomRPSGift, source command.SendGift) {
|
||
target.RocketTouched = source.RocketTouched
|
||
target.RocketAddedFuel = source.RocketAddedFuel
|
||
target.RocketEffectiveFuel = source.RocketEffectiveFuel
|
||
target.RocketOverflowFuel = source.RocketOverflowFuel
|
||
target.RocketLevel = source.RocketLevel
|
||
target.RocketFuel = source.RocketFuel
|
||
target.RocketStatus = source.RocketStatus
|
||
target.RocketFuelThreshold = source.RocketFuelThreshold
|
||
target.RocketIgnitedAtMS = source.RocketIgnitedAtMS
|
||
target.RocketLaunchAtMS = source.RocketLaunchAtMS
|
||
target.RocketResetAtMS = source.RocketResetAtMS
|
||
target.RocketTop1UserID = source.RocketTop1UserID
|
||
target.RocketIgniterUserID = source.RocketIgniterUserID
|
||
target.RocketID = source.RocketID
|
||
target.RocketConfigVersion = source.RocketConfigVersion
|
||
target.RocketPendingLaunches = source.RocketPendingLaunches
|
||
target.RocketCurrentContributions = source.RocketCurrentContributions
|
||
}
|