diff --git a/common/constant/gadget_state.go b/common/constant/gadget_state.go new file mode 100644 index 00000000..163c8ca4 --- /dev/null +++ b/common/constant/gadget_state.go @@ -0,0 +1,24 @@ +package constant + +const ( + GADGET_STATE_DEFAULT = 0 + GADGET_STATE_GATHER_DROP = 1 + GADGET_STATE_CHEST_LOCKED = 101 + GADGET_STATE_CHEST_OPENED = 102 + GADGET_STATE_CHEST_TRAP = 103 + GADGET_STATE_CHEST_BRAMBLE = 104 + GADGET_STATE_CHEST_FROZEN = 105 + GADGET_STATE_CHEST_ROCK = 106 + GADGET_STATE_GEAR_START = 201 + GADGET_STATE_GEAR_STOP = 202 + GADGET_STATE_GEAR_ACTION1 = 203 + GADGET_STATE_GEAR_ACTION2 = 204 + GADGET_STATE_CRYSTAL_RESONATE1 = 301 + GADGET_STATE_CRYSTAL_RESONATE2 = 302 + GADGET_STATE_CRYSTAL_EXPLODE = 303 + GADGET_STATE_CRYSTAL_DRAIN = 304 + GADGET_STATE_STATUE_ACTIVE = 401 + GADGET_STATE_ACTION01 = 901 + GADGET_STATE_ACTION02 = 902 + GADGET_STATE_ACTION03 = 903 +) diff --git a/dispatch/controller/controller.go b/dispatch/controller/controller.go index 7552acec..a531359c 100644 --- a/dispatch/controller/controller.go +++ b/dispatch/controller/controller.go @@ -2,6 +2,7 @@ package controller import ( "context" + "net" "net/http" "strconv" @@ -47,7 +48,17 @@ func NewController(dao *dao.Dao, discovery *rpc.DiscoveryClient) (r *Controller) func (c *Controller) authorize() gin.HandlerFunc { return func(context *gin.Context) { - if context.Query("key") == "flswld" { + addr := context.ClientIP() + if addr == "" { + addr = context.Request.RemoteAddr + } + ip := net.ParseIP(addr) + ipv4 := ip.To4() + if ip.IsLoopback() || + ipv4[0] == 10 || + ipv4[0] == 169 && ipv4[1] == 254 || + ipv4[0] == 172 && ipv4[1] >= 16 && ipv4[1] <= 31 || + ipv4[0] == 192 && ipv4[1] == 168 { context.Next() return } diff --git a/gate/net/session.go b/gate/net/session.go index 1bc92f70..c7a7a973 100644 --- a/gate/net/session.go +++ b/gate/net/session.go @@ -321,7 +321,7 @@ func (k *KcpConnectManager) getPlayerToken(req *proto.GetPlayerTokenReq, session } } tokenVerifyRsp, err := httpclient.PostJson[controller.TokenVerifyRsp]( - config.GetConfig().Hk4e.LoginSdkUrl+"/gate/token/verify?key=flswld", + config.GetConfig().Hk4e.LoginSdkUrl+"/gate/token/verify", &controller.TokenVerifyReq{ AccountId: req.AccountUid, AccountToken: req.AccountToken, diff --git a/gdconf/avatar_costume_data.go b/gdconf/avatar_costume_data.go index 63eae155..9ece28fe 100644 --- a/gdconf/avatar_costume_data.go +++ b/gdconf/avatar_costume_data.go @@ -13,13 +13,12 @@ type AvatarCostumeData struct { func (g *GameDataConfig) loadAvatarCostumeData() { g.AvatarCostumeDataMap = make(map[int32]*AvatarCostumeData) avatarCostumeDataList := make([]*AvatarCostumeData, 0) - readTable[AvatarCostumeData](g.tablePrefix+"AvatarCostumeData.txt", &avatarCostumeDataList) + readTable[AvatarCostumeData](g.txtPrefix+"AvatarCostumeData.txt", &avatarCostumeDataList) for _, avatarCostumeData := range avatarCostumeDataList { // 屏蔽默认时装 if avatarCostumeData.ItemID == 0 { continue } - // list -> map g.AvatarCostumeDataMap[avatarCostumeData.CostumeID] = avatarCostumeData } logger.Info("AvatarCostumeData count: %v", len(g.AvatarCostumeDataMap)) diff --git a/gdconf/avatar_data.go b/gdconf/avatar_data.go index f591a74e..5ab058ec 100644 --- a/gdconf/avatar_data.go +++ b/gdconf/avatar_data.go @@ -43,7 +43,7 @@ type ConfigAvatarAbility struct { func (g *GameDataConfig) loadAvatarData() { g.AvatarDataMap = make(map[int32]*AvatarData) avatarDataList := make([]*AvatarData, 0) - readTable[AvatarData](g.tablePrefix+"AvatarData.txt", &avatarDataList) + readTable[AvatarData](g.txtPrefix+"AvatarData.txt", &avatarDataList) for _, avatarData := range avatarDataList { // 读取战斗config解析技能并转化为哈希码 fileData, err := os.ReadFile(g.jsonPrefix + "avatar/" + avatarData.ConfigJson + ".json") @@ -72,7 +72,6 @@ func (g *GameDataConfig) loadAvatarData() { avatarData.PromoteRewardMap[uint32(promoteLevel)] = uint32(rewardId) } } - // list -> map g.AvatarDataMap[avatarData.AvatarId] = avatarData } logger.Info("AvatarData count: %v", len(g.AvatarDataMap)) diff --git a/gdconf/avatar_flycloak_data.go b/gdconf/avatar_flycloak_data.go index cbc3e326..71c413f2 100644 --- a/gdconf/avatar_flycloak_data.go +++ b/gdconf/avatar_flycloak_data.go @@ -13,9 +13,8 @@ type AvatarFlycloakData struct { func (g *GameDataConfig) loadAvatarFlycloakData() { g.AvatarFlycloakDataMap = make(map[int32]*AvatarFlycloakData) avatarFlycloakDataList := make([]*AvatarFlycloakData, 0) - readTable[AvatarFlycloakData](g.tablePrefix+"AvatarFlycloakData.txt", &avatarFlycloakDataList) + readTable[AvatarFlycloakData](g.txtPrefix+"AvatarFlycloakData.txt", &avatarFlycloakDataList) for _, avatarFlycloakData := range avatarFlycloakDataList { - // list -> map g.AvatarFlycloakDataMap[avatarFlycloakData.FlycloakID] = avatarFlycloakData } logger.Info("AvatarFlycloakData count: %v", len(g.AvatarFlycloakDataMap)) diff --git a/gdconf/avatar_level_data.go b/gdconf/avatar_level_data.go index a7e8c54f..85ac94ad 100644 --- a/gdconf/avatar_level_data.go +++ b/gdconf/avatar_level_data.go @@ -13,9 +13,8 @@ type AvatarLevelData struct { func (g *GameDataConfig) loadAvatarLevelData() { g.AvatarLevelDataMap = make(map[int32]*AvatarLevelData) avatarLevelDataList := make([]*AvatarLevelData, 0) - readTable[AvatarLevelData](g.tablePrefix+"AvatarLevelData.txt", &avatarLevelDataList) + readTable[AvatarLevelData](g.txtPrefix+"AvatarLevelData.txt", &avatarLevelDataList) for _, avatarLevelData := range avatarLevelDataList { - // list -> map g.AvatarLevelDataMap[avatarLevelData.Level] = avatarLevelData } logger.Info("AvatarLevelData count: %v", len(g.AvatarLevelDataMap)) diff --git a/gdconf/avatar_promote_data.go b/gdconf/avatar_promote_data.go index acc03676..b4ee2eb0 100644 --- a/gdconf/avatar_promote_data.go +++ b/gdconf/avatar_promote_data.go @@ -26,9 +26,8 @@ type AvatarPromoteData struct { func (g *GameDataConfig) loadAvatarPromoteData() { g.AvatarPromoteDataMap = make(map[int32]map[int32]*AvatarPromoteData) avatarPromoteDataList := make([]*AvatarPromoteData, 0) - readTable[AvatarPromoteData](g.tablePrefix+"AvatarPromoteData.txt", &avatarPromoteDataList) + readTable[AvatarPromoteData](g.txtPrefix+"AvatarPromoteData.txt", &avatarPromoteDataList) for _, avatarPromoteData := range avatarPromoteDataList { - // list -> map _, ok := g.AvatarPromoteDataMap[avatarPromoteData.PromoteId] if !ok { g.AvatarPromoteDataMap[avatarPromoteData.PromoteId] = make(map[int32]*AvatarPromoteData) diff --git a/gdconf/avatar_skill_data.go b/gdconf/avatar_skill_data.go index 7589f5f5..5be95349 100644 --- a/gdconf/avatar_skill_data.go +++ b/gdconf/avatar_skill_data.go @@ -17,9 +17,8 @@ type AvatarSkillData struct { func (g *GameDataConfig) loadAvatarSkillData() { g.AvatarSkillDataMap = make(map[int32]*AvatarSkillData) avatarSkillDataList := make([]*AvatarSkillData, 0) - readTable[AvatarSkillData](g.tablePrefix+"AvatarSkillData.txt", &avatarSkillDataList) + readTable[AvatarSkillData](g.txtPrefix+"AvatarSkillData.txt", &avatarSkillDataList) for _, avatarSkillData := range avatarSkillDataList { - // list -> map g.AvatarSkillDataMap[avatarSkillData.AvatarSkillId] = avatarSkillData } logger.Info("AvatarSkillData count: %v", len(g.AvatarSkillDataMap)) diff --git a/gdconf/avatar_skill_depot_data.go b/gdconf/avatar_skill_depot_data.go index 500453f0..28c7c04c 100644 --- a/gdconf/avatar_skill_depot_data.go +++ b/gdconf/avatar_skill_depot_data.go @@ -43,7 +43,7 @@ type InherentProudSkillOpens struct { func (g *GameDataConfig) loadAvatarSkillDepotData() { g.AvatarSkillDepotDataMap = make(map[int32]*AvatarSkillDepotData) avatarSkillDepotDataList := make([]*AvatarSkillDepotData, 0) - readTable[AvatarSkillDepotData](g.tablePrefix+"AvatarSkillDepotData.txt", &avatarSkillDepotDataList) + readTable[AvatarSkillDepotData](g.txtPrefix+"AvatarSkillDepotData.txt", &avatarSkillDepotDataList) playerElementsFilePath := g.jsonPrefix + "ability_group/AbilityGroup_Other_PlayerElementAbility.json" playerElementsFile, err := os.ReadFile(playerElementsFilePath) if err != nil { @@ -113,7 +113,6 @@ func (g *GameDataConfig) loadAvatarSkillDepotData() { } } } - // list -> map g.AvatarSkillDepotDataMap[avatarSkillDepotData.AvatarSkillDepotId] = avatarSkillDepotData } logger.Info("AvatarSkillDepotData count: %v", len(g.AvatarSkillDepotDataMap)) diff --git a/gdconf/chest_drop_data.go b/gdconf/chest_drop_data.go new file mode 100644 index 00000000..12fb607c --- /dev/null +++ b/gdconf/chest_drop_data.go @@ -0,0 +1,39 @@ +package gdconf + +import ( + "hk4e/pkg/logger" +) + +// ChestDropData 宝箱掉落配置表 +type ChestDropData struct { + Level int32 `csv:"最小等级"` + DropTag string `csv:"总索引"` + DropId int32 `csv:"掉落ID,omitempty"` + DropCount int32 `csv:"掉落次数,omitempty"` +} + +func (g *GameDataConfig) loadChestDropData() { + g.ChestDropDataMap = make(map[string]map[int32]*ChestDropData) + chestDropDataList := make([]*ChestDropData, 0) + readTable[ChestDropData](g.txtPrefix+"ChestDropData.txt", &chestDropDataList) + for _, chestDropData := range chestDropDataList { + _, exist := g.ChestDropDataMap[chestDropData.DropTag] + if !exist { + g.ChestDropDataMap[chestDropData.DropTag] = make(map[int32]*ChestDropData) + } + g.ChestDropDataMap[chestDropData.DropTag][chestDropData.Level] = chestDropData + } + logger.Info("ChestDropData count: %v", len(g.ChestDropDataMap)) +} + +func GetChestDropDataByDropTagAndLevel(dropTag string, level int32) *ChestDropData { + value, exist := CONF.ChestDropDataMap[dropTag] + if !exist { + return nil + } + return value[level] +} + +func GetChestDropDataMap() map[string]map[int32]*ChestDropData { + return CONF.ChestDropDataMap +} diff --git a/gdconf/drop_data.go b/gdconf/drop_data.go new file mode 100644 index 00000000..b444f6fb --- /dev/null +++ b/gdconf/drop_data.go @@ -0,0 +1,248 @@ +package gdconf + +import ( + "fmt" + + "hk4e/pkg/logger" +) + +type SubDrop struct { + Id int32 // 子掉落ID + CountRange []int32 // 子掉落数量区间 + Weight int32 // 子掉落权重 +} + +const ( + RandomTypeChoose = 0 + RandomTypeIndep = 1 + RandomTypeIndepWeight = 10000 +) + +// DropData 掉落配置表 +type DropData struct { + DropId int32 `csv:"掉落ID"` + RandomType int32 `csv:"随机方式,omitempty"` // 0:轮盘选择法掉落单个权重项 1:每个权重项独立随机(分母为10000) + DropLayer int32 `csv:"掉落层级,omitempty"` + SubDrop1Id int32 `csv:"子掉落1ID,omitempty"` + SubDrop1CountRange FloatArray `csv:"子掉落1数量区间,omitempty"` + SubDrop1Weight int32 `csv:"子掉落1权重,omitempty"` + SubDrop2Id int32 `csv:"子掉落2ID,omitempty"` + SubDrop2CountRange FloatArray `csv:"子掉落2数量区间,omitempty"` + SubDrop2Weight int32 `csv:"子掉落2权重,omitempty"` + SubDrop3Id int32 `csv:"子掉落3ID,omitempty"` + SubDrop3CountRange FloatArray `csv:"子掉落3数量区间,omitempty"` + SubDrop3Weight int32 `csv:"子掉落3权重,omitempty"` + SubDrop4Id int32 `csv:"子掉落4ID,omitempty"` + SubDrop4CountRange FloatArray `csv:"子掉落4数量区间,omitempty"` + SubDrop4Weight int32 `csv:"子掉落4权重,omitempty"` + SubDrop5Id int32 `csv:"子掉落5ID,omitempty"` + SubDrop5CountRange FloatArray `csv:"子掉落5数量区间,omitempty"` + SubDrop5Weight int32 `csv:"子掉落5权重,omitempty"` + SubDrop6Id int32 `csv:"子掉落6ID,omitempty"` + SubDrop6CountRange FloatArray `csv:"子掉落6数量区间,omitempty"` + SubDrop6Weight int32 `csv:"子掉落6权重,omitempty"` + SubDrop7Id int32 `csv:"子掉落7ID,omitempty"` + SubDrop7CountRange FloatArray `csv:"子掉落7数量区间,omitempty"` + SubDrop7Weight int32 `csv:"子掉落7权重,omitempty"` + SubDrop8Id int32 `csv:"子掉落8ID,omitempty"` + SubDrop8CountRange FloatArray `csv:"子掉落8数量区间,omitempty"` + SubDrop8Weight int32 `csv:"子掉落8权重,omitempty"` + SubDrop9Id int32 `csv:"子掉落9ID,omitempty"` + SubDrop9CountRange FloatArray `csv:"子掉落9数量区间,omitempty"` + SubDrop9Weight int32 `csv:"子掉落9权重,omitempty"` + SubDrop10Id int32 `csv:"子掉落10ID,omitempty"` + SubDrop10CountRange FloatArray `csv:"子掉落10数量区间,omitempty"` + SubDrop10Weight int32 `csv:"子掉落10权重,omitempty"` + SubDrop11Id int32 `csv:"子掉落11ID,omitempty"` + SubDrop11CountRange FloatArray `csv:"子掉落11数量区间,omitempty"` + SubDrop11Weight int32 `csv:"子掉落11权重,omitempty"` + SubDrop12Id int32 `csv:"子掉落12ID,omitempty"` + SubDrop12CountRange FloatArray `csv:"子掉落12数量区间,omitempty"` + SubDrop12Weight int32 `csv:"子掉落12权重,omitempty"` + + SubDropList []*SubDrop // 子掉落列表 + SubDropTotalWeight int32 // 总权重 +} + +func (g *GameDataConfig) loadDropData() { + g.DropDataMap = make(map[int32]*DropData) + fileNameList := []string{"DropLeafData.txt", "DropTreeData.txt"} + for _, fileName := range fileNameList { + dropDataList := make([]*DropData, 0) + readTable[DropData](g.txtPrefix+fileName, &dropDataList) + for _, dropData := range dropDataList { + // 子掉落列合并 + dropData.SubDropList = make([]*SubDrop, 0) + if dropData.SubDrop1Id != 0 { + countRange := make([]int32, 0) + for _, v := range dropData.SubDrop1CountRange { + countRange = append(countRange, int32(v)) + } + dropData.SubDropList = append(dropData.SubDropList, &SubDrop{ + Id: dropData.SubDrop1Id, + CountRange: countRange, + Weight: dropData.SubDrop1Weight, + }) + } + if dropData.SubDrop2Id != 0 { + countRange := make([]int32, 0) + for _, v := range dropData.SubDrop2CountRange { + countRange = append(countRange, int32(v)) + } + dropData.SubDropList = append(dropData.SubDropList, &SubDrop{ + Id: dropData.SubDrop2Id, + CountRange: countRange, + Weight: dropData.SubDrop2Weight, + }) + } + if dropData.SubDrop3Id != 0 { + countRange := make([]int32, 0) + for _, v := range dropData.SubDrop3CountRange { + countRange = append(countRange, int32(v)) + } + dropData.SubDropList = append(dropData.SubDropList, &SubDrop{ + Id: dropData.SubDrop3Id, + CountRange: countRange, + Weight: dropData.SubDrop3Weight, + }) + } + if dropData.SubDrop4Id != 0 { + countRange := make([]int32, 0) + for _, v := range dropData.SubDrop4CountRange { + countRange = append(countRange, int32(v)) + } + dropData.SubDropList = append(dropData.SubDropList, &SubDrop{ + Id: dropData.SubDrop4Id, + CountRange: countRange, + Weight: dropData.SubDrop4Weight, + }) + } + if dropData.SubDrop5Id != 0 { + countRange := make([]int32, 0) + for _, v := range dropData.SubDrop5CountRange { + countRange = append(countRange, int32(v)) + } + dropData.SubDropList = append(dropData.SubDropList, &SubDrop{ + Id: dropData.SubDrop5Id, + CountRange: countRange, + Weight: dropData.SubDrop5Weight, + }) + } + if dropData.SubDrop6Id != 0 { + countRange := make([]int32, 0) + for _, v := range dropData.SubDrop6CountRange { + countRange = append(countRange, int32(v)) + } + dropData.SubDropList = append(dropData.SubDropList, &SubDrop{ + Id: dropData.SubDrop6Id, + CountRange: countRange, + Weight: dropData.SubDrop6Weight, + }) + } + if dropData.SubDrop7Id != 0 { + countRange := make([]int32, 0) + for _, v := range dropData.SubDrop7CountRange { + countRange = append(countRange, int32(v)) + } + dropData.SubDropList = append(dropData.SubDropList, &SubDrop{ + Id: dropData.SubDrop7Id, + CountRange: countRange, + Weight: dropData.SubDrop7Weight, + }) + } + if dropData.SubDrop8Id != 0 { + countRange := make([]int32, 0) + for _, v := range dropData.SubDrop8CountRange { + countRange = append(countRange, int32(v)) + } + dropData.SubDropList = append(dropData.SubDropList, &SubDrop{ + Id: dropData.SubDrop8Id, + CountRange: countRange, + Weight: dropData.SubDrop8Weight, + }) + } + if dropData.SubDrop9Id != 0 { + countRange := make([]int32, 0) + for _, v := range dropData.SubDrop9CountRange { + countRange = append(countRange, int32(v)) + } + dropData.SubDropList = append(dropData.SubDropList, &SubDrop{ + Id: dropData.SubDrop9Id, + CountRange: countRange, + Weight: dropData.SubDrop9Weight, + }) + } + if dropData.SubDrop10Id != 0 { + countRange := make([]int32, 0) + for _, v := range dropData.SubDrop10CountRange { + countRange = append(countRange, int32(v)) + } + dropData.SubDropList = append(dropData.SubDropList, &SubDrop{ + Id: dropData.SubDrop10Id, + CountRange: countRange, + Weight: dropData.SubDrop10Weight, + }) + } + if dropData.SubDrop11Id != 0 { + countRange := make([]int32, 0) + for _, v := range dropData.SubDrop11CountRange { + countRange = append(countRange, int32(v)) + } + dropData.SubDropList = append(dropData.SubDropList, &SubDrop{ + Id: dropData.SubDrop11Id, + CountRange: countRange, + Weight: dropData.SubDrop11Weight, + }) + } + if dropData.SubDrop12Id != 0 { + countRange := make([]int32, 0) + for _, v := range dropData.SubDrop12CountRange { + countRange = append(countRange, int32(v)) + } + dropData.SubDropList = append(dropData.SubDropList, &SubDrop{ + Id: dropData.SubDrop12Id, + CountRange: countRange, + Weight: dropData.SubDrop12Weight, + }) + } + if dropData.RandomType == RandomTypeChoose { + // 计算轮盘总权重 + for _, subDrop := range dropData.SubDropList { + dropData.SubDropTotalWeight += subDrop.Weight + } + } + g.DropDataMap[dropData.DropId] = dropData + } + } + // 检查 + for _, dropData := range g.DropDataMap { + if dropData.RandomType == RandomTypeIndep { + for _, subDrop := range dropData.SubDropList { + if subDrop.Weight > RandomTypeIndepWeight { + info := fmt.Sprintf("invalid weight for indep rand type, weight: %v, dropId: %v", subDrop.Weight, dropData.DropId) + panic(info) + } + } + } + for _, subDrop := range dropData.SubDropList { + // 掉落id优先在掉落表里找 找不到就去道具表里找 + _, exist := g.DropDataMap[subDrop.Id] + if !exist { + _, exist := g.ItemDataMap[subDrop.Id] + if !exist { + info := fmt.Sprintf("drop item id not exist, itemId: %v, dropId: %v", subDrop.Id, dropData.DropId) + panic(info) + } + } + } + } + logger.Info("DropData count: %v", len(g.DropDataMap)) +} + +func GetDropDataById(dropId int32) *DropData { + return CONF.DropDataMap[dropId] +} + +func GetDropDataMap() map[int32]*DropData { + return CONF.DropDataMap +} diff --git a/gdconf/drop_group_data.go b/gdconf/drop_group_data.go deleted file mode 100644 index 5c7dc693..00000000 --- a/gdconf/drop_group_data.go +++ /dev/null @@ -1,42 +0,0 @@ -package gdconf - -import ( - "hk4e/pkg/logger" -) - -// 当初写卡池算法的时候临时建立的表 以后再做迁移吧 - -type Drop struct { - DropId int32 `csv:"DropId"` - Weight int32 `csv:"Weight"` - Result int32 `csv:"Result"` - IsEnd bool `csv:"IsEnd"` -} - -type DropGroupData struct { - DropId int32 - WeightAll int32 - DropConfig []*Drop -} - -func (g *GameDataConfig) loadDropGroupData() { - g.DropGroupDataMap = make(map[int32]*DropGroupData) - fileNameList := []string{"DropGachaAvatarUp.csv", "DropGachaWeaponUp.csv", "DropGachaNormal.csv"} - for _, fileName := range fileNameList { - dropList := make([]*Drop, 0) - readExtCsv[Drop](g.extPrefix+fileName, &dropList) - for _, drop := range dropList { - dropGroupData, exist := g.DropGroupDataMap[drop.DropId] - if !exist { - dropGroupData = new(DropGroupData) - dropGroupData.DropId = drop.DropId - dropGroupData.WeightAll = 0 - dropGroupData.DropConfig = make([]*Drop, 0) - g.DropGroupDataMap[drop.DropId] = dropGroupData - } - dropGroupData.WeightAll += drop.Weight - dropGroupData.DropConfig = append(dropGroupData.DropConfig, drop) - } - } - logger.Info("DropGroupData count: %v", len(g.DropGroupDataMap)) -} diff --git a/gdconf/fetter_data.go b/gdconf/fetter_data.go index 2f2ccee9..a52255f7 100644 --- a/gdconf/fetter_data.go +++ b/gdconf/fetter_data.go @@ -16,9 +16,8 @@ func (g *GameDataConfig) loadFetterData() { fileNameList := []string{"FettersData.txt", "FetterDataStory.txt", "FetterDataIformation.txt", "PhotographExpressionName.txt", "PhotographPoseName.txt"} for _, fileName := range fileNameList { fetterDataList := make([]*FetterData, 0) - readTable[FetterData](g.tablePrefix+fileName, &fetterDataList) + readTable[FetterData](g.txtPrefix+fileName, &fetterDataList) for _, fetterData := range fetterDataList { - // list -> map g.FetterDataMap[fetterData.FetterId] = fetterData fetterIdList := g.FetterDataAvatarIdMap[fetterData.AvatarId] if fetterIdList == nil { diff --git a/gdconf/gacha_drop_group_data.go b/gdconf/gacha_drop_group_data.go new file mode 100644 index 00000000..83dbab5c --- /dev/null +++ b/gdconf/gacha_drop_group_data.go @@ -0,0 +1,42 @@ +package gdconf + +import ( + "hk4e/pkg/logger" +) + +// 当初写卡池算法的时候临时建立的表 以后再做迁移吧 + +type GachaDrop struct { + DropId int32 `csv:"DropId"` + Weight int32 `csv:"Weight"` + Result int32 `csv:"Result"` + IsEnd bool `csv:"IsEnd"` +} + +type GachaDropGroupData struct { + DropId int32 + WeightAll int32 + DropConfig []*GachaDrop +} + +func (g *GameDataConfig) loadGachaDropGroupData() { + g.GachaDropGroupDataMap = make(map[int32]*GachaDropGroupData) + fileNameList := []string{"GachaDropAvatarUp.csv", "GachaDropWeaponUp.csv", "GachaDropNormal.csv"} + for _, fileName := range fileNameList { + gachaDropList := make([]*GachaDrop, 0) + readExtCsv[GachaDrop](g.extPrefix+fileName, &gachaDropList) + for _, gachaDrop := range gachaDropList { + gachaDropGroupData, exist := g.GachaDropGroupDataMap[gachaDrop.DropId] + if !exist { + gachaDropGroupData = new(GachaDropGroupData) + gachaDropGroupData.DropId = gachaDrop.DropId + gachaDropGroupData.WeightAll = 0 + gachaDropGroupData.DropConfig = make([]*GachaDrop, 0) + g.GachaDropGroupDataMap[gachaDrop.DropId] = gachaDropGroupData + } + gachaDropGroupData.WeightAll += gachaDrop.Weight + gachaDropGroupData.DropConfig = append(gachaDropGroupData.DropConfig, gachaDrop) + } + } + logger.Info("GachaDropGroupData count: %v", len(g.GachaDropGroupDataMap)) +} diff --git a/gdconf/game_data_config.go b/gdconf/game_data_config.go index b8016c44..e48c136d 100644 --- a/gdconf/game_data_config.go +++ b/gdconf/game_data_config.go @@ -27,26 +27,24 @@ var CONF_RELOAD *GameDataConfig = nil type GameDataConfig struct { // 配置表路径前缀 - tablePrefix string - jsonPrefix string - luaPrefix string - extPrefix string + txtPrefix string + jsonPrefix string + luaPrefix string + extPrefix string // 配置表数据 - AvatarDataMap map[int32]*AvatarData // 角色 - AvatarSkillDataMap map[int32]*AvatarSkillData // 角色技能 - AvatarSkillDepotDataMap map[int32]*AvatarSkillDepotData // 角色技能库 - DropGroupDataMap map[int32]*DropGroupData // 掉落组 - GCGCharDataMap map[int32]*GCGCharData // 角色卡牌 - GCGSkillDataMap map[int32]*GCGSkillData // 卡牌技能 SceneDataMap map[int32]*SceneData // 场景 - ScenePointMap map[int32]*ScenePoint // 场景传送点 - SceneTagDataMap map[int32]*SceneTagData // 场景标签 SceneLuaConfigMap map[int32]*SceneLuaConfig // 场景LUA配置 GroupMap map[int32]*Group // 场景LUA区块group索引 LuaStateLruMap map[int32]*LuaStateLru // 场景LUA虚拟机LRU内存淘汰 - WorldAreaDataMap map[int32]*WorldAreaData // 世界区域 + TriggerDataMap map[int32]*TriggerData // 场景LUA触发器 + ScenePointMap map[int32]*ScenePoint // 场景传送点 + SceneTagDataMap map[int32]*SceneTagData // 场景标签 GatherDataMap map[int32]*GatherData // 采集物 GatherDataPointTypeMap map[int32]*GatherData // 采集物场景节点索引 + WorldAreaDataMap map[int32]*WorldAreaData // 世界区域 + AvatarDataMap map[int32]*AvatarData // 角色 + AvatarSkillDataMap map[int32]*AvatarSkillData // 角色技能 + AvatarSkillDepotDataMap map[int32]*AvatarSkillDepotData // 角色技能库 FetterDataMap map[int32]*FetterData // 角色资料解锁 FetterDataAvatarIdMap map[int32][]int32 // 角色资料解锁角色id索引 ItemDataMap map[int32]*ItemData // 统一道具 @@ -61,7 +59,12 @@ type GameDataConfig struct { ReliquaryMainDataMap map[int32]map[int32]*ReliquaryMainData // 圣遗物主属性 ReliquaryAffixDataMap map[int32]map[int32]*ReliquaryAffixData // 圣遗物追加属性 QuestDataMap map[int32]*QuestData // 任务 - TriggerDataMap map[int32]*TriggerData // 场景LUA触发器 + DropDataMap map[int32]*DropData // 掉落 + MonsterDropDataMap map[string]map[int32]*MonsterDropData // 怪物掉落 + ChestDropDataMap map[string]map[int32]*ChestDropData // 宝箱掉落 + GCGCharDataMap map[int32]*GCGCharData // 七圣召唤角色卡牌 + GCGSkillDataMap map[int32]*GCGSkillData // 七圣召唤卡牌技能 + GachaDropGroupDataMap map[int32]*GachaDropGroupData // 卡池掉落组 临时的 } func InitGameDataConfig() { @@ -95,13 +98,13 @@ func (g *GameDataConfig) loadAll() { panic(info) } - g.tablePrefix = pathPrefix + "/txt" - dirInfo, err = os.Stat(g.tablePrefix) + g.txtPrefix = pathPrefix + "/txt" + dirInfo, err = os.Stat(g.txtPrefix) if err != nil || !dirInfo.IsDir() { info := fmt.Sprintf("open game data config txt dir error: %v", err) panic(info) } - g.tablePrefix += "/" + g.txtPrefix += "/" g.jsonPrefix = pathPrefix + "/json" dirInfo, err = os.Stat(g.jsonPrefix) @@ -131,34 +134,35 @@ func (g *GameDataConfig) loadAll() { } func (g *GameDataConfig) load() { + g.loadSceneData() // 场景 + g.loadSceneLuaConfig() // 场景LUA配置 + g.loadTriggerData() // 场景LUA触发器 + g.loadScenePoint() // 场景传送点 + g.loadSceneTagData() // 场景标签 + g.loadGatherData() // 采集物 + g.loadWorldAreaData() // 世界区域 g.loadAvatarData() // 角色 g.loadAvatarSkillData() // 角色技能 g.loadAvatarSkillDepotData() // 角色技能库 - g.loadDropGroupData() // 掉落组 卡池 临时的 - g.loadGCGCharData() // 角色卡牌 - g.loadGCGSkillData() // 卡牌技能 - g.loadSceneData() // 场景 - g.loadScenePoint() // 场景传送点 - g.loadSceneTagData() // 场景地图图标 - if config.GetConfig().Hk4e.LoadSceneLuaConfig { - g.loadSceneLuaConfig() // 场景LUA配置 - } - g.loadWorldAreaData() // 世界区域 - g.loadGatherData() // 采集物 - g.loadFetterData() // 角色资料解锁 - g.loadItemData() // 统一道具 - g.loadAvatarLevelData() // 角色等级 - g.loadAvatarPromoteData() // 角色突破 - g.loadPlayerLevelData() // 玩家等级 - g.loadWeaponLevelData() // 武器等级 - g.loadWeaponPromoteData() // 武器突破 - g.loadRewardData() // 奖励 - g.loadAvatarCostumeData() // 角色时装 - g.loadAvatarFlycloakData() // 角色风之翼 - g.loadReliquaryMainData() // 圣遗物主属性 - g.loadReliquaryAffixData() // 圣遗物追加属性 - g.loadQuestData() // 任务 - g.loadTriggerData() // 场景LUA触发器 + g.loadFetterData() // 角色资料解锁 + g.loadItemData() // 统一道具 + g.loadAvatarLevelData() // 角色等级 + g.loadAvatarPromoteData() // 角色突破 + g.loadPlayerLevelData() // 玩家等级 + g.loadWeaponLevelData() // 武器等级 + g.loadWeaponPromoteData() // 武器突破 + g.loadRewardData() // 奖励 + g.loadAvatarCostumeData() // 角色时装 + g.loadAvatarFlycloakData() // 角色风之翼 + g.loadReliquaryMainData() // 圣遗物主属性 + g.loadReliquaryAffixData() // 圣遗物追加属性 + g.loadQuestData() // 任务 + g.loadDropData() // 掉落 + g.loadMonsterDropData() // 怪物掉落 + g.loadChestDropData() // 宝箱掉落 + g.loadGCGCharData() // 七圣召唤角色卡牌 + g.loadGCGSkillData() // 七圣召唤卡牌技能 + g.loadGachaDropGroupData() // 卡池掉落组 临时的 } // CSV相关 @@ -191,6 +195,22 @@ func (a *IntArray) UnmarshalCSV(data []byte) error { return nil } +type FloatArray []float32 + +func (a *FloatArray) UnmarshalCSV(data []byte) error { + str := string(data) + str = strings.ReplaceAll(str, " ", "") + floatStrList := splitStringArray(str) + for _, floatStr := range floatStrList { + v, err := strconv.ParseFloat(floatStr, 32) + if err != nil { + panic(err) + } + *a = append(*a, float32(v)) + } + return nil +} + func readExtCsv[T any](tablePath string, table *[]*T) { fileData, err := os.ReadFile(tablePath) if err != nil { @@ -260,6 +280,9 @@ func initLuaState(luaState *lua.LState) { luaState.SetField(eventType, "EVENT_NONE", lua.LNumber(constant.LUA_EVENT_NONE)) luaState.SetField(eventType, "EVENT_ENTER_REGION", lua.LNumber(constant.LUA_EVENT_ENTER_REGION)) luaState.SetField(eventType, "EVENT_LEAVE_REGION", lua.LNumber(constant.LUA_EVENT_LEAVE_REGION)) + luaState.SetField(eventType, "EVENT_ANY_MONSTER_DIE", lua.LNumber(constant.LUA_EVENT_ANY_MONSTER_DIE)) + luaState.SetField(eventType, "EVENT_ANY_MONSTER_LIVE", lua.LNumber(constant.LUA_EVENT_ANY_MONSTER_LIVE)) + luaState.SetField(eventType, "EVENT_QUEST_START", lua.LNumber(constant.LUA_EVENT_QUEST_START)) entityType := luaState.NewTable() luaState.SetGlobal("EntityType", entityType) @@ -287,11 +310,17 @@ func initLuaState(luaState *lua.LState) { gadgetState := luaState.NewTable() luaState.SetGlobal("GadgetState", gadgetState) - luaState.SetField(gadgetState, "NONE", lua.LNumber(0)) + luaState.SetField(gadgetState, "Default", lua.LNumber(constant.GADGET_STATE_DEFAULT)) + luaState.SetField(gadgetState, "ChestLocked", lua.LNumber(constant.GADGET_STATE_CHEST_LOCKED)) + luaState.SetField(gadgetState, "GearStart", lua.LNumber(constant.GADGET_STATE_GEAR_START)) + luaState.SetField(gadgetState, "GearStop", lua.LNumber(constant.GADGET_STATE_GEAR_STOP)) visionLevelType := luaState.NewTable() luaState.SetGlobal("VisionLevelType", visionLevelType) - luaState.SetField(visionLevelType, "NONE", lua.LNumber(0)) + luaState.SetField(visionLevelType, "VISION_LEVEL_NEARBY", lua.LNumber(1)) + luaState.SetField(visionLevelType, "VISION_LEVEL_NORMAL", lua.LNumber(2)) + luaState.SetField(visionLevelType, "VISION_LEVEL_REMOTE", lua.LNumber(3)) + luaState.SetField(visionLevelType, "VISION_LEVEL_LITTLE_REMOTE", lua.LNumber(4)) } func newLuaState(luaStr string) *lua.LState { diff --git a/gdconf/game_data_config/ext/Avatar.csv b/gdconf/game_data_config/ext/Avatar.csv deleted file mode 100644 index b9b1ddbe..00000000 --- a/gdconf/game_data_config/ext/Avatar.csv +++ /dev/null @@ -1,54 +0,0 @@ -AvatarId,GachaItemId,Name -int32,int32,string -角色id,卡池道具id,角色名称 -10000002,1002,神里绫华 -10000003,1003,琴 -10000006,1006,丽莎 -10000014,1014,芭芭拉 -10000015,1015,凯亚 -10000016,1016,迪卢克 -10000020,1020,雷泽 -10000021,1021,安柏 -10000022,1022,温迪 -10000023,1023,香菱 -10000024,1024,北斗 -10000025,1025,行秋 -10000026,1026,魈 -10000027,1027,凝光 -10000029,1029,可莉 -10000030,1030,钟离 -10000031,1031,菲谢尔 -10000032,1032,班尼特 -10000033,1033,达达利亚 -10000034,1034,诺艾尔 -10000035,1035,七七 -10000036,1036,重云 -10000037,1037,甘雨 -10000038,1038,阿贝多 -10000039,1039,迪奥娜 -10000041,1041,莫娜 -10000042,1042,刻晴 -10000043,1043,砂糖 -10000044,1044,辛焱 -10000045,1045,罗莎莉亚 -10000046,1046,胡桃 -10000047,1047,枫原万叶 -10000048,1048,烟绯 -10000049,1049,宵宫 -10000050,1050,托马 -10000051,1051,优菈 -10000052,1052,雷电将军 -10000053,1053,早柚 -10000054,1054,珊瑚宫心海 -10000055,1055,五郎 -10000056,1056,九条裟罗 -10000057,1057,荒泷一斗 -10000058,1058,八重神子 -10000062,1062,埃洛伊 -10000063,1063,申鹤 -10000064,1064,云堇 -10000065,1065,久歧忍 -10000066,1066,神里绫人 -10000067,1067,柯莱 -10000068,1068,多莉 -10000069,1069,提纳里 \ No newline at end of file diff --git a/gdconf/game_data_config/ext/DropGachaAvatarUp.csv b/gdconf/game_data_config/ext/GachaDropAvatarUp.csv similarity index 100% rename from gdconf/game_data_config/ext/DropGachaAvatarUp.csv rename to gdconf/game_data_config/ext/GachaDropAvatarUp.csv diff --git a/gdconf/game_data_config/ext/DropGachaNormal.csv b/gdconf/game_data_config/ext/GachaDropNormal.csv similarity index 100% rename from gdconf/game_data_config/ext/DropGachaNormal.csv rename to gdconf/game_data_config/ext/GachaDropNormal.csv diff --git a/gdconf/game_data_config/ext/DropGachaWeaponUp.csv b/gdconf/game_data_config/ext/GachaDropWeaponUp.csv similarity index 100% rename from gdconf/game_data_config/ext/DropGachaWeaponUp.csv rename to gdconf/game_data_config/ext/GachaDropWeaponUp.csv diff --git a/gdconf/game_data_config_test.go b/gdconf/game_data_config_test.go index 6873c242..85298b7f 100644 --- a/gdconf/game_data_config_test.go +++ b/gdconf/game_data_config_test.go @@ -25,7 +25,7 @@ func TestInitGameDataConfig(t *testing.T) { logger.Info("start load conf") InitGameDataConfig() logger.Info("load conf finish") - time.Sleep(time.Second) + time.Sleep(time.Minute) } func CheckJsonLoop(path string, errorJsonFileList *[]string, totalJsonFileCount *int) { diff --git a/gdconf/gather_data.go b/gdconf/gather_data.go index 81ee8fba..5ab4a868 100644 --- a/gdconf/gather_data.go +++ b/gdconf/gather_data.go @@ -8,17 +8,16 @@ import ( type GatherData struct { PointType int32 `csv:"挂节点类型"` GatherId int32 `csv:"ID"` - GadgetId int32 `csv:"采集物ID"` - ItemId int32 `csv:"获得物品ID"` + GadgetId int32 `csv:"采集物ID,omitempty"` + ItemId int32 `csv:"获得物品ID,omitempty"` } func (g *GameDataConfig) loadGatherData() { g.GatherDataMap = make(map[int32]*GatherData) gatherDataList := make([]*GatherData, 0) - readTable[GatherData](g.tablePrefix+"GatherData.txt", &gatherDataList) + readTable[GatherData](g.txtPrefix+"GatherData.txt", &gatherDataList) g.GatherDataPointTypeMap = make(map[int32]*GatherData) for _, gatherData := range gatherDataList { - // list -> map g.GatherDataMap[gatherData.GatherId] = gatherData g.GatherDataPointTypeMap[gatherData.PointType] = gatherData } diff --git a/gdconf/gcg_char_data.go b/gdconf/gcg_char_data.go index 3dad39ac..a5ea6596 100644 --- a/gdconf/gcg_char_data.go +++ b/gdconf/gcg_char_data.go @@ -22,7 +22,7 @@ type GCGCharData struct { func (g *GameDataConfig) loadGCGCharData() { g.GCGCharDataMap = make(map[int32]*GCGCharData) gcgCharDataList := make([]*GCGCharData, 0) - readTable[GCGCharData](g.tablePrefix+"GCGCharData.txt", &gcgCharDataList) + readTable[GCGCharData](g.txtPrefix+"GCGCharData.txt", &gcgCharDataList) for _, gcgCharData := range gcgCharDataList { // 将TagId整合进TagList gcgCharData.TagList = make([]uint32, 0, 5) @@ -35,7 +35,6 @@ func (g *GameDataConfig) loadGCGCharData() { } gcgCharData.TagList = append(gcgCharData.TagList, uint32(tagId)) } - // list -> map g.GCGCharDataMap[gcgCharData.CharId] = gcgCharData } logger.Info("GCGCharData count: %v", len(g.GCGCharDataMap)) diff --git a/gdconf/gcg_skill_data.go b/gdconf/gcg_skill_data.go index aad3d3c6..9e1ba7a0 100644 --- a/gdconf/gcg_skill_data.go +++ b/gdconf/gcg_skill_data.go @@ -35,7 +35,7 @@ type ConfigSkillEffectValue struct { func (g *GameDataConfig) loadGCGSkillData() { g.GCGSkillDataMap = make(map[int32]*GCGSkillData) gcgSkillDataList := make([]*GCGSkillData, 0) - readTable[GCGSkillData](g.tablePrefix+"GCGSkillData.txt", &gcgSkillDataList) + readTable[GCGSkillData](g.txtPrefix+"GCGSkillData.txt", &gcgSkillDataList) for _, gcgSkillData := range gcgSkillDataList { // 技能消耗整合进CostMap gcgSkillData.CostMap = map[uint32]uint32{ @@ -97,7 +97,6 @@ func (g *GameDataConfig) loadGCGSkillData() { } } } - // list -> map g.GCGSkillDataMap[gcgSkillData.SkillId] = gcgSkillData } logger.Info("GCGSkillData count: %v", len(g.GCGSkillDataMap)) diff --git a/gdconf/item_data.go b/gdconf/item_data.go index 18ef5ec9..a193ea85 100644 --- a/gdconf/item_data.go +++ b/gdconf/item_data.go @@ -38,9 +38,8 @@ func (g *GameDataConfig) loadItemData() { fileNameList := []string{"MaterialData.txt", "WeaponData.txt", "ReliquaryData.txt", "FurnitureExcelData.txt"} for _, fileName := range fileNameList { itemDataList := make([]*ItemData, 0) - readTable[ItemData](g.tablePrefix+fileName, &itemDataList) + readTable[ItemData](g.txtPrefix+fileName, &itemDataList) for _, itemData := range itemDataList { - // list -> map itemData.SkillAffix = make([]int32, 0) if itemData.SkillAffix1 != 0 { itemData.SkillAffix = append(itemData.SkillAffix, itemData.SkillAffix1) diff --git a/gdconf/monster_drop_data.go b/gdconf/monster_drop_data.go new file mode 100644 index 00000000..abb9f8ee --- /dev/null +++ b/gdconf/monster_drop_data.go @@ -0,0 +1,39 @@ +package gdconf + +import ( + "hk4e/pkg/logger" +) + +// MonsterDropData 怪物掉落配置表 +type MonsterDropData struct { + Level int32 `csv:"最小等级"` + DropTag string `csv:"总索引"` + DropId int32 `csv:"掉落ID,omitempty"` + DropCount int32 `csv:"掉落次数,omitempty"` +} + +func (g *GameDataConfig) loadMonsterDropData() { + g.MonsterDropDataMap = make(map[string]map[int32]*MonsterDropData) + monsterDropDataList := make([]*MonsterDropData, 0) + readTable[MonsterDropData](g.txtPrefix+"MonsterDropData.txt", &monsterDropDataList) + for _, monsterDropData := range monsterDropDataList { + _, exist := g.MonsterDropDataMap[monsterDropData.DropTag] + if !exist { + g.MonsterDropDataMap[monsterDropData.DropTag] = make(map[int32]*MonsterDropData) + } + g.MonsterDropDataMap[monsterDropData.DropTag][monsterDropData.Level] = monsterDropData + } + logger.Info("MonsterDropData count: %v", len(g.MonsterDropDataMap)) +} + +func GetMonsterDropDataByDropTagAndLevel(dropTag string, level int32) *MonsterDropData { + value, exist := CONF.MonsterDropDataMap[dropTag] + if !exist { + return nil + } + return value[level] +} + +func GetMonsterDropDataMap() map[string]map[int32]*MonsterDropData { + return CONF.MonsterDropDataMap +} diff --git a/gdconf/player_level_data.go b/gdconf/player_level_data.go index 245b79b1..9047f05f 100644 --- a/gdconf/player_level_data.go +++ b/gdconf/player_level_data.go @@ -13,9 +13,8 @@ type PlayerLevelData struct { func (g *GameDataConfig) loadPlayerLevelData() { g.PlayerLevelDataMap = make(map[int32]*PlayerLevelData) playerLevelDataList := make([]*PlayerLevelData, 0) - readTable[PlayerLevelData](g.tablePrefix+"PlayerLevelData.txt", &playerLevelDataList) + readTable[PlayerLevelData](g.txtPrefix+"PlayerLevelData.txt", &playerLevelDataList) for _, playerLevelData := range playerLevelDataList { - // list -> map g.PlayerLevelDataMap[playerLevelData.Level] = playerLevelData } logger.Info("PlayerLevelData count: %v", len(g.PlayerLevelDataMap)) diff --git a/gdconf/quest_data.go b/gdconf/quest_data.go index befb55d8..b4d77018 100644 --- a/gdconf/quest_data.go +++ b/gdconf/quest_data.go @@ -75,9 +75,8 @@ func (g *GameDataConfig) loadQuestData() { fileNameList := []string{"QuestData.txt", "QuestData_Exported.txt"} for _, fileName := range fileNameList { questDataList := make([]*QuestData, 0) - readTable[QuestData](g.tablePrefix+fileName, &questDataList) + readTable[QuestData](g.txtPrefix+fileName, &questDataList) for _, questData := range questDataList { - // list -> map // 领取条件 questData.AcceptCondList = make([]*QuestCond, 0) if questData.AcceptCondType1 != 0 { diff --git a/gdconf/reliquary_affix_data.go b/gdconf/reliquary_affix_data.go index b6dcd166..62093921 100644 --- a/gdconf/reliquary_affix_data.go +++ b/gdconf/reliquary_affix_data.go @@ -15,14 +15,13 @@ type ReliquaryAffixData struct { func (g *GameDataConfig) loadReliquaryAffixData() { g.ReliquaryAffixDataMap = make(map[int32]map[int32]*ReliquaryAffixData) reliquaryAffixDataList := make([]*ReliquaryAffixData, 0) - readTable[ReliquaryAffixData](g.tablePrefix+"ReliquaryAffixData.txt", &reliquaryAffixDataList) + readTable[ReliquaryAffixData](g.txtPrefix+"ReliquaryAffixData.txt", &reliquaryAffixDataList) for _, reliquaryAffixData := range reliquaryAffixDataList { // 通过主属性库ID找到 _, ok := g.ReliquaryAffixDataMap[reliquaryAffixData.AppendPropDepotId] if !ok { g.ReliquaryAffixDataMap[reliquaryAffixData.AppendPropDepotId] = make(map[int32]*ReliquaryAffixData) } - // list -> map g.ReliquaryAffixDataMap[reliquaryAffixData.AppendPropDepotId][reliquaryAffixData.AppendPropId] = reliquaryAffixData } logger.Info("ReliquaryAffixData count: %v", len(g.ReliquaryAffixDataMap)) diff --git a/gdconf/reliquary_main_data.go b/gdconf/reliquary_main_data.go index f8150a5e..0f03a8e9 100644 --- a/gdconf/reliquary_main_data.go +++ b/gdconf/reliquary_main_data.go @@ -15,14 +15,13 @@ type ReliquaryMainData struct { func (g *GameDataConfig) loadReliquaryMainData() { g.ReliquaryMainDataMap = make(map[int32]map[int32]*ReliquaryMainData) reliquaryMainDataList := make([]*ReliquaryMainData, 0) - readTable[ReliquaryMainData](g.tablePrefix+"ReliquaryMainData.txt", &reliquaryMainDataList) + readTable[ReliquaryMainData](g.txtPrefix+"ReliquaryMainData.txt", &reliquaryMainDataList) for _, reliquaryMainData := range reliquaryMainDataList { // 通过主属性库ID找到 _, ok := g.ReliquaryMainDataMap[reliquaryMainData.MainPropDepotId] if !ok { g.ReliquaryMainDataMap[reliquaryMainData.MainPropDepotId] = make(map[int32]*ReliquaryMainData) } - // list -> map g.ReliquaryMainDataMap[reliquaryMainData.MainPropDepotId][reliquaryMainData.MainPropId] = reliquaryMainData } logger.Info("ReliquaryMainData count: %v", len(g.ReliquaryMainDataMap)) diff --git a/gdconf/reward_data.go b/gdconf/reward_data.go index bea8633f..2bbf9e47 100644 --- a/gdconf/reward_data.go +++ b/gdconf/reward_data.go @@ -32,9 +32,8 @@ type RewardData struct { func (g *GameDataConfig) loadRewardData() { g.RewardDataMap = make(map[int32]*RewardData) rewardDataList := make([]*RewardData, 0) - readTable[RewardData](g.tablePrefix+"RewardData.txt", &rewardDataList) + readTable[RewardData](g.txtPrefix+"RewardData.txt", &rewardDataList) for _, rewardData := range rewardDataList { - // list -> map // 奖励物品整合 rewardData.RewardItemMap = map[uint32]uint32{ uint32(rewardData.RewardItem1ID): uint32(rewardData.RewardItem1Count), diff --git a/gdconf/scene_data.go b/gdconf/scene_data.go index f3c1119e..dedb705e 100644 --- a/gdconf/scene_data.go +++ b/gdconf/scene_data.go @@ -13,9 +13,8 @@ type SceneData struct { func (g *GameDataConfig) loadSceneData() { g.SceneDataMap = make(map[int32]*SceneData) sceneDataList := make([]*SceneData, 0) - readTable[SceneData](g.tablePrefix+"SceneData.txt", &sceneDataList) + readTable[SceneData](g.txtPrefix+"SceneData.txt", &sceneDataList) for _, sceneData := range sceneDataList { - // list -> map g.SceneDataMap[sceneData.SceneId] = sceneData } logger.Info("SceneData count: %v", len(g.SceneDataMap)) diff --git a/gdconf/scene_lua_config.go b/gdconf/scene_lua_config.go index 52731d41..08ca9313 100644 --- a/gdconf/scene_lua_config.go +++ b/gdconf/scene_lua_config.go @@ -5,9 +5,9 @@ import ( "sort" "strconv" "sync" - "sync/atomic" "time" + "hk4e/common/config" "hk4e/pkg/logger" lua "github.com/yuin/gopher-lua" @@ -19,8 +19,6 @@ const ( SceneGroupLoaderLimit = 4 // 加载文件的并发数 此操作很耗内存 调大之前请确保你的机器内存足够 ) -var OBJECT_ID_COUNTER uint64 - type SceneLuaConfig struct { Id int32 SceneConfig *SceneConfig // 地图配置 @@ -55,77 +53,27 @@ type BlockRange struct { } type Group struct { - Id int32 `json:"id"` - RefreshId int32 `json:"refresh_id"` - Area int32 `json:"area"` - Pos *Vector `json:"pos"` - DynamicLoad bool `json:"dynamic_load"` - IsReplaceable *Replaceable `json:"is_replaceable"` - MonsterList []*Monster `json:"monsters"` // 怪物 - NpcList []*Npc `json:"npcs"` // NPC - GadgetList []*Gadget `json:"gadgets"` // 物件 - RegionList []*Region `json:"regions"` - TriggerList []*Trigger `json:"triggers"` - LuaStr string `json:"-"` - LuaState *lua.LState `json:"-"` + Id int32 `json:"id"` + RefreshId int32 `json:"refresh_id"` + Area int32 `json:"area"` + Pos *Vector `json:"pos"` + DynamicLoad bool `json:"dynamic_load"` + IsReplaceable *Replaceable `json:"is_replaceable"` + MonsterMap map[int32]*Monster `json:"-"` // 怪物 + NpcMap map[int32]*Npc `json:"-"` // NPC + GadgetMap map[int32]*Gadget `json:"-"` // 物件 + RegionMap map[int32]*Region `json:"-"` // 区域 + TriggerMap map[string]*Trigger `json:"-"` // 触发器 + GroupInitConfig *GroupInitConfig `json:"-"` // 初始化配置 + SuiteList []*Suite `json:"-"` // 小组配置 + LuaStr string `json:"-"` // LUA原始字符串缓存 + LuaState *lua.LState `json:"-"` // LUA虚拟机实例 } -const ( - LuaStateLruKeepNum = 1000 -) - -type LuaStateLru struct { - GroupId int32 - AccessTime int64 -} - -type LuaStateLruList []*LuaStateLru - -func (l LuaStateLruList) Len() int { - return len(l) -} - -func (l LuaStateLruList) Less(i, j int) bool { - return l[i].AccessTime < l[j].AccessTime -} - -func (l LuaStateLruList) Swap(i, j int) { - l[i], l[j] = l[j], l[i] -} - -func LuaStateLruRemove() { - removeNum := len(CONF.LuaStateLruMap) - LuaStateLruKeepNum - if removeNum <= 0 { - return - } - luaStateLruList := make(LuaStateLruList, 0) - for _, luaStateLru := range CONF.LuaStateLruMap { - luaStateLruList = append(luaStateLruList, luaStateLru) - } - sort.Stable(luaStateLruList) - for i := 0; i < removeNum; i++ { - luaStateLru := luaStateLruList[i] - group := GetSceneGroup(luaStateLru.GroupId) - group.LuaState = nil - delete(CONF.LuaStateLruMap, luaStateLru.GroupId) - } - logger.Info("lua state lru remove finish, remove num: %v", removeNum) -} - -func (g *Group) GetLuaState() *lua.LState { - CONF.LuaStateLruMap[g.Id] = &LuaStateLru{ - GroupId: g.Id, - AccessTime: time.Now().UnixMilli(), - } - if g.LuaState == nil { - g.LuaState = newLuaState(g.LuaStr) - scriptLib := g.LuaState.NewTable() - g.LuaState.SetGlobal("ScriptLib", scriptLib) - for _, scriptLibFunc := range SCRIPT_LIB_FUNC_LIST { - g.LuaState.SetField(scriptLib, scriptLibFunc.fnName, g.LuaState.NewFunction(scriptLibFunc.fn)) - } - } - return g.LuaState +type GroupInitConfig struct { + Suite int32 `json:"suite"` + EndSuite int32 `json:"end_suite"` + RandSuite bool `json:"rand_suite"` } type Replaceable struct { @@ -141,7 +89,7 @@ type Monster struct { Rot *Vector `json:"rot"` Level int32 `json:"level"` AreaId int32 `json:"area_id"` - ObjectId uint64 `json:"-"` + DropTag string `json:"drop_tag"` // 关联MonsterDropData表 } type Npc struct { @@ -150,18 +98,19 @@ type Npc struct { Pos *Vector `json:"pos"` Rot *Vector `json:"rot"` AreaId int32 `json:"area_id"` - ObjectId uint64 `json:"-"` } type Gadget struct { - ConfigId int32 `json:"config_id"` - GadgetId int32 `json:"gadget_id"` - Pos *Vector `json:"pos"` - Rot *Vector `json:"rot"` - Level int32 `json:"level"` - AreaId int32 `json:"area_id"` - PointType int32 `json:"point_type"` // 关联GatherData表 - ObjectId uint64 `json:"-"` + ConfigId int32 `json:"config_id"` + GadgetId int32 `json:"gadget_id"` + Pos *Vector `json:"pos"` + Rot *Vector `json:"rot"` + Level int32 `json:"level"` + AreaId int32 `json:"area_id"` + PointType int32 `json:"point_type"` // 关联GatherData表 + State int32 `json:"state"` + VisionLevel int32 `json:"vision_level"` + DropTag string `json:"drop_tag"` } type Region struct { @@ -185,6 +134,22 @@ type Trigger struct { TriggerCount int32 `json:"trigger_count"` } +type SuiteLuaTable struct { + MonsterConfigIdList any `json:"monsters"` // 怪物 + GadgetConfigIdList any `json:"gadgets"` // 物件 + RegionConfigIdList any `json:"regions"` // 区域 + TriggerNameList any `json:"triggers"` // 触发器 + RandWeight int32 `json:"rand_weight"` +} + +type Suite struct { + MonsterConfigIdList []int32 + GadgetConfigIdList []int32 + RegionConfigIdList []int32 + TriggerNameList []string + RandWeight int32 +} + func (g *GameDataConfig) loadGroup(group *Group, block *Block, sceneId int32, blockId int32) { sceneLuaPrefix := g.luaPrefix + "scene/" sceneIdStr := strconv.Itoa(int(sceneId)) @@ -197,55 +162,120 @@ func (g *GameDataConfig) loadGroup(group *Group, block *Block, sceneId int32, bl } group.LuaStr = string(groupLuaData) luaState := newLuaState(group.LuaStr) + // init_config + group.GroupInitConfig = new(GroupInitConfig) + ok := getSceneLuaConfigTable[*GroupInitConfig](luaState, "init_config", group.GroupInitConfig) + if !ok { + logger.Error("get init_config object error, sceneId: %v, blockId: %v, groupId: %v", sceneId, blockId, groupId) + luaState.Close() + return + } // monsters - group.MonsterList = make([]*Monster, 0) - ok := getSceneLuaConfigTable[*[]*Monster](luaState, "monsters", &group.MonsterList) + monsterList := make([]*Monster, 0) + ok = getSceneLuaConfigTable[*[]*Monster](luaState, "monsters", &monsterList) if !ok { logger.Error("get monsters object error, sceneId: %v, blockId: %v, groupId: %v", sceneId, blockId, groupId) luaState.Close() return } - for _, monster := range group.MonsterList { - monster.ObjectId = atomic.AddUint64(&OBJECT_ID_COUNTER, 1) + group.MonsterMap = make(map[int32]*Monster) + for _, monster := range monsterList { + group.MonsterMap[monster.ConfigId] = monster } // npcs - group.NpcList = make([]*Npc, 0) - ok = getSceneLuaConfigTable[*[]*Npc](luaState, "npcs", &group.NpcList) + npcList := make([]*Npc, 0) + ok = getSceneLuaConfigTable[*[]*Npc](luaState, "npcs", &npcList) if !ok { logger.Error("get npcs object error, sceneId: %v, blockId: %v, groupId: %v", sceneId, blockId, groupId) luaState.Close() return } - for _, npc := range group.NpcList { - npc.ObjectId = atomic.AddUint64(&OBJECT_ID_COUNTER, 1) + group.NpcMap = make(map[int32]*Npc) + for _, npc := range npcList { + group.NpcMap[npc.ConfigId] = npc } // gadgets - group.GadgetList = make([]*Gadget, 0) - ok = getSceneLuaConfigTable[*[]*Gadget](luaState, "gadgets", &group.GadgetList) + gadgetList := make([]*Gadget, 0) + ok = getSceneLuaConfigTable[*[]*Gadget](luaState, "gadgets", &gadgetList) if !ok { logger.Error("get gadgets object error, sceneId: %v, blockId: %v, groupId: %v", sceneId, blockId, groupId) luaState.Close() return } - for _, gadget := range group.GadgetList { - gadget.ObjectId = atomic.AddUint64(&OBJECT_ID_COUNTER, 1) + group.GadgetMap = make(map[int32]*Gadget) + for _, gadget := range gadgetList { + group.GadgetMap[gadget.ConfigId] = gadget } // regions - group.RegionList = make([]*Region, 0) - ok = getSceneLuaConfigTable[*[]*Region](luaState, "regions", &group.RegionList) + regionList := make([]*Region, 0) + ok = getSceneLuaConfigTable[*[]*Region](luaState, "regions", ®ionList) if !ok { logger.Error("get regions object error, sceneId: %v, blockId: %v, groupId: %v", sceneId, blockId, groupId) luaState.Close() return } + group.RegionMap = make(map[int32]*Region) + for _, region := range regionList { + group.RegionMap[region.ConfigId] = region + } // triggers - group.TriggerList = make([]*Trigger, 0) - ok = getSceneLuaConfigTable[*[]*Trigger](luaState, "triggers", &group.TriggerList) + triggerList := make([]*Trigger, 0) + ok = getSceneLuaConfigTable[*[]*Trigger](luaState, "triggers", &triggerList) if !ok { logger.Error("get triggers object error, sceneId: %v, blockId: %v, groupId: %v", sceneId, blockId, groupId) luaState.Close() return } + group.TriggerMap = make(map[string]*Trigger) + for _, trigger := range triggerList { + group.TriggerMap[trigger.Name] = trigger + } + // suites + suiteLuaTableList := make([]*SuiteLuaTable, 0) + ok = getSceneLuaConfigTable[*[]*SuiteLuaTable](luaState, "suites", &suiteLuaTableList) + if !ok { + logger.Error("get suites object error, sceneId: %v, blockId: %v, groupId: %v", sceneId, blockId, groupId) + luaState.Close() + return + } + if len(suiteLuaTableList) == 0 { + logger.Info("get suites object is nil, sceneId: %v, blockId: %v, groupId: %v", sceneId, blockId, groupId) + } + group.SuiteList = make([]*Suite, 0) + for _, suiteLuaTable := range suiteLuaTableList { + suite := &Suite{ + MonsterConfigIdList: make([]int32, 0), + GadgetConfigIdList: make([]int32, 0), + RegionConfigIdList: make([]int32, 0), + TriggerNameList: make([]string, 0), + RandWeight: suiteLuaTable.RandWeight, + } + idAnyList, ok := suiteLuaTable.MonsterConfigIdList.([]any) + if ok { + for _, idAny := range idAnyList { + suite.MonsterConfigIdList = append(suite.MonsterConfigIdList, int32(idAny.(float64))) + } + } + idAnyList, ok = suiteLuaTable.GadgetConfigIdList.([]any) + if ok { + for _, idAny := range idAnyList { + suite.GadgetConfigIdList = append(suite.GadgetConfigIdList, int32(idAny.(float64))) + } + } + idAnyList, ok = suiteLuaTable.RegionConfigIdList.([]any) + if ok { + for _, idAny := range idAnyList { + suite.RegionConfigIdList = append(suite.RegionConfigIdList, int32(idAny.(float64))) + } + } + nameAnyList, ok := suiteLuaTable.TriggerNameList.([]any) + if ok { + for _, nameAny := range nameAnyList { + suite.TriggerNameList = append(suite.TriggerNameList, nameAny.(string)) + } + } + group.SuiteList = append(group.SuiteList, suite) + } luaState.Close() block.groupMapLoadLock.Lock() block.GroupMap[group.Id] = group @@ -253,10 +283,12 @@ func (g *GameDataConfig) loadGroup(group *Group, block *Block, sceneId int32, bl } func (g *GameDataConfig) loadSceneLuaConfig() { - OBJECT_ID_COUNTER = 0 g.SceneLuaConfigMap = make(map[int32]*SceneLuaConfig) g.GroupMap = make(map[int32]*Group) g.LuaStateLruMap = make(map[int32]*LuaStateLru) + if !config.GetConfig().Hk4e.LoadSceneLuaConfig { + return + } sceneLuaPrefix := g.luaPrefix + "scene/" for _, sceneData := range g.SceneDataMap { sceneId := sceneData.SceneId @@ -345,9 +377,9 @@ func (g *GameDataConfig) loadSceneLuaConfig() { for _, scene := range g.SceneLuaConfigMap { for _, block := range scene.BlockMap { for _, group := range block.GroupMap { - monsterCount += len(group.MonsterList) - npcCount += len(group.NpcList) - gadgetCount += len(group.GadgetList) + monsterCount += len(group.MonsterMap) + npcCount += len(group.NpcMap) + gadgetCount += len(group.GadgetMap) groupCount++ } blockCount++ @@ -373,3 +405,61 @@ func GetSceneGroup(groupId int32) *Group { } return groupConfig } + +const ( + LuaStateLruKeepNum = 10 +) + +type LuaStateLru struct { + GroupId int32 + AccessTime int64 +} + +type LuaStateLruList []*LuaStateLru + +func (l LuaStateLruList) Len() int { + return len(l) +} + +func (l LuaStateLruList) Less(i, j int) bool { + return l[i].AccessTime < l[j].AccessTime +} + +func (l LuaStateLruList) Swap(i, j int) { + l[i], l[j] = l[j], l[i] +} + +func LuaStateLruRemove() { + removeNum := len(CONF.LuaStateLruMap) - LuaStateLruKeepNum + if removeNum <= 0 { + return + } + luaStateLruList := make(LuaStateLruList, 0) + for _, luaStateLru := range CONF.LuaStateLruMap { + luaStateLruList = append(luaStateLruList, luaStateLru) + } + sort.Stable(luaStateLruList) + for i := 0; i < removeNum; i++ { + luaStateLru := luaStateLruList[i] + group := GetSceneGroup(luaStateLru.GroupId) + group.LuaState = nil + delete(CONF.LuaStateLruMap, luaStateLru.GroupId) + } + logger.Info("lua state lru remove finish, remove num: %v", removeNum) +} + +func (g *Group) GetLuaState() *lua.LState { + CONF.LuaStateLruMap[g.Id] = &LuaStateLru{ + GroupId: g.Id, + AccessTime: time.Now().UnixMilli(), + } + if g.LuaState == nil { + g.LuaState = newLuaState(g.LuaStr) + scriptLib := g.LuaState.NewTable() + g.LuaState.SetGlobal("ScriptLib", scriptLib) + for _, scriptLibFunc := range SCRIPT_LIB_FUNC_LIST { + g.LuaState.SetField(scriptLib, scriptLibFunc.fnName, g.LuaState.NewFunction(scriptLibFunc.fn)) + } + } + return g.LuaState +} diff --git a/gdconf/scene_tag_data.go b/gdconf/scene_tag_data.go index d640cedd..c5a14c0e 100644 --- a/gdconf/scene_tag_data.go +++ b/gdconf/scene_tag_data.go @@ -13,9 +13,8 @@ type SceneTagData struct { func (g *GameDataConfig) loadSceneTagData() { g.SceneTagDataMap = make(map[int32]*SceneTagData) sceneTagDataList := make([]*SceneTagData, 0) - readTable[SceneTagData](g.tablePrefix+"SceneTagData.txt", &sceneTagDataList) + readTable[SceneTagData](g.txtPrefix+"SceneTagData.txt", &sceneTagDataList) for _, sceneTagData := range sceneTagDataList { - // list -> map g.SceneTagDataMap[sceneTagData.SceneTagId] = sceneTagData } logger.Info("SceneTagData count: %v", len(g.SceneTagDataMap)) diff --git a/gdconf/trigger_data.go b/gdconf/trigger_data.go index 7ebf1311..6d7566af 100644 --- a/gdconf/trigger_data.go +++ b/gdconf/trigger_data.go @@ -15,7 +15,7 @@ type TriggerData struct { func (g *GameDataConfig) loadTriggerData() { g.TriggerDataMap = make(map[int32]*TriggerData) triggerDataList := make([]*TriggerData, 0) - readTable[TriggerData](g.tablePrefix+"TriggerData.txt", &triggerDataList) + readTable[TriggerData](g.txtPrefix+"TriggerData.txt", &triggerDataList) for _, triggerData := range triggerDataList { g.TriggerDataMap[triggerData.TriggerId] = triggerData } diff --git a/gdconf/weapon_level_data.go b/gdconf/weapon_level_data.go index 1c9ee386..a055a1fc 100644 --- a/gdconf/weapon_level_data.go +++ b/gdconf/weapon_level_data.go @@ -19,9 +19,8 @@ type WeaponLevelData struct { func (g *GameDataConfig) loadWeaponLevelData() { g.WeaponLevelDataMap = make(map[int32]*WeaponLevelData) weaponLevelDataList := make([]*WeaponLevelData, 0) - readTable[WeaponLevelData](g.tablePrefix+"WeaponLevelData.txt", &weaponLevelDataList) + readTable[WeaponLevelData](g.txtPrefix+"WeaponLevelData.txt", &weaponLevelDataList) for _, weaponLevelData := range weaponLevelDataList { - // list -> map weaponLevelData.ExpByStarMap = map[uint32]uint32{ 1: uint32(weaponLevelData.ExpByStar1), 2: uint32(weaponLevelData.ExpByStar2), diff --git a/gdconf/weapon_promote_data.go b/gdconf/weapon_promote_data.go index 0664c3f9..28cbf06c 100644 --- a/gdconf/weapon_promote_data.go +++ b/gdconf/weapon_promote_data.go @@ -24,9 +24,8 @@ type WeaponPromoteData struct { func (g *GameDataConfig) loadWeaponPromoteData() { g.WeaponPromoteDataMap = make(map[int32]map[int32]*WeaponPromoteData) weaponPromoteDataList := make([]*WeaponPromoteData, 0) - readTable[WeaponPromoteData](g.tablePrefix+"WeaponPromoteData.txt", &weaponPromoteDataList) + readTable[WeaponPromoteData](g.txtPrefix+"WeaponPromoteData.txt", &weaponPromoteDataList) for _, weaponPromoteData := range weaponPromoteDataList { - // list -> map _, ok := g.WeaponPromoteDataMap[weaponPromoteData.PromoteId] if !ok { g.WeaponPromoteDataMap[weaponPromoteData.PromoteId] = make(map[int32]*WeaponPromoteData) diff --git a/gdconf/world_area_data.go b/gdconf/world_area_data.go index a3a2cc0e..6684bd3e 100644 --- a/gdconf/world_area_data.go +++ b/gdconf/world_area_data.go @@ -15,9 +15,8 @@ type WorldAreaData struct { func (g *GameDataConfig) loadWorldAreaData() { g.WorldAreaDataMap = make(map[int32]*WorldAreaData) worldAreaDataList := make([]*WorldAreaData, 0) - readTable[WorldAreaData](g.tablePrefix+"WorldAreaData.txt", &worldAreaDataList) + readTable[WorldAreaData](g.txtPrefix+"WorldAreaData.txt", &worldAreaDataList) for _, worldAreaData := range worldAreaDataList { - // list -> map g.WorldAreaDataMap[worldAreaData.WorldAreaId] = worldAreaData } logger.Info("WorldAreaData count: %v", len(g.WorldAreaDataMap)) diff --git a/gs/game/audio_video.go b/gs/game/audio_video.go index 37307408..ddec19cf 100644 --- a/gs/game/audio_video.go +++ b/gs/game/audio_video.go @@ -4,12 +4,12 @@ import ( "image" "image/color" "image/jpeg" - "math" "os" "sort" "strconv" "time" + "hk4e/common/constant" "hk4e/pkg/logger" "hk4e/gs/model" @@ -297,8 +297,6 @@ func LoadFrameFile() error { return nil } -var OBJECT_ID_COUNTER uint64 = math.MaxUint64 - func UpdateFrame(rgb bool) { err := LoadFrameFile() if err != nil { @@ -323,13 +321,12 @@ func UpdateFrame(rgb bool) { for w := 0; w < SCREEN_WIDTH; w++ { for h := 0; h < SCREEN_HEIGHT; h++ { // 创建像素点 - OBJECT_ID_COUNTER++ if rgb { entityId := scene.CreateEntityGadgetNormal(&model.Vector{ X: leftTopPos.X - float64(w)*SCREEN_DPI, Y: leftTopPos.Y - float64(h)*SCREEN_DPI, Z: leftTopPos.Z, - }, new(model.Vector), uint32(FRAME_COLOR[w][h]), 271003, OBJECT_ID_COUNTER) + }, new(model.Vector), uint32(FRAME_COLOR[w][h]), 271003, uint32(constant.GADGET_STATE_DEFAULT), 0) SCREEN_ENTITY_ID_LIST = append(SCREEN_ENTITY_ID_LIST, entityId) } else { if !FRAME[w][h] { @@ -337,7 +334,7 @@ func UpdateFrame(rgb bool) { X: leftTopPos.X - float64(w)*SCREEN_DPI, Y: leftTopPos.Y - float64(h)*SCREEN_DPI, Z: leftTopPos.Z, - }, new(model.Vector), uint32(GADGET_ID), 271003, OBJECT_ID_COUNTER) + }, new(model.Vector), uint32(GADGET_ID), 271003, uint32(constant.GADGET_STATE_DEFAULT), 0) SCREEN_ENTITY_ID_LIST = append(SCREEN_ENTITY_ID_LIST, entityId) } } diff --git a/gs/game/player_fight_sync.go b/gs/game/player_fight_sync.go index 44ee67a0..8f00b950 100644 --- a/gs/game/player_fight_sync.go +++ b/gs/game/player_fight_sync.go @@ -167,6 +167,11 @@ func (g *GameManager) CombatInvocationsNotify(player *model.Player, payloadMsg p X: float64(motionInfo.Pos.X), Y: float64(motionInfo.Pos.Y), Z: float64(motionInfo.Pos.Z), + }) + g.TriggerCheck(player, player.Pos, &model.Vector{ + X: float64(motionInfo.Pos.X), + Y: float64(motionInfo.Pos.Y), + Z: float64(motionInfo.Pos.Z), }, sceneEntity.GetId()) // 更新玩家的位置信息 player.Pos.X = float64(motionInfo.Pos.X) @@ -258,7 +263,7 @@ func (g *GameManager) CombatInvocationsNotify(player *model.Player, payloadMsg p } } -func (g *GameManager) AoiPlayerMove(player *model.Player, oldPos *model.Vector, newPos *model.Vector, entityId uint32) { +func (g *GameManager) AoiPlayerMove(player *model.Player, oldPos *model.Vector, newPos *model.Vector) { world := WORLD_MANAGER.GetWorldByID(player.WorldId) if world == nil { logger.Error("get player world is nil, uid: %v", player.PlayerID) @@ -281,167 +286,162 @@ func (g *GameManager) AoiPlayerMove(player *model.Player, oldPos *model.Vector, oldVisionGroupMap := make(map[uint32]*gdconf.Group) oldGroupList := aoiManager.GetObjectListByPos(float32(oldPos.X), 0.0, float32(oldPos.Z)) for groupId, groupAny := range oldGroupList { - group := groupAny.(*gdconf.Group) - distance2D := math.Sqrt(math.Pow(oldPos.X-float64(group.Pos.X), 2.0) + math.Pow(oldPos.Z-float64(group.Pos.Z), 2.0)) + groupConfig := groupAny.(*gdconf.Group) + distance2D := math.Sqrt((oldPos.X-float64(groupConfig.Pos.X))*(oldPos.X-float64(groupConfig.Pos.X)) + + (oldPos.Z-float64(groupConfig.Pos.Z))*(oldPos.Z-float64(groupConfig.Pos.Z))) if distance2D > ENTITY_LOD { continue } - if group.DynamicLoad { + if groupConfig.DynamicLoad { continue } - oldVisionGroupMap[uint32(groupId)] = group + oldVisionGroupMap[uint32(groupId)] = groupConfig } // 新位置视野范围内的group newVisionGroupMap := make(map[uint32]*gdconf.Group) newGroupList := aoiManager.GetObjectListByPos(float32(newPos.X), 0.0, float32(newPos.Z)) for groupId, groupAny := range newGroupList { - group := groupAny.(*gdconf.Group) - distance2D := math.Sqrt(math.Pow(newPos.X-float64(group.Pos.X), 2.0) + math.Pow(newPos.Z-float64(group.Pos.Z), 2.0)) + groupConfig := groupAny.(*gdconf.Group) + distance2D := math.Sqrt((newPos.X-float64(groupConfig.Pos.X))*(newPos.X-float64(groupConfig.Pos.X)) + + (newPos.Z-float64(groupConfig.Pos.Z))*(newPos.Z-float64(groupConfig.Pos.Z))) if distance2D > ENTITY_LOD { continue } - if group.DynamicLoad { + if groupConfig.DynamicLoad { continue } - newVisionGroupMap[uint32(groupId)] = group + newVisionGroupMap[uint32(groupId)] = groupConfig } // 消失的场景实体 delEntityIdList := make([]uint32, 0) - for groupId, group := range oldVisionGroupMap { + for groupId, groupConfig := range oldVisionGroupMap { _, exist := newVisionGroupMap[groupId] if exist { continue } // 旧有新没有的group即为消失的 - for _, monster := range group.MonsterList { - entity := scene.GetEntityByObjectId(monster.ObjectId) - if entity == nil { - continue - } - scene.DestroyEntity(entity.GetId()) - delEntityIdList = append(delEntityIdList, entity.GetId()) - } - for _, npc := range group.NpcList { - entity := scene.GetEntityByObjectId(npc.ObjectId) - if entity == nil { - continue - } - scene.DestroyEntity(entity.GetId()) - delEntityIdList = append(delEntityIdList, entity.GetId()) - } - for _, gadget := range group.GadgetList { - entity := scene.GetEntityByObjectId(gadget.ObjectId) - if entity == nil { - continue - } - scene.DestroyEntity(entity.GetId()) + group := scene.GetGroupById(groupId) + for _, entity := range group.GetAllEntity() { delEntityIdList = append(delEntityIdList, entity.GetId()) } + g.RemoveGroup(scene, groupConfig) } // 出现的场景实体 addEntityIdList := make([]uint32, 0) - for groupId, group := range newVisionGroupMap { + for groupId, groupConfig := range newVisionGroupMap { _, exist := oldVisionGroupMap[groupId] if exist { continue } // 新有旧没有的group即为出现的 - for _, monster := range group.MonsterList { - entityId := g.CreateConfigEntity(scene, monster.ObjectId, monster) - addEntityIdList = append(addEntityIdList, entityId) - } - for _, npc := range group.NpcList { - entityId := g.CreateConfigEntity(scene, npc.ObjectId, npc) - addEntityIdList = append(addEntityIdList, entityId) - } - for _, gadget := range group.GadgetList { - entityId := g.CreateConfigEntity(scene, gadget.ObjectId, gadget) - addEntityIdList = append(addEntityIdList, entityId) + g.AddSceneGroup(scene, groupConfig) + group := scene.GetGroupById(groupId) + for _, entity := range group.GetAllEntity() { + addEntityIdList = append(addEntityIdList, entity.GetId()) } } // 同步客户端消失和出现的场景实体 g.RemoveSceneEntityNotifyToPlayer(player, proto.VisionType_VISION_MISS, delEntityIdList) g.AddSceneEntityNotify(player, proto.VisionType_VISION_MEET, addEntityIdList, false, false) - // 场景区域触发器 - for _, group := range newVisionGroupMap { - for _, region := range group.RegionList { - shape := alg.NewShape() - switch uint8(region.Shape) { - case constant.REGION_SHAPE_SPHERE: - shape.NewSphere(&alg.Vector3{X: region.Pos.X, Y: region.Pos.Y, Z: region.Pos.Z}, region.Radius) - case constant.REGION_SHAPE_CUBIC: - shape.NewCubic(&alg.Vector3{X: region.Pos.X, Y: region.Pos.Y, Z: region.Pos.Z}, - &alg.Vector3{X: region.Size.X, Y: region.Size.Y, Z: region.Size.Z}) - case constant.REGION_SHAPE_CYLINDER: - shape.NewCylinder(&alg.Vector3{X: region.Pos.X, Y: region.Pos.Y, Z: region.Pos.Z}, - region.Radius, region.Height) - case constant.REGION_SHAPE_POLYGON: - vector2PointArray := make([]*alg.Vector2, 0) - for _, vector := range region.PointArray { - // z就是y - vector2PointArray = append(vector2PointArray, &alg.Vector2{X: vector.X, Z: vector.Y}) - } - shape.NewPolygon(&alg.Vector3{X: region.Pos.X, Y: region.Pos.Y, Z: region.Pos.Z}, - vector2PointArray, region.Height) - } - oldPosInRegion := shape.Contain(&alg.Vector3{ - X: float32(oldPos.X), - Y: float32(oldPos.Y), - Z: float32(oldPos.Z), - }) - newPosInRegion := shape.Contain(&alg.Vector3{ - X: float32(newPos.X), - Y: float32(newPos.Y), - Z: float32(newPos.Z), - }) - if !oldPosInRegion && newPosInRegion { - logger.Debug("player enter region: %v, uid: %v", region, player.PlayerID) - for _, trigger := range group.TriggerList { - if trigger.Event != constant.LUA_EVENT_ENTER_REGION { - continue +} + +// TriggerCheck 场景区域触发器检测 +func (g *GameManager) TriggerCheck(player *model.Player, oldPos *model.Vector, newPos *model.Vector, entityId uint32) { + world := WORLD_MANAGER.GetWorldByID(player.WorldId) + if world == nil { + logger.Error("get player world is nil, uid: %v", player.PlayerID) + return + } + scene := world.GetSceneById(player.SceneId) + for groupId, group := range scene.GetAllGroup() { + groupConfig := gdconf.GetSceneGroup(int32(groupId)) + if groupConfig == nil { + continue + } + for suiteId := range group.GetAllSuite() { + suiteConfig := groupConfig.SuiteList[suiteId-1] + for _, regionConfigId := range suiteConfig.RegionConfigIdList { + regionConfig := groupConfig.RegionMap[regionConfigId] + shape := alg.NewShape() + switch uint8(regionConfig.Shape) { + case constant.REGION_SHAPE_SPHERE: + shape.NewSphere(&alg.Vector3{X: regionConfig.Pos.X, Y: regionConfig.Pos.Y, Z: regionConfig.Pos.Z}, regionConfig.Radius) + case constant.REGION_SHAPE_CUBIC: + shape.NewCubic(&alg.Vector3{X: regionConfig.Pos.X, Y: regionConfig.Pos.Y, Z: regionConfig.Pos.Z}, + &alg.Vector3{X: regionConfig.Size.X, Y: regionConfig.Size.Y, Z: regionConfig.Size.Z}) + case constant.REGION_SHAPE_CYLINDER: + shape.NewCylinder(&alg.Vector3{X: regionConfig.Pos.X, Y: regionConfig.Pos.Y, Z: regionConfig.Pos.Z}, + regionConfig.Radius, regionConfig.Height) + case constant.REGION_SHAPE_POLYGON: + vector2PointArray := make([]*alg.Vector2, 0) + for _, vector := range regionConfig.PointArray { + // z就是y + vector2PointArray = append(vector2PointArray, &alg.Vector2{X: vector.X, Z: vector.Y}) } - if trigger.Condition != "" { - cond := CallLuaFunc(group.GetLuaState(), trigger.Condition, - &LuaCtx{uid: player.PlayerID}, - &LuaEvt{param1: region.ConfigId, targetEntityId: entityId}) - if !cond { + shape.NewPolygon(&alg.Vector3{X: regionConfig.Pos.X, Y: regionConfig.Pos.Y, Z: regionConfig.Pos.Z}, + vector2PointArray, regionConfig.Height) + } + oldPosInRegion := shape.Contain(&alg.Vector3{ + X: float32(oldPos.X), + Y: float32(oldPos.Y), + Z: float32(oldPos.Z), + }) + newPosInRegion := shape.Contain(&alg.Vector3{ + X: float32(newPos.X), + Y: float32(newPos.Y), + Z: float32(newPos.Z), + }) + if !oldPosInRegion && newPosInRegion { + logger.Debug("player enter region: %v, uid: %v", regionConfig, player.PlayerID) + for _, triggerName := range suiteConfig.TriggerNameList { + triggerConfig := groupConfig.TriggerMap[triggerName] + if triggerConfig.Event != constant.LUA_EVENT_ENTER_REGION { continue } - } - logger.Debug("scene group trigger fire, trigger: %v, uid: %v", trigger, player.PlayerID) - if trigger.Action != "" { - logger.Debug("scene group trigger do action, trigger: %v, uid: %v", trigger, player.PlayerID) - ok := CallLuaFunc(group.GetLuaState(), trigger.Action, - &LuaCtx{uid: player.PlayerID}, - &LuaEvt{}) - if !ok { - logger.Error("trigger action fail, trigger: %v, uid: %v", trigger, player.PlayerID) + if triggerConfig.Condition != "" { + cond := CallLuaFunc(groupConfig.GetLuaState(), triggerConfig.Condition, + &LuaCtx{uid: player.PlayerID}, + &LuaEvt{param1: regionConfig.ConfigId, targetEntityId: entityId}) + if !cond { + continue + } } + logger.Debug("scene group trigger fire, trigger: %v, uid: %v", triggerConfig, player.PlayerID) + if triggerConfig.Action != "" { + logger.Debug("scene group trigger do action, trigger: %v, uid: %v", triggerConfig, player.PlayerID) + ok := CallLuaFunc(groupConfig.GetLuaState(), triggerConfig.Action, + &LuaCtx{uid: player.PlayerID}, + &LuaEvt{}) + if !ok { + logger.Error("trigger action fail, trigger: %v, uid: %v", triggerConfig, player.PlayerID) + } + } + g.TriggerFire(player, triggerConfig) } - g.TriggerFire(player, trigger) - } - } else if oldPosInRegion && !newPosInRegion { - logger.Debug("player leave region: %v, uid: %v", region, player.PlayerID) - for _, trigger := range group.TriggerList { - if trigger.Event != constant.LUA_EVENT_LEAVE_REGION { - continue - } - if trigger.Condition != "" { - cond := CallLuaFunc(group.GetLuaState(), trigger.Condition, - &LuaCtx{uid: player.PlayerID}, - &LuaEvt{param1: region.ConfigId, targetEntityId: entityId}) - if !cond { + } else if oldPosInRegion && !newPosInRegion { + logger.Debug("player leave region: %v, uid: %v", regionConfig, player.PlayerID) + for _, triggerName := range suiteConfig.TriggerNameList { + triggerConfig := groupConfig.TriggerMap[triggerName] + if triggerConfig.Event != constant.LUA_EVENT_LEAVE_REGION { continue } - } - logger.Debug("scene group trigger fire, trigger: %v, uid: %v", trigger, player.PlayerID) - if trigger.Action != "" { - logger.Debug("scene group trigger do action, trigger: %v, uid: %v", trigger, player.PlayerID) - ok := CallLuaFunc(group.GetLuaState(), trigger.Action, - &LuaCtx{uid: player.PlayerID}, - &LuaEvt{}) - if !ok { - logger.Error("trigger action fail, trigger: %v, uid: %v", trigger, player.PlayerID) + if triggerConfig.Condition != "" { + cond := CallLuaFunc(groupConfig.GetLuaState(), triggerConfig.Condition, + &LuaCtx{uid: player.PlayerID}, + &LuaEvt{param1: regionConfig.ConfigId, targetEntityId: entityId}) + if !cond { + continue + } + } + logger.Debug("scene group trigger fire, trigger: %v, uid: %v", triggerConfig, player.PlayerID) + if triggerConfig.Action != "" { + logger.Debug("scene group trigger do action, trigger: %v, uid: %v", triggerConfig, player.PlayerID) + ok := CallLuaFunc(groupConfig.GetLuaState(), triggerConfig.Action, + &LuaCtx{uid: player.PlayerID}, + &LuaEvt{}) + if !ok { + logger.Error("trigger action fail, trigger: %v, uid: %v", triggerConfig, player.PlayerID) + } } } } diff --git a/gs/game/player_gacha.go b/gs/game/player_gacha.go index 991418c0..118c2e9f 100644 --- a/gs/game/player_gacha.go +++ b/gs/game/player_gacha.go @@ -382,7 +382,7 @@ func (g *GameManager) doGachaOnce(userId uint32, gachaType uint32, mustGetUpEnab } // 找到卡池对应的掉落组 - dropGroupDataConfig := gdconf.CONF.DropGroupDataMap[int32(gachaType)] + dropGroupDataConfig := gdconf.CONF.GachaDropGroupDataMap[int32(gachaType)] if dropGroupDataConfig == nil { logger.Error("drop group not found, drop id: %v", gachaType) return false, 0 @@ -417,7 +417,7 @@ func (g *GameManager) doGachaOnce(userId uint32, gachaType uint32, mustGetUpEnab PurpleTimesFixValue = WeaponPurpleTimesFixValue } if gachaPoolInfo.OrangeTimes >= OrangeTimesFixThreshold || gachaPoolInfo.PurpleTimes >= PurpleTimesFixThreshold { - fixDropGroupDataConfig := new(gdconf.DropGroupData) + fixDropGroupDataConfig := new(gdconf.GachaDropGroupData) fixDropGroupDataConfig.DropId = dropGroupDataConfig.DropId fixDropGroupDataConfig.WeightAll = dropGroupDataConfig.WeightAll // 计算4星和5星权重修正值 @@ -430,7 +430,7 @@ func (g *GameManager) doGachaOnce(userId uint32, gachaType uint32, mustGetUpEnab addPurpleWeight = 0 } for _, drop := range dropGroupDataConfig.DropConfig { - fixDrop := new(gdconf.Drop) + fixDrop := new(gdconf.GachaDrop) fixDrop.Result = drop.Result fixDrop.DropId = drop.DropId fixDrop.IsEnd = drop.IsEnd @@ -525,7 +525,7 @@ func (g *GameManager) doGachaOnce(userId uint32, gachaType uint32, mustGetUpEnab // 替换本次结果为5星大保底 if gachaPoolInfo.MustGetUpOrange { logger.Debug("trigger must get up orange, uid: %v", userId) - upOrangeDropGroupDataConfig := gdconf.CONF.DropGroupDataMap[upOrangeDropId] + upOrangeDropGroupDataConfig := gdconf.CONF.GachaDropGroupDataMap[upOrangeDropId] if upOrangeDropGroupDataConfig == nil { logger.Error("drop group not found, drop id: %v", upOrangeDropId) return false, 0 @@ -552,7 +552,7 @@ func (g *GameManager) doGachaOnce(userId uint32, gachaType uint32, mustGetUpEnab // 替换本次结果为4星大保底 if gachaPoolInfo.MustGetUpPurple { logger.Debug("trigger must get up purple, uid: %v", userId) - upPurpleDropGroupDataConfig := gdconf.CONF.DropGroupDataMap[upPurpleDropId] + upPurpleDropGroupDataConfig := gdconf.CONF.GachaDropGroupDataMap[upPurpleDropId] if upPurpleDropGroupDataConfig == nil { logger.Error("drop group not found, drop id: %v", upPurpleDropId) return false, 0 @@ -576,7 +576,7 @@ func (g *GameManager) doGachaOnce(userId uint32, gachaType uint32, mustGetUpEnab } // 走一次完整流程的掉落组 -func (g *GameManager) doFullRandDrop(dropGroupDataConfig *gdconf.DropGroupData) (bool, *gdconf.Drop) { +func (g *GameManager) doFullRandDrop(dropGroupDataConfig *gdconf.GachaDropGroupData) (bool, *gdconf.GachaDrop) { for { drop := g.doRandDropOnce(dropGroupDataConfig) if drop == nil { @@ -588,7 +588,7 @@ func (g *GameManager) doFullRandDrop(dropGroupDataConfig *gdconf.DropGroupData) return true, drop } // 进行下一步掉落流程 - dropGroupDataConfig = gdconf.CONF.DropGroupDataMap[drop.Result] + dropGroupDataConfig = gdconf.CONF.GachaDropGroupDataMap[drop.Result] if dropGroupDataConfig == nil { logger.Error("drop config tab exist error, invalid drop id: %v", drop.Result) return false, nil @@ -597,7 +597,7 @@ func (g *GameManager) doFullRandDrop(dropGroupDataConfig *gdconf.DropGroupData) } // 进行单次随机掉落 -func (g *GameManager) doRandDropOnce(dropGroupDataConfig *gdconf.DropGroupData) *gdconf.Drop { +func (g *GameManager) doRandDropOnce(dropGroupDataConfig *gdconf.GachaDropGroupData) *gdconf.GachaDrop { randNum := random.GetRandomInt32(0, dropGroupDataConfig.WeightAll-1) sumWeight := int32(0) // 轮盘选择法 diff --git a/gs/game/player_scene.go b/gs/game/player_scene.go index 6067f508..86915e5e 100644 --- a/gs/game/player_scene.go +++ b/gs/game/player_scene.go @@ -242,6 +242,21 @@ func (g *GameManager) SceneInitFinishReq(player *model.Player, payloadMsg pb.Mes player.SceneLoadState = model.SceneInitFinish } +func (g *GameManager) AddSceneGroup(scene *Scene, groupConfig *gdconf.Group) { + initSuiteId := int(groupConfig.GroupInitConfig.Suite) + if initSuiteId > len(groupConfig.SuiteList) { + return + } + scene.AddGroupSuite(uint32(groupConfig.Id), uint8(initSuiteId)) +} + +func (g *GameManager) RemoveGroup(scene *Scene, groupConfig *gdconf.Group) { + group := scene.GetGroupById(uint32(groupConfig.Id)) + for suiteId := range group.GetAllSuite() { + scene.RemoveGroupSuite(uint32(groupConfig.Id), suiteId) + } +} + func (g *GameManager) EnterSceneDoneReq(player *model.Player, payloadMsg pb.Message) { logger.Debug("player enter scene done, uid: %v", player.PlayerID) world := WORLD_MANAGER.GetWorldByID(player.WorldId) @@ -275,22 +290,15 @@ func (g *GameManager) EnterSceneDoneReq(player *model.Player, payloadMsg pb.Mess objectList := aoiManager.GetObjectListByPos(float32(player.Pos.X), 0.0, float32(player.Pos.Z)) for _, groupAny := range objectList { group := groupAny.(*gdconf.Group) - distance2D := math.Sqrt(math.Pow(player.Pos.X-float64(group.Pos.X), 2.0) + math.Pow(player.Pos.Z-float64(group.Pos.Z), 2.0)) + distance2D := math.Sqrt((player.Pos.X-float64(group.Pos.X))*(player.Pos.X-float64(group.Pos.X)) + + (player.Pos.Z-float64(group.Pos.Z))*(player.Pos.Z-float64(group.Pos.Z))) if distance2D > ENTITY_LOD { continue } if group.DynamicLoad { continue } - for _, monster := range group.MonsterList { - g.CreateConfigEntity(scene, monster.ObjectId, monster) - } - for _, npc := range group.NpcList { - g.CreateConfigEntity(scene, npc.ObjectId, npc) - } - for _, gadget := range group.GadgetList { - g.CreateConfigEntity(scene, gadget.ObjectId, gadget) - } + g.AddSceneGroup(scene, group) } } if player.SceneJump { @@ -385,64 +393,6 @@ func (g *GameManager) SceneEntityDrownReq(player *model.Player, payloadMsg pb.Me g.SendMsg(cmd.SceneEntityDrownRsp, player.PlayerID, player.ClientSeq, sceneEntityDrownRsp) } -// CreateConfigEntity 创建配置表里的实体 -func (g *GameManager) CreateConfigEntity(scene *Scene, objectId uint64, entityConfig any) uint32 { - switch entityConfig.(type) { - case *gdconf.Monster: - monster := entityConfig.(*gdconf.Monster) - return scene.CreateEntityMonster(&model.Vector{ - X: float64(monster.Pos.X), - Y: float64(monster.Pos.Y), - Z: float64(monster.Pos.Z), - }, &model.Vector{ - X: float64(monster.Rot.X), - Y: float64(monster.Rot.Y), - Z: float64(monster.Rot.Z), - }, uint32(monster.MonsterId), uint8(monster.Level), g.GetTempFightPropMap(), uint32(monster.ConfigId), objectId) - case *gdconf.Npc: - npc := entityConfig.(*gdconf.Npc) - return scene.CreateEntityNpc(&model.Vector{ - X: float64(npc.Pos.X), - Y: float64(npc.Pos.Y), - Z: float64(npc.Pos.Z), - }, &model.Vector{ - X: float64(npc.Rot.X), - Y: float64(npc.Rot.Y), - Z: float64(npc.Rot.Z), - }, uint32(npc.NpcId), 0, 0, 0, uint32(npc.ConfigId), objectId) - case *gdconf.Gadget: - gadget := entityConfig.(*gdconf.Gadget) - // 70500000并不是实际的装置id 根据节点类型对应采集物配置表 - if gadget.PointType != 0 && gadget.GadgetId == 70500000 { - gatherDataConfig := gdconf.GetGatherDataByPointType(gadget.PointType) - if gatherDataConfig == nil { - return 0 - } - return scene.CreateEntityGadgetGather(&model.Vector{ - X: float64(gadget.Pos.X), - Y: float64(gadget.Pos.Y), - Z: float64(gadget.Pos.Z), - }, &model.Vector{ - X: float64(gadget.Rot.X), - Y: float64(gadget.Rot.Y), - Z: float64(gadget.Rot.Z), - }, uint32(gatherDataConfig.GadgetId), uint32(gatherDataConfig.GatherId), uint32(gadget.ConfigId), objectId) - } else { - return scene.CreateEntityGadgetNormal(&model.Vector{ - X: float64(gadget.Pos.X), - Y: float64(gadget.Pos.Y), - Z: float64(gadget.Pos.Z), - }, &model.Vector{ - X: float64(gadget.Rot.X), - Y: float64(gadget.Rot.Y), - Z: float64(gadget.Rot.Z), - }, uint32(gadget.GadgetId), uint32(gadget.ConfigId), objectId) - } - default: - return 0 - } -} - func (g *GameManager) PacketPlayerEnterSceneNotifyLogin(player *model.Player, enterType proto.EnterType) *proto.PlayerEnterSceneNotify { world := WORLD_MANAGER.GetWorldByID(player.WorldId) scene := world.GetSceneById(player.SceneId) @@ -550,8 +500,8 @@ func (g *GameManager) AddSceneEntityNotifyBroadcast(player *model.Player, scene continue } g.SendMsg(cmd.SceneEntityAppearNotify, scenePlayer.PlayerID, scenePlayer.ClientSeq, sceneEntityAppearNotify) - // logger.Debug("SceneEntityAppearNotify, uid: %v, type: %v, len: %v", - // scenePlayer.PlayerID, sceneEntityAppearNotify.AppearType, len(sceneEntityAppearNotify.EntityList)) + logger.Debug("SceneEntityAppearNotify, uid: %v, type: %v, len: %v", + scenePlayer.PlayerID, sceneEntityAppearNotify.AppearType, len(sceneEntityAppearNotify.EntityList)) } } @@ -561,8 +511,8 @@ func (g *GameManager) RemoveSceneEntityNotifyToPlayer(player *model.Player, visi DisappearType: visionType, } g.SendMsg(cmd.SceneEntityDisappearNotify, player.PlayerID, player.ClientSeq, sceneEntityDisappearNotify) - // logger.Debug("SceneEntityDisappearNotify, uid: %v, type: %v, len: %v", - // player.PlayerID, sceneEntityDisappearNotify.DisappearType, len(sceneEntityDisappearNotify.EntityList)) + logger.Debug("SceneEntityDisappearNotify, uid: %v, type: %v, len: %v", + player.PlayerID, sceneEntityDisappearNotify.DisappearType, len(sceneEntityDisappearNotify.EntityList)) } func (g *GameManager) RemoveSceneEntityNotifyBroadcast(scene *Scene, visionType proto.VisionType, entityIdList []uint32) { @@ -995,9 +945,9 @@ func (g *GameManager) PacketSceneGadgetInfoNormal(entity *Entity) *proto.SceneGa gadgetEntity := entity.GetGadgetEntity() sceneGadgetInfo := &proto.SceneGadgetInfo{ GadgetId: gadgetEntity.GetGadgetId(), - GroupId: 0, + GroupId: entity.GetGroupId(), ConfigId: entity.GetConfigId(), - GadgetState: 0, + GadgetState: gadgetEntity.GetGadgetState(), IsEnableInteract: true, AuthorityPeerId: 1, } @@ -1014,9 +964,9 @@ func (g *GameManager) PacketSceneGadgetInfoGather(entity *Entity) *proto.SceneGa } sceneGadgetInfo := &proto.SceneGadgetInfo{ GadgetId: gadgetEntity.GetGadgetId(), - GroupId: 0, + GroupId: entity.GetGroupId(), ConfigId: entity.GetConfigId(), - GadgetState: 0, + GadgetState: gadgetEntity.GetGadgetState(), IsEnableInteract: true, AuthorityPeerId: 1, Content: &proto.SceneGadgetInfo_GatherGadget{ @@ -1071,24 +1021,3 @@ func (g *GameManager) PacketDelTeamEntityNotify(scene *Scene, player *model.Play } return delTeamEntityNotify } - -func (g *GameManager) GetTempFightPropMap() map[uint32]float32 { - fpm := map[uint32]float32{ - constant.FIGHT_PROP_CUR_HP: float32(72.91699), - constant.FIGHT_PROP_PHYSICAL_SUB_HURT: float32(0.1), - constant.FIGHT_PROP_CUR_DEFENSE: float32(505.0), - constant.FIGHT_PROP_CUR_ATTACK: float32(45.679916), - constant.FIGHT_PROP_ICE_SUB_HURT: float32(0.1), - constant.FIGHT_PROP_BASE_ATTACK: float32(45.679916), - constant.FIGHT_PROP_MAX_HP: float32(72.91699), - constant.FIGHT_PROP_FIRE_SUB_HURT: float32(0.1), - constant.FIGHT_PROP_ELEC_SUB_HURT: float32(0.1), - constant.FIGHT_PROP_WIND_SUB_HURT: float32(0.1), - constant.FIGHT_PROP_ROCK_SUB_HURT: float32(0.1), - constant.FIGHT_PROP_GRASS_SUB_HURT: float32(0.1), - constant.FIGHT_PROP_WATER_SUB_HURT: float32(0.1), - constant.FIGHT_PROP_BASE_HP: float32(72.91699), - constant.FIGHT_PROP_BASE_DEFENSE: float32(505.0), - } - return fpm -} diff --git a/gs/game/player_vehicle.go b/gs/game/player_vehicle.go index 51e2fcf8..17d99dcc 100644 --- a/gs/game/player_vehicle.go +++ b/gs/game/player_vehicle.go @@ -59,7 +59,7 @@ func (g *GameManager) CreateVehicleReq(player *model.Player, payloadMsg pb.Messa // 创建载具实体 pos := &model.Vector{X: float64(req.Pos.X), Y: float64(req.Pos.Y), Z: float64(req.Pos.Z)} rot := &model.Vector{X: float64(req.Rot.X), Y: float64(req.Rot.Y), Z: float64(req.Rot.Z)} - entityId := scene.CreateEntityGadgetVehicle(player.PlayerID, pos, rot, req.VehicleId) + entityId := scene.CreateEntityGadgetVehicle(player, pos, rot, req.VehicleId) if entityId == 0 { logger.Error("vehicle entityId is 0, uid: %v", player.PlayerID) g.SendError(cmd.VehicleInteractRsp, player, &proto.VehicleInteractRsp{}) diff --git a/gs/game/world_manager.go b/gs/game/world_manager.go index cd73184f..b1c9c049 100644 --- a/gs/game/world_manager.go +++ b/gs/game/world_manager.go @@ -717,14 +717,14 @@ func (w *World) RemoveWaitPlayer(uid uint32) { func (w *World) CreateScene(sceneId uint32) *Scene { scene := &Scene{ - id: sceneId, - world: w, - playerMap: make(map[uint32]*model.Player), - entityMap: make(map[uint32]*Entity), - objectIdEntityMap: make(map[uint64]*Entity), - gameTime: 18 * 60, - createTime: time.Now().UnixMilli(), - meeoIndex: 0, + id: sceneId, + world: w, + playerMap: make(map[uint32]*model.Player), + entityMap: make(map[uint32]*Entity), + groupMap: make(map[uint32]*Group), + gameTime: 18 * 60, + createTime: time.Now().UnixMilli(), + meeoIndex: 0, } w.sceneMap[sceneId] = scene return scene diff --git a/gs/game/world_scene.go b/gs/game/world_scene.go index c044bb72..da7564f7 100644 --- a/gs/game/world_scene.go +++ b/gs/game/world_scene.go @@ -5,6 +5,7 @@ import ( "time" "hk4e/common/constant" + "hk4e/gdconf" "hk4e/gs/model" "hk4e/pkg/logger" "hk4e/protocol/cmd" @@ -13,14 +14,40 @@ import ( // Scene 场景数据结构 type Scene struct { - id uint32 - world *World - playerMap map[uint32]*model.Player - entityMap map[uint32]*Entity - objectIdEntityMap map[uint64]*Entity // 用于标识配置档里的唯一实体是否已被创建 - gameTime uint32 // 游戏内提瓦特大陆的时间 - createTime int64 // 场景创建时间 - meeoIndex uint32 // 客户端风元素染色同步协议的计数器 + id uint32 + world *World + playerMap map[uint32]*model.Player + entityMap map[uint32]*Entity + groupMap map[uint32]*Group + gameTime uint32 // 游戏内提瓦特大陆的时间 + createTime int64 // 场景创建时间 + meeoIndex uint32 // 客户端风元素染色同步协议的计数器 +} + +type Group struct { + suiteMap map[uint8]*Suite +} + +func (g *Group) GetAllSuite() map[uint8]*Suite { + return g.suiteMap +} + +func (g *Group) GetAllEntity() map[uint32]*Entity { + entityMap := make(map[uint32]*Entity) + for _, suite := range g.suiteMap { + for _, entity := range suite.entityMap { + entityMap[entity.id] = entity + } + } + return entityMap +} + +type Suite struct { + entityMap map[uint32]*Entity +} + +func (s *Suite) GetAllEntity() map[uint32]*Entity { + return s.entityMap } func (s *Scene) GetId() uint32 { @@ -39,6 +66,14 @@ func (s *Scene) GetAllEntity() map[uint32]*Entity { return s.entityMap } +func (s *Scene) GetGroupById(groupId uint32) *Group { + return s.groupMap[groupId] +} + +func (s *Scene) GetAllGroup() map[uint32]*Group { + return s.groupMap +} + func (s *Scene) GetGameTime() uint32 { return s.gameTime } @@ -161,7 +196,7 @@ func (s *Scene) CreateEntityAvatar(player *model.Player, avatarId uint32) uint32 avatarId: avatarId, }, } - s.CreateEntity(entity, 0) + s.CreateEntity(entity) return entity.id } @@ -179,15 +214,11 @@ func (s *Scene) CreateEntityWeapon() uint32 { fightProp: nil, entityType: constant.ENTITY_TYPE_WEAPON, } - s.CreateEntity(entity, 0) + s.CreateEntity(entity) return entity.id } -func (s *Scene) CreateEntityMonster(pos, rot *model.Vector, monsterId uint32, level uint8, fightProp map[uint32]float32, configId uint32, objectId uint64) uint32 { - _, exist := s.objectIdEntityMap[objectId] - if exist { - return 0 - } +func (s *Scene) CreateEntityMonster(pos, rot *model.Vector, monsterId uint32, level uint8, fightProp map[uint32]float32, configId, groupId uint32) uint32 { entityId := s.world.GetNextWorldEntityId(constant.ENTITY_TYPE_MONSTER) entity := &Entity{ id: entityId, @@ -205,17 +236,13 @@ func (s *Scene) CreateEntityMonster(pos, rot *model.Vector, monsterId uint32, le monsterId: monsterId, }, configId: configId, - objectId: objectId, + groupId: groupId, } - s.CreateEntity(entity, objectId) + s.CreateEntity(entity) return entity.id } -func (s *Scene) CreateEntityNpc(pos, rot *model.Vector, npcId, roomId, parentQuestId, blockId, configId uint32, objectId uint64) uint32 { - _, exist := s.objectIdEntityMap[objectId] - if exist { - return 0 - } +func (s *Scene) CreateEntityNpc(pos, rot *model.Vector, npcId, roomId, parentQuestId, blockId, configId, groupId uint32) uint32 { entityId := s.world.GetNextWorldEntityId(constant.ENTITY_TYPE_NPC) entity := &Entity{ id: entityId, @@ -239,17 +266,13 @@ func (s *Scene) CreateEntityNpc(pos, rot *model.Vector, npcId, roomId, parentQue BlockId: blockId, }, configId: configId, - objectId: objectId, + groupId: groupId, } - s.CreateEntity(entity, objectId) + s.CreateEntity(entity) return entity.id } -func (s *Scene) CreateEntityGadgetNormal(pos, rot *model.Vector, gadgetId uint32, configId uint32, objectId uint64) uint32 { - _, exist := s.objectIdEntityMap[objectId] - if exist { - return 0 - } +func (s *Scene) CreateEntityGadgetNormal(pos, rot *model.Vector, gadgetId, gadgetState, configId, groupId uint32) uint32 { entityId := s.world.GetNextWorldEntityId(constant.ENTITY_TYPE_GADGET) entity := &Entity{ id: entityId, @@ -267,21 +290,18 @@ func (s *Scene) CreateEntityGadgetNormal(pos, rot *model.Vector, gadgetId uint32 }, entityType: constant.ENTITY_TYPE_GADGET, gadgetEntity: &GadgetEntity{ - gadgetId: gadgetId, - gadgetType: GADGET_TYPE_NORMAL, + gadgetId: gadgetId, + gadgetState: gadgetState, + gadgetType: GADGET_TYPE_NORMAL, }, configId: configId, - objectId: objectId, + groupId: groupId, } - s.CreateEntity(entity, objectId) + s.CreateEntity(entity) return entity.id } -func (s *Scene) CreateEntityGadgetGather(pos, rot *model.Vector, gadgetId uint32, gatherId uint32, configId uint32, objectId uint64) uint32 { - _, exist := s.objectIdEntityMap[objectId] - if exist { - return 0 - } +func (s *Scene) CreateEntityGadgetGather(pos, rot *model.Vector, gadgetId, gadgetState, gatherId, configId, groupId uint32) uint32 { entityId := s.world.GetNextWorldEntityId(constant.ENTITY_TYPE_GADGET) entity := &Entity{ id: entityId, @@ -299,20 +319,21 @@ func (s *Scene) CreateEntityGadgetGather(pos, rot *model.Vector, gadgetId uint32 }, entityType: constant.ENTITY_TYPE_GADGET, gadgetEntity: &GadgetEntity{ - gadgetId: gadgetId, - gadgetType: GADGET_TYPE_GATHER, + gadgetId: gadgetId, + gadgetState: gadgetState, + gadgetType: GADGET_TYPE_GATHER, gadgetGatherEntity: &GadgetGatherEntity{ gatherId: gatherId, }, }, configId: configId, - objectId: objectId, + groupId: groupId, } - s.CreateEntity(entity, objectId) + s.CreateEntity(entity) return entity.id } -func (s *Scene) CreateEntityGadgetClient(pos, rot *model.Vector, entityId uint32, configId, campId, campType, ownerEntityId, targetEntityId, propOwnerEntityId uint32) { +func (s *Scene) CreateEntityGadgetClient(pos, rot *model.Vector, entityId, configId, campId, campType, ownerEntityId, targetEntityId, propOwnerEntityId uint32) { entity := &Entity{ id: entityId, scene: s, @@ -340,15 +361,10 @@ func (s *Scene) CreateEntityGadgetClient(pos, rot *model.Vector, entityId uint32 }, }, } - s.CreateEntity(entity, 0) + s.CreateEntity(entity) } -func (s *Scene) CreateEntityGadgetVehicle(uid uint32, pos, rot *model.Vector, vehicleId uint32) uint32 { - player := USER_MANAGER.GetOnlineUser(uid) - if player == nil { - logger.Error("player is nil, uid: %v", uid) - return 0 - } +func (s *Scene) CreateEntityGadgetVehicle(player *model.Player, pos, rot *model.Vector, vehicleId uint32) uint32 { entityId := s.world.GetNextWorldEntityId(constant.ENTITY_TYPE_GADGET) entity := &Entity{ id: entityId, @@ -377,18 +393,15 @@ func (s *Scene) CreateEntityGadgetVehicle(uid uint32, pos, rot *model.Vector, ve }, }, } - s.CreateEntity(entity, 0) + s.CreateEntity(entity) return entity.id } -func (s *Scene) CreateEntity(entity *Entity, objectId uint64) { +func (s *Scene) CreateEntity(entity *Entity) { if len(s.entityMap) >= ENTITY_MAX_SEND_NUM && !ENTITY_NUM_UNLIMIT { logger.Error("above max scene entity num limit: %v, id: %v, pos: %v", ENTITY_MAX_SEND_NUM, entity.id, entity.pos) return } - if objectId != 0 { - s.objectIdEntityMap[objectId] = entity - } s.entityMap[entity.id] = entity } @@ -398,15 +411,145 @@ func (s *Scene) DestroyEntity(entityId uint32) { return } delete(s.entityMap, entity.id) - delete(s.objectIdEntityMap, entity.objectId) } func (s *Scene) GetEntity(entityId uint32) *Entity { return s.entityMap[entityId] } -func (s *Scene) GetEntityByObjectId(objectId uint64) *Entity { - return s.objectIdEntityMap[objectId] +func (s *Scene) AddGroupSuite(groupId uint32, suiteId uint8) { + groupConfig := gdconf.GetSceneGroup(int32(groupId)) + if groupConfig == nil { + return + } + suiteConfig := groupConfig.SuiteList[suiteId-1] + suite := &Suite{ + entityMap: make(map[uint32]*Entity), + } + for _, monsterConfigId := range suiteConfig.MonsterConfigIdList { + monster, exist := groupConfig.MonsterMap[monsterConfigId] + if !exist { + continue + } + entityId := s.createConfigEntity(uint32(groupConfig.Id), monster) + entity := s.GetEntity(entityId) + suite.entityMap[entityId] = entity + } + for _, gadgetConfigId := range suiteConfig.GadgetConfigIdList { + gadget, exist := groupConfig.GadgetMap[gadgetConfigId] + if !exist { + continue + } + entityId := s.createConfigEntity(uint32(groupConfig.Id), gadget) + entity := s.GetEntity(entityId) + suite.entityMap[entityId] = entity + } + for _, npc := range groupConfig.NpcMap { + entityId := s.createConfigEntity(uint32(groupConfig.Id), npc) + entity := s.GetEntity(entityId) + suite.entityMap[entityId] = entity + } + group, exist := s.groupMap[groupId] + if !exist { + group = &Group{ + suiteMap: make(map[uint8]*Suite), + } + } + group.suiteMap[suiteId] = suite +} + +func (s *Scene) RemoveGroupSuite(groupId uint32, suiteId uint8) { + group := s.groupMap[groupId] + if group == nil { + return + } + suite := group.suiteMap[suiteId] + if suite == nil { + return + } + for _, entity := range suite.entityMap { + s.DestroyEntity(entity.id) + } + delete(group.suiteMap, suiteId) +} + +// 创建配置表里的实体 +func (s *Scene) createConfigEntity(groupId uint32, entityConfig any) uint32 { + switch entityConfig.(type) { + case *gdconf.Monster: + monster := entityConfig.(*gdconf.Monster) + return s.CreateEntityMonster(&model.Vector{ + X: float64(monster.Pos.X), + Y: float64(monster.Pos.Y), + Z: float64(monster.Pos.Z), + }, &model.Vector{ + X: float64(monster.Rot.X), + Y: float64(monster.Rot.Y), + Z: float64(monster.Rot.Z), + }, uint32(monster.MonsterId), uint8(monster.Level), getTempFightPropMap(), uint32(monster.ConfigId), groupId) + case *gdconf.Npc: + npc := entityConfig.(*gdconf.Npc) + return s.CreateEntityNpc(&model.Vector{ + X: float64(npc.Pos.X), + Y: float64(npc.Pos.Y), + Z: float64(npc.Pos.Z), + }, &model.Vector{ + X: float64(npc.Rot.X), + Y: float64(npc.Rot.Y), + Z: float64(npc.Rot.Z), + }, uint32(npc.NpcId), 0, 0, 0, uint32(npc.ConfigId), groupId) + case *gdconf.Gadget: + gadget := entityConfig.(*gdconf.Gadget) + // 70500000并不是实际的装置id 根据节点类型对应采集物配置表 + if gadget.PointType != 0 && gadget.GadgetId == 70500000 { + gatherDataConfig := gdconf.GetGatherDataByPointType(gadget.PointType) + if gatherDataConfig == nil { + return 0 + } + return s.CreateEntityGadgetGather(&model.Vector{ + X: float64(gadget.Pos.X), + Y: float64(gadget.Pos.Y), + Z: float64(gadget.Pos.Z), + }, &model.Vector{ + X: float64(gadget.Rot.X), + Y: float64(gadget.Rot.Y), + Z: float64(gadget.Rot.Z), + }, uint32(gatherDataConfig.GadgetId), uint32(constant.GADGET_STATE_DEFAULT), uint32(gatherDataConfig.GatherId), uint32(gadget.ConfigId), groupId) + } else { + return s.CreateEntityGadgetNormal(&model.Vector{ + X: float64(gadget.Pos.X), + Y: float64(gadget.Pos.Y), + Z: float64(gadget.Pos.Z), + }, &model.Vector{ + X: float64(gadget.Rot.X), + Y: float64(gadget.Rot.Y), + Z: float64(gadget.Rot.Z), + }, uint32(gadget.GadgetId), uint32(gadget.State), uint32(gadget.ConfigId), groupId) + } + default: + return 0 + } +} + +func getTempFightPropMap() map[uint32]float32 { + fpm := map[uint32]float32{ + constant.FIGHT_PROP_CUR_HP: float32(72.91699), + constant.FIGHT_PROP_PHYSICAL_SUB_HURT: float32(0.1), + constant.FIGHT_PROP_CUR_DEFENSE: float32(505.0), + constant.FIGHT_PROP_CUR_ATTACK: float32(45.679916), + constant.FIGHT_PROP_ICE_SUB_HURT: float32(0.1), + constant.FIGHT_PROP_BASE_ATTACK: float32(45.679916), + constant.FIGHT_PROP_MAX_HP: float32(72.91699), + constant.FIGHT_PROP_FIRE_SUB_HURT: float32(0.1), + constant.FIGHT_PROP_ELEC_SUB_HURT: float32(0.1), + constant.FIGHT_PROP_WIND_SUB_HURT: float32(0.1), + constant.FIGHT_PROP_ROCK_SUB_HURT: float32(0.1), + constant.FIGHT_PROP_GRASS_SUB_HURT: float32(0.1), + constant.FIGHT_PROP_WATER_SUB_HURT: float32(0.1), + constant.FIGHT_PROP_BASE_HP: float32(72.91699), + constant.FIGHT_PROP_BASE_DEFENSE: float32(505.0), + } + return fpm } // Entity 场景实体数据结构 @@ -426,8 +569,8 @@ type Entity struct { monsterEntity *MonsterEntity npcEntity *NpcEntity gadgetEntity *GadgetEntity - configId uint32 // 配置表相关 - objectId uint64 + configId uint32 // LUA配置相关 + groupId uint32 } func (e *Entity) GetId() uint32 { @@ -502,6 +645,10 @@ func (e *Entity) GetConfigId() uint32 { return e.configId } +func (e *Entity) GetGroupId() uint32 { + return e.groupId +} + type AvatarEntity struct { uid uint32 avatarId uint32 @@ -533,6 +680,7 @@ type NpcEntity struct { type GadgetEntity struct { gadgetType int gadgetId uint32 + gadgetState uint32 gadgetClientEntity *GadgetClientEntity gadgetGatherEntity *GadgetGatherEntity gadgetVehicleEntity *GadgetVehicleEntity @@ -546,6 +694,10 @@ func (g *GadgetEntity) GetGadgetId() uint32 { return g.gadgetId } +func (g *GadgetEntity) GetGadgetState() uint32 { + return g.gadgetState +} + func (g *GadgetEntity) GetGadgetClientEntity() *GadgetClientEntity { return g.gadgetClientEntity } diff --git a/pkg/alg/shape.go b/pkg/alg/shape.go index b7f9a260..c0942149 100644 --- a/pkg/alg/shape.go +++ b/pkg/alg/shape.go @@ -161,9 +161,9 @@ func regionCubicContainPos(cubic *RegionCubic, pos *Vector3) bool { // 检测一个点是否在球体内 func regionSphereContainPos(sphere *RegionSphere, pos *Vector3) bool { - distance3D := math.Sqrt(math.Pow(float64(sphere.pos.X-pos.X), 2) + - math.Pow(float64(sphere.pos.Y-pos.Y), 2) + - math.Pow(float64(sphere.pos.Z-pos.Z), 2)) + distance3D := math.Sqrt(float64(sphere.pos.X-pos.X)*float64(sphere.pos.X-pos.X) + + float64(sphere.pos.Y-pos.Y)*float64(sphere.pos.Y-pos.Y) + + float64(sphere.pos.Z-pos.Z)*float64(sphere.pos.Z-pos.Z)) if float32(distance3D) < sphere.radius { return true } else { @@ -173,8 +173,8 @@ func regionSphereContainPos(sphere *RegionSphere, pos *Vector3) bool { // 检测一个点是否在圆柱体内 func regionCylinderContainPos(cylinder *RegionCylinder, pos *Vector3) bool { - distance2D := math.Sqrt(math.Pow(float64(cylinder.pos.X-pos.X), 2) + - math.Pow(float64(cylinder.pos.Z-pos.Z), 2)) + distance2D := math.Sqrt(float64(cylinder.pos.X-pos.X)*float64(cylinder.pos.X-pos.X) + + float64(cylinder.pos.Z-pos.Z)*float64(cylinder.pos.Z-pos.Z)) if float32(distance2D) >= cylinder.radius { return false }