配方 替换方块ceshi2
This commit is contained in:
1 parent
f79bd3f0e7
commit
2f79f08b97
1 file changed
+47
-79
@@ -24,6 +24,22 @@ comp = serverApi.GetEngineCompFactory()
|
|||||||
from ..RecipeData import RECIPES
|
from ..RecipeData import RECIPES
|
||||||
|
|
||||||
|
|
||||||
|
def _getUserDataField(itemDict, *keys):
|
||||||
|
"""
|
||||||
|
读取物品 dict 里的 userData 嵌套字段(纯本地操作,不调API)。
|
||||||
|
例如 _getUserDataField(itemDict, 'rtdd', 'oil') → 返回 itemDict['userData']['rtdd']['oil']
|
||||||
|
如果中间任何一层的 key 不存在,自动创建空 dict。
|
||||||
|
"""
|
||||||
|
itemDict['userData'] = itemDict.get('userData', {})
|
||||||
|
if itemDict.get('userData') is None:
|
||||||
|
itemDict['userData'] = {}
|
||||||
|
node = itemDict['userData']
|
||||||
|
for key in keys:
|
||||||
|
node[key] = node.get(key, {})
|
||||||
|
node = node[key]
|
||||||
|
return node
|
||||||
|
|
||||||
|
|
||||||
class CookingService(ServerSystem):
|
class CookingService(ServerSystem):
|
||||||
"""
|
"""
|
||||||
通用烹饪引擎
|
通用烹饪引擎
|
||||||
@@ -51,7 +67,6 @@ class CookingService(ServerSystem):
|
|||||||
self.UnListenEvent()
|
self.UnListenEvent()
|
||||||
|
|
||||||
def ListenEvent(self):
|
def ListenEvent(self):
|
||||||
"""注册事件监听:玩家右键方块、玩家拆方块"""
|
|
||||||
self.ListenForEvent(serverApi.GetEngineNamespace(),
|
self.ListenForEvent(serverApi.GetEngineNamespace(),
|
||||||
serverApi.GetEngineSystemName(),
|
serverApi.GetEngineSystemName(),
|
||||||
"ServerBlockUseEvent", self, self.OnBlockUse)
|
"ServerBlockUseEvent", self, self.OnBlockUse)
|
||||||
@@ -81,34 +96,25 @@ class CookingService(ServerSystem):
|
|||||||
dim = comp.CreateDimension(playerId).GetEntityDimensionId()
|
dim = comp.CreateDimension(playerId).GetEntityDimensionId()
|
||||||
key = (dim, x, y, z)
|
key = (dim, x, y, z)
|
||||||
|
|
||||||
# 获取玩家手里拿的物品
|
|
||||||
itemDict = self._getCarriedItem(playerId)
|
itemDict = self._getCarriedItem(playerId)
|
||||||
|
|
||||||
# 在配方列表里找匹配的配方
|
|
||||||
recipe = self._findRecipe(blockName, itemDict)
|
recipe = self._findRecipe(blockName, itemDict)
|
||||||
if not recipe:
|
if not recipe:
|
||||||
return
|
return
|
||||||
|
|
||||||
# ===== 处理需要翻炒的配方 =====
|
|
||||||
if recipe.get("stirCount"):
|
if recipe.get("stirCount"):
|
||||||
self._handleStir(key, recipe, playerId, pos, dim, itemDict)
|
self._handleStir(key, recipe, playerId, pos, dim, itemDict)
|
||||||
return
|
return
|
||||||
|
|
||||||
# ===== 处理普通配方(直接替换) =====
|
|
||||||
self._executeRecipe(recipe, playerId, pos, dim, itemDict)
|
self._executeRecipe(recipe, playerId, pos, dim, itemDict)
|
||||||
|
|
||||||
# ==================== 配方匹配 ====================
|
# ==================== 配方匹配 ====================
|
||||||
|
|
||||||
def _findRecipe(self, blockName, itemDict):
|
def _findRecipe(self, blockName, itemDict):
|
||||||
"""
|
|
||||||
在 RECIPES 列表里找匹配的配方。
|
|
||||||
匹配条件:source 对上 + item 对上(或 item 为 None)
|
|
||||||
"""
|
|
||||||
itemName = itemDict.get("newItemName") if itemDict else None
|
itemName = itemDict.get("newItemName") if itemDict else None
|
||||||
for recipe in RECIPES:
|
for recipe in RECIPES:
|
||||||
if recipe["source"] != blockName:
|
if recipe["source"] != blockName:
|
||||||
continue
|
continue
|
||||||
# item 为 None 表示不限制物品类型
|
|
||||||
if recipe["item"] is not None and recipe["item"] != itemName:
|
if recipe["item"] is not None and recipe["item"] != itemName:
|
||||||
continue
|
continue
|
||||||
return recipe
|
return recipe
|
||||||
@@ -117,14 +123,11 @@ class CookingService(ServerSystem):
|
|||||||
# ==================== 配方执行(普通替换) ====================
|
# ==================== 配方执行(普通替换) ====================
|
||||||
|
|
||||||
def _executeRecipe(self, recipe, playerId, pos, dim, itemDict):
|
def _executeRecipe(self, recipe, playerId, pos, dim, itemDict):
|
||||||
"""
|
|
||||||
执行一条普通配方:检查条件 → 消耗物品 → 替换方块 → 给物品 → 播声音
|
|
||||||
"""
|
|
||||||
# 1. 检查附加条件
|
# 1. 检查附加条件
|
||||||
if not self._checkConditions(recipe, playerId, pos, dim, itemDict):
|
if not self._checkConditions(recipe, playerId, pos, dim, itemDict):
|
||||||
return
|
return
|
||||||
|
|
||||||
# 2. 消耗物品(扣除数量、去掉油标签)
|
# 2. 消耗物品
|
||||||
if recipe.get("consume", 1) > 0:
|
if recipe.get("consume", 1) > 0:
|
||||||
self._consumeItem(playerId, itemDict, recipe.get("consume", 1))
|
self._consumeItem(playerId, itemDict, recipe.get("consume", 1))
|
||||||
if recipe.get("needOil"):
|
if recipe.get("needOil"):
|
||||||
@@ -138,25 +141,17 @@ class CookingService(ServerSystem):
|
|||||||
if recipe.get("giveItem"):
|
if recipe.get("giveItem"):
|
||||||
self._giveItem(playerId, recipe["giveItem"])
|
self._giveItem(playerId, recipe["giveItem"])
|
||||||
|
|
||||||
# 5. 播放声音
|
# 5. 播放声音(需要配合 BlueFox 框架的客户端 PlaySound 事件,此处暂不实现)
|
||||||
if recipe.get("sound"):
|
|
||||||
self._playSound(playerId, recipe["sound"], recipe.get("soundPitch", 1.0))
|
|
||||||
|
|
||||||
# ==================== 翻炒处理 ====================
|
# ==================== 翻炒处理 ====================
|
||||||
|
|
||||||
def _handleStir(self, key, recipe, playerId, pos, dim, itemDict):
|
def _handleStir(self, key, recipe, playerId, pos, dim, itemDict):
|
||||||
"""
|
|
||||||
处理需要翻炒的配方。
|
|
||||||
翻炒逻辑:
|
|
||||||
1. 检查冷却时间
|
|
||||||
2. 没到冷却 → 提示"这时候翻动会不好熟的!"
|
|
||||||
3. 到了冷却 → 翻炒次数+1 → 播声音+挥剑动画
|
|
||||||
4. 翻够次数 → 执行替换或标记熟了
|
|
||||||
"""
|
|
||||||
now = time.time()
|
now = time.time()
|
||||||
data = self.stirData.get(key, {"count": 0, "lastTime": 0, "finished": False,
|
data = self.stirData.get(key) or {
|
||||||
"dropIfDone": recipe.get("dropIfDone", []),
|
"count": 0, "lastTime": 0.0, "finished": False,
|
||||||
"dropIfNot": recipe.get("dropIfNot", [])})
|
"dropIfDone": recipe.get("dropIfDone", []),
|
||||||
|
"dropIfNot": recipe.get("dropIfNot", [])
|
||||||
|
}
|
||||||
|
|
||||||
# 冷却检查
|
# 冷却检查
|
||||||
if now - data["lastTime"] < recipe.get("stirCd", 1.0):
|
if now - data["lastTime"] < recipe.get("stirCd", 1.0):
|
||||||
@@ -169,33 +164,21 @@ class CookingService(ServerSystem):
|
|||||||
data["lastTime"] = now
|
data["lastTime"] = now
|
||||||
self.stirData[key] = data
|
self.stirData[key] = data
|
||||||
|
|
||||||
# 播放声音和挥剑动画
|
|
||||||
if recipe.get("sound"):
|
|
||||||
self._playSound(playerId, recipe["sound"], recipe.get("soundPitch", 1.0))
|
|
||||||
self._playAttack(playerId)
|
|
||||||
|
|
||||||
# 判断是否翻够了
|
# 判断是否翻够了
|
||||||
if data["count"] >= recipe["stirCount"]:
|
if data["count"] >= recipe["stirCount"]:
|
||||||
if recipe.get("onDone") == "finish":
|
if recipe.get("onDone") == "finish":
|
||||||
# 标记熟了,不替换方块
|
|
||||||
data["finished"] = True
|
data["finished"] = True
|
||||||
self.stirData[key] = data
|
self.stirData[key] = data
|
||||||
if recipe.get("doneMsg"):
|
if recipe.get("doneMsg"):
|
||||||
comp.CreateMsg(playerId).NotifyOneMessage(playerId, recipe["doneMsg"])
|
comp.CreateMsg(playerId).NotifyOneMessage(playerId, recipe["doneMsg"])
|
||||||
elif recipe.get("target"):
|
elif recipe.get("target"):
|
||||||
# 替换方块
|
|
||||||
self._replaceBlock(pos, dim, recipe["target"], playerId)
|
self._replaceBlock(pos, dim, recipe["target"], playerId)
|
||||||
# 清理翻炒数据
|
|
||||||
self.stirData.pop(key, None)
|
self.stirData.pop(key, None)
|
||||||
|
|
||||||
# ==================== 条件检查 ====================
|
# ==================== 条件检查 ====================
|
||||||
|
|
||||||
def _checkConditions(self, recipe, playerId, pos, dim, itemDict):
|
def _checkConditions(self, recipe, playerId, pos, dim, itemDict):
|
||||||
"""
|
# 检查下面是否有指定方块
|
||||||
检查配方的附加条件。
|
|
||||||
返回 True = 通过,False = 不通过。
|
|
||||||
"""
|
|
||||||
# 检查下面是否有指定方块(如营火)
|
|
||||||
if recipe.get("below"):
|
if recipe.get("below"):
|
||||||
belowPos = (pos[0], pos[1] - 1, pos[2])
|
belowPos = (pos[0], pos[1] - 1, pos[2])
|
||||||
blockComp = comp.CreateBlockInfo(playerId)
|
blockComp = comp.CreateBlockInfo(playerId)
|
||||||
@@ -218,10 +201,15 @@ class CookingService(ServerSystem):
|
|||||||
def _getCarriedItem(self, playerId):
|
def _getCarriedItem(self, playerId):
|
||||||
"""获取玩家主手拿的物品"""
|
"""获取玩家主手拿的物品"""
|
||||||
itemComp = comp.CreateItem(playerId)
|
itemComp = comp.CreateItem(playerId)
|
||||||
return itemComp.GetPlayerItem(serverApi.GetMinecraftEnum().ItemPosType.CARRIED, 0)
|
return itemComp.GetPlayerItem(
|
||||||
|
serverApi.GetMinecraftEnum().ItemPosType.CARRIED, 0)
|
||||||
|
|
||||||
def _consumeItem(self, playerId, itemDict, amount=1):
|
def _consumeItem(self, playerId, itemDict, amount=1):
|
||||||
"""消耗玩家手里的物品(减少数量)"""
|
"""
|
||||||
|
消耗玩家手里的物品(减少数量)。
|
||||||
|
注意:SetEntityItem 接收的 key 是 itemName/auxValue/count,
|
||||||
|
而 GetPlayerItem 返回的 key 是 newItemName/newAuxValue/count。
|
||||||
|
"""
|
||||||
count = itemDict.get("count", 0)
|
count = itemDict.get("count", 0)
|
||||||
if count <= amount:
|
if count <= amount:
|
||||||
comp.CreateItem(playerId).SetInvItemNum(
|
comp.CreateItem(playerId).SetInvItemNum(
|
||||||
@@ -230,11 +218,12 @@ class CookingService(ServerSystem):
|
|||||||
itemDict["count"] = count - amount
|
itemDict["count"] = count - amount
|
||||||
comp.CreateItem(playerId).SetEntityItem(
|
comp.CreateItem(playerId).SetEntityItem(
|
||||||
serverApi.GetMinecraftEnum().ItemPosType.CARRIED,
|
serverApi.GetMinecraftEnum().ItemPosType.CARRIED,
|
||||||
{"itemName": itemDict["newItemName"], "count": itemDict["count"],
|
{"itemName": itemDict["newItemName"],
|
||||||
"auxValue": itemDict.get("auxValue", 0)})
|
"count": itemDict["count"],
|
||||||
|
"auxValue": itemDict.get("newAuxValue", 0)})
|
||||||
|
|
||||||
def _replaceBlock(self, pos, dim, newBlockName, playerId):
|
def _replaceBlock(self, pos, dim, newBlockName, playerId):
|
||||||
"""替换方块(一行搞定!)"""
|
"""替换方块"""
|
||||||
comp.CreateBlockInfo(playerId).SetBlockNew(
|
comp.CreateBlockInfo(playerId).SetBlockNew(
|
||||||
pos, {"name": newBlockName}, 0, dim)
|
pos, {"name": newBlockName}, 0, dim)
|
||||||
|
|
||||||
@@ -243,45 +232,27 @@ class CookingService(ServerSystem):
|
|||||||
comp.CreateItem(playerId).SpawnItemToPlayerInv(
|
comp.CreateItem(playerId).SpawnItemToPlayerInv(
|
||||||
{"itemName": itemName, "count": count, "auxValue": 0}, playerId)
|
{"itemName": itemName, "count": count, "auxValue": 0}, playerId)
|
||||||
|
|
||||||
def _playSound(self, playerId, soundName, pitch=1.0):
|
# ==================== 油标签操作(纯本地 dict 操作,不调 API) ====================
|
||||||
"""在玩家位置播放声音"""
|
|
||||||
pos = comp.CreatePlayer(playerId).GetPos()
|
|
||||||
comp.CreateGame(playerId).PlaySound(
|
|
||||||
soundName, pos, pitch, 1.0, False)
|
|
||||||
|
|
||||||
def _playAttack(self, playerId):
|
|
||||||
"""让玩家播放攻击动画(挥剑)"""
|
|
||||||
# 通过引擎的 Attack 组件触发动画
|
|
||||||
try:
|
|
||||||
comp.CreatePlayer(playerId).Attack()
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# ==================== 油标签操作 ====================
|
|
||||||
|
|
||||||
def _getItemOil(self, itemDict):
|
def _getItemOil(self, itemDict):
|
||||||
"""读取物品上的油标签"""
|
"""读取物品上的油标签"""
|
||||||
try:
|
try:
|
||||||
itemComp = comp.CreateItem(serverApi.GetLevelId())
|
return _getUserDataField(itemDict, 'rtdd').get('oil', False)
|
||||||
userData = itemComp.GetItemUserData(itemDict, "rtdd")
|
|
||||||
return userData.get("oil", False) if userData else False
|
|
||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _removeOil(self, itemDict, playerId):
|
def _removeOil(self, itemDict, playerId):
|
||||||
"""去掉物品上的油标签"""
|
"""去掉物品上的油标签,并同步到玩家手里"""
|
||||||
try:
|
try:
|
||||||
itemComp = comp.CreateItem(serverApi.GetLevelId())
|
_getUserDataField(itemDict, 'rtdd')['oil'] = False
|
||||||
userData = itemComp.GetItemUserData(itemDict, "rtdd")
|
# 更新玩家手里的物品(userData 跟着 itemDict 一起写回去)
|
||||||
if userData:
|
itemComp = comp.CreateItem(playerId)
|
||||||
userData["oil"] = False
|
itemComp.SetEntityItem(
|
||||||
itemComp.SetItemUserData(itemDict, "rtdd", userData)
|
serverApi.GetMinecraftEnum().ItemPosType.CARRIED,
|
||||||
# 更新玩家手里的物品
|
{"itemName": itemDict["newItemName"],
|
||||||
comp.CreateItem(playerId).SetEntityItem(
|
"count": itemDict.get("count", 1),
|
||||||
serverApi.GetMinecraftEnum().ItemPosType.CARRIED,
|
"auxValue": itemDict.get("newAuxValue", 0),
|
||||||
{"itemName": itemDict["newItemName"], "count": itemDict.get("count", 1),
|
"userData": itemDict.get("userData", {})})
|
||||||
"auxValue": itemDict.get("auxValue", 0),
|
|
||||||
"userData": {"rtdd": userData}})
|
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -293,7 +264,6 @@ class CookingService(ServerSystem):
|
|||||||
如果有翻炒数据且标记了熟了 → 掉落熟的东西
|
如果有翻炒数据且标记了熟了 → 掉落熟的东西
|
||||||
如果没熟 → 掉落生的东西
|
如果没熟 → 掉落生的东西
|
||||||
"""
|
"""
|
||||||
blockName = args.get("blockName")
|
|
||||||
playerId = args.get("playerId")
|
playerId = args.get("playerId")
|
||||||
x, y, z = args.get("x"), args.get("y"), args.get("z")
|
x, y, z = args.get("x"), args.get("y"), args.get("z")
|
||||||
dim = comp.CreateDimension(playerId).GetEntityDimensionId()
|
dim = comp.CreateDimension(playerId).GetEntityDimensionId()
|
||||||
@@ -303,7 +273,6 @@ class CookingService(ServerSystem):
|
|||||||
if not data:
|
if not data:
|
||||||
return
|
return
|
||||||
|
|
||||||
# 根据是否熟了决定掉落什么
|
|
||||||
if data.get("finished"):
|
if data.get("finished"):
|
||||||
dropItems = data.get("dropIfDone", [])
|
dropItems = data.get("dropIfDone", [])
|
||||||
else:
|
else:
|
||||||
@@ -312,5 +281,4 @@ class CookingService(ServerSystem):
|
|||||||
for itemName in dropItems:
|
for itemName in dropItems:
|
||||||
self._giveItem(playerId, itemName)
|
self._giveItem(playerId, itemName)
|
||||||
|
|
||||||
# 清理翻炒数据
|
|
||||||
self.stirData.pop(key, None)
|
self.stirData.pop(key, None)
|
||||||
Reference in new issue
Block a user