场景group分suite加载、读取掉落表

This commit is contained in:
flswld
2023-03-21 23:03:00 +08:00
parent 62b929902d
commit f99d845d57
46 changed files with 1076 additions and 594 deletions

View File

@@ -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", &regionList)
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
}