pet_home_server/src/server/game/PlayerChessMod.go
2025-12-09 12:08:44 +08:00

371 lines
12 KiB
Go

package game
import (
"fmt"
"math"
"server/GoUtil"
"server/conf"
mergeDataCfg "server/conf/mergeData"
orderCfg "server/conf/order"
"server/game/mod/item"
"server/game/mod/limitedTimeEvent"
"server/game/mod/order"
"server/game/mod/quest"
"server/msg"
"server/pkg/github.com/name5566/leaf/log"
"sort"
"google.golang.org/protobuf/proto"
)
type PlayerChessData struct {
Data msg.ResPlayerChessData
ColorData msg.ResChessColorData
}
func (p *PlayerChessData) LoadDataFromDB(dwUin interface{}) bool {
return true
}
func (p *PlayerChessData) Reconnect(b bool) {
}
func (p *PlayerChessData) SaveDataFromDB(Key interface{}) bool {
return true
}
func (p *PlayerChessData) ResPlayerChessData(player *Player) {
agent := player.GetAgentByPlayer()
Msg := &p.Data
ChessMod := player.PlayMod.getChessMod()
Msg.ChessList = ChessMod.BackData().ChessList
Msg.MChessData = ChessMod.ChessMap
data, _ := proto.Marshal(Msg)
G_getGameLogic().PackResInfo(agent, "ResPlayerChessData", data)
}
func (p *PlayerChessData) ResChessColorData(player *Player) {
agent := player.GetAgentByPlayer()
data, _ := proto.Marshal(&p.ColorData)
G_getGameLogic().PackResInfo(agent, "ResChessColorData", data)
}
// 同步棋盘数据
func (p *PlayerChessData) UpdatePlayerChessData(player *Player, buf []byte) error {
update := &msg.UpdatePlayerChessData{}
proto.Unmarshal(buf, update)
LastMap := player.PlayMod.getChessMod().ChessMap
AddChessList, AddNewEmit, err := p.HandleChess(player, update.MChessHandle)
if err != nil {
res := &msg.ResUpdatePlayerChessData{
Code: msg.RES_CODE_FAIL,
Msg: err.Error(),
}
HandleStr := ""
sort.Slice(update.MChessHandle, func(i, j int) bool {
return update.MChessHandle[i].Id < update.MChessHandle[j].Id
})
for _, v := range update.MChessHandle {
HandleStr += fmt.Sprintf("%v-%v-%v,", v.Id, v.ChessId, v.Type)
}
log.Debug("棋子操作队列错误, %v===%v===%v===%v", HandleStr, LastMap, update.MChessData, player.PlayMod.getChessMod().GetChessList())
player.SendErrClienRes(res)
return err
}
player.PushClientRes(&msg.ResUpdatePlayerChessData{
Code: msg.RES_CODE_SUCCESS,
})
p.Data.MChessData = update.MChessData
if !p.checkChessEqual(player) {
res := &msg.ResUpdatePlayerChessData{
Code: msg.RES_CODE_FAIL,
Msg: "棋子数据不一致",
}
HandleStr := ""
sort.Slice(update.MChessHandle, func(i, j int) bool {
return update.MChessHandle[i].Id < update.MChessHandle[j].Id
})
for _, v := range update.MChessHandle {
HandleStr += fmt.Sprintf("%v-%v-%v,", v.Id, v.ChessId, v.Type)
}
log.Debug("棋子数据不一致, %v===%v===%v===%v", HandleStr, LastMap, update.MChessData, player.PlayMod.getChessMod().GetChessList())
player.SendErrClienRes(res)
player.TeLog("outsync_event", map[string]interface{}{
"outsync_event": "UpdatePlayerChessDataFunc",
})
return fmt.Errorf("棋子数据不一致")
}
ChessMod := player.PlayMod.getChessMod()
BaseMod := player.PlayMod.getBaseMod()
OrderMod := player.PlayMod.getOrderMod()
ChessMod.ChessMap = update.MChessData
Update := OrderMod.CreateExtraOrder(AddChessList, AddNewEmit, ChessMod.GetUnlockChessList(), BaseMod.GetEnergyMul(), BaseMod.GetLevel())
if Update {
player.InitOrderItem()
player.PushClientRes(OrderMod.BackData())
}
return nil
}
func (p *PlayerChessData) UpdateChessData(player *Player, MChessData map[string]int32) error {
p.Data.MChessData = MChessData
if !p.checkChessEqual(player) {
res := &msg.ResUpdatePlayerChessData{
Code: msg.RES_CODE_FAIL,
Msg: "棋子数据不一致",
}
log.Debug("棋子数据不一致, %v---%v", p.Data.MChessData, player.PlayMod.getChessMod().GetChessList())
player.SendErrClienRes(res)
player.TeLog("outsync_event", map[string]interface{}{
"outsync_event": "UpdatePlayerChessDataFunc",
})
return fmt.Errorf("棋子数据不一致")
}
player.PlayMod.getChessMod().ChessMap = MChessData
return nil
}
// 检查棋子数据是否一致
func (p *PlayerChessData) checkChessEqual(player *Player) bool {
if len(p.Data.MChessData) == 0 && conf.Server.GameName == "Merge_Pet_Local" {
return true
}
ChessList := player.PlayMod.getChessMod().GetChessList()
if len(ChessList) != len(p.Data.MChessData) {
return false
}
aCopy := make([]int, len(ChessList))
bCopy := make([]int, len(p.Data.MChessData))
for _, v := range ChessList {
aCopy = append(aCopy, int(v))
}
for _, v := range p.Data.MChessData {
bCopy = append(bCopy, int(v))
}
return SlicesEqual(aCopy, bCopy)
}
// 棋子操作
func (p *PlayerChessData) HandleChess(player *Player, handle_list []*msg.ChessHandle) ([]int, []int, error) {
sort.Slice(handle_list, func(i, j int) bool {
return handle_list[i].Id < handle_list[j].Id
})
ChessMod := player.PlayMod.getChessMod()
BaseMod := player.PlayMod.getBaseMod()
HandbookMod := player.PlayMod.getHandbookMod()
var addChessCostEnergy int
var buyChess int
LimitPush := false // 限时事件推送
TriggerList := make([]*quest.Trigger, 0)
itemList := make([]*item.Item, 0)
AddChessList := make([]int, 0)
AddNewEmit := make([]int, 0)
EmitList := ChessMod.GetEmitList()
for _, v := range handle_list {
ChessId := int(v.ChessId)
EmitId := int(v.Emit)
switch v.Type {
case msg.HANDLE_TYPE_ADD: //增加棋子
err := ChessMod.AddChess(ChessId)
if err != nil {
return nil, nil, err
}
Type := mergeDataCfg.GetTypeById(ChessId)
AddChessList = append(AddChessList, ChessId)
if !GoUtil.InArray(EmitId, []int{561, 562, 563, 564, 701, 702, 703, 704, 705, 706, 0}) && Type != "Resource" { // 宝箱生成的棋子不扣体力
addChessCostEnergy++
}
b := HandbookMod.SetHandbook(ChessId) // 添加图鉴
if b {
player.TeLog("collection_add", map[string]interface{}{
"item_id": ChessId,
"item_name": mergeDataCfg.GetNameById(ChessId),
})
AddNewEmit = append(AddNewEmit, ChessId)
}
player.PushClientRes(HandbookMod.BackData())
case msg.HANDLE_TYPE_COMPOSE: //合成棋子
NewChessId, err := ChessMod.ComposeChess(ChessId)
if err != nil {
return nil, nil, err
}
HandbookMod := player.PlayMod.getHandbookMod() // 添加图鉴
b := HandbookMod.SetHandbook(NewChessId)
if b {
AddNewEmit = append(AddNewEmit, NewChessId)
}
AddChessList = append(AddChessList, NewChessId)
NewChessIdLv := mergeDataCfg.GetLvById(NewChessId)
TriggerList = append(TriggerList, &quest.Trigger{Label: quest.TRIGGER_LABEL_MERGELVTIME, A: []interface{}{NewChessIdLv}})
TriggerList = append(TriggerList, &quest.Trigger{Label: quest.TRIGGER_LABEL_MERGETIME})
player.PushClientRes(HandbookMod.BackData())
triggerComposeChess(player, NewChessId, player.PlayMod.getBaseMod().EnergyMul, player.PlayMod.getChessMod().GetEmitList())
// 获取活动道具
ActItem := player.GetActivityItem(GoUtil.Int32ToInt(v.ActType))
itemList = item.Merge(itemList, ActItem)
case msg.HANDLE_TYPE_BUY: //购买棋子
loseGold, err := ChessMod.BuyChess(ChessId)
if err != nil {
return nil, nil, err
}
AddChessList = append(AddChessList, ChessId)
buyChess += loseGold
itemList = append(itemList, &item.Item{Id: item.ITEM_STAR_ID, Num: int(-loseGold)})
case msg.HANDLE_TYPE_SELL: //出售棋子
items, err := ChessMod.SellChess(ChessId)
if checkChess(ChessId, BaseMod.GetEnergyMul(), ChessMod.GetEmitList()) { // 在订单中无法生成的棋子 出售获得原价宠物币
items = []*item.Item{{Id: item.ITEM_STAR_ID, Num: mergeDataCfg.GetStarById(ChessId)}}
}
LimitedTimeEventMod := player.PlayMod.getLimitedTimeEventMod()
ChessType := mergeDataCfg.GetTypeById(ChessId)
if LimitedTimeEventMod.CheckExist(limitedTimeEvent.EVENT_TYPE_PAYBACK_DAY) && ChessType == "Product" { // 限时活动 返利日
err = LimitedTimeEventMod.SubPaybackDay()
if err == nil {
items = []*item.Item{{Id: item.ITEM_STAR_ID, Num: mergeDataCfg.GetStarById(ChessId)}}
}
LimitPush = true
}
if err != nil {
return nil, nil, err
}
get_star_num := 0
if len(items) > 0 && items[0].Id == item.ITEM_STAR_ID {
get_star_num = items[0].Num
}
player.TeLog("sell_item", map[string]interface{}{
"merge_item_id": ChessId,
"product_name": mergeDataCfg.GetNameById(ChessId),
"get_star_num": get_star_num,
})
itemList = item.Merge(itemList, items)
case msg.HANDLE_TYPE_REMOVE: //移除棋子
ChessMod.RemoveChess(ChessId)
}
}
//扣除体力
EnergyPow := BaseMod.GetEnergyMul()
ReduceEneny := 0
if addChessCostEnergy > 0 {
ReduceEneny = int(math.Pow(2, float64(EnergyPow))) * addChessCostEnergy
itemList = append(itemList, &item.Item{Id: item.ITEM_ENERGY_ID, Num: -ReduceEneny})
}
err := player.HandleItem(itemList, msg.ITEM_POP_LABEL_HandleChess.String())
if err != nil {
return nil, nil, err
}
NewEmitList := ChessMod.GetEmitList()
EmitProductList := make([]string, 0)
for _, v := range EmitList {
ColorList := mergeDataCfg.GetEmitProduceType(v)
EmitProductList = append(EmitProductList, ColorList...)
}
NewEmitProductList := make([]string, 0)
for _, v := range NewEmitList {
ColorList := mergeDataCfg.GetEmitProduceType(v)
NewEmitProductList = append(NewEmitProductList, ColorList...)
}
OrderMod := player.PlayMod.getOrderMod()
if !GoUtil.SlicesEqualString(EmitProductList, NewEmitProductList) {
// 发射器系列变化,重新洗牌
OrderMod.ResetChessPool()
}
// 限时事件 小猫戏法
LimitedTimeEventMod := player.PlayMod.getLimitedTimeEventMod()
if LimitedTimeEventMod.CheckExist(limitedTimeEvent.EVENT_TYPE_CAT_TRICK) {
LimitedTimeEventMod.AddCatTrickEnergy(ReduceEneny)
LimitPush = true
}
if LimitPush {
player.PushClientRes(LimitedTimeEventMod.BackData())
}
player.QuestTriggerList(TriggerList)
player.EmitRetireTrigger1()
player.InitOrderItem()
player.PushClientRes(ChessMod.BackData())
player.PlayMod.save()
return AddChessList, AddNewEmit, nil
}
func (p *PlayerChessData) ClearData() bool {
return true
}
func checkChess(ChessId, EnergyMul int, Emit []int) bool {
if len(Emit) == 0 {
return false
}
ChessIdLv := mergeDataCfg.GetLvById(ChessId)
ChessIdType := mergeDataCfg.GetTypeById(ChessId)
if ChessIdType != "Product" {
return false
}
ChessIdColor := mergeDataCfg.GetColorById(ChessId)
if ChessIdColor == "Star" || ChessIdColor == "Energy" || ChessIdColor == "Diamond" {
return false
}
EmitId := 0
for _, v := range Emit {
ProduceColor := mergeDataCfg.GetEmitProduceType(v)
if GoUtil.InStringArray(ChessIdColor, ProduceColor) {
EmitId = v
break
}
}
_, Max := getChesslvRange(EmitId, EnergyMul, false)
Adjust := mergeDataCfg.GetAdjust(EmitId, ChessIdColor, EnergyMul)
return ChessIdLv > Max-Adjust
}
func getChesslvRange(Emit int, EnergyMul int, IsCharge bool) (int, int) {
RandEmitLv := mergeDataCfg.GetLvById(Emit)
EmitId := mergeDataCfg.GetEmitId(Emit)
RandMaxLv := mergeDataCfg.GetMaxLvById(Emit)
RandEmitMinLv := mergeDataCfg.GetEmitMinLvById(EmitId)
Ratio := mergeDataCfg.GetEmitRatio(EmitId)
m := int(float64(1+RandEmitLv-RandEmitMinLv) / float64(1+RandMaxLv-RandEmitMinLv) / Ratio * 100)
if IsCharge {
m += 10
}
m = max(1, m)
m = min(100, m)
ChessMinLev := orderCfg.GetLvMin(EnergyMul)
ChessMaxLev := orderCfg.GetLvMax(EnergyMul, m)
return ChessMinLev, ChessMaxLev
}
func triggerComposeChess(player *Player, ChessId, EnergyMul int, Emit []int) {
OrderMod := player.PlayMod.getOrderMod()
if OrderMod.Step < 12 {
return
}
if !checkChess(ChessId, EnergyMul, Emit) {
return
}
ChessMod := player.PlayMod.getChessMod()
ChessList := ChessMod.GetUnlockChessList()
ChessNum := 0
for _, v := range ChessList {
if v == ChessId {
ChessNum++
}
}
OrderNum := 0
for _, v := range OrderMod.GetOrderList() {
if v.Type == order.Clean_Order_type && v.MergeId[0] == ChessId {
OrderNum++
}
}
if OrderNum >= ChessNum {
return
}
OrderMod.CreateCleanOrder2([]int{ChessId})
player.PushClientRes(OrderMod.BackData())
}