828 lines
25 KiB
Go
Raw Normal View History

2025-12-05 20:15:55 +08:00
package model
import (
2025-12-12 11:48:39 +08:00
"fmt"
2025-12-05 20:15:55 +08:00
"math"
2026-01-08 12:45:09 +08:00
"math/rand"
2026-01-10 14:39:46 +08:00
"rocommon/service"
2025-12-05 20:15:55 +08:00
"rocommon/util"
2025-12-12 11:48:39 +08:00
"roserver/baseserver/model"
2026-01-08 12:45:09 +08:00
model2 "roserver/game/model"
2025-12-05 20:15:55 +08:00
"roserver/serverproto"
"sort"
2025-12-12 11:48:39 +08:00
"strconv"
2025-12-05 20:15:55 +08:00
)
type MakeNtfMsgFunc func(uid uint64) interface{}
type LiveRoomInterface interface {
Update(deltaMS uint32)
Join(uid uint64)
Leave(uid uint64)
GetReady(uid uint64) bool
2025-12-13 17:06:18 +08:00
IsReady(uid uint64) bool
2026-01-08 12:45:09 +08:00
SendGift(uid uint64, giftId uint32) int32
2025-12-05 20:15:55 +08:00
RoomId() uint32
2026-01-10 14:39:46 +08:00
Heart() int64
AddHeart() int64
2025-12-05 20:15:55 +08:00
RoomType() uint32
StageSec() uint32
StageTimerSec() uint32
Stage() uint32
HasPlayer(uid uint64) bool
IsFree(uid uint64) bool
2026-01-08 12:45:09 +08:00
GiftRecords() []*serverproto.LiveRoomPlayerInfo
2025-12-12 11:48:39 +08:00
GiftRank() []*serverproto.LiveRoomPlayerInfo
2025-12-05 20:15:55 +08:00
ChatRecords() []*serverproto.LiveRoomChatData
2025-12-13 17:06:18 +08:00
GetReadyPlayerInfoList(uid uint64) []*serverproto.LiveRoomPlayerInfo
2025-12-05 20:15:55 +08:00
SendChat(senderId uint64, chatContent string)
2025-12-09 17:49:29 +08:00
ShowSubmit(uid uint64, data []*serverproto.KeyValueType64) []*serverproto.KeyValueType64
2026-01-12 19:27:32 +08:00
RoomState() string
2026-01-27 20:11:48 +08:00
RoomUserNum() int32
RoomUserHeads() []string
2025-12-05 20:15:55 +08:00
}
2025-12-13 17:06:18 +08:00
// 被子类重载函数
type LiveRoomTemplate interface {
GetMaxReadyNum(roomType uint32)
GetCMDPlayDataList(readyUidList []uint64, uid uint64, cfg *serverproto.LiveRoomTalkCfg) []*serverproto.KeyValueType64
GetShowResultList(readyUidList []uint64, uid uint64) []*serverproto.LiveRoomPlayerInfo
GetShowRewardList(readyUidList []uint64, uid uint64) []*serverproto.KeyValueType64
HasShowData() bool
GetShowData(readyUidList []uint64, uid uint64) []*serverproto.KeyValueType64
HandleShowSubmit(uid uint64, data []*serverproto.KeyValueType64) []*serverproto.KeyValueType64
GetStageEnterParams(stage uint32) string
ReadyStart()
ShowStart()
CheckIfShowEnd() bool
ShowEnd()
HandlePlayCMD(cfg *serverproto.LiveRoomTalkCfg)
}
2025-12-05 20:15:55 +08:00
type TimelineFrame struct {
sn int32
talkCfgList []*serverproto.LiveRoomTalkCfg
}
type LiveRoomSubmitData struct {
uid uint64
2025-12-09 17:49:29 +08:00
data *serverproto.KeyValueType64
2025-12-05 20:15:55 +08:00
}
type LiveRoom struct {
2025-12-12 11:48:39 +08:00
roomId uint32
roomType uint32
uidList []uint64
readyUidList []uint64
chatSN uint64
updateCount uint64
stageTick int32
tickIntervalMS uint32 //1000ms, 100ms
stage uint32
roomCfg *serverproto.LiveRoomCfg
2026-01-08 12:45:09 +08:00
sumGiftPoint int32
2025-12-12 11:48:39 +08:00
giftRankResetTime uint64
giftRank []*serverproto.LiveRoomPlayerInfo
2026-01-08 12:45:09 +08:00
giftRecords []*serverproto.LiveRoomPlayerInfo
2025-12-12 11:48:39 +08:00
chatRecords []*serverproto.LiveRoomChatData
idleTimeline map[int32]*TimelineFrame
readyTimeline map[int32]*TimelineFrame
showTimeline map[int32]*TimelineFrame
resultTimeline map[int32]*TimelineFrame
2026-01-12 19:27:32 +08:00
roomStateData map[string]string
2026-01-10 14:39:46 +08:00
heart int64
2025-12-05 20:15:55 +08:00
submitDataList []*LiveRoomSubmitData
2025-12-13 17:06:18 +08:00
// 函数字段:模拟虚函数
VF_GetMaxReadyNum func(roomType uint32) int
VF_GetCMDPlayDataList func(readyUidList []uint64, uid uint64, cfg *serverproto.LiveRoomTalkCfg) []*serverproto.KeyValueType64
VF_GetShowResultList func(readyUidList []uint64, uid uint64) []*serverproto.LiveRoomPlayerInfo
VF_GetShowRewardList func(readyUidList []uint64, uid uint64) []*serverproto.KeyValueType64
VF_HasShowData func() bool
VF_GetShowData func(readyUidList []uint64, uid uint64) []*serverproto.KeyValueType64
VF_HandleShowSubmit func(uid uint64, data []*serverproto.KeyValueType64) []*serverproto.KeyValueType64
VF_GetStageEnterParams func(stage uint32) string
VF_ReadyStart func()
VF_ShowStart func()
VF_CheckIfShowEnd func() bool
VF_ShowEnd func()
VF_HandlePlayCMD func(cfg *serverproto.LiveRoomTalkCfg)
2026-01-12 19:27:32 +08:00
VF_GetRoomState func() string
2025-12-05 20:15:55 +08:00
}
func newLiveRoom(roomId uint32, roomType uint32, tickInterval uint32) LiveRoom {
liveRoom := LiveRoom{
roomId: roomId,
roomType: roomType,
uidList: make([]uint64, 0),
readyUidList: make([]uint64, 0),
chatSN: 0,
updateCount: 0,
stageTick: 0,
tickIntervalMS: tickInterval,
stage: LIVEROOM_STAGE_NULL,
2025-12-09 17:49:29 +08:00
roomCfg: serverproto.LiveRoomCfgLoader[int32(roomType)],
2026-01-08 12:45:09 +08:00
sumGiftPoint: 0,
2026-01-10 14:39:46 +08:00
heart: 0,
2025-12-12 11:48:39 +08:00
giftRank: make([]*serverproto.LiveRoomPlayerInfo, 0),
2026-01-08 12:45:09 +08:00
giftRecords: make([]*serverproto.LiveRoomPlayerInfo, 0),
2025-12-05 20:15:55 +08:00
chatRecords: make([]*serverproto.LiveRoomChatData, 0),
2026-01-12 19:27:32 +08:00
roomStateData: make(map[string]string),
2025-12-05 20:15:55 +08:00
}
2025-12-13 17:06:18 +08:00
liveRoom.BaseSetVF()
liveRoom.BaseInit()
2025-12-05 20:15:55 +08:00
return liveRoom
}
2025-12-13 17:06:18 +08:00
func (self *LiveRoom) BaseSetVF() {
self.VF_GetMaxReadyNum = self.GetMaxReadyNum
self.VF_GetCMDPlayDataList = self.GetCMDPlayDataList
self.VF_GetShowResultList = self.GetShowResultList
self.VF_GetShowRewardList = self.GetShowRewardList
self.VF_HasShowData = self.HasShowData
self.VF_GetShowData = self.GetShowData
self.VF_HandleShowSubmit = self.HandleShowSubmit
self.VF_GetStageEnterParams = self.GetStageEnterParams
self.VF_ReadyStart = self.ReadyStart
self.VF_ShowStart = self.ShowStart
self.VF_CheckIfShowEnd = self.CheckIfShowEnd
self.VF_ShowEnd = self.ShowEnd
self.VF_HandlePlayCMD = self.HandlePlayCMD
2026-01-12 19:27:32 +08:00
self.VF_GetRoomState = self.GetRoomState
2025-12-13 17:06:18 +08:00
}
2025-12-05 20:15:55 +08:00
/*----------------------------------- 重载函数 -----------------------------------*/
func (self *LiveRoom) GetMaxReadyNum(roomType uint32) int {
2025-12-13 17:06:18 +08:00
util.InfoF("LiveRoom: GetMaxReadyNum")
2025-12-05 20:15:55 +08:00
return 0
}
2025-12-12 19:20:10 +08:00
func (self *LiveRoom) GetCMDPlayDataList(readyUidList []uint64, uid uint64, cfg *serverproto.LiveRoomTalkCfg) []*serverproto.KeyValueType64 {
2025-12-05 20:15:55 +08:00
return nil
}
2025-12-09 17:49:29 +08:00
func (self *LiveRoom) GetShowResultList(readyUidList []uint64, uid uint64) []*serverproto.LiveRoomPlayerInfo {
2025-12-05 20:15:55 +08:00
return nil
}
2025-12-12 19:20:10 +08:00
func (self *LiveRoom) GetShowRewardList(readyUidList []uint64, uid uint64) []*serverproto.KeyValueType64 {
2025-12-05 20:15:55 +08:00
return nil
}
2025-12-09 17:49:29 +08:00
func (self *LiveRoom) HasShowData() bool {
return false
}
func (self *LiveRoom) GetShowData(readyUidList []uint64, uid uint64) []*serverproto.KeyValueType64 {
return nil
}
func (self *LiveRoom) HandleShowSubmit(uid uint64, data []*serverproto.KeyValueType64) []*serverproto.KeyValueType64 {
return nil
}
func (self *LiveRoom) GetStageEnterParams(stage uint32) string {
return ""
2025-12-05 20:15:55 +08:00
}
2025-12-12 19:20:10 +08:00
func (self *LiveRoom) ReadyStart() {}
func (self *LiveRoom) ShowStart() {}
func (self *LiveRoom) CheckIfShowEnd() bool {
return false
}
2025-12-05 20:15:55 +08:00
func (self *LiveRoom) ShowEnd() {}
2025-12-12 19:20:10 +08:00
func (self *LiveRoom) HandlePlayCMD(cfg *serverproto.LiveRoomTalkCfg) {}
2026-01-12 19:27:32 +08:00
func (self *LiveRoom) GetRoomState() string {
return MapToString(self.roomStateData)
}
2025-12-12 19:20:10 +08:00
2025-12-05 20:15:55 +08:00
/*----------------------------------- 内部函数 -----------------------------------*/
2025-12-13 17:06:18 +08:00
func (self *LiveRoom) BaseInit() {
2025-12-05 20:15:55 +08:00
self.idleTimeline = self.CreateTimeline(LIVEROOM_STAGE_IDLE)
self.readyTimeline = self.CreateTimeline(LIVEROOM_STAGE_READY)
self.showTimeline = self.CreateTimeline(LIVEROOM_STAGE_SHOW)
self.resultTimeline = self.CreateTimeline(LIVEROOM_STAGE_RESULT)
2025-12-12 11:48:39 +08:00
self.giftRankResetTime = util.GetCurrentTime()
2025-12-05 20:15:55 +08:00
time1 := self.CalcTimelineSec(self.idleTimeline)
time2 := self.CalcTimelineSec(self.readyTimeline)
time3 := self.CalcTimelineSec(self.showTimeline)
time4 := self.CalcTimelineSec(self.resultTimeline)
util.InfoF("GetTimelineTime: ", time1, time2, time3, time4)
2025-12-12 11:48:39 +08:00
2026-01-10 14:39:46 +08:00
heartStr, err := service.GetRedis().HGet(model.LiveRoomHeartPrefix, string(self.roomType)).Result()
if err != nil {
util.InfoF("ERR: Redis HGet %s:%s err", model.LiveRoomHeartPrefix, string(self.roomType))
}
heartNum, _ := strconv.ParseInt(heartStr, 10, 64)
self.heart = heartNum
2025-12-05 20:15:55 +08:00
self.ChangeStage(LIVEROOM_STAGE_IDLE)
}
func (self *LiveRoom) CreateTimeline(stage int32) map[int32]*TimelineFrame {
timeline := make(map[int32]*TimelineFrame, 0)
var currentSN int32 = 0
liveRoomTalkCfg := serverproto.LiveRoomTalkCfgLoader
for i := 1; i <= len(liveRoomTalkCfg); i++ {
cfg := liveRoomTalkCfg[int32(i)]
if uint32(cfg.Type) == self.roomType && cfg.Stage == stage {
if frame, exist := timeline[currentSN]; exist {
frame.talkCfgList = append(frame.talkCfgList, cfg)
} else {
newFrame := &TimelineFrame{sn: currentSN, talkCfgList: make([]*serverproto.LiveRoomTalkCfg, 0)}
newFrame.talkCfgList = append(newFrame.talkCfgList, cfg)
timeline[currentSN] = newFrame
}
currentSN += cfg.Time
}
}
return timeline
}
func (self *LiveRoom) CalcTimelineSec(timeline map[int32]*TimelineFrame) int32 {
var totalTime int32 = 0
for _, frame := range timeline {
totalTime += frame.talkCfgList[0].Time
}
return totalTime
}
func (self *LiveRoom) Update(deltaMS uint32) {
self.updateCount += 1
if self.updateCount*uint64(deltaMS) > math.MaxUint64-10000 {
self.updateCount = 1
}
if (self.updateCount*uint64(deltaMS))%uint64(self.tickIntervalMS) == 0 {
switch self.stage {
case LIVEROOM_STAGE_IDLE:
self.LIVEROOM_STAGE_IDLE_Update(self.tickIntervalMS)
case LIVEROOM_STAGE_READY:
self.LIVEROOM_STAGE_READY_Update(self.tickIntervalMS)
case LIVEROOM_STAGE_SHOW:
self.LIVEROOM_STAGE_SHOW_Update(self.tickIntervalMS)
case LIVEROOM_STAGE_RESULT:
self.LIVEROOM_STAGE_RESULT_Update(self.tickIntervalMS)
}
self.stageTick += 1
}
2025-12-12 11:48:39 +08:00
if model.IsDailyResetHour5(self.giftRankResetTime) {
self.giftRank = make([]*serverproto.LiveRoomPlayerInfo, 0)
self.giftRankResetTime = util.GetCurrentTime()
util.InfoF("ResetGiftRank: RoomType=%d, time=%d", self.roomType, self.giftRankResetTime)
}
2025-12-05 20:15:55 +08:00
}
func (self *LiveRoom) ChangeStage(newStage uint32) {
self.stageTick = 0
// 1. Current Stage Exit
switch self.stage {
case LIVEROOM_STAGE_IDLE:
self.LIVEROOM_STAGE_IDLE_Exit()
case LIVEROOM_STAGE_READY:
self.LIVEROOM_STAGE_READY_Exit()
case LIVEROOM_STAGE_SHOW:
self.LIVEROOM_STAGE_SHOW_Exit()
case LIVEROOM_STAGE_RESULT:
self.LIVEROOM_STAGE_RESULT_Exit()
}
// 2. Next Stage Enter
switch newStage {
case LIVEROOM_STAGE_IDLE:
self.LIVEROOM_STAGE_IDLE_Enter()
case LIVEROOM_STAGE_READY:
self.LIVEROOM_STAGE_READY_Enter()
case LIVEROOM_STAGE_SHOW:
self.LIVEROOM_STAGE_SHOW_Enter()
case LIVEROOM_STAGE_RESULT:
self.LIVEROOM_STAGE_RESULT_Enter()
}
2025-12-09 17:49:29 +08:00
self.SendAllPlayers(func(uid uint64) interface{} {
return &serverproto.SCLiveRoomStageNtf{
Uid: uid,
RoomId: self.roomId,
Stage: newStage,
StageTimerSec: self.GetStageTimerSec(newStage),
2025-12-13 17:06:18 +08:00
StageParams: self.VF_GetStageEnterParams(newStage),
2025-12-09 17:49:29 +08:00
}
})
2025-12-05 20:15:55 +08:00
// 3. Update Current Stage
self.stage = newStage
}
2026-01-08 12:45:09 +08:00
func (self *LiveRoom) makeTalkParams(cfg *serverproto.LiveRoomTalkCfg, player string, gift int32, item int32) string {
actIdx := rand.Intn(len(cfg.Params1)) + 1
talkIdx := rand.Intn(len(cfg.Params2)) + 1
return fmt.Sprintf("act:%d;talk:%d;player:%s;gift:%d;item:%d", actIdx, talkIdx, player, gift, item)
}
2025-12-05 20:15:55 +08:00
func (self *LiveRoom) HandleCMD(sn int32, cfg *serverproto.LiveRoomTalkCfg) {
switch cfg.CMD {
case LIVEROOM_CMD_TALK:
self.SendAllPlayers(func(uid uint64) interface{} {
return &serverproto.SCLiveRoomCMDTalkNtf{
Uid: uid,
RoomId: self.roomId,
TalkId: uint32(cfg.Id),
2026-01-08 12:45:09 +08:00
TalkParams: self.makeTalkParams(cfg, "nil", 0, 0),
2025-12-05 20:15:55 +08:00
}
})
case LIVEROOM_CMD_PLAY:
2025-12-13 17:06:18 +08:00
self.VF_HandlePlayCMD(cfg)
2025-12-05 20:15:55 +08:00
self.SendAllPlayers(func(uid uint64) interface{} {
return &serverproto.SCLiveRoomCMDPlayNtf{
2025-12-09 17:49:29 +08:00
Uid: uid,
RoomId: self.roomId,
2025-12-13 17:06:18 +08:00
PlayDataList: self.VF_GetCMDPlayDataList(self.readyUidList, uid, cfg),
2025-12-05 20:15:55 +08:00
}
})
}
}
/*----------------------------------- Stage: IDLE -----------------------------------*/
func (self *LiveRoom) LIVEROOM_STAGE_IDLE_Enter() {
2025-12-13 17:06:18 +08:00
util.InfoF("LIVEROOM_STAGE_IDLE_Enter")
2025-12-05 20:15:55 +08:00
self.readyUidList = make([]uint64, 0)
self.submitDataList = make([]*LiveRoomSubmitData, 0)
2026-01-12 19:27:32 +08:00
self.roomStateData = make(map[string]string)
2026-01-08 12:45:09 +08:00
self.sumGiftPoint = 0
2025-12-05 20:15:55 +08:00
}
func (self *LiveRoom) LIVEROOM_STAGE_IDLE_Update(deltaMS uint32) {
2025-12-15 14:37:39 +08:00
if self.stageTick >= self.CalcTimelineSec(self.idleTimeline) {
2026-01-08 12:45:09 +08:00
if self.sumGiftPoint >= serverproto.LiveRoomCfgLoader[int32(self.roomType)].MaxGiftPoint {
2025-12-12 11:48:39 +08:00
self.ChangeStage(LIVEROOM_STAGE_READY)
} else {
self.ChangeStage(LIVEROOM_STAGE_IDLE)
}
2025-12-05 20:15:55 +08:00
return
}
//util.InfoF("LIVEROOM_STAGE_IDLE_Update: Tick %d", uint32(self.stageTick))
if frame, exist := self.idleTimeline[self.stageTick]; exist {
for i := 0; i < len(frame.talkCfgList); i++ {
cfg := frame.talkCfgList[i]
self.HandleCMD(frame.sn, cfg)
}
}
}
func (self *LiveRoom) LIVEROOM_STAGE_IDLE_Exit() {}
/*----------------------------------- Stage: READY -----------------------------------*/
func (self *LiveRoom) LIVEROOM_STAGE_READY_Enter() {
2025-12-13 17:06:18 +08:00
util.InfoF("LIVEROOM_STAGE_READY_Enter")
self.VF_ReadyStart()
2025-12-05 20:15:55 +08:00
}
func (self *LiveRoom) LIVEROOM_STAGE_READY_Update(deltaMS uint32) {
2025-12-15 14:37:39 +08:00
if self.stageTick >= self.CalcTimelineSec(self.readyTimeline) {
2025-12-05 20:15:55 +08:00
if len(self.readyUidList) > 0 {
self.ChangeStage(LIVEROOM_STAGE_SHOW)
} else {
self.ChangeStage(LIVEROOM_STAGE_IDLE)
}
return
}
//util.InfoF("LIVEROOM_STAGE_READY_Update: Tick %d", uint32(self.stageTick))
if frame, exist := self.readyTimeline[self.stageTick]; exist {
for i := 0; i < len(frame.talkCfgList); i++ {
cfg := frame.talkCfgList[i]
self.HandleCMD(frame.sn, cfg)
}
}
}
func (self *LiveRoom) LIVEROOM_STAGE_READY_Exit() {}
/*----------------------------------- Stage: SHOW -----------------------------------*/
func (self *LiveRoom) LIVEROOM_STAGE_SHOW_Enter() {
2025-12-13 17:06:18 +08:00
util.InfoF("LIVEROOM_STAGE_SHOW_Enter")
self.VF_ShowStart()
2025-12-05 20:15:55 +08:00
}
func (self *LiveRoom) LIVEROOM_STAGE_SHOW_Update(deltaMS uint32) {
2025-12-15 14:37:39 +08:00
if self.stageTick >= self.CalcTimelineSec(self.showTimeline) {
2025-12-05 20:15:55 +08:00
self.ChangeStage(LIVEROOM_STAGE_RESULT)
return
}
2025-12-13 17:06:18 +08:00
if self.VF_CheckIfShowEnd() {
2025-12-12 19:20:10 +08:00
self.ChangeStage(LIVEROOM_STAGE_RESULT)
return
}
2025-12-05 20:15:55 +08:00
//util.InfoF("LIVEROOM_STAGE_SHOW_Update: Tick %d", uint32(self.stageTick))
if frame, exist := self.showTimeline[self.stageTick]; exist {
for i := 0; i < len(frame.talkCfgList); i++ {
cfg := frame.talkCfgList[i]
self.HandleCMD(frame.sn, cfg)
}
}
2025-12-09 17:49:29 +08:00
2025-12-13 17:06:18 +08:00
if self.VF_HasShowData() {
2025-12-09 17:49:29 +08:00
self.ShowDataNtf()
}
2025-12-05 20:15:55 +08:00
}
func (self *LiveRoom) LIVEROOM_STAGE_SHOW_Exit() {
2025-12-13 17:06:18 +08:00
self.VF_ShowEnd()
2025-12-05 20:15:55 +08:00
}
/*----------------------------------- Stage: RESULT -----------------------------------*/
func (self *LiveRoom) LIVEROOM_STAGE_RESULT_Enter() {
//util.InfoF("LIVEROOM_STAGE_RESULT_Enter")
self.SendAllPlayers(func(currUid uint64) interface{} {
2025-12-13 17:06:18 +08:00
showResultList := self.VF_GetShowResultList(self.readyUidList, currUid)
showRewardList := self.VF_GetShowRewardList(self.readyUidList, currUid)
2025-12-05 20:15:55 +08:00
return &serverproto.SCLiveRoomResultNtf{
2025-12-09 17:49:29 +08:00
Uid: currUid,
RoomId: self.roomId,
PlayerResultList: showResultList,
PlayerRewardList: showRewardList,
2025-12-05 20:15:55 +08:00
}
})
}
func (self *LiveRoom) LIVEROOM_STAGE_RESULT_Update(deltaMS uint32) {
2025-12-15 14:37:39 +08:00
if self.stageTick >= self.CalcTimelineSec(self.resultTimeline) {
2025-12-05 20:15:55 +08:00
self.ChangeStage(LIVEROOM_STAGE_IDLE)
return
}
//util.InfoF("LIVEROOM_STAGE_RESULT_Update: Tick %d", uint32(self.stageTick))
if frame, exist := self.resultTimeline[self.stageTick]; exist {
for i := 0; i < len(frame.talkCfgList); i++ {
cfg := frame.talkCfgList[i]
self.HandleCMD(frame.sn, cfg)
}
}
}
func (self *LiveRoom) LIVEROOM_STAGE_RESULT_Exit() {}
func (self *LiveRoom) GetStageTimerSec(stage uint32) uint32 {
var timeline map[int32]*TimelineFrame
switch stage {
case LIVEROOM_STAGE_IDLE:
timeline = self.idleTimeline
case LIVEROOM_STAGE_READY:
timeline = self.readyTimeline
case LIVEROOM_STAGE_SHOW:
timeline = self.showTimeline
case LIVEROOM_STAGE_RESULT:
timeline = self.resultTimeline
}
return uint32(self.CalcTimelineSec(timeline))
}
func (self *LiveRoom) Join(uid uint64) {
if SliceIsExist(self.uidList, uid) == false {
self.uidList = append(self.uidList, uid)
}
player := RoomMgr.GetPlayer(uid)
player.LeaveRoom = false
player.WaitLeaveRoom = false
}
func (self *LiveRoom) Leave(uid uint64) {
player := RoomMgr.GetPlayer(uid)
player.WaitLeaveRoom = true
self.uidList = SliceRemoveByValue(self.uidList, uid)
}
2025-12-13 17:06:18 +08:00
func (self *LiveRoom) IsReady(uid uint64) bool {
if SliceIsExist(self.readyUidList, uid) {
return true
}
return false
}
2025-12-05 20:15:55 +08:00
func (self *LiveRoom) GetReady(currUid uint64) bool {
if self.stage != LIVEROOM_STAGE_READY {
2026-01-10 14:39:46 +08:00
util.InfoF("[GetReady] ERR: current stage is not LIVEROOM_STAGE_READY")
2025-12-05 20:15:55 +08:00
return false
}
if SliceIsExist(self.readyUidList, currUid) {
2026-01-10 14:39:46 +08:00
util.InfoF("[GetReady] ERR: %s already getReady", currUid)
2025-12-05 20:15:55 +08:00
return false
}
2025-12-13 17:06:18 +08:00
if len(self.readyUidList) > self.VF_GetMaxReadyNum(self.roomType) {
2026-01-10 14:39:46 +08:00
util.InfoF("[GetReady] ERR: readyUidList=%d > GetMaxReadyNum", len(self.readyUidList))
2025-12-05 20:15:55 +08:00
return false
}
self.readyUidList = append(self.readyUidList, currUid)
self.SendAllPlayers(func(currUid uint64) interface{} {
// 给客户端显示自己和其他4个玩家的准备信息
maxCount := 5
readyPlayerInfoList := make([]*serverproto.LiveRoomPlayerInfo, 0)
if SliceIsExist(self.readyUidList, currUid) {
// 1. 添加当前玩家的信息
currPlayer := RoomMgr.GetPlayer(currUid)
readyPlayerInfoList = append(readyPlayerInfoList, &serverproto.LiveRoomPlayerInfo{
2026-01-08 12:45:09 +08:00
Uid: currUid,
2025-12-05 20:15:55 +08:00
Nickname: currPlayer.Name,
Level: currPlayer.Level,
HeadId: currPlayer.HeadId,
HeadTitle: currPlayer.HeadTitle,
})
// 2. 先添加其他准备玩家信息
for i := len(self.readyUidList) - 1; i >= 0; i-- {
tmpUid := self.readyUidList[i]
if tmpUid != currUid {
player := RoomMgr.GetPlayer(tmpUid)
readyPlayerInfoList = append(readyPlayerInfoList, &serverproto.LiveRoomPlayerInfo{
2026-01-08 12:45:09 +08:00
Uid: tmpUid,
2025-12-05 20:15:55 +08:00
Nickname: player.Name,
Level: player.Level,
HeadId: player.HeadId,
HeadTitle: player.HeadTitle,
})
if len(readyPlayerInfoList) > maxCount-1 {
break
}
}
}
} else {
for i := len(self.readyUidList) - 1; i >= 0; i-- {
tmpUid := self.readyUidList[i]
player := RoomMgr.GetPlayer(tmpUid)
readyPlayerInfoList = append(readyPlayerInfoList, &serverproto.LiveRoomPlayerInfo{
2026-01-08 12:45:09 +08:00
Uid: tmpUid,
2025-12-05 20:15:55 +08:00
Nickname: player.Name,
Level: player.Level,
HeadId: player.HeadId,
HeadTitle: player.HeadTitle,
})
if len(readyPlayerInfoList) > maxCount {
break
}
}
}
return &serverproto.SCLiveRoomGetReadyNtf{
Uid: currUid,
RoomId: self.roomId,
ReadyPlayerInfoList: readyPlayerInfoList,
}
})
2025-12-13 17:06:18 +08:00
if len(self.readyUidList) >= self.VF_GetMaxReadyNum(self.roomType) {
2025-12-05 20:15:55 +08:00
self.ChangeStage(LIVEROOM_STAGE_SHOW)
}
return true
}
func (self *LiveRoom) RoomId() uint32 {
return self.roomId
}
2026-01-10 14:39:46 +08:00
func (self *LiveRoom) Heart() int64 { return self.heart }
func (self *LiveRoom) AddHeart() int64 {
self.heart = self.heart + 1
return self.heart
}
2025-12-05 20:15:55 +08:00
func (self *LiveRoom) RoomType() uint32 {
return self.roomType
}
func (self *LiveRoom) Stage() uint32 {
return self.stage
}
func (self *LiveRoom) StageTimerSec() uint32 {
return self.GetStageTimerSec(self.stage)
}
func (self *LiveRoom) StageSec() uint32 {
2025-12-15 14:37:39 +08:00
return self.GetStageTimerSec(self.stage) - uint32(self.stageTick)
2025-12-05 20:15:55 +08:00
}
func (self *LiveRoom) HasPlayer(uid uint64) bool {
for i := 0; i < len(self.uidList); i++ {
if uid == self.uidList[i] {
return true
}
}
return false
}
2026-01-12 19:27:32 +08:00
func (self *LiveRoom) RoomState() string {
return self.VF_GetRoomState()
}
2025-12-05 20:15:55 +08:00
func (self *LiveRoom) IsFree(uid uint64) bool {
if len(self.uidList) > LIVEROOM_MAX_PLAYER_NUM {
return false
}
return true
}
2025-12-13 17:06:18 +08:00
func (self *LiveRoom) GetReadyPlayerInfoList(uid uint64) []*serverproto.LiveRoomPlayerInfo {
readyPlayerInfoList := make([]*serverproto.LiveRoomPlayerInfo, 0)
if self.stage == LIVEROOM_STAGE_READY {
if SliceIsExist(self.readyUidList, uid) {
readyPlayerInfoList = append(readyPlayerInfoList, MakeLiveRoomPlayerInfo(uid))
}
for _, readyUid := range self.readyUidList {
if len(readyPlayerInfoList) < 5 {
readyPlayerInfoList = append(readyPlayerInfoList, MakeLiveRoomPlayerInfo(readyUid))
}
}
}
return readyPlayerInfoList
}
2025-12-12 11:48:39 +08:00
func (self *LiveRoom) GiftRank() []*serverproto.LiveRoomPlayerInfo {
2026-01-08 12:45:09 +08:00
return self.giftRank
}
func (self *LiveRoom) GiftRecords() []*serverproto.LiveRoomPlayerInfo {
//sort.Slice(self.giftRank, func(i, j int) bool {
// return self.giftRank[i].Data > self.giftRank[j].Data
//})
//topCount := 10
//var rank []*serverproto.LiveRoomPlayerInfo
//if len(self.giftRank) >= topCount {
// rank = self.giftRank[:topCount]
//} else {
// rank = self.giftRank
//}
//return rank
return self.giftRecords
2025-12-05 20:15:55 +08:00
}
func (self *LiveRoom) ChatRecords() []*serverproto.LiveRoomChatData {
return self.chatRecords
}
2026-01-27 20:11:48 +08:00
func (self *LiveRoom) RoomUserNum() int32 {
return int32(len(self.uidList))
}
func (self *LiveRoom) RoomUserHeads() []string {
heads := make([]string, 0)
for _, uid := range self.uidList {
player := RoomMgr.GetPlayer(uid)
heads = append(heads, player.HeadId)
if len(heads) > 3 {
break
}
}
return heads
}
2025-12-05 20:15:55 +08:00
func (self *LiveRoom) RecordChatData(chatSN uint64, chatData *serverproto.LiveRoomChatData) {
var maxChatRecordNum int = 10
2026-01-10 14:39:46 +08:00
self.chatRecords = append(self.chatRecords, chatData)
if len(self.chatRecords) > maxChatRecordNum {
self.chatRecords = self.chatRecords[1:]
2025-12-05 20:15:55 +08:00
}
}
2025-12-09 17:49:29 +08:00
func (self *LiveRoom) ShowDataNtf() {
self.SendAllPlayers(func(uid uint64) interface{} {
2025-12-13 17:06:18 +08:00
showData := self.VF_GetShowData(self.readyUidList, uid)
2025-12-09 17:49:29 +08:00
return &serverproto.SCLiveRoomShowDataNtf{
Uid: uid,
RoomId: self.roomId,
ShowDataList: showData,
}
})
}
2025-12-05 20:15:55 +08:00
func (self *LiveRoom) SendChat(senderId uint64, chatContent string) {
senderPlayer := RoomMgr.GetPlayer(senderId)
self.chatSN = self.chatSN + 1
if self.chatSN >= math.MaxUint64-100 {
self.chatSN = 1
}
chatData := &serverproto.LiveRoomChatData{
SN: self.chatSN,
PlayerInfo: &serverproto.LiveRoomPlayerInfo{
Nickname: senderPlayer.Name,
Level: senderPlayer.Level,
2026-03-04 15:54:01 +08:00
VipLevel: senderPlayer.VipLevel,
2025-12-05 20:15:55 +08:00
HeadId: senderPlayer.HeadId,
HeadTitle: 1,
},
ChatContent: chatContent,
}
self.RecordChatData(self.chatSN, chatData)
self.SendAllPlayers(func(uid uint64) interface{} {
return &serverproto.SCLiveRoomChatNtf{
Uid: uid,
RoomId: self.roomId,
ChatData: chatData,
}
})
}
2025-12-09 17:49:29 +08:00
func (self *LiveRoom) AddItemList(uid uint64, items []*serverproto.KeyValueType, from int32, notify bool) {
SendToAllGame(&serverproto.SSGameRoleAddItemListReq{
Uid: uid,
ItemList: items,
From: from,
Notify: notify,
})
}
func (self *LiveRoom) DeleteItemList(uid uint64, items []*serverproto.KeyValueType, from int32, notify bool) {
SendToAllGame(&serverproto.SSGameRoleDeleteItemListReq{
Uid: uid,
ItemList: items,
From: from,
Notify: notify,
})
}
func (self *LiveRoom) ShowSubmit(uid uint64, data []*serverproto.KeyValueType64) []*serverproto.KeyValueType64 {
2025-12-13 17:06:18 +08:00
return self.VF_HandleShowSubmit(uid, data)
2025-12-05 20:15:55 +08:00
}
2026-01-08 12:45:09 +08:00
func (self *LiveRoom) SendGift(uid uint64, giftId uint32) int32 {
2025-12-12 11:48:39 +08:00
player := RoomMgr.GetPlayer(uid)
2026-01-08 12:45:09 +08:00
giftCfg := serverproto.LiveRoomGiftCfgLoader[int32(giftId)]
costItemId, costItemNum := model.Str2Res(giftCfg.Price)
if player.GameChipNum < uint32(costItemNum) {
util.InfoF("[SendGift] Err: GameChipNum=%d < CostItemNum=%d", player.GameChipNum, costItemNum)
return int32(serverproto.ErrorCode_ERROR_RES_NOT_ENOUGH)
}
rewardItemId, _ := RollForRateCfg(giftCfg.RewardItems)
util.InfoF("[SendGift] RollForRateCfg rewardItemId = %d", rewardItemId)
giftRewardStatus := 0
if rewardItemId != -1 {
giftRewardStatus = 1
addItems := make([]*serverproto.KeyValueType, 0)
addItems = append(addItems, &serverproto.KeyValueType{Key: int32(rewardItemId), Value: 1})
self.AddItemList(uid, addItems, int32(model2.AddFrom_LiveRoom_Gift), true)
}
costItems := make([]*serverproto.KeyValueType, 0)
costItems = append(costItems, &serverproto.KeyValueType{Key: int32(costItemId), Value: costItemNum})
self.DeleteItemList(uid, costItems, int32(model2.AddFrom_LiveRoom_Gift), true)
sendGiftInfo := &serverproto.LiveRoomPlayerInfo{
2026-01-10 14:39:46 +08:00
Uid: uid,
Nickname: player.Name,
HeadId: player.HeadId,
Level: player.Level,
Data: fmt.Sprintf("gift:%d;status:%d", giftId, giftRewardStatus),
2026-01-08 12:45:09 +08:00
}
self.giftRecords = append(self.giftRecords, sendGiftInfo)
if len(self.giftRecords) > 10 {
self.giftRecords = self.giftRecords[1:]
}
2025-12-12 11:48:39 +08:00
isFind := false
2026-01-08 12:45:09 +08:00
currGiftPoint := giftCfg.GiftPoint
self.sumGiftPoint += int32(currGiftPoint)
2025-12-12 11:48:39 +08:00
for _, v := range self.giftRank {
if v.Uid == player.Uid {
giftNum, _ := strconv.Atoi(v.Data)
2026-01-08 12:45:09 +08:00
giftNum += int(currGiftPoint)
2025-12-12 11:48:39 +08:00
isFind = true
break
}
}
if isFind == false {
playerInfo := MakeLiveRoomPlayerInfo(uid)
2026-01-08 12:45:09 +08:00
playerInfo.Data = string(currGiftPoint)
2025-12-12 11:48:39 +08:00
self.giftRank = append(self.giftRank, playerInfo)
}
sort.Slice(self.giftRank, func(i, j int) bool {
val1, _ := strconv.Atoi(self.giftRank[i].Data)
val2, _ := strconv.Atoi(self.giftRank[j].Data)
return val1 > val2
})
2026-01-08 12:45:09 +08:00
if len(self.giftRank) > 20 {
self.giftRank = self.giftRank[1:]
}
2025-12-12 11:48:39 +08:00
sendGiftTalkCfg := serverproto.LiveRoomTalkCfgLoader[LIVEROOM_TYPE_SEND_GIFT]
self.SendAllPlayers(func(uid uint64) interface{} {
return &serverproto.SCLiveRoomCMDTalkNtf{
Uid: uid,
RoomId: self.roomId,
TalkId: uint32(sendGiftTalkCfg.Id),
2026-01-08 12:45:09 +08:00
TalkParams: self.makeTalkParams(sendGiftTalkCfg, player.Name, int32(giftId), int32(rewardItemId)),
2025-12-12 11:48:39 +08:00
}
})
self.SendAllPlayers(func(uid uint64) interface{} {
2026-01-08 12:45:09 +08:00
return &serverproto.SCLiveRoomSendGiftNtf{
Uid: uid,
RoomId: self.roomId,
SendGiftInfo: sendGiftInfo,
2025-12-12 11:48:39 +08:00
}
})
2026-01-08 12:45:09 +08:00
return 0
2025-12-12 11:48:39 +08:00
}
2025-12-05 20:15:55 +08:00
func (self *LiveRoom) SendAllPlayers(makeNtfMsgFunc MakeNtfMsgFunc) {
for i := 0; i < len(self.uidList); i++ {
uid := self.uidList[i]
ntfMsg := makeNtfMsgFunc(uid)
SendToAllGame(ntfMsg)
}
}