mirror of
https://github.com/FlourishingWorld/hk4e.git
synced 2026-02-04 16:02:26 +08:00
add: midi audio player
This commit is contained in:
3
go.mod
3
go.mod
@@ -53,6 +53,9 @@ require github.com/spf13/cobra v1.6.1
|
|||||||
// redis
|
// redis
|
||||||
require github.com/go-redis/redis/v8 v8.11.5
|
require github.com/go-redis/redis/v8 v8.11.5
|
||||||
|
|
||||||
|
// midi
|
||||||
|
require gitlab.com/gomidi/midi/v2 v2.0.25
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
|
|||||||
2
go.sum
2
go.sum
@@ -147,6 +147,8 @@ github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37 h1:EWU6Pktpas0n8lL
|
|||||||
github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37/go.mod h1:HpMP7DB2CyokmAh4lp0EQnnWhmycP/TvwBGzvuie+H0=
|
github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37/go.mod h1:HpMP7DB2CyokmAh4lp0EQnnWhmycP/TvwBGzvuie+H0=
|
||||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA=
|
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA=
|
||||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
|
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
|
||||||
|
gitlab.com/gomidi/midi/v2 v2.0.25 h1:dkzVBqbaFHjyWwP71MrQNX7IeRUIDonddmHbPpO/Ucg=
|
||||||
|
gitlab.com/gomidi/midi/v2 v2.0.25/go.mod h1:quTyMKSQ4Klevxu6gY4gy2USbeZra0fV5SalndmPfsY=
|
||||||
go.mongodb.org/mongo-driver v1.8.3 h1:TDKlTkGDKm9kkJVUOAXDK5/fkqKHJVwYQSpoRfB43R4=
|
go.mongodb.org/mongo-driver v1.8.3 h1:TDKlTkGDKm9kkJVUOAXDK5/fkqKHJVwYQSpoRfB43R4=
|
||||||
go.mongodb.org/mongo-driver v1.8.3/go.mod h1:0sQWfOeY63QTntERDJJ/0SuKK0T1uVSgKCuAROlKEPY=
|
go.mongodb.org/mongo-driver v1.8.3/go.mod h1:0sQWfOeY63QTntERDJJ/0SuKK0T1uVSgKCuAROlKEPY=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
|||||||
91
gs/game/audio_player.go
Normal file
91
gs/game/audio_player.go
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
package game
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"hk4e/pkg/logger"
|
||||||
|
|
||||||
|
"gitlab.com/gomidi/midi/v2"
|
||||||
|
"gitlab.com/gomidi/midi/v2/smf"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
KeyOffset = -12 * 1 // 八度修正偏移
|
||||||
|
)
|
||||||
|
|
||||||
|
var AUDIO_CHAN chan uint32
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
AUDIO_CHAN = make(chan uint32, 1000)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RunPlayAudio() {
|
||||||
|
audio, err := smf.ReadFile("./in.mid")
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("read midi file error: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tempoChangeList := audio.TempoChanges()
|
||||||
|
if len(tempoChangeList) != 1 {
|
||||||
|
logger.Error("midi file format not support")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tempoChange := tempoChangeList[0]
|
||||||
|
metricTicks := audio.TimeFormat.(smf.MetricTicks)
|
||||||
|
tickTime := ((60000000.0 / tempoChange.BPM) / float64(metricTicks.Resolution())) / 1000.0
|
||||||
|
for {
|
||||||
|
// 洗脑循环
|
||||||
|
logger.Debug("start play audio")
|
||||||
|
for _, track := range audio.Tracks {
|
||||||
|
// 全部轨道
|
||||||
|
totalTick := uint64(0)
|
||||||
|
for _, event := range track {
|
||||||
|
// 单个轨道
|
||||||
|
delay := uint32(float64(event.Delta) * tickTime)
|
||||||
|
busyPoolWaitMilliSecond(delay)
|
||||||
|
// interruptWaitMilliSecond(delay)
|
||||||
|
totalTick += uint64(delay)
|
||||||
|
|
||||||
|
msg := event.Message
|
||||||
|
if msg.Type() != midi.NoteOnMsg {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
midiMsg := midi.Message(msg)
|
||||||
|
var channel, key, velocity uint8
|
||||||
|
midiMsg.GetNoteOn(&channel, &key, &velocity)
|
||||||
|
// TODO 测试一下客户端是否支持更宽的音域
|
||||||
|
// 60 -> 中央C C4
|
||||||
|
// if key < 36 || key > 71 {
|
||||||
|
// continue
|
||||||
|
// }
|
||||||
|
note := int32(key) + int32(KeyOffset)
|
||||||
|
if note < 21 || note > 108 {
|
||||||
|
// 非88键钢琴音域
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if velocity == 0 {
|
||||||
|
// 可能是NoteOffMsg
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
AUDIO_CHAN <- uint32(note)
|
||||||
|
// logger.Debug("send midi note: %v, delay: %v, totalTick: %v", note, delay, totalTick)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func interruptWaitMilliSecond(delay uint32) {
|
||||||
|
time.Sleep(time.Millisecond * time.Duration(delay))
|
||||||
|
}
|
||||||
|
|
||||||
|
func busyPoolWaitMilliSecond(delay uint32) {
|
||||||
|
start := time.Now()
|
||||||
|
end := start.Add(time.Millisecond * time.Duration(delay))
|
||||||
|
for {
|
||||||
|
now := time.Now()
|
||||||
|
if now.After(end) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -252,14 +252,14 @@ func (g *GameManager) CommonRetSucc(cmdId uint16, player *model.Player, rsp pb.M
|
|||||||
|
|
||||||
// SendToWorldA 给世界内所有玩家发消息
|
// SendToWorldA 给世界内所有玩家发消息
|
||||||
func (g *GameManager) SendToWorldA(world *World, cmdId uint16, seq uint32, msg pb.Message) {
|
func (g *GameManager) SendToWorldA(world *World, cmdId uint16, seq uint32, msg pb.Message) {
|
||||||
for _, v := range world.playerMap {
|
for _, v := range world.GetAllPlayer() {
|
||||||
GAME_MANAGER.SendMsg(cmdId, v.PlayerID, seq, msg)
|
GAME_MANAGER.SendMsg(cmdId, v.PlayerID, seq, msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendToWorldAEC 给世界内除自己以外的所有玩家发消息
|
// SendToWorldAEC 给世界内除自己以外的所有玩家发消息
|
||||||
func (g *GameManager) SendToWorldAEC(world *World, cmdId uint16, seq uint32, msg pb.Message, uid uint32) {
|
func (g *GameManager) SendToWorldAEC(world *World, cmdId uint16, seq uint32, msg pb.Message, uid uint32) {
|
||||||
for _, v := range world.playerMap {
|
for _, v := range world.GetAllPlayer() {
|
||||||
if uid == v.PlayerID {
|
if uid == v.PlayerID {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,11 @@ import (
|
|||||||
|
|
||||||
// 游戏服务器定时帧管理器
|
// 游戏服务器定时帧管理器
|
||||||
|
|
||||||
|
const (
|
||||||
|
ServerTickTime = 20 // 服务器全局tick最小间隔毫秒
|
||||||
|
UserTickTime = 1000 // 玩家自身tick最小间隔毫秒
|
||||||
|
)
|
||||||
|
|
||||||
type UserTimer struct {
|
type UserTimer struct {
|
||||||
timer *time.Timer
|
timer *time.Timer
|
||||||
action int
|
action int
|
||||||
@@ -33,7 +38,7 @@ type TickManager struct {
|
|||||||
|
|
||||||
func NewTickManager() (r *TickManager) {
|
func NewTickManager() (r *TickManager) {
|
||||||
r = new(TickManager)
|
r = new(TickManager)
|
||||||
r.globalTick = time.NewTicker(time.Millisecond * 100)
|
r.globalTick = time.NewTicker(time.Millisecond * ServerTickTime)
|
||||||
r.globalTickCount = 0
|
r.globalTickCount = 0
|
||||||
r.userTickMap = make(map[uint32]*UserTick)
|
r.userTickMap = make(map[uint32]*UserTick)
|
||||||
logger.Info("game server tick start at: %v", time.Now().UnixMilli())
|
logger.Info("game server tick start at: %v", time.Now().UnixMilli())
|
||||||
@@ -45,7 +50,7 @@ func NewTickManager() (r *TickManager) {
|
|||||||
// CreateUserGlobalTick 创建玩家tick对象
|
// CreateUserGlobalTick 创建玩家tick对象
|
||||||
func (t *TickManager) CreateUserGlobalTick(userId uint32) {
|
func (t *TickManager) CreateUserGlobalTick(userId uint32) {
|
||||||
t.userTickMap[userId] = &UserTick{
|
t.userTickMap[userId] = &UserTick{
|
||||||
globalTick: time.NewTicker(time.Second * 1),
|
globalTick: time.NewTicker(time.Millisecond * UserTickTime),
|
||||||
globalTickCount: 0,
|
globalTickCount: 0,
|
||||||
timerIdCounter: 0,
|
timerIdCounter: 0,
|
||||||
timerMap: make(map[uint64]*UserTimer),
|
timerMap: make(map[uint64]*UserTimer),
|
||||||
@@ -74,11 +79,9 @@ func (t *TickManager) CreateUserTimer(userId uint32, action int, delay uint32) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *TickManager) onUserTickSecond(userId uint32, now int64) {
|
func (t *TickManager) onUserTickSecond(userId uint32, now int64) {
|
||||||
// logger.Info("on user tick second, uid: %v, time: %v", userId, now)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TickManager) onUserTickMinute(userId uint32, now int64) {
|
func (t *TickManager) onUserTickMinute(userId uint32, now int64) {
|
||||||
logger.Info("on user tick minute, uid: %v, time: %v", userId, now)
|
|
||||||
// 每分钟保存玩家数据
|
// 每分钟保存玩家数据
|
||||||
saveUserIdList := []uint32{userId}
|
saveUserIdList := []uint32{userId}
|
||||||
LOCAL_EVENT_MANAGER.localEventChan <- &LocalEvent{
|
LOCAL_EVENT_MANAGER.localEventChan <- &LocalEvent{
|
||||||
@@ -105,32 +108,34 @@ func (t *TickManager) userTimerHandle(userId uint32, action int) {
|
|||||||
func (t *TickManager) OnGameServerTick() {
|
func (t *TickManager) OnGameServerTick() {
|
||||||
t.globalTickCount++
|
t.globalTickCount++
|
||||||
now := time.Now().UnixMilli()
|
now := time.Now().UnixMilli()
|
||||||
t.onTick100MilliSecond(now)
|
if t.globalTickCount%(50/ServerTickTime) == 0 {
|
||||||
if t.globalTickCount%2 == 0 {
|
t.onTick50MilliSecond(now)
|
||||||
|
}
|
||||||
|
if t.globalTickCount%(100/ServerTickTime) == 0 {
|
||||||
|
t.onTick100MilliSecond(now)
|
||||||
|
}
|
||||||
|
if t.globalTickCount%(200/ServerTickTime) == 0 {
|
||||||
t.onTick200MilliSecond(now)
|
t.onTick200MilliSecond(now)
|
||||||
}
|
}
|
||||||
if t.globalTickCount%(10*1) == 0 {
|
if t.globalTickCount%(1000/ServerTickTime) == 0 {
|
||||||
t.onTickSecond(now)
|
t.onTickSecond(now)
|
||||||
}
|
}
|
||||||
if t.globalTickCount%(10*5) == 0 {
|
if t.globalTickCount%(5000/ServerTickTime) == 0 {
|
||||||
t.onTick5Second(now)
|
t.onTick5Second(now)
|
||||||
}
|
}
|
||||||
if t.globalTickCount%(10*10) == 0 {
|
if t.globalTickCount%(10000/ServerTickTime) == 0 {
|
||||||
t.onTick10Second(now)
|
t.onTick10Second(now)
|
||||||
}
|
}
|
||||||
if t.globalTickCount%(10*60) == 0 {
|
if t.globalTickCount%(60000/ServerTickTime) == 0 {
|
||||||
t.onTickMinute(now)
|
t.onTickMinute(now)
|
||||||
}
|
}
|
||||||
if t.globalTickCount%(10*60*10) == 0 {
|
if t.globalTickCount%(60000*60/ServerTickTime) == 0 {
|
||||||
t.onTick10Minute(now)
|
|
||||||
}
|
|
||||||
if t.globalTickCount%(10*3600) == 0 {
|
|
||||||
t.onTickHour(now)
|
t.onTickHour(now)
|
||||||
}
|
}
|
||||||
if t.globalTickCount%(10*3600*24) == 0 {
|
if t.globalTickCount%(60000*60*24/ServerTickTime) == 0 {
|
||||||
t.onTickDay(now)
|
t.onTickDay(now)
|
||||||
}
|
}
|
||||||
if t.globalTickCount%(10*3600*24*7) == 0 {
|
if t.globalTickCount%(60000*60*24*7/ServerTickTime) == 0 {
|
||||||
t.onTickWeek(now)
|
t.onTickWeek(now)
|
||||||
}
|
}
|
||||||
for userId, userTick := range t.userTickMap {
|
for userId, userTick := range t.userTickMap {
|
||||||
@@ -138,11 +143,12 @@ func (t *TickManager) OnGameServerTick() {
|
|||||||
// 跳过还没到时间的定时器
|
// 跳过还没到时间的定时器
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
<-userTick.globalTick.C
|
||||||
userTick.globalTickCount++
|
userTick.globalTickCount++
|
||||||
if userTick.globalTickCount%(10*1) == 0 {
|
if userTick.globalTickCount%(1000/UserTickTime) == 0 {
|
||||||
t.onUserTickSecond(userId, now)
|
t.onUserTickSecond(userId, now)
|
||||||
}
|
}
|
||||||
if userTick.globalTickCount%(10*60) == 0 {
|
if userTick.globalTickCount%(60000/UserTickTime) == 0 {
|
||||||
t.onUserTickMinute(userId, now)
|
t.onUserTickMinute(userId, now)
|
||||||
}
|
}
|
||||||
for timerId, timer := range userTick.timerMap {
|
for timerId, timer := range userTick.timerMap {
|
||||||
@@ -150,6 +156,7 @@ func (t *TickManager) OnGameServerTick() {
|
|||||||
// 跳过还没到时间的定时器
|
// 跳过还没到时间的定时器
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
<-timer.timer.C
|
||||||
timer.timer.Stop()
|
timer.timer.Stop()
|
||||||
delete(userTick.timerMap, timerId)
|
delete(userTick.timerMap, timerId)
|
||||||
t.userTimerHandle(userId, timer.action)
|
t.userTimerHandle(userId, timer.action)
|
||||||
@@ -169,20 +176,10 @@ func (t *TickManager) onTickHour(now int64) {
|
|||||||
logger.Info("on tick hour, time: %v", now)
|
logger.Info("on tick hour, time: %v", now)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TickManager) onTick10Minute(now int64) {
|
|
||||||
for _, world := range WORLD_MANAGER.worldMap {
|
|
||||||
for _, player := range world.playerMap {
|
|
||||||
// 蓝球粉球
|
|
||||||
GAME_MANAGER.AddUserItem(player.PlayerID, []*UserItem{{ItemId: 223, ChangeCount: 1}}, true, 0)
|
|
||||||
GAME_MANAGER.AddUserItem(player.PlayerID, []*UserItem{{ItemId: 224, ChangeCount: 1}}, true, 0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *TickManager) onTickMinute(now int64) {
|
func (t *TickManager) onTickMinute(now int64) {
|
||||||
// GAME_MANAGER.ServerAnnounceNotify(100, "test123")
|
// GAME_MANAGER.ServerAnnounceNotify(100, "test123")
|
||||||
for _, world := range WORLD_MANAGER.worldMap {
|
for _, world := range WORLD_MANAGER.GetAllWorld() {
|
||||||
for _, player := range world.playerMap {
|
for _, player := range world.GetAllPlayer() {
|
||||||
// 随机物品
|
// 随机物品
|
||||||
allItemDataConfig := GAME_MANAGER.GetAllItemDataConfig()
|
allItemDataConfig := GAME_MANAGER.GetAllItemDataConfig()
|
||||||
count := random.GetRandomInt32(0, 4)
|
count := random.GetRandomInt32(0, 4)
|
||||||
@@ -208,131 +205,133 @@ func (t *TickManager) onTickMinute(now int64) {
|
|||||||
GAME_MANAGER.AddUserItem(player.PlayerID, []*UserItem{{ItemId: 201, ChangeCount: 10}}, true, 0)
|
GAME_MANAGER.AddUserItem(player.PlayerID, []*UserItem{{ItemId: 201, ChangeCount: 10}}, true, 0)
|
||||||
GAME_MANAGER.AddUserItem(player.PlayerID, []*UserItem{{ItemId: 202, ChangeCount: 100}}, true, 0)
|
GAME_MANAGER.AddUserItem(player.PlayerID, []*UserItem{{ItemId: 202, ChangeCount: 100}}, true, 0)
|
||||||
GAME_MANAGER.AddUserItem(player.PlayerID, []*UserItem{{ItemId: 203, ChangeCount: 10}}, true, 0)
|
GAME_MANAGER.AddUserItem(player.PlayerID, []*UserItem{{ItemId: 203, ChangeCount: 10}}, true, 0)
|
||||||
|
// 蓝球粉球
|
||||||
|
GAME_MANAGER.AddUserItem(player.PlayerID, []*UserItem{{ItemId: 223, ChangeCount: 1}}, true, 0)
|
||||||
|
GAME_MANAGER.AddUserItem(player.PlayerID, []*UserItem{{ItemId: 224, ChangeCount: 1}}, true, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TickManager) onTick10Second(now int64) {
|
func (t *TickManager) onTick10Second(now int64) {
|
||||||
for _, world := range WORLD_MANAGER.worldMap {
|
for _, world := range WORLD_MANAGER.GetAllWorld() {
|
||||||
for _, scene := range world.sceneMap {
|
for _, scene := range world.GetAllScene() {
|
||||||
for _, player := range scene.playerMap {
|
for _, player := range scene.GetAllPlayer() {
|
||||||
|
|
||||||
sceneTimeNotify := &proto.SceneTimeNotify{
|
sceneTimeNotify := &proto.SceneTimeNotify{
|
||||||
SceneId: player.SceneId,
|
SceneId: player.SceneId,
|
||||||
SceneTime: uint64(scene.GetSceneTime()),
|
SceneTime: uint64(scene.GetSceneTime()),
|
||||||
}
|
}
|
||||||
GAME_MANAGER.SendMsg(cmd.SceneTimeNotify, player.PlayerID, 0, sceneTimeNotify)
|
GAME_MANAGER.SendMsg(cmd.SceneTimeNotify, player.PlayerID, 0, sceneTimeNotify)
|
||||||
|
|
||||||
playerTimeNotify := &proto.PlayerTimeNotify{
|
|
||||||
IsPaused: player.Pause,
|
|
||||||
PlayerTime: uint64(player.TotalOnlineTime),
|
|
||||||
ServerTime: uint64(time.Now().UnixMilli()),
|
|
||||||
}
|
|
||||||
GAME_MANAGER.SendMsg(cmd.PlayerTimeNotify, player.PlayerID, 0, playerTimeNotify)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for _, player := range world.GetAllPlayer() {
|
||||||
|
playerTimeNotify := &proto.PlayerTimeNotify{
|
||||||
|
IsPaused: player.Pause,
|
||||||
|
PlayerTime: uint64(player.TotalOnlineTime),
|
||||||
|
ServerTime: uint64(time.Now().UnixMilli()),
|
||||||
|
}
|
||||||
|
GAME_MANAGER.SendMsg(cmd.PlayerTimeNotify, player.PlayerID, 0, playerTimeNotify)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TickManager) onTick5Second(now int64) {
|
func (t *TickManager) onTick5Second(now int64) {
|
||||||
for _, world := range WORLD_MANAGER.worldMap {
|
for _, world := range WORLD_MANAGER.GetAllWorld() {
|
||||||
if world.IsBigWorld() {
|
if world.IsBigWorld() {
|
||||||
for applyUid := range world.owner.CoopApplyMap {
|
for applyUid := range world.owner.CoopApplyMap {
|
||||||
GAME_MANAGER.UserDealEnterWorld(world.owner, applyUid, true)
|
GAME_MANAGER.UserDealEnterWorld(world.owner, applyUid, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, player := range world.playerMap {
|
// 多人世界其他玩家的坐标位置广播
|
||||||
// 多人世界其他玩家的坐标位置广播
|
worldPlayerLocationNotify := &proto.WorldPlayerLocationNotify{
|
||||||
worldPlayerLocationNotify := &proto.WorldPlayerLocationNotify{
|
PlayerWorldLocList: make([]*proto.PlayerWorldLocationInfo, 0),
|
||||||
PlayerWorldLocList: make([]*proto.PlayerWorldLocationInfo, 0),
|
}
|
||||||
|
for _, worldPlayer := range world.GetAllPlayer() {
|
||||||
|
playerWorldLocationInfo := &proto.PlayerWorldLocationInfo{
|
||||||
|
SceneId: worldPlayer.SceneId,
|
||||||
|
PlayerLoc: &proto.PlayerLocationInfo{
|
||||||
|
Uid: worldPlayer.PlayerID,
|
||||||
|
Pos: &proto.Vector{
|
||||||
|
X: float32(worldPlayer.Pos.X),
|
||||||
|
Y: float32(worldPlayer.Pos.Y),
|
||||||
|
Z: float32(worldPlayer.Pos.Z),
|
||||||
|
},
|
||||||
|
Rot: &proto.Vector{
|
||||||
|
X: float32(worldPlayer.Rot.X),
|
||||||
|
Y: float32(worldPlayer.Rot.Y),
|
||||||
|
Z: float32(worldPlayer.Rot.Z),
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, worldPlayer := range world.playerMap {
|
worldPlayerLocationNotify.PlayerWorldLocList = append(worldPlayerLocationNotify.PlayerWorldLocList, playerWorldLocationInfo)
|
||||||
playerWorldLocationInfo := &proto.PlayerWorldLocationInfo{
|
}
|
||||||
SceneId: worldPlayer.SceneId,
|
GAME_MANAGER.SendToWorldA(world, cmd.WorldPlayerLocationNotify, 0, worldPlayerLocationNotify)
|
||||||
PlayerLoc: &proto.PlayerLocationInfo{
|
|
||||||
Uid: worldPlayer.PlayerID,
|
for _, scene := range world.GetAllScene() {
|
||||||
Pos: &proto.Vector{
|
scenePlayerLocationNotify := &proto.ScenePlayerLocationNotify{
|
||||||
X: float32(worldPlayer.Pos.X),
|
SceneId: scene.id,
|
||||||
Y: float32(worldPlayer.Pos.Y),
|
PlayerLocList: make([]*proto.PlayerLocationInfo, 0),
|
||||||
Z: float32(worldPlayer.Pos.Z),
|
VehicleLocList: make([]*proto.VehicleLocationInfo, 0),
|
||||||
},
|
}
|
||||||
Rot: &proto.Vector{
|
for _, scenePlayer := range scene.GetAllPlayer() {
|
||||||
X: float32(worldPlayer.Rot.X),
|
// 玩家位置
|
||||||
Y: float32(worldPlayer.Rot.Y),
|
playerLocationInfo := &proto.PlayerLocationInfo{
|
||||||
Z: float32(worldPlayer.Rot.Z),
|
Uid: scenePlayer.PlayerID,
|
||||||
},
|
Pos: &proto.Vector{
|
||||||
|
X: float32(scenePlayer.Pos.X),
|
||||||
|
Y: float32(scenePlayer.Pos.Y),
|
||||||
|
Z: float32(scenePlayer.Pos.Z),
|
||||||
|
},
|
||||||
|
Rot: &proto.Vector{
|
||||||
|
X: float32(scenePlayer.Rot.X),
|
||||||
|
Y: float32(scenePlayer.Rot.Y),
|
||||||
|
Z: float32(scenePlayer.Rot.Z),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
worldPlayerLocationNotify.PlayerWorldLocList = append(worldPlayerLocationNotify.PlayerWorldLocList, playerWorldLocationInfo)
|
scenePlayerLocationNotify.PlayerLocList = append(scenePlayerLocationNotify.PlayerLocList, playerLocationInfo)
|
||||||
}
|
// 载具位置
|
||||||
GAME_MANAGER.SendMsg(cmd.WorldPlayerLocationNotify, player.PlayerID, 0, worldPlayerLocationNotify)
|
for _, entityId := range scenePlayer.VehicleInfo.LastCreateEntityIdMap {
|
||||||
|
entity := scene.GetEntity(entityId)
|
||||||
for _, scene := range world.sceneMap {
|
// 确保实体类型是否为载具
|
||||||
scenePlayerLocationNotify := &proto.ScenePlayerLocationNotify{
|
if entity != nil && entity.gadgetEntity != nil && entity.gadgetEntity.gadgetVehicleEntity != nil {
|
||||||
SceneId: scene.id,
|
vehicleLocationInfo := &proto.VehicleLocationInfo{
|
||||||
PlayerLocList: make([]*proto.PlayerLocationInfo, 0),
|
Rot: &proto.Vector{
|
||||||
VehicleLocList: make([]*proto.VehicleLocationInfo, 0),
|
X: float32(entity.rot.X),
|
||||||
}
|
Y: float32(entity.rot.Y),
|
||||||
for _, scenePlayer := range scene.playerMap {
|
Z: float32(entity.rot.Z),
|
||||||
// 玩家位置
|
},
|
||||||
playerLocationInfo := &proto.PlayerLocationInfo{
|
EntityId: entity.id,
|
||||||
Uid: scenePlayer.PlayerID,
|
CurHp: entity.fightProp[uint32(constant.FightPropertyConst.FIGHT_PROP_CUR_HP)],
|
||||||
Pos: &proto.Vector{
|
OwnerUid: entity.gadgetEntity.gadgetVehicleEntity.owner.PlayerID,
|
||||||
X: float32(scenePlayer.Pos.X),
|
Pos: &proto.Vector{
|
||||||
Y: float32(scenePlayer.Pos.Y),
|
X: float32(entity.pos.X),
|
||||||
Z: float32(scenePlayer.Pos.Z),
|
Y: float32(entity.pos.Y),
|
||||||
},
|
Z: float32(entity.pos.Z),
|
||||||
Rot: &proto.Vector{
|
},
|
||||||
X: float32(scenePlayer.Rot.X),
|
UidList: make([]uint32, 0, len(entity.gadgetEntity.gadgetVehicleEntity.memberMap)),
|
||||||
Y: float32(scenePlayer.Rot.Y),
|
GadgetId: entity.gadgetEntity.gadgetVehicleEntity.vehicleId,
|
||||||
Z: float32(scenePlayer.Rot.Z),
|
MaxHp: entity.fightProp[uint32(constant.FightPropertyConst.FIGHT_PROP_MAX_HP)],
|
||||||
},
|
|
||||||
}
|
|
||||||
scenePlayerLocationNotify.PlayerLocList = append(scenePlayerLocationNotify.PlayerLocList, playerLocationInfo)
|
|
||||||
// 载具位置
|
|
||||||
for _, entityId := range scenePlayer.VehicleInfo.LastCreateEntityIdMap {
|
|
||||||
entity := scene.GetEntity(entityId)
|
|
||||||
// 确保实体类型是否为载具
|
|
||||||
if entity != nil && entity.gadgetEntity != nil && entity.gadgetEntity.gadgetVehicleEntity != nil {
|
|
||||||
vehicleLocationInfo := &proto.VehicleLocationInfo{
|
|
||||||
Rot: &proto.Vector{
|
|
||||||
X: float32(entity.rot.X),
|
|
||||||
Y: float32(entity.rot.Y),
|
|
||||||
Z: float32(entity.rot.Z),
|
|
||||||
},
|
|
||||||
EntityId: entity.id,
|
|
||||||
CurHp: entity.fightProp[uint32(constant.FightPropertyConst.FIGHT_PROP_CUR_HP)],
|
|
||||||
OwnerUid: entity.gadgetEntity.gadgetVehicleEntity.owner.PlayerID,
|
|
||||||
Pos: &proto.Vector{
|
|
||||||
X: float32(entity.pos.X),
|
|
||||||
Y: float32(entity.pos.Y),
|
|
||||||
Z: float32(entity.pos.Z),
|
|
||||||
},
|
|
||||||
UidList: make([]uint32, 0, len(entity.gadgetEntity.gadgetVehicleEntity.memberMap)),
|
|
||||||
GadgetId: entity.gadgetEntity.gadgetVehicleEntity.vehicleId,
|
|
||||||
MaxHp: entity.fightProp[uint32(constant.FightPropertyConst.FIGHT_PROP_MAX_HP)],
|
|
||||||
}
|
|
||||||
for _, p := range entity.gadgetEntity.gadgetVehicleEntity.memberMap {
|
|
||||||
vehicleLocationInfo.UidList = append(vehicleLocationInfo.UidList, p.PlayerID)
|
|
||||||
}
|
|
||||||
scenePlayerLocationNotify.VehicleLocList = append(scenePlayerLocationNotify.VehicleLocList, vehicleLocationInfo)
|
|
||||||
}
|
}
|
||||||
|
for _, p := range entity.gadgetEntity.gadgetVehicleEntity.memberMap {
|
||||||
|
vehicleLocationInfo.UidList = append(vehicleLocationInfo.UidList, p.PlayerID)
|
||||||
|
}
|
||||||
|
scenePlayerLocationNotify.VehicleLocList = append(scenePlayerLocationNotify.VehicleLocList, vehicleLocationInfo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GAME_MANAGER.SendMsg(cmd.ScenePlayerLocationNotify, player.PlayerID, 0, scenePlayerLocationNotify)
|
|
||||||
}
|
}
|
||||||
|
GAME_MANAGER.SendToWorldA(world, cmd.ScenePlayerLocationNotify, 0, scenePlayerLocationNotify)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TickManager) onTickSecond(now int64) {
|
func (t *TickManager) onTickSecond(now int64) {
|
||||||
for _, world := range WORLD_MANAGER.worldMap {
|
for _, world := range WORLD_MANAGER.GetAllWorld() {
|
||||||
for _, player := range world.playerMap {
|
for _, player := range world.GetAllPlayer() {
|
||||||
// 世界里所有玩家的网络延迟广播
|
// 世界里所有玩家的网络延迟广播
|
||||||
worldPlayerRTTNotify := &proto.WorldPlayerRTTNotify{
|
worldPlayerRTTNotify := &proto.WorldPlayerRTTNotify{
|
||||||
PlayerRttList: make([]*proto.PlayerRTTInfo, 0),
|
PlayerRttList: make([]*proto.PlayerRTTInfo, 0),
|
||||||
}
|
}
|
||||||
for _, worldPlayer := range world.playerMap {
|
for _, worldPlayer := range world.GetAllPlayer() {
|
||||||
playerRTTInfo := &proto.PlayerRTTInfo{Uid: worldPlayer.PlayerID, Rtt: worldPlayer.ClientRTT}
|
playerRTTInfo := &proto.PlayerRTTInfo{Uid: worldPlayer.PlayerID, Rtt: worldPlayer.ClientRTT}
|
||||||
worldPlayerRTTNotify.PlayerRttList = append(worldPlayerRTTNotify.PlayerRttList, playerRTTInfo)
|
worldPlayerRTTNotify.PlayerRttList = append(worldPlayerRTTNotify.PlayerRttList, playerRTTInfo)
|
||||||
}
|
}
|
||||||
@@ -367,9 +366,9 @@ func (t *TickManager) onTickSecond(now int64) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *TickManager) onTick200MilliSecond(now int64) {
|
func (t *TickManager) onTick200MilliSecond(now int64) {
|
||||||
// 耐力消耗
|
for _, world := range WORLD_MANAGER.GetAllWorld() {
|
||||||
for _, world := range WORLD_MANAGER.worldMap {
|
for _, player := range world.GetAllPlayer() {
|
||||||
for _, player := range world.playerMap {
|
// 耐力消耗
|
||||||
GAME_MANAGER.SustainStaminaHandler(player)
|
GAME_MANAGER.SustainStaminaHandler(player)
|
||||||
GAME_MANAGER.VehicleRestoreStaminaHandler(player)
|
GAME_MANAGER.VehicleRestoreStaminaHandler(player)
|
||||||
GAME_MANAGER.DrownBackHandler(player)
|
GAME_MANAGER.DrownBackHandler(player)
|
||||||
@@ -380,6 +379,20 @@ func (t *TickManager) onTick200MilliSecond(now int64) {
|
|||||||
func (t *TickManager) onTick100MilliSecond(now int64) {
|
func (t *TickManager) onTick100MilliSecond(now int64) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *TickManager) onTick50MilliSecond(now int64) {
|
||||||
|
// 音乐播放器
|
||||||
|
for i := 0; i < len(AUDIO_CHAN); i++ {
|
||||||
|
bigWorld := WORLD_MANAGER.GetBigWorld()
|
||||||
|
GAME_MANAGER.SendToWorldA(bigWorld, cmd.SceneAudioNotify, 0, &proto.SceneAudioNotify{
|
||||||
|
Type: 5,
|
||||||
|
SourceUid: bigWorld.owner.PlayerID,
|
||||||
|
Param1: []uint32{1, <-AUDIO_CHAN},
|
||||||
|
Param2: nil,
|
||||||
|
Param3: nil,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (t *TickManager) createMonster(scene *Scene) uint32 {
|
func (t *TickManager) createMonster(scene *Scene) uint32 {
|
||||||
pos := &model.Vector{
|
pos := &model.Vector{
|
||||||
X: 2747,
|
X: 2747,
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ func (w *WorldManager) GetWorldByID(worldId uint32) *World {
|
|||||||
return w.worldMap[worldId]
|
return w.worldMap[worldId]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *WorldManager) GetWorldMap() map[uint32]*World {
|
func (w *WorldManager) GetAllWorld() map[uint32]*World {
|
||||||
return w.worldMap
|
return w.worldMap
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,6 +90,7 @@ func (w *WorldManager) GetBigWorld() *World {
|
|||||||
func (w *WorldManager) InitBigWorld(owner *model.Player) {
|
func (w *WorldManager) InitBigWorld(owner *model.Player) {
|
||||||
w.bigWorld = w.GetWorldByID(owner.WorldId)
|
w.bigWorld = w.GetWorldByID(owner.WorldId)
|
||||||
w.bigWorld.ChangeToMultiplayer()
|
w.bigWorld.ChangeToMultiplayer()
|
||||||
|
go RunPlayAudio()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *World) IsBigWorld() bool {
|
func (w *World) IsBigWorld() bool {
|
||||||
@@ -115,6 +116,14 @@ type World struct {
|
|||||||
peerList []*model.Player // 玩家编号列表
|
peerList []*model.Player // 玩家编号列表
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *World) GetAllPlayer() map[uint32]*model.Player {
|
||||||
|
return w.playerMap
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *World) GetAllScene() map[uint32]*Scene {
|
||||||
|
return w.sceneMap
|
||||||
|
}
|
||||||
|
|
||||||
func (w *World) GetNextWorldEntityId(entityType uint16) uint32 {
|
func (w *World) GetNextWorldEntityId(entityType uint16) uint32 {
|
||||||
for {
|
for {
|
||||||
w.entityIdCounter++
|
w.entityIdCounter++
|
||||||
@@ -517,6 +526,14 @@ type Scene struct {
|
|||||||
meeoIndex uint32 // 客户端风元素染色同步协议的计数器
|
meeoIndex uint32 // 客户端风元素染色同步协议的计数器
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Scene) GetAllPlayer() map[uint32]*model.Player {
|
||||||
|
return s.playerMap
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Scene) GetAllEntity() map[uint32]*Entity {
|
||||||
|
return s.entityMap
|
||||||
|
}
|
||||||
|
|
||||||
type AvatarEntity struct {
|
type AvatarEntity struct {
|
||||||
uid uint32
|
uid uint32
|
||||||
avatarId uint32
|
avatarId uint32
|
||||||
|
|||||||
@@ -107,6 +107,7 @@ func (c *CmdProtoMap) registerAllMessage() {
|
|||||||
c.registerMessage(ObstacleModifyNotify, &proto.ObstacleModifyNotify{}) // 寻路阻挡变动通知
|
c.registerMessage(ObstacleModifyNotify, &proto.ObstacleModifyNotify{}) // 寻路阻挡变动通知
|
||||||
c.registerMessage(DungeonWayPointNotify, &proto.DungeonWayPointNotify{}) // 地牢副本相关
|
c.registerMessage(DungeonWayPointNotify, &proto.DungeonWayPointNotify{}) // 地牢副本相关
|
||||||
c.registerMessage(DungeonDataNotify, &proto.DungeonDataNotify{}) // 地牢副本相关
|
c.registerMessage(DungeonDataNotify, &proto.DungeonDataNotify{}) // 地牢副本相关
|
||||||
|
c.registerMessage(SceneAudioNotify, &proto.SceneAudioNotify{}) // 场景风物之琴音乐同步通知
|
||||||
|
|
||||||
// 战斗与同步
|
// 战斗与同步
|
||||||
c.registerMessage(AvatarFightPropNotify, &proto.AvatarFightPropNotify{}) // 角色战斗属性通知
|
c.registerMessage(AvatarFightPropNotify, &proto.AvatarFightPropNotify{}) // 角色战斗属性通知
|
||||||
|
|||||||
Reference in New Issue
Block a user