Godot 4.0 alpha 14
数据管家,暂时只想到了用于管理物品数据
数据状态
#============================================================
# Data State
#============================================================
# - datetime: 2022-08-24 12:46:54
#============================================================
## 数据状态。操作数据时的数据的状态,对数据进行修改以影响添加时的内容
class_name DataState
## 当前的数据
var data : Dictionary
## 是否是新的数据
var is_new := false
## 是否要添加这个数据
var add := true
## 是否已经添加过了
var is_added := false
数据管家
#============================================================
# Data Steward
#============================================================
# - datetime: 2022-08-23 23:42:06
#============================================================
## 数据管家
class_name DataSteward
extends Node
## 操作数据。如果对 state 的属性进行修改会影响后面添加时的操作
signal operation_data(state: DataState)
## 属性发生改变
signal property_changed(id, old_data: Dictionary, new_data: Dictionary)
# ID key
var __id_key
# ID 到数据的映射
var __id_to_data_map : Dictionary = {}
# 分组 key 列表
var __group_key_list : Array = []
# 分组数据
var __group_value_to_data_map : Dictionary = {}
#============================================================
# SetGet
#============================================================
## 添加 ID。可以通过这个 Key 的值获取到对应的数据
func set_id_key(key):
assert(__id_key == null, "只能设置一次 ID key")
__id_key = key
## 获取 ID key
func get_id_key():
return __id_key
## 获取数据
##[br]
##[br][code]id_value[/code] ID 值
func get_data(id_value) -> Dictionary:
return __id_to_data_map.get(id_value)
## 获取所有数据
func get_all_data() -> Dictionary:
return __id_to_data_map
## 获取数据列表
func get_data_list() -> Array[Dictionary]:
return __id_to_data_map.values()
## 获取这个组中的数据
##[br]
##[br][code]group_key[/code] 这个组的key
##[br][code]group_value[/code] 这个组的 Key 包含有的值
func get_data_by_group(group_key, group_value) -> Array[Dictionary]:
return __group_value_to_data_map.get(group_key, {}).get(group_value, {}).keys()
## 筛选
##[br]
##[br][code]condition[/code] 条件方法。这个方法需要有一个 [code]Dictionary[/code] 类型的参数用于接收判断数据,
## 并返回 [code]bool[/code] 类型结果
func filter(condition: Callable) -> Array[Dictionary]:
var list : Array[Dictionary] = []
for data in get_data_list():
if condition.call(data):
list.append(data)
return list
## 获取这个组中符合条件的数据数据
##[br]
##[br][code]condition[/code] 条件数据。只要 [code]condition[/code] 里的数据都包含于数据中则符合条件
func filter_by_dict(condition: Dictionary) -> Array[Dictionary]:
var list : Array[Dictionary] = []
var condi_hash := condition.hash()
var temp := {}
for data in get_data_list():
for k in condition:
temp[k] = data[k]
if temp.hash() == condi_hash:
list.append(data)
return list
#============================================================
# 自定义
#============================================================
# 新的数据
func __new_data(state: DataState):
operation_data.emit(state)
if state.add:
if state.is_new:
__id_to_data_map[state.data[__id_key]] = state.data
# 数据发生改变
property_changed.emit(state.data[__id_key], {}, state.data)
else:
__add_data(state)
# 追加数据
func __add_data(state: DataState):
operation_data.emit(state)
if state.add:
if state.is_new:
__new_data(state)
else:
# 获取数据
var id_to_data := __id_to_data_map[state.data[__id_key]] as Dictionary
# 记录为旧数据
var old_data = id_to_data.duplicate(true)
# 追加数据值
for key in state.data:
if typeof(state.data[key]) in [TYPE_FLOAT, TYPE_INT]:
if id_to_data.has(key):
id_to_data[key] += state.data[key]
else:
id_to_data[key] = state.data[key]
# 数据发生改变
if old_data.hash() != id_to_data.hash():
property_changed.emit(state.data[__id_key], old_data, id_to_data)
# 添加到分组中
func __add_to_group(dict: Dictionary):
var group_data : Dictionary
var group_value
for group_key in __group_key_list:
# 获取这个组,并添加到这个组中
group_data = __group_value_to_data_map[group_key]
group_value = dict.get(group_key)
__group_value_to_data_map[group_key]
if group_value:
if not group_data.has(group_value):
group_data[group_value] = {}
group_data[group_value][dict] = null
## 添加组别 Key。通过这个 key 的值获取这个组里的所有数据
func add_group_key(group_key):
__group_key_list.append(group_key)
__group_value_to_data_map[group_key] = {}
## 添加数据
func add_data(dict: Dictionary):
var state := DataState.new()
state.data = dict
state.is_added = false
state.add = true
if __id_to_data_map.has(state.data[__id_key]):
state.is_new = false
__add_data(state)
else:
state.is_new = true
__new_data(state)
__add_to_group(state.data)
return state.data[__id_key]
## 根据ID添加数据
func add_data_by_id(id, dict: Dictionary):
dict[__id_key] = id
add_data(dict)
测试
测试代码,按 ctrl + shift + X 执行,或者点击脚本编辑上方的 文件-运行
#============================================================
# Demo
#============================================================
# - datetime: 2022-08-24 01:15:45
#============================================================
# 测试功能
@tool
extends EditorScript
func _run() -> void:
# 创建数据管家
var d = DataSteward.new()
# 设置数据的 ID,通过这个 ID key 的值获取对应的数据
d.set_id_key("name")
# 设置数据分组,通过这个组的 key 的值获取这个值的组的所有数据
# 比如数据中包含有 type 的 key,这个 key 里有 “食物”“武器”“药品”等
# 添加这个组别,将会对这个几个key进行分组,获取组别为“武器”,
# 将会得到这个组里的所有type的值为“武器”的数据
d.add_group_key("type")
# 操作数据,添加数据时会发出 operation_data 信号
d.operation_data.connect(func(state: DataState):
# 没有添加这个数据时
if not state.is_added:
# 没有 count 这个 key 时
if not state.data.has("count"):
# 我们对数据自动添加 count 键,就是物品的数量
state.data["count"] = 1
)
# 连接数据发生改变时,调用这个 lambda 表达式
d.property_changed.connect(func(id, old_data: Dictionary, new_data: Dictionary):
prints(" -> ", id, " 数据发生改变,新数据为:", new_data)
)
# 添加数据
d.add_data({
"name": "黄酒",
"type": "食物",
"health": 100,
"coin": 10,
})
d.add_data({
"name": "青铜剑",
"type": "武器",
"coin": 500,
})
d.add_data({
"name": "精钢剑",
"type": "武器",
"coin": 900,
})
# 获取所有数据
print(d.get_data_list())
print("-".repeat(40))
# 增加黄酒的 count 值
d.add_data({
"name":"黄酒",
"count": 10,
})
# 添加青铜剑的数量(也可以这样添加数据)
d.add_data_by_id("青铜剑", {
"count": 2,
})
# 获取“黄酒”的数据
print(d.get_data("黄酒"))
print("黄酒数量:", d.get_data("黄酒").get("count") )
# 获取所有 type 为 “武器” 的数据
print(d.get_data_by_group("type", "武器"))
# 筛选
print("价格超过400的物品:", d.filter(func(data: Dictionary):
return data.get('coin') > 400
) )
执行结果如下: