钓鱼获得龙虾/螃蟹 改小bug(可用版本)

This commit is contained in:
wenhe committed 2026-09-24 16:01:17 +08:00
1 parent 23598ed3dd
commit a647878ac1
12 files changed
+373 -36

No files matched your search

@@ -117,6 +117,15 @@ OIL_CAN_ITEM = "rtdd:oilcan" # 油罐(石磨产物)
# 石磨材料标识(存方块实体 rtdd_stm): 'soybean'=黄豆, 'wheat'=小麦
STONEMILL_MATERIAL_KEY = "rtdd_stm"
# 石磨·客户端消闪拦截(BlockUse): 手持 玻璃罐/黄豆/小麦 右键石磨, 提前取消"放置预览",
# 再显式通知服务端(见 InterceptData.BLOCKUSE_CANCEL / ClientFeatureDispatcher)。
# 实际行为仍由服务端 handleStonemill 决定(加料研磨 / 玻璃罐取油罐 / 空手取面粉)。
STONEMILL_BLOCKUSE = [
{"item": GLASS_TANK_ITEM, "block": "rtdd:stonemill"}, # 玻璃罐取油罐
{"item": SOYBEAN_ITEM, "block": "rtdd:stonemill"}, # 加黄豆研磨
{"item": WHEAT_ITEM, "block": "rtdd:stonemill"}, # 加小麦研磨
]
# ============================================================================
# 四B、手持厨具物品(七、手持厨具物品): 锅铲 <-> 带油锅铲, 油罐蘸油/上油炒锅
# 19. 锅铲(spatula) 右键油罐(oilcan) -> 带油锅铲(spatula_oil, 附魔光效), 油罐次数-1
@@ -547,7 +547,8 @@ class ChujuService(BlueFoxServerSystem):
if prog is None or prog < 0:
return False
mat = self._readMillMat((x, y, z), dim) or "soybean"
ret = FLOUR_ITEM if mat == "wheat" else SOYBEAN_ITEM
# 打碎返还【放入的原料】(不是成品): 小麦返小麦, 黄豆返黄豆
ret = WHEAT_ITEM if mat == "wheat" else SOYBEAN_ITEM
count = WHEAT_COUNT if mat == "wheat" else SOYBEAN_COUNT
# 有材料:额外掉落对应原料(石磨本体由默认破坏掉落)
try:
@@ -559,11 +560,17 @@ class ChujuService(BlueFoxServerSystem):
return False
def _handleStonemill(self, playerId, pos, dim, itemDict, itemName, key):
prog = self._readMill(pos, dim) # None=空, 0~3=研磨中, 4=完成
prog = self._readMill(pos, dim) # None/负=空(未放料, 或已取走成品), 0~3=研磨中, 4=完成
mat = self._readMillMat(pos, dim) or "soybean" # 默认黄豆; 'wheat'=小麦
# 空磨: prog 为 None(从未放料) 或 <0(_clearMill 取走成品后写成 -1)
isEmpty = prog is None or prog < 0
# 研磨已完成: prog 达到 STONEMILL_GRIND_COUNT(4)
isComplete = prog is not None and prog >= STONEMILL_GRIND_COUNT
# ---- 空石磨 + 黄豆(16) 或 小麦(6) -> 加入 ----
if prog is None:
# ---- 加入研磨材料: 仅空磨(从未放料, 或已取走成品后)。 ----
# 完成态(prog=4)必须先取走成品(空手取面粉/玻璃罐取油罐)变回空磨,
# 然后才能手持 黄豆(16)/小麦(6) 重新放入开工。
if isEmpty:
if itemName == WHEAT_ITEM:
if (itemDict.get("count") or 0) < WHEAT_COUNT:
comp.CreateMsg(playerId).NotifyOneMessage(
@@ -590,10 +597,12 @@ class ChujuService(BlueFoxServerSystem):
comp.CreateMsg(playerId).NotifyOneMessage(
playerId, "§a加入黄豆,空手右键研磨")
return True
return False
# 空磨 + 空手: 无操作(交还默认); 完成态 + 手持非材料(玻璃罐/空手取粉) 不在此拦住
if isEmpty and (not itemName or itemName == "minecraft:air"):
return False
# ---- 研磨中: 空手右键旋转一次 ----
if 0 <= prog < STONEMILL_GRIND_COUNT:
if prog is not None and 0 <= prog < STONEMILL_GRIND_COUNT:
if itemName and itemName != "minecraft:air":
return False
if not self.checkCooldown(key, 0.5):
@@ -610,8 +619,8 @@ class ChujuService(BlueFoxServerSystem):
playerId, "§a研磨中,(%d/%d)" % (newProg, STONEMILL_GRIND_COUNT))
return True
# ---- 完成 ----
if prog >= STONEMILL_GRIND_COUNT:
# ---- 完成: 取成品 ----
if isComplete:
if mat == "wheat":
# 小麦已磨成面粉: 空手右键 -> 掉落 1 面粉 + 还原空
if itemName and itemName != "minecraft:air":
@@ -49,6 +49,9 @@ from ...BlueFoxTools.ModConfig import MOD_NAME
# 它是"普通逻辑类"(自己不监听), 由本分发器实例化并把 ServerEntityDieEvent 转给它。
from ..siwangshengwu.service.DeadmobGeneratorService import DeadmobGeneratorService
# ---- 钓鱼掉落: 螃蟹/龙虾(普通逻辑类, 由本分发器转发 PlayerFishingServerEvent) ----
from ..yuanbanfangzhi.service.YuanbanFishing import YuanbanFishingService
# ---- 汤锅盛出自定义事件名(与客户端 ClientFeatureDispatcher TAKEOUT_EVENT 一致) ----
TAKEOUT_EVENT = "TakeoutRequest"
@@ -206,6 +209,7 @@ class FeatureDispatcher(BlueFoxServerSystem):
print "===== FeatureDispatcher init ====="
self._cancelItemUse = {} # 将要取消下一次物品使用的玩家ID集合(防止喝药水等)
self._deadmobGen = DeadmobGeneratorService() # 死亡生物·生成引擎(杀猪牛羊等->尸体方块)
self._fishing = YuanbanFishingService() # 钓鱼掉落(螃蟹/龙虾)
self.ListenEvent()
def Destroy(self):
@@ -675,25 +679,12 @@ class FeatureDispatcher(BlueFoxServerSystem):
def OnFishing(self, args):
"""
玩家收杆时、钓鱼掉落物生成前触发(PlayerFishingServerEvent)。
让 螃蟹(rtdd:crab)/龙虾(rtdd:lobster) 直接作为"钓上来的物品":
有几率把本次钓上来的东西【替换】成 螃蟹 或 龙虾 —— 不再像 After 事件那样
额外多掉一只, 更贴近原版"钓上来什么就是什么"。
args.关键字段: playerId / hookEntity / itemList(本次钓上的物品列表, 生成前可改)。
概率(草稿, 可调): 螃蟹 10% / 龙虾 6%。
玩家钓鱼收杆时触发(PlayerFishingServerEvent)。
转给 原版放置·钓鱼掉落(YuanbanFishingService): 取消默认钓物并在鱼钩位置
生成 螃蟹/龙虾。
"""
try:
playerId = args.get("playerId")
itemList = args.get("itemList")
if not playerId or not isinstance(itemList, list) or not itemList:
return
# 【测试用】概率 100%: 每次收杆都替换成 螃蟹/龙虾(50/50), 方便验证两者都能钓到。
# 测试完请调回(如 螃蟹0.10 / 龙虾0.06)。
if random.random() < 0.5:
sea = "rtdd:crab"
else:
sea = "rtdd:lobster"
args["itemList"] = [{"itemName": sea, "count": 1, "auxValue": 0}]
self._fishing.OnFishing(args)
except Exception as e:
print "[FD-OnFishing-ERR]", e
@@ -129,11 +129,13 @@ except Exception:
pass
# 厨具(炉灶/丸子机/石磨: 木条+炉灶 等): ChujuData.STOVE_RULES / MEATBALLMAKER_RULES
# / STEAMER_RULES / STONEMILL_BLOCKUSE
try:
from ..chuju.ChujuData import (STOVE_RULES as CHUJU_STOVE,
MEATBALLMAKER_RULES as CHUJU_MEAT,
STEAMER_RULES as CHUJU_STEAM)
_BLOCK_USE_TABLES.extend([CHUJU_STOVE, CHUJU_MEAT, CHUJU_STEAM])
STEAMER_RULES as CHUJU_STEAM,
STONEMILL_BLOCKUSE as CHUJU_MILL)
_BLOCK_USE_TABLES.extend([CHUJU_STOVE, CHUJU_MEAT, CHUJU_STEAM, CHUJU_MILL])
except Exception:
pass
@@ -0,0 +1,74 @@
# -*- coding: utf-8 -*-
"""
================================================================================
原版放置·钓鱼掉落(螃蟹/龙虾)
================================================================================
给"螃蟹(rtdd:crab)/龙虾(rtdd:lobster)"提供钓鱼获取渠道:
玩家收杆时(PlayerFishingServerEvent, 掉落物生成前)触发本类:
- 尝试把本次钓鱼的默认掉落取消(cancel=True), 避免原版鱼再出现;
- 直接在鱼钩位置生成 1 只 螃蟹/龙虾, 让"钓上来的是什么就是什么"。
【为什么是普通逻辑类、不监听事件】
全模组只有 FeatureDispatcher 监听游戏事件。本类不监听, 由 FeatureDispatcher
实例化并在 PlayerFishingServerEvent 时把事件转发给本类 OnFishing。
(与 siwangshengwu/DeadmobGeneratorService 同架构。)
【概率】
现为测试用 100%(50/50 螃蟹/龙虾); 测试通过后请改回正式概率。
================================================================================
"""
import random
import mod.server.extraServerApi as serverApi
comp = serverApi.GetEngineCompFactory()
# ---- 只有方块/游戏相关才用 LevelId(这里 CreateItem 用玩家 id, 不依赖 LevelId) ----
from ....BlueFoxTools.ToolsConfig import LevelId
class YuanbanFishingService(object):
"""
钓鱼掉落·螃蟹/龙虾(逻辑类, 由 FeatureDispatcher 实例化并转发事件)
"""
def __init__(self):
print "===== YuanbanFishingService 钓鱼掉落(螃蟹/龙虾)已挂载 ====="
def OnFishing(self, args):
"""
PlayerFishingServerEvent(收杆时、掉落物生成前):
取消默认钓物 + 在鱼钩位置生成螃蟹/龙虾。
args 关键字段: playerId(玩家) / hookEntity(鱼钩实体id)。
"""
try:
playerId = args.get("playerId")
if not playerId:
return
# 正式概率: 螃蟹 10% / 龙虾 6%
roll = random.random()
if roll < 0.10:
sea = "rtdd:crab"
elif roll < 0.16:
sea = "rtdd:lobster"
else:
return # 未命中: 不取消默认, 保持原版钓鱼出原版物品
# 命中才取消默认鱼/杂物掉落, 避免"原版鱼+螃蟹"两只
args["cancel"] = True
pos = self._spawnPos(playerId, args.get("hookEntity"))
dim = comp.CreateDimension(playerId).GetEntityDimensionId()
comp.CreateItem(playerId).SpawnItemToLevel(
{"itemName": sea, "count": 1, "auxValue": 0}, dim, pos)
print "[YBFishing] 钓到 %s at %s" % (sea, pos)
except Exception as e:
print "[YBFishing-ERR]", e
def _spawnPos(self, playerId, hookId):
"""生成位置: 优先鱼钩位置, 取不到再用玩家脚下"""
if hookId:
try:
p = comp.CreatePos(hookId).GetFootPos()
return (p[0], p[1], p[2])
except Exception:
pass
foot = comp.CreatePos(playerId).GetFootPos()
return (foot[0], foot[1] + 0.5, foot[2])