2026-03-05 20:20:24 +08:00

846 lines
26 KiB
Go

package model
import (
"fmt"
"math"
"math/rand"
"rocommon/service"
"rocommon/util"
"roserver/baseserver/model"
model2 "roserver/game/model"
"roserver/serverproto"
"sort"
"strconv"
)
type MakeNtfMsgFunc func(uid uint64) interface{}
type LiveRoomInterface interface {
Update(deltaMS uint32)
Join(uid uint64)
Leave(uid uint64)
GetReady(uid uint64) bool
IsReady(uid uint64) bool
SendGift(uid uint64, giftId uint32) int32
RoomId() uint32
Heart() int64
AddHeart() int64
RoomType() uint32
StageSec() uint32
StageTimerSec() uint32
Stage() uint32
HasPlayer(uid uint64) bool
IsFree(uid uint64) bool
GiftRecords() []*serverproto.LiveRoomPlayerInfo
GiftRank() []*serverproto.LiveRoomPlayerInfo
ChatRecords() []*serverproto.LiveRoomChatData
GetReadyPlayerInfoList(uid uint64) []*serverproto.LiveRoomPlayerInfo
SendChat(senderId uint64, chatContent string)
ShowSubmit(uid uint64, data []*serverproto.KeyValueType64) []*serverproto.KeyValueType64
RoomState() string
RoomUserNum() int32
RoomUserHeads() []string
}
// 被子类重载函数
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)
}
type TimelineFrame struct {
sn int32
talkCfgList []*serverproto.LiveRoomTalkCfg
}
type LiveRoomSubmitData struct {
uid uint64
data *serverproto.KeyValueType64
}
type LiveRoom struct {
roomId uint32
roomType uint32
uidList []uint64
readyUidList []uint64
chatSN uint64
updateCount uint64
stageTick int32
tickIntervalMS uint32 //1000ms, 100ms
stage uint32
roomCfg *serverproto.LiveRoomCfg
sumGiftPoint int32
giftRankResetTime uint64
giftRank []*serverproto.LiveRoomPlayerInfo
giftRecords []*serverproto.LiveRoomPlayerInfo
chatRecords []*serverproto.LiveRoomChatData
idleTimeline map[int32]*TimelineFrame
readyTimeline map[int32]*TimelineFrame
showTimeline map[int32]*TimelineFrame
resultTimeline map[int32]*TimelineFrame
roomStateData map[string]string
heart int64
submitDataList []*LiveRoomSubmitData
// 函数字段:模拟虚函数
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)
VF_GetRoomState func() string
}
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,
roomCfg: serverproto.LiveRoomCfgLoader[int32(roomType)],
sumGiftPoint: 0,
heart: 0,
giftRank: make([]*serverproto.LiveRoomPlayerInfo, 0),
giftRecords: make([]*serverproto.LiveRoomPlayerInfo, 0),
chatRecords: make([]*serverproto.LiveRoomChatData, 0),
roomStateData: make(map[string]string),
}
liveRoom.BaseSetVF()
liveRoom.BaseInit()
return liveRoom
}
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
self.VF_GetRoomState = self.GetRoomState
}
/*----------------------------------- 重载函数 -----------------------------------*/
func (self *LiveRoom) GetMaxReadyNum(roomType uint32) int {
util.InfoF("LiveRoom: GetMaxReadyNum")
return 0
}
func (self *LiveRoom) GetCMDPlayDataList(readyUidList []uint64, uid uint64, cfg *serverproto.LiveRoomTalkCfg) []*serverproto.KeyValueType64 {
return nil
}
func (self *LiveRoom) GetShowResultList(readyUidList []uint64, uid uint64) []*serverproto.LiveRoomPlayerInfo {
return nil
}
func (self *LiveRoom) GetShowRewardList(readyUidList []uint64, uid uint64) []*serverproto.KeyValueType64 {
return nil
}
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 ""
}
func (self *LiveRoom) ReadyStart() {}
func (self *LiveRoom) ShowStart() {}
func (self *LiveRoom) CheckIfShowEnd() bool {
return false
}
func (self *LiveRoom) ShowEnd() {}
func (self *LiveRoom) HandlePlayCMD(cfg *serverproto.LiveRoomTalkCfg) {}
func (self *LiveRoom) GetRoomState() string {
return MapToString(self.roomStateData)
}
/*----------------------------------- 内部函数 -----------------------------------*/
func (self *LiveRoom) BaseInit() {
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)
self.giftRankResetTime = util.GetCurrentTime()
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)
heartStr, err := service.GetRedis().HGet(model.LiveRoomHeartPrefix, fmt.Sprintf("%d", self.roomType)).Result()
if err != nil {
util.InfoF("ERR: Redis HGet %s:%s err", model.LiveRoomHeartPrefix, fmt.Sprintf("%d", self.roomType))
}
heartNum, _ := strconv.ParseInt(heartStr, 10, 64)
self.heart = heartNum
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.stageTick += 1
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)
}
}
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)
}
if self.updateCount%300 == 0 {
ret, err := service.GetRedis().HSet(model.LiveRoomHeartPrefix, fmt.Sprintf("%d", self.roomType), fmt.Sprintf("%d", self.heart)).Result()
if err != nil {
util.InfoF("[LiveRoom] Update HSet: %v %v", err, ret)
}
}
}
func (self *LiveRoom) ChangeStage(newStage uint32) {
// 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()
}
self.SendAllPlayers(func(uid uint64) interface{} {
return &serverproto.SCLiveRoomStageNtf{
Uid: uid,
RoomId: self.roomId,
Stage: newStage,
StageTimerSec: self.GetStageTimerSec(newStage),
StageParams: self.VF_GetStageEnterParams(newStage),
}
})
// 3. Update Current Stage
self.stage = newStage
self.stageTick = -1
}
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)
}
func (self *LiveRoom) HandleCMD(sn int32, cfg *serverproto.LiveRoomTalkCfg) {
if self.roomId == 1 {
util.InfoF("LIVEROOM_CMD_TALK: roomId=%d, stage=%d, sn=%d, talkId=%d", self.roomId, self.stage, sn, cfg.Id)
}
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),
TalkParams: self.makeTalkParams(cfg, "nil", 0, 0),
}
})
case LIVEROOM_CMD_PLAY:
self.VF_HandlePlayCMD(cfg)
self.SendAllPlayers(func(uid uint64) interface{} {
return &serverproto.SCLiveRoomCMDPlayNtf{
Uid: uid,
RoomId: self.roomId,
PlayDataList: self.VF_GetCMDPlayDataList(self.readyUidList, uid, cfg),
}
})
}
}
/*----------------------------------- Stage: IDLE -----------------------------------*/
func (self *LiveRoom) LIVEROOM_STAGE_IDLE_Enter() {
//util.InfoF("LIVEROOM_STAGE_IDLE_Enter")
self.readyUidList = make([]uint64, 0)
self.submitDataList = make([]*LiveRoomSubmitData, 0)
self.roomStateData = make(map[string]string)
self.sumGiftPoint = 0
}
func (self *LiveRoom) LIVEROOM_STAGE_IDLE_Update(deltaMS uint32) {
if self.roomId == 1 {
util.InfoF("LIVEROOM_STAGE_IDLE_Update: roomId=%d, stageTick=%d", self.roomId, uint32(self.stageTick))
}
if self.stageTick >= self.CalcTimelineSec(self.idleTimeline) {
if self.sumGiftPoint >= serverproto.LiveRoomCfgLoader[int32(self.roomType)].MaxGiftPoint {
self.ChangeStage(LIVEROOM_STAGE_READY)
} else {
self.ChangeStage(LIVEROOM_STAGE_IDLE)
}
return
}
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() {
//util.InfoF("LIVEROOM_STAGE_READY_Enter")
self.VF_ReadyStart()
}
func (self *LiveRoom) LIVEROOM_STAGE_READY_Update(deltaMS uint32) {
if self.stageTick >= self.CalcTimelineSec(self.readyTimeline) {
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() {
//util.InfoF("LIVEROOM_STAGE_SHOW_Enter")
self.VF_ShowStart()
}
func (self *LiveRoom) LIVEROOM_STAGE_SHOW_Update(deltaMS uint32) {
if self.stageTick >= self.CalcTimelineSec(self.showTimeline) {
self.ChangeStage(LIVEROOM_STAGE_RESULT)
return
}
if self.VF_CheckIfShowEnd() {
self.ChangeStage(LIVEROOM_STAGE_RESULT)
return
}
//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)
}
}
if self.VF_HasShowData() {
self.ShowDataNtf()
}
}
func (self *LiveRoom) LIVEROOM_STAGE_SHOW_Exit() {
self.VF_ShowEnd()
}
/*----------------------------------- Stage: RESULT -----------------------------------*/
func (self *LiveRoom) LIVEROOM_STAGE_RESULT_Enter() {
//util.InfoF("LIVEROOM_STAGE_RESULT_Enter")
self.SendAllPlayers(func(currUid uint64) interface{} {
showResultList := self.VF_GetShowResultList(self.readyUidList, currUid)
showRewardList := self.VF_GetShowRewardList(self.readyUidList, currUid)
return &serverproto.SCLiveRoomResultNtf{
Uid: currUid,
RoomId: self.roomId,
PlayerResultList: showResultList,
PlayerRewardList: showRewardList,
}
})
}
func (self *LiveRoom) LIVEROOM_STAGE_RESULT_Update(deltaMS uint32) {
if self.stageTick >= self.CalcTimelineSec(self.resultTimeline) {
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
//self.SendChat(1000, fmt.Sprintf("玩家【%s】进入了直播间", player.Name))
}
func (self *LiveRoom) Leave(uid uint64) {
player := RoomMgr.GetPlayer(uid)
player.WaitLeaveRoom = true
self.uidList = SliceRemoveByValue(self.uidList, uid)
}
func (self *LiveRoom) IsReady(uid uint64) bool {
if SliceIsExist(self.readyUidList, uid) {
return true
}
return false
}
func (self *LiveRoom) GetReady(currUid uint64) bool {
if self.stage != LIVEROOM_STAGE_READY {
util.InfoF("[GetReady] ERR: current stage is not LIVEROOM_STAGE_READY")
return false
}
if SliceIsExist(self.readyUidList, currUid) {
util.InfoF("[GetReady] ERR: %s already getReady", currUid)
return false
}
if len(self.readyUidList) > self.VF_GetMaxReadyNum(self.roomType) {
util.InfoF("[GetReady] ERR: readyUidList=%d > GetMaxReadyNum", len(self.readyUidList))
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{
Uid: currUid,
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{
Uid: tmpUid,
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{
Uid: tmpUid,
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,
}
})
if len(self.readyUidList) >= self.VF_GetMaxReadyNum(self.roomType) {
self.ChangeStage(LIVEROOM_STAGE_SHOW)
}
return true
}
func (self *LiveRoom) RoomId() uint32 {
return self.roomId
}
func (self *LiveRoom) Heart() int64 { return self.heart }
func (self *LiveRoom) AddHeart() int64 {
self.heart = self.heart + 1
return self.heart
}
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 {
return self.GetStageTimerSec(self.stage) - uint32(self.stageTick)
}
func (self *LiveRoom) HasPlayer(uid uint64) bool {
for i := 0; i < len(self.uidList); i++ {
if uid == self.uidList[i] {
return true
}
}
return false
}
func (self *LiveRoom) RoomState() string {
return self.VF_GetRoomState()
}
func (self *LiveRoom) IsFree(uid uint64) bool {
if len(self.uidList) > LIVEROOM_MAX_PLAYER_NUM {
return false
}
return true
}
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
}
func (self *LiveRoom) GiftRank() []*serverproto.LiveRoomPlayerInfo {
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
}
func (self *LiveRoom) ChatRecords() []*serverproto.LiveRoomChatData {
return self.chatRecords
}
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
}
func (self *LiveRoom) RecordChatData(chatSN uint64, chatData *serverproto.LiveRoomChatData) {
var maxChatRecordNum int = 10
self.chatRecords = append(self.chatRecords, chatData)
if len(self.chatRecords) > maxChatRecordNum {
self.chatRecords = self.chatRecords[1:]
}
}
func (self *LiveRoom) ShowDataNtf() {
self.SendAllPlayers(func(uid uint64) interface{} {
showData := self.VF_GetShowData(self.readyUidList, uid)
return &serverproto.SCLiveRoomShowDataNtf{
Uid: uid,
RoomId: self.roomId,
ShowDataList: showData,
}
})
}
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{
Uid: senderId,
Nickname: senderPlayer.Name,
Level: senderPlayer.Level,
VipLevel: senderPlayer.VipLevel,
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,
}
})
}
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 {
return self.VF_HandleShowSubmit(uid, data)
}
func (self *LiveRoom) SendGift(uid uint64, giftId uint32) int32 {
player := RoomMgr.GetPlayer(uid)
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{
Uid: uid,
Nickname: player.Name,
HeadId: player.HeadId,
Level: player.Level,
VipLevel: player.VipLevel,
Data: fmt.Sprintf("gift:%d;status:%d", giftId, giftRewardStatus),
}
self.giftRecords = append(self.giftRecords, sendGiftInfo)
if len(self.giftRecords) > 10 {
self.giftRecords = self.giftRecords[1:]
}
isFind := false
currGiftPoint := giftCfg.GiftPoint
self.sumGiftPoint += int32(currGiftPoint)
for _, v := range self.giftRank {
if v.Uid == player.Uid {
giftNum, _ := strconv.Atoi(v.Data)
giftNum += int(currGiftPoint)
isFind = true
break
}
}
if isFind == false {
playerInfo := MakeLiveRoomPlayerInfo(uid)
playerInfo.Data = string(currGiftPoint)
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
})
if len(self.giftRank) > 20 {
self.giftRank = self.giftRank[1:]
}
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),
TalkParams: self.makeTalkParams(sendGiftTalkCfg, player.Name, int32(giftId), int32(rewardItemId)),
}
})
self.SendAllPlayers(func(uid uint64) interface{} {
return &serverproto.SCLiveRoomSendGiftNtf{
Uid: uid,
RoomId: self.roomId,
SendGiftInfo: sendGiftInfo,
}
})
self.SendChat(1000, fmt.Sprintf("玩家【%s】向主播打赏了【%s】", player.Name, giftCfg.Name))
return 0
}
func (self *LiveRoom) SendAllPlayers(makeNtfMsgFunc MakeNtfMsgFunc) {
for i := 0; i < len(self.uidList); i++ {
uid := self.uidList[i]
ntfMsg := makeNtfMsgFunc(uid)
SendToAllGame(ntfMsg)
}
}