package game import ( // "server/GoUtil" // "server/MergeConst" "context" "database/sql" "encoding/json" "errors" "fmt" "server/GoUtil" "server/MergeConst" itemCfg "server/conf/item" "server/db" "server/game/mod/item" "server/game/mod/limitedTimeEvent" MsgMod "server/game/mod/msg" "server/game/mod/quest" "server/msg" telog "server/thinkdata" "strconv" "sync" "time" "server/pkg/github.com/name5566/leaf/gate" "server/pkg/github.com/name5566/leaf/log" "server/pkg/github.com/name5566/leaf/timer" "github.com/robfig/cron/v3" "google.golang.org/protobuf/proto" ) // import "reflect" //"fmt" type Player struct { playerdata map[string]PlayerDataModule playerdataIF map[string]interface{} PlayMod PlayerMod M_DwUin int32 agent gate.Agent PAMgr *PlayerActiveMgr lock sync.Mutex stopSignal chan bool Msg map[string]PlayerMsg Trigger []*quest.Trigger MDispatr *timer.Dispatcher McronSave *cron.Cron McronSaveID cron.EntryID msgChan chan *MsgMod.Msg args map[string]interface{} timerList map[string]*timer.Timer stop bool } type PlayerBackUp struct { PlayerBaseData *PlayerBaseData PlayMod []byte } type PlayerMsg struct { F string B []byte } func (p *Player) Stop() { select { case <-p.stopSignal: // 通道已经关闭 return default: close(p.stopSignal) close(p.msgChan) } G_GameLogicPtr.AddLog(&Log{ Uid: p.M_DwUin, Type: LoginOut_log, }) p.McronSave.Stop() p.stop = true } func (p *Player) CallEvent(Duration time.Duration, F func(), Label string) { log.Debug("CallEvent:%s", Label) if v, ok := p.timerList[Label]; ok { v.Stop() } t := p.MDispatr.AfterFunc(Duration, F) p.timerList[Label] = t } // 异步请求 func (p *Player) Send(m *MsgMod.Msg) { p.msgChan <- m } func (p *Player) Call(m MsgMod.Msg) { HandleMsg(p, &m) } func (p *Player) SendClientRes() { for _, v := range p.Msg { G_GameLogicPtr.PackResInfo(p.GetAgent(), v.F, v.B) } p.Msg = make(map[string]PlayerMsg) } func (p *Player) PushClientRes(m proto.Message) { key := GetStructName(m) buff, _ := proto.Marshal(m) p.Msg[key] = PlayerMsg{ F: key, B: buff, } } func (p *Player) PushAndSendClienRes(m proto.Message) { key := GetStructName(m) buff, _ := proto.Marshal(m) G_GameLogicPtr.PackResInfo(p.GetAgent(), key, buff) } func (p *Player) SendErrClienRes(m proto.Message) { key := GetStructName(m) buff, _ := proto.Marshal(m) G_GameLogicPtr.PackResInfo(p.GetAgent(), key, buff) } func (p *Player) QuestTrigger(tr *quest.Trigger) { p.Trigger = append(p.Trigger, tr) } func (p *Player) QuestTriggerList(tr []*quest.Trigger) { p.Trigger = append(p.Trigger, tr...) } func (p *Player) ProcessTrigger() { IsDailyBack := false DailyTaskMod := p.PlayMod.getDailyTaskMod() for _, tr := range p.Trigger { if DailyTaskMod.Trigger(tr) { IsDailyBack = true } } if IsDailyBack { p.PushClientRes(DailyTaskMod.BackData()) } p.Trigger = make([]*quest.Trigger, 0) } // 接口请求之前备份数据 func (p *Player) BackUp() *PlayerBackUp { BackUp := PlayerBackUp{} p.PlayMod.BackUp(&BackUp) BackUp.PlayerBaseData = p.GetPlayerBaseMod().BackUp() return &BackUp } // 接口发生错误时 还原数据 func (p *Player) Recover(backUp *PlayerBackUp) { backUp.PlayerBaseData.PlayerData = NewPlayerData(PLAYER_BASE_DATA, p) p.playerdata[PLAYER_BASE_DATA] = backUp.PlayerBaseData p.playerdataIF[PLAYER_BASE_DATA] = backUp.PlayerBaseData p.PlayMod.Recover(backUp) p.Msg = make(map[string]PlayerMsg) } func (p *Player) InitPlayer(UserName string) error { p.lock.Lock() defer p.lock.Unlock() p.msgChan = make(chan *MsgMod.Msg, 100) p.Msg = make(map[string]PlayerMsg) p.args = make(map[string]interface{}) p.timerList = make(map[string]*timer.Timer) p.MDispatr = timer.NewDispatcher(10) p.stopSignal = make(chan bool) p.playerdata = make(map[string]PlayerDataModule) p.playerdataIF = make(map[string]interface{}) Base := &PlayerBaseData{PlayerData: NewPlayerData(PLAYER_BASE_DATA, p)} p.playerdata[PLAYER_BASE_DATA] = Base p.playerdataIF[PLAYER_BASE_DATA] = Base // 玩家基础数据 ok := Base.LoadDataFromDB(UserName) if !ok { log.Debug("load PlayerBaseData failed:", UserName) return errors.New("load PlayerBaseData failed") } p.playerdata[PLAYER_BASE_DATA] = Base p.playerdataIF[PLAYER_BASE_DATA] = Base p.M_DwUin = Base.Data.DwUin // 发射器解锁数据 unlock := &PlayerEmitUnlockData{PlayerData: NewPlayerData("PlayerEmitUnlockData", p)} ok = unlock.LoadDataFromDB(Base.Data.DwUin) if !ok { log.Debug("load PlayerEmitUnlockData failed:", UserName) return errors.New("load PlayerEmitUnlockData failed") } p.playerdata["PlayerEmitUnlockData"] = unlock p.playerdataIF["PlayerEmitUnlockData"] = unlock // 发射器数据 Detail := &PlayerEmitDetailData{PlayerData: NewPlayerData("PlayerEmitDetailData", p)} ok = Detail.LoadDataFromDB(Base.Data.DwUin) if !ok { log.Debug("load PlayerEmitDetailData failed! username: %s", UserName) return errors.New("load PlayerEmitDetailData failed") } p.playerdata["PlayerEmitDetailData"] = Detail p.playerdataIF["PlayerEmitDetailData"] = Detail G_getGameLogic().Mlogger.Debug("load PlayerEmitDetailData:", Base.Data.DwUin) // 棋盘数据 Chess := &PlayerChessData{PlayerData: NewPlayerData("PlayerChessData", p)} ok = Chess.LoadDataFromDB(Base.Data.DwUin) if !ok { log.Debug("load PlayerChessData failed:", UserName) return errors.New("load PlayerChessData failed") } p.playerdata["PlayerChessData"] = Chess p.playerdataIF["PlayerChessData"] = Chess // 玩家解锁宝箱数据 Chest := &PlayerUnlockingChestData{PlayerData: NewPlayerData("PlayerUnlockingChestData", p)} ok = Chest.LoadDataFromDB(Base.Data.DwUin) if !ok { log.Debug("load PlayerUnlockingChestData failed:", UserName) return errors.New("load PlayerUnlockingChestData failed") } p.playerdata["PlayerUnlockingChestData"] = Chest p.playerdataIF["PlayerUnlockingChestData"] = Chest // 玩家解锁宝箱数据 Single := &PlayerSingleData{PlayerData: NewPlayerData("PlayerSingleData", p)} ok = Single.LoadDataFromDB(Base.Data.DwUin) if !ok { log.Debug("load PlayerSingleData failed:", UserName) return errors.New("load PlayerSingleData failed") } p.playerdata["PlayerSingleData"] = Single p.playerdataIF["PlayerSingleData"] = Single // 玩家订单数据 Charge := &PlayerChargeData{PlayerData: NewPlayerData("PlayerChargeData", p)} ok = Charge.LoadDataFromDB(Base.Data.DwUin) if !ok { log.Debug("load PlayerChargeData failed:", UserName) return errors.New("load PlayerChargeData failed") } p.playerdata["PlayerChargeData"] = Charge p.playerdataIF["PlayerChargeData"] = Charge // 玩家好友数据 friendEvt := &PlayerFriendEventData{PlayerData: NewPlayerData("PlayerFriendEventData", p)} ok = friendEvt.LoadDataFromDB(Base.Data.DwUin) if !ok { log.Debug("load PlayerFriendEventData failed:", UserName) return errors.New("load PlayerFriendEventData failed") } p.playerdata["PlayerFriendEventData"] = friendEvt p.playerdataIF["PlayerFriendEventData"] = friendEvt // 玩家模块数据 modData := &PlayerModData{PlayerData: NewPlayerData("PlayerModData", p)} ok = modData.LoadDataFromDB(Base.Data.DwUin) if !ok { log.Debug("load PlayerModData failed:", UserName) return errors.New("load PlayerModData failed") } IsUpdate, err := modData.InitMod() if err != nil { log.Debug("InitMod failed:", err) return err } p.PlayMod.mod_list = modData.ModList p.PlayMod.is_update = IsUpdate p.PAMgr = new(PlayerActiveMgr) p.PAMgr.InitActiveMgr(p) go func() { // 处理数据回调 var cb *timer.Timer for { select { case <-p.stopSignal: return case cb = <-p.MDispatr.ChanTimer: if cb != nil { cb.Cb() } else { log.Debug("Timer callback or Timer is nil") } case msg := <-p.msgChan: fmt.Println("player recive msg:", msg) go HandleMsg(p, msg) } } }() p.McronSave = cron.New() _, err = p.McronSave.AddFunc("@every 1m", p.AutoSaveData) if err != nil { log.Debug("AddFunc failed:", err) } p.McronSave.Start() p.ZeroUpdate(nil) p.NoonUpdate(nil) p.Login() p.LoginBackData() GoUtil.RegisterEvent(MergeConst.Notify_Daily_Renew, p.ZeroUpdate, p) GoUtil.RegisterEvent(MergeConst.Notify_Midday_Renew, p.ZeroUpdate, p) SyncFriendMsg(p) return nil } // 异步发送消息 func (p *Player) SendMsg(m *MsgMod.Msg) { p.msgChan <- m } func (p *Player) Test() { p.PlayMod.getBaseMod().EnergyMul = 100 } // 零点更新 func (p *Player) ZeroUpdate(a []interface{}) { VarMod := p.PlayMod.getVarMod() zeroTimestamp := GoUtil.ZeroTimestamp() PlayerBaseMod := p.GetPlayerBaseMod() // 零点更新 if VarMod.DailyResetTime < zeroTimestamp { VarMod.DailyResetTime = zeroTimestamp VarMod.DailyVar = make(map[int]interface{}) //卡牌 p.PlayMod.getCardMod().ZeroUpdate() p.PushClientRes(p.PlayMod.getCardMod().BackData()) // 每日任务 p.PlayMod.getDailyTaskMod().ZeroUpdate(p.GetPlayerBaseMod().GetLevel(), p.PlayMod.getDecorateMod().GetAreaId()) p.PushClientRes(p.PlayMod.getDailyTaskMod().BackData()) // 能量商店 p.PlayMod.getBaseMod().ZeroUpdate() p.PushClientRes(p.PlayMod.getBaseMod().BackData()) // 七日签到 p.PlayMod.getSevenLoginMod().ZeroUpdate(PlayerBaseMod.GetSevenLoginAdd(), PlayerBaseMod.GetLastLoginTime()) p.PushClientRes(p.PlayMod.getSevenLoginMod().BackData()) // 礼包充值 ChessMod := p.PlayMod.getChessMod() p.PlayMod.getChargeMod().ZeroUpdate(ChessMod.GetEmitList()) p.PushClientRes(p.PlayMod.getChargeMod().BackData()) // 无尽礼包 p.PlayMod.getEndlessMod().ZeroUpdate(p.PlayMod.getChargeMod().GetMaxCharge()) p.PushClientRes(p.PlayMod.getEndlessMod().BackData()) p.PlayMod.getChampshipMod().ZeroUpdate() p.PlayMod.save() } // 周更新 weekZeroTimestamp := GoUtil.WeekZeroTimestamp() if VarMod.WeeklyResetTime < weekZeroTimestamp { VarMod.WeeklyResetTime = weekZeroTimestamp VarMod.WeeklyVar = make(map[int]interface{}) p.PlayMod.getDailyTaskMod().WeekUpdate() p.PushClientRes(p.PlayMod.getDailyTaskMod().BackData()) p.PlayMod.getLimitedTimeEventMod().WeekUpdate() p.PlayMod.save() } } // 十二点更新 func (p *Player) NoonUpdate(a []interface{}) { VarMod := p.PlayMod.getVarMod() noonTimestamp := GoUtil.NoonTimestamp() // 零点更新 if VarMod.NoonResetTime < noonTimestamp { VarMod.NoonResetTime = noonTimestamp ChessMod := p.PlayMod.getChessMod() // 礼包充值 p.PlayMod.getChargeMod().NoonUpdate(ChessMod.GetEmitList()) p.PushClientRes(p.PlayMod.getChargeMod().BackData()) p.PlayMod.save() } } func (p *Player) Login() { // 添加定时器 // 限时事件触发 LimitedTimeEventTrigger(p, 0) // 猪猪银行触发 LimitedTimePiggyBankTrigger(p) p.PlayMod.getCardMod().Login(G_GameLogicPtr.SeverInfo.OpenTime) } // 离线 保存数据 func (p *Player) ClearData() { p.lock.Lock() defer p.lock.Unlock() log.Release("uid: %d, ClearData", p.M_DwUin) for k, v := range p.playerdata { if k == PLAYER_BASE_DATA || k == "PlayerChessData" { v.ClearData() } } p.PlayMod.ClearData(p) GoUtil.RemoveEvent(MergeConst.Notify_Daily_Renew, p.ZeroUpdate, p) p.Stop() } func (p *Player) AutoSaveData() { //保存数据 ctx := context.Background() txOptions := &sql.TxOptions{} tx, err := db.SqlDb.BeginTx(ctx, txOptions) if err != nil { log.Debug("AutoSaveData BeginTx failed:", err) return } for _, v := range p.playerdata { v.SaveDataFromDB("") } p.PlayMod.ClearData(p) tx.Commit() } // 重新连接 func (p *Player) Reconnect() { for _, v := range p.playerdata { v.Reconnect(true) } p.LoginBackData() } // 获取conn连接 func (p *Player) GetAgent() gate.Agent { return p.agent } // 设置conn连接 func (p *Player) SetAgent(a gate.Agent) { p.agent = a } func (p *Player) GetIFGameData(key string) interface{} { v, ok := p.playerdataIF[key] if ok { return v } return nil } func (p *Player) GetPlayerBaseMod() *PlayerBaseData { v, ok := p.playerdataIF[PLAYER_BASE_DATA] if ok { return v.(*PlayerBaseData) } return nil } func (p *Player) GetGameData(key string) PlayerDataModule { v, ok := p.playerdata[key] if ok { return v } return nil } func (p *Player) GetGameMod(key string) interface{} { v, ok := p.playerdata[key] if ok { return v } return nil } func (p *Player) GetAgentByPlayer() gate.Agent { return p.agent } // 处理物品 func (p *Player) HandleItem(itemList []*item.Item, Label string) error { if len(itemList) == 0 { return nil } is_update := false ResCard := make([]*msg.CardPack, 0) ResItem := make([]*msg.ItemInfo, 0) for _, v := range itemList { if v.Num == 0 { continue } if v.Num > 0 && Label != "" { ResItem = append(ResItem, &msg.ItemInfo{Id: int32(v.Id), Num: int32(v.Num)}) } var change_type string if v.Num < 0 { change_type = "gain" } else { change_type = "consume" } IType := itemCfg.GetItemType(v.Id) switch IType { case item.ITEM_TYPE_ENERGY: // 能量 err := p.GetPlayerBaseMod().AddEnergy(v.Num) p.TeLog("asset_change", map[string]interface{}{ "item_id": v.Id, "change_type": change_type, "change_num": v.Num, "change_after": p.GetPlayerBaseMod().GetEnergy(), }) is_update = true if err != nil { return err } case item.ITEM_TYPE_STAR: // 星星 err := p.GetPlayerBaseMod().AddStar(v.Num) is_update = true if err != nil { return err } p.TeLog("asset_change", map[string]interface{}{ "item_id": v.Id, "change_type": change_type, "change_num": v.Num, "change_after": p.GetPlayerBaseMod().GetStar(), }) case item.ITEM_TYPE_DIAMOND: // 钻石 err := p.GetPlayerBaseMod().AddDiamond(v.Num) is_update = true if err != nil { return err } p.TeLog("asset_change", map[string]interface{}{ "item_id": v.Id, "change_type": change_type, "change_num": v.Num, "change_after": p.GetPlayerBaseMod().GetDiamond(), }) case item.ITEM_TYPE_CARD_PACK: // 卡包 CardMod := p.PlayMod.getCardMod() Effect := itemCfg.GetItemEffect(v.Id) for i := 0; i < v.Num; i++ { NewCard, err := CardMod.OpenCardPack(Effect) if err != nil { return err } ResCard = append(ResCard, &msg.CardPack{Id: int32(v.Id), Card: GoUtil.SliceIntToInt32(NewCard)}) } case item.ITEM_TYPE_MASTER_CARD: // 万能卡 CardMod := p.PlayMod.getCardMod() Effect := itemCfg.GetItemEffect(v.Id) for i := 0; i < v.Num; i++ { CardMod.AddMasterCard(Effect) } p.PushClientRes(CardMod.BackData()) case item.ITEM_TYPE_CHESS: // 棋子 ChessMod := p.PlayMod.getChessMod() for i := 0; i < v.Num; i++ { ChessMod.AddChessBuff(v.Id) } p.PushClientRes(ChessMod.BackData()) case item.ITEM_TYPE_LIMIED_TIME_EVENT: // 限时事件 EffectList := itemCfg.GetItemEffectList(v.Id) LimitedTimeEventMod := p.PlayMod.getLimitedTimeEventMod() if len(EffectList) < 2 { log.Debug("Effect List error;item id :%d", v.Id) continue } EndTime := LimitedTimeEventMod.AddEvent(EffectList[0], EffectList[1]) p.PushClientRes(&msg.LimitEventNotify{ Id: int32(EffectList[0]), Type: limitedTimeEvent.EVENT_NOTIFY_TYPE_ADD, EndTime: int32(EndTime), Cd: int32(EffectList[1]), }) LimitedTimeEventTrigger(p, EffectList[0]) case item.ITEM_TYPE_PIGGY_BANK: // 猪猪银行 PiggyBankMod := p.PlayMod.getPiggyBankMod() Effect := itemCfg.GetItemEffect(v.Id) PiggyBankMod.AddPiggyBank(Effect) LimitedTimePiggyBankTrigger(p) p.PushClientRes(PiggyBankMod.BackData()) default: log.Debug("Item type error;item id :%d", v.Id) } } ResItemPopId := 0 if v, ok := p.args["ResItemPopId"]; ok { ResItemPopId = v.(int) } if len(ResItem) != 0 || len(ResCard) != 0 { p.SendErrClienRes(&msg.ResItemPop{ Id: int32(ResItemPopId), Items: ResItem, CardPacks: ResCard, Lable: Label, }) } CardMod := p.PlayMod.getCardMod() p.PushClientRes(CardMod.NotifyCard()) if is_update { p.PushClientRes(p.GetPlayerBaseMod().BackAsset()) } return nil } // 登录返回数据 func (p *Player) LoginBackData() { p.PushClientRes(p.PlayMod.mod_list.Base.BackData()) p.PushClientRes(p.PlayMod.mod_list.Handbook.BackData()) p.PushClientRes(p.PlayMod.mod_list.Base.BackData()) p.PushClientRes(p.PlayMod.mod_list.Chess.BackData()) p.PushClientRes(p.PlayMod.mod_list.Order.BackData()) p.PushClientRes(p.PlayMod.mod_list.Card.BackData()) p.PushClientRes(p.PlayMod.mod_list.Decorate.BackData()) p.PushClientRes(p.PlayMod.mod_list.DailyTask.BackData()) p.PushClientRes(p.PlayMod.mod_list.SevenLogin.BackData()) p.PushClientRes(p.PlayMod.mod_list.Activity.BackData()) p.PushClientRes(p.PlayMod.mod_list.LimitedTimeEvent.ProgressBackData()) p.PushClientRes(p.PlayMod.mod_list.Charge.BackData()) p.PushClientRes(p.PlayMod.mod_list.Endless.BackData()) p.PushClientRes(p.PlayMod.mod_list.PiggyBank.BackData()) p.PushClientRes(p.GetPlayerBaseMod().BackAsset()) p.PushClientRes(p.GetPlayerBaseMod().BackKv()) BackChampship(p) BackUserInfo(p) } // 获取玩家简单数据 func (p *Player) GetSimpleData(Uid int, simple *PlayerSimpleData) error { p.lock.Lock() defer p.lock.Unlock() p.Msg = make(map[string]PlayerMsg) p.args = make(map[string]interface{}) p.timerList = make(map[string]*timer.Timer) p.MDispatr = timer.NewDispatcher(10) p.stopSignal = make(chan bool) p.playerdata = make(map[string]PlayerDataModule) p.playerdataIF = make(map[string]interface{}) Base := &PlayerBaseData{PlayerData: NewPlayerData(PLAYER_BASE_DATA, p)} p.playerdata[PLAYER_BASE_DATA] = Base p.playerdataIF[PLAYER_BASE_DATA] = Base // 玩家基础数据 ok := Base.GetDataByUid(Uid) if !ok { return errors.New("load PlayerBaseData failed") } p.playerdata[PLAYER_BASE_DATA] = Base p.playerdataIF[PLAYER_BASE_DATA] = Base p.M_DwUin = Base.Data.DwUin // 玩家模块数据 modData := &PlayerModData{PlayerData: NewPlayerData("PlayerModData", p)} ok = modData.LoadDataFromDB(Base.Data.DwUin) if !ok { return errors.New("load PlayerModData failed") } modData.InitMod() p.PlayMod.mod_list = modData.ModList simple.Name = p.GetPlayerBaseMod().GetName() simple.Avatar = p.PlayMod.getAvatarMod().SetId simple.Face = p.PlayMod.getFaceMod().SetId simple.Level = p.GetPlayerBaseMod().GetLevel() simple.Decorate = p.PlayMod.getDecorateMod().DecorateNum simple.Login = int64(Base.Data.LoginTime) simple.Loginout = int64(Base.Data.LogoutTime) simple.FaceBook = Base.Data.FaceBookId return nil } func (p *Player) UpdateUserInfo() { simple := &PlayerSimpleData{} Base := p.GetPlayerBaseMod() simple.Name = p.GetPlayerBaseMod().GetName() simple.Avatar = p.PlayMod.getAvatarMod().SetId simple.Uid = int(p.M_DwUin) simple.Face = p.PlayMod.getFaceMod().SetId simple.Level = p.GetPlayerBaseMod().GetLevel() simple.Decorate = p.PlayMod.getDecorateMod().DecorateNum simple.Login = int64(Base.Data.LoginTime) simple.Loginout = int64(Base.Data.LogoutTime) simple.FaceBook = Base.Data.FaceBookId value, _ := json.Marshal(simple) IdStr := strconv.Itoa(int(p.M_DwUin)) db.RedisSetKey(IdStr, string(value), 0) } func (p *Player) HandleInUserRank() { DecorateMod := p.PlayMod.getDecorateMod() AreaId := DecorateMod.GetAreaId() Progress := DecorateMod.GetProgress() Score := float64(AreaId*1000 + Progress) // 更新排行榜 m := &MsgMod.Msg{ Type: MsgMod.HANDLE_TYPE_RANK, SendT: GoUtil.Now(), Extra: RankMsg{ Uid: int(p.M_DwUin), Score: Score, RankType: RANK_TYPE_USER, }, } G_GameLogicPtr.RankMgrSend(m) } func (p *Player) HandleInChampshipRank() { ChampshipMod := p.PlayMod.getChampshipMod() Score := float64(ChampshipMod.GetScore()) // 更新排行榜 m := &MsgMod.Msg{ Type: MsgMod.HANDLE_TYPE_CHAMPSHIP_INRANK, SendT: GoUtil.Now(), Extra: CRank{ Uid: int(p.M_DwUin), Score: Score, H: ChampshipMod.GetH(), N: ChampshipMod.GetN(), }, } G_GameLogicPtr.ChampshipMgrSend(m) } func (p *Player) AddLog(Uid int, Type int, Param string) { FriendMod := p.PlayMod.getFriendMod() Id := FriendMod.AddLog(Uid, Type, Param) p.PlayMod.save() p.PushClientRes(&msg.NotifyFriendLog{ Info: &msg.ResFriendLog{ Player: G_GameLogicPtr.GetResSimplePlayerByUid(Uid), Type: int32(Type), Param: Param, Id: int32(Id), Time: int32(GoUtil.Now()), }, }) } func (p *Player) TeLog(Type string, Param map[string]interface{}) { telog.Te.Track(p.GetPlayerBaseMod().GetName(), p.GetPlayerBaseMod().GetName(), Type, Param) }