Files
bl/logic/service/player/player.go

276 lines
6.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package player
import (
"blazing/common/data"
"blazing/common/data/xmlres"
"blazing/common/socket/errorcode"
"blazing/common/utils"
"blazing/cool"
"blazing/logic/service/common"
"blazing/logic/service/fight/info"
"blazing/logic/service/space"
"sync/atomic"
"blazing/modules/base/service"
blservice "blazing/modules/blazing/service"
"context"
"github.com/antlabs/timer"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/util/gconv"
"github.com/panjf2000/gnet/v2"
)
func ConutPlayer() int {
count := 0
Mainplayer.Range(func(uint32, *Player) bool {
count++
return true // 继续遍历
})
return count
}
var Mainplayer = &utils.SyncMap[uint32, *Player]{} //玩家数据
type OgreInfo struct {
Data [9]OgrePetInfo
}
type OgrePetInfo struct {
Id uint32
ShinyLen uint32 `json:"-" struc:"sizeof=ShinyInfo"`
ShinyInfo []data.GlowFilter `json:"ShinyInfo,omitempty"`
Lv uint32 `struc:"skip"` //等级
Item uint32 `struc:"skip"` //奖励,如果有的话
Ext uint32 `struc:"skip"` //是否变尼尔尼奥
}
func (o *OgrePetInfo) RandSHiny(t int64) {
o.ShinyInfo = make([]data.GlowFilter, 1)
// 假设 t 是包含 ShinyInfo 字段的结构体ShinyInfo 是 GlowFilter 类型的切片
o.ShinyInfo[0] = data.GlowFilter{
// 光晕颜色:白色(十六进制 0xFFFFFF符合 uint32 类型
Color: 65535,
// 透明度0.80.0~1.0 范围内的合理值float64 类型)
Alpha: 0.3,
// 水平模糊量100~255 范围内uint8 类型略高于默认值6
BlurX: 20,
// 垂直模糊量10与 BlurX 对称uint8 类型)
BlurY: 20,
// 发光强度80~255 范围内uint8 类型略高于默认值2
Strength: 1,
// 滤镜应用次数21~3 范围内int 类型非默认值1
Quality: 2,
// 内侧发光truebool 类型,模拟开启内侧发光)
Inner: true,
// 挖空falsebool 类型,保持默认逻辑)
Knockout: false,
// 颜色矩阵:标准 RGBA 矩阵20个uint8符合 [20]uint8 数组类型)
// 矩阵含义R=100%、G=100%、B=100%、A=100%,无颜色偏移
}
o.ShinyInfo[0].ColorMatrixFilter = GenerateRandomOffspringMatrix().Get()
//g.Dump(ttt.ShinyInfo)
// ttt.Shiny = 0 //待确认是否刷新异色
}
type Player struct {
MainConn gnet.Conn
baseplayer
IsLogin bool //是否登录
Done
MapNPC timer.TimeNoder
context.Context
Fightinfo info.Fightinfo //当前邀请的玩家ID
Logintime uint32 //当前登录时间
OgreInfo OgreInfo
Service *blservice.UserService
User *service.BaseSysUserService
// PVP被邀请信息
HavePVPinfo []common.PlayerI
monsters [3]int
//0 无,1可以刷怪,2是切换过地图
Canmon uint32 //可以刷怪
// Changemap bool //是否切换过地图
}
// PlayerOption 定义配置 Player 的函数类型
type PlayerOption func(*Player)
func WithConn(c gnet.Conn) PlayerOption {
return func(p *Player) {
p.MainConn = c
}
}
func (p *Player) UseCoins(t uint32) bool {
if p.Info.Coins < t {
return false
}
return true
}
func (p *Player) UseGold(t uint32) bool {
if p.User.GetGold(uint(p.Info.UserID)) < t {
return false
}
//p.Info.GoldBean = p.Info.GoldBean - t
return true
}
func (p *Player) GetAction() {
}
func (f *Player) InvitePlayer(ff common.PlayerI) {
f.HavePVPinfo = append(f.HavePVPinfo, ff)
tt := common.NewTomeeHeader(2501, f.GetInfo().UserID)
f.SendPack(tt.Pack(&info.NoteInviteToFightOutboundInfo{
UserID: ff.GetInfo().UserID,
Nick: ff.GetInfo().Nick,
Mode: ff.Getfightinfo().Mode,
}))
}
func (p *Player) Getfightinfo() info.Fightinfo {
return p.Fightinfo
}
func (p *Player) QuitFight() {
p.FightC = nil
atomic.StoreUint32(&p.Fightinfo.Mode, 0)
}
func (p *Player) GetSpace() *space.Space {
return space.GetSpace(p.Info.MapID)
}
// 0无战斗1PVP2,BOOS,3PVE
func (p *Player) CanFight() bool {
if len(p.Info.PetList) == 0 {
atomic.StoreUint32(&p.Fightinfo.Mode, 0)
return false
}
if p.FightC != nil {
atomic.StoreUint32(&p.Fightinfo.Mode, 0)
return false
}
// if p.GetSpace().ARENA.ChallengerID == p.Info.UserID || p.GetSpace().ARENA.Id == p.Info.UserID {
// return false
// }
for _, v := range p.Info.PetList {
if v.Hp > 0 { // 只要找到一个血量大于0的宠物就可以战斗
return true
}
}
// 遍历完所有宠物都没有血量大于0的才不能战斗
atomic.StoreUint32(&p.Fightinfo.Mode, 0)
return false
// }
// return false
}
func (p *Player) SendPack(b []byte) error {
if p.MainConn == nil {
return nil
}
_, ok := p.MainConn.Context().(*ClientData)
if ok {
return p.MainConn.Context().(*ClientData).SendPack(b)
}
return nil
}
// 添加物品 返回成功添加的物品
func (p *Player) ItemAdd(ItemId, ItemCnt uint32) (result bool) {
switch ItemId {
case 1: //塞尔豆
p.Info.Coins = p.Info.Coins + ItemCnt
return true
case 3: //累计经验
p.Info.ExpPool = p.Info.ExpPool + ItemCnt
return true
case 5: //金豆ItemAdd
p.User.UpdateGold(p.Info.UserID, int64(ItemCnt*100))
return true
default:
itemx, ok := xmlres.ItemsMAP[int(ItemId)]
if !ok {
cool.Loger.Error(context.TODO(), "物品不存在", ItemId)
t1 := common.NewTomeeHeader(2601, p.Info.UserID)
t1.Result = uint32(errorcode.ErrorCodes.ErrSystemError200007)
p.SendPack(t1.Pack(nil)) //准备包由各自发,因为协议不一样
return false
}
if itemx.Max == 0 {
itemx.Max = 1
}
if p.Service.Item.CheakItem(ItemId)+ItemCnt > uint32(itemx.Max) {
println(p.Info.UserID, "物品超过拥有最大限制", ItemId)
t1 := common.NewTomeeHeader(2601, p.Info.UserID)
t1.Result = uint32(errorcode.ErrorCodes.ErrTooManyOfItem)
p.SendPack(t1.Pack(nil)) //准备包由各自发,因为协议不一样
return false
}
p.Service.Item.UPDATE(ItemId, gconv.Int(ItemCnt))
return true
}
return false
}
func (player1 *Player) Kick() {
if player1.IsLogin {
//取成功,否则创建
//player1.Save() //先保存数据再返回
head := common.NewTomeeHeader(1001, player1.Info.UserID)
head.Result = uint32(errorcode.ErrorCodes.ErrAccountLoggedInElsewhere)
//实际上这里有个问题,会造成重复保存问题
player1.SendPack(head.Pack(nil))
CloseChan := make(chan struct{})
player1.MainConn.CloseWithCallback(func(c gnet.Conn, err error) error {
close(CloseChan)
return nil
})
<-CloseChan
}
}
func (p *Player) Cheak(b error) {
if b != nil {
g.Log().Error(context.Background(), "出现错误", p.Info.UserID, b.Error())
}
}