代码测试 2026年7月30日 1

This commit is contained in:
wenhe committed 2026-07-30 12:25:28 +08:00
1 parent 3c90a1c613
commit 842befe7dd
2 files changed
+155 -55

No files matched your search

@@ -41,10 +41,11 @@ from ...BlueFoxTools.SpecialFunciton.BlueFoxSystem import BlueFoxServerSystem
from ...BlueFoxTools.ToolsConfig import LevelId
# ---- 方块实体数据组件 ----
# 每个方块都可以存一点自定义数据(比如"翻炒了几次"),
# 这个组件就是读写这些数据的。LevelId 是全局唯一的标识符,
# 所有方块数据统一存在这个 LevelId 下,和之前的 Function.py 用同一个
blockEntityDataComp = comp.CreateBlockEntityData(LevelId)
# 每个方块都可以存一点自定义数据(比如"翻炒了几次")。
# GetBlockEntityData / SetBlockEntityData 都在 BlockInfo 组件上。
# 注意:CreateBlockEntityData 返回的组件只有 GetBlockEntityData(只读),
# 没有 SetBlockEntityData,所以必须用 CreateBlockInfo。
blockEntityDataComp = comp.CreateBlockInfo(LevelId)
# ---- 导入所有配方 ----
# RECIPES 是一个列表,每条配方是一个 dict,格式见 RecipeData.py 顶部注释
@@ -225,19 +226,18 @@ class CookingService(BlueFoxServerSystem):
# type="switch" 或 "timer" → 工具方块切换(箭桶、挂肉钩、水槽等)
# 没有 type 或 type="cook" → 做菜配方(炒锅、煎锅等)
# ---- 统一加载:把方块里的历史数据恢复到内存 ----
# 不管是做菜还是工具切换,先把方块数据加载到内存,后面直接用
self._loadBlockDataToMemory(key, playerId, pos, dim, recipe)
if recipeType == "switch" or recipeType == "timer":
self.handleSwitch(recipe, playerId, pos, dim, itemDict, key, blockName)
return
# ---- 第五步:以下为做菜配方逻辑 ----
# ---- 加载翻炒进度(如果这个方块之前翻过的话) ----
# 先从内存取,内存没有就从方块实体数据加载(服务器重启后恢复)
# 内存中已有数据(_loadBlockDataToMemory 已加载),直接用
stirInfo = self.stirData.get(key, {})
if not stirInfo:
stirInfo = self.loadStirData(playerId, pos, dim, recipe)
if stirInfo:
self.stirData[key] = stirInfo # 加载成功后写入内存缓存
# ---- 根据配方类型判断 ----
# needFinished=True 的配方 → 需要先翻炒熟了才能操作(比如出锅)
@@ -321,12 +321,13 @@ class CookingService(BlueFoxServerSystem):
return
# ---- 切换型 ----
# 获取当前方块的记录数据
# 内存中已有数据(_loadBlockDataToMemory 已加载),直接用
record = self.switchRecord.get(key)
# ---- 正向操作:往方块里放东西(source == 被右键的方块) ----
if recipe["source"] == blockName and recipe.get("item") is not None:
# 玩家手里有物品,往方块里放
needSave = False # 标记是否需要保存记录到方块
if recipe.get("record"):
if recipe.get("recordType") == "count":
# 数量记录型:只记录一种物品的总数
@@ -335,20 +336,18 @@ class CookingService(BlueFoxServerSystem):
"count": 0,
"itemName": itemDict["newItemName"],
}
self.switchRecord[key] = record
# 检查是否满了
maxCount = recipe.get("maxCount", 999)
if record["count"] >= maxCount:
return # 满了,不能再放
# 记录物品+1
record["count"] += 1
self.switchRecord[key] = record
needSave = True
elif recipe.get("recordType") == "stack":
# 堆栈记录型:后进先出,记录每种物品的完整信息
if not record:
record = {"stack": []}
self.switchRecord[key] = record
maxCount = recipe.get("maxCount", 999)
if len(record["stack"]) >= maxCount:
return # 满了
@@ -359,16 +358,20 @@ class CookingService(BlueFoxServerSystem):
"auxValue": itemDict.get("newAuxValue", 0),
"userData": itemDict.get("userData", {}),
})
self.switchRecord[key] = record
needSave = True
# 消耗物品
if recipe.get("consume", 1) > 0:
self.consumeItem(playerId, itemDict, recipe.get("consume", 1))
# 替换方块
# 替换方块(旧方块销毁,新方块出现)
if recipe.get("target"):
self.replaceBlock(pos, dim, recipe["target"], playerId)
# ★ 关键:替换完方块后再保存记录到新方块上,否则数据随旧方块一起销毁
if needSave:
self._saveRecord(key, playerId, pos, dim, record)
# 如果配方指定了给物品(如烧烤架浇水给桶)
if recipe.get("giveItem"):
self.giveItem(playerId, recipe["giveItem"])
@@ -377,6 +380,9 @@ class CookingService(BlueFoxServerSystem):
# ---- 逆向操作:从方块里取东西(空手右键或取回物品) ----
if recipe["source"] == blockName and recipe.get("item") is None:
needSaveRecord = False # 是否需要保存记录
needClearRecord = False # 是否需要清除记录
if recipe.get("record") and record:
if recipe.get("recordType") == "count":
# 数量记录型取回:给玩家对应的物品,数量-1
@@ -384,9 +390,9 @@ class CookingService(BlueFoxServerSystem):
self.giveItem(playerId, record["itemName"])
record["count"] -= 1
if record["count"] <= 0:
self.switchRecord.pop(key, None)
needClearRecord = True
else:
self.switchRecord[key] = record
needSaveRecord = True
elif recipe.get("recordType") == "stack":
# 堆栈记录型取回:后进先出,取最后一个放的物品
@@ -399,18 +405,24 @@ class CookingService(BlueFoxServerSystem):
"userData": topItem.get("userData", {})},
playerId)
if not record["stack"]:
self.switchRecord.pop(key, None)
needClearRecord = True
else:
self.switchRecord[key] = record
needSaveRecord = True
# 如果配方直接指定了给什么物品(水槽、盘子架取回、挂肉钩退回等)
if recipe.get("giveItem"):
self.giveItem(playerId, recipe["giveItem"])
# 替换方块
# 替换方块(旧方块销毁,新方块出现)
if recipe.get("target"):
self.replaceBlock(pos, dim, recipe["target"], playerId)
# ★ 关键:替换完方块后再保存/清除记录,否则数据随旧方块一起销毁
if needClearRecord:
self.clearSwitchRecord(key, playerId, pos, dim)
elif needSaveRecord:
self._saveRecord(key, playerId, pos, dim, record)
return
# ============================================================================
@@ -475,7 +487,7 @@ class CookingService(BlueFoxServerSystem):
- 熟了之后可以继续右键"出锅"(变成成品菜)
流程:
1. 从内存或方块数据加载当前翻炒进度
1. 从内存取翻炒进度(_loadBlockDataToMemory 已提前加载)
2. 检查冷却时间,没冷却好就忽略
3. 翻炒次数+1,更新进度
4. 给玩家发进度提示("翻炒中... 3/10")
@@ -483,17 +495,22 @@ class CookingService(BlueFoxServerSystem):
"""
now = time.time()
# ---- 第一步:加载或初始化翻炒数据 ----
data = self.stirData.get(key) or self.loadStirData(playerId, pos, dim, recipe)
# ---- 第一步:从内存取翻炒数据(入口已通过 _loadBlockDataToMemory 加载) ----
data = self.stirData.get(key)
if not data:
# 全新的翻炒,初始化数据
data = {
"count": 0, # 从0次开始
"lastTime": 0.0, # 上次翻的时间(初始为0,第一次翻不受冷却限制)
"finished": False, # 还没熟
"dropIfDone": recipe.get("dropIfDone", []), # 熟了拆掉掉什么
"dropIfNot": recipe.get("dropIfNot", []), # 没熟拆掉掉什么
"count": 0,
"lastTime": 0.0,
"finished": False,
"dropIfDone": recipe.get("dropIfDone", []),
"dropIfNot": recipe.get("dropIfNot", []),
}
else:
# 兜底防止 None 值(方块数据可能不完整)
for field, default in [("lastTime", 0.0), ("count", 0), ("finished", False)]:
if data.get(field) is None:
data[field] = default
self.stirData[key] = data
# ---- 第二步:冷却检查 ----
@@ -705,6 +722,61 @@ class CookingService(BlueFoxServerSystem):
except:
pass
# ============================================================================
# 通用持久化帮手(避免重复的 try/except/Get/Set 写法)
# ============================================================================
def _writeBlockData(self, dim, pos, **kwargs):
"""
通用方块实体数据写入:读 → 改 → 写。
把 saveStirData / clearStirData / saveSwitchRecord / clearSwitchRecord
四个方法里重复的 try/except/GetBlockEntityData/SetBlockEntityData 抽出来,
一行搞定,不用每次写一样的 try/except。
"""
try:
blockData = blockEntityDataComp.GetBlockEntityData(dim, pos)
if blockData is None:
blockData = {}
for key, value in kwargs.items():
blockData[key] = value
blockEntityDataComp.SetBlockEntityData(dim, pos, blockData)
except Exception as e:
print "[CookingService] _writeBlockData 写入失败: pos=%s dim=%s err=%s" % (pos, dim, str(e))
def _saveRecord(self, key, playerId, pos, dim, record):
"""
同时更新内存和方块实体数据中的工具方块记录。
替代原本重复出现的:
self.switchRecord[key] = record
self.saveSwitchRecord(playerId, pos, dim, record)
"""
self.switchRecord[key] = record
self.saveSwitchRecord(playerId, pos, dim, record)
# ============================================================================
# 统一数据加载入口(玩家右键方块时先把方块数据恢复到内存)
# ============================================================================
def _loadBlockDataToMemory(self, key, playerId, pos, dim, recipe):
"""
在确定玩家右键命中了一个配方后,立刻把方块里存的历史数据加载到内存。
这样 handleStir / handleSwitch 里就不用各自加载了,
直接从 self.stirData / self.switchRecord 取就行。
两个数据源互不干扰:翻炒数据用 stirData,工具切换记录用 switchRecord。
"""
if key not in self.stirData:
stirInfo = self.loadStirData(playerId, pos, dim, recipe)
if stirInfo:
self.stirData[key] = stirInfo
if key not in self.switchRecord:
switchInfo = self.loadSwitchRecord(playerId, pos, dim)
if switchInfo:
self.switchRecord[key] = switchInfo
# ============================================================================
# 翻炒数据持久化(存方块里,不存JSON文件)
# ============================================================================
@@ -742,40 +814,68 @@ class CookingService(BlueFoxServerSystem):
def saveStirData(self, playerId, pos, dim, data):
"""
把翻炒进度写入方块的实体数据。
每次翻炒后都调用一次,保证数据实时同步。
用方括号 [] 直接赋值,网易API会自动保存到方块中。
把翻炒进度写入方块实体数据。
"""
try:
blockData = blockEntityDataComp.GetBlockEntityData(dim, pos)
blockData["rtdd_sc"] = data["count"] # 保存翻炒次数
blockData["rtdd_slt"] = data["lastTime"] # 保存最后翻炒时间
blockData["rtdd_sf"] = data["finished"] # 保存是否熟了
except:
# 如果方块没有实体数据对象,忽略(下次加载会重新初始化)
pass
self._writeBlockData(dim, pos,
rtdd_sc=data["count"],
rtdd_slt=data["lastTime"],
rtdd_sf=data["finished"])
def clearStirData(self, key, playerId, pos, dim):
"""
清除方块上的翻炒数据。
调用时机:
- 方块被替换(比如炒锅变成了成品菜)
- 方块被拆掉(玩家把锅拆了)
同时清除内存和方块实体数据。
清除方块上的翻炒数据(内存+方块实体数据)。
"""
# 清除内存中的数据
self.stirData.pop(key, None)
# 清除方块实体数据(重置为初始值)
self._writeBlockData(dim, pos, rtdd_sc=0, rtdd_slt=0.0, rtdd_sf=False)
# ============================================================================
# 工具方块记录持久化(药水架、书柜、箭桶等)
# ============================================================================
def saveSwitchRecord(self, playerId, pos, dim, record):
"""
把工具方块的记录数据写入方块实体数据。
记录类型:count型(箭桶)→ rtdd_swt/swc/swi,stack型(书柜/药水架)→ rtdd_swt/sws
"""
if "count" in record:
self._writeBlockData(dim, pos,
rtdd_swt="count",
rtdd_swc=record["count"],
rtdd_swi=record.get("itemName", ""))
elif "stack" in record:
self._writeBlockData(dim, pos,
rtdd_swt="stack",
rtdd_sws=record["stack"])
def loadSwitchRecord(self, playerId, pos, dim):
"""
从方块实体数据里读取工具方块的记录数据。
返回:
有数据 → {"count": N, "itemName": "xxx"} 或 {"stack": [...]}
没有 → None
"""
try:
blockData = blockEntityDataComp.GetBlockEntityData(dim, pos)
blockData["rtdd_sc"] = 0
blockData["rtdd_slt"] = 0.0
blockData["rtdd_sf"] = False
swt = blockData["rtdd_swt"] # 记录类型:"count" 或 "stack"
if swt == "count":
return {
"count": blockData["rtdd_swc"],
"itemName": blockData["rtdd_swi"],
}
elif swt == "stack":
return {
"stack": blockData["rtdd_sws"],
}
except:
pass
return None
def clearSwitchRecord(self, key, playerId, pos, dim):
"""
清除工具方块的记录数据(内存+方块实体数据)。
"""
self.switchRecord.pop(key, None)
self._writeBlockData(dim, pos, rtdd_swt="", rtdd_swc=0, rtdd_swi="", rtdd_sws=[])
# ============================================================================
# 拆方块处理
+1 -1
View File
@@ -3,7 +3,7 @@
底座方块分析(锅下面是灶)
菜品做出后方块化
盘子 清洗/盛饭/放置
附魔书柜 放置/取回
附魔书柜 放置/取回 (1)
切菜
鳕鱼没有鲑鱼的晾干流程模型
水槽只有四个脏盘子和满水状态,没有满水放脏盘子的模型