实现新功能:玩家不影响生物生成消失
LXYan2333 opened this issue · 11 comments
Motivation
Why do you want this feature? What problem do you want to solve? How can the suggested feature help with that?
玩家靠近刷怪塔时,生物停止刷出,影响刷怪塔运作。如果玩家想在刷怪塔运作时靠近修改刷怪塔则需要频繁在创造模式和旁观模式之间切换,比较麻烦。
Description
对于订阅了某个logger的玩家:
1、怪物生成时,不将此玩家视为最近玩家,并不检查自身碰撞箱是否与玩家接触。怪物消失时,不考虑是否与该玩家过近
2、刷怪笼刷怪时,不将此玩家视为最近的玩家,并且刷出怪物时不检测怪物是否与玩家碰撞箱有接触
3、僵尸增援生成时,不将此玩家视为最近玩家,并且刷出增援时不检测怪物是否与玩家碰撞箱有接触
4、村庄刷猫时,跳过此玩家
5、生成幻翼时,跳过此玩家
6、生成游商时,跳过此玩家
是否需要拆分功能
昨天的讨论的更多的是关于程序实现是否应该解耦。
从功能与用户体验上,我认为这些功能不需要拆分解耦。
- 上述修改的游戏机制均列在wiki的生成一页,说明这些游戏机制本身就具有较强的相关性,适合同时进行修改,也方便玩家理解记忆。
- 从程序实现的角度来说,这当然涉及到修改MC不同的部分,将一些不相关的部分耦合起来;但是从用户的角度来说,这些修改这使得玩家在设计各种涉及生物生成的农场时类似一个旁观者模式的玩家,玩家只需记住这条规则即可,无需关心背后的实现。在原版中有类似的“doMobSpawn”,在carpet中有类似的“creativeNoClip”,都是将许多从代码实现上不相关的规则耦合起来,提升用户体验。
- 在实际使用过程中,上述功能绝大部分时候相互正交。设计消失刷怪塔的玩家不会同时设计刷怪笼农场,设计刷猫农场的玩家不会同时设计幻翼农场。因此使用同一个开关控制所有功能并无不妥。在极特殊的情况下,玩家也能回到创造旁观来回切换的老方法。
昨天的讨论是什么?请在 issue 中提供完整上下文
我依然认为需要拆分功能。不同的功能交给不同的规则做
wiki 是人为编写的,其归类仅仅是划分的一种,我并不认为这与本 mod 的规则设计有什么联系
”类似旁观者的玩家“,怎么定义“类似”,这便是理解和学习成本。doMobSpawn
和 creativeNoClip
我并不认为存在多向功能的耦合,这两者的具体功能与其定义是匹配的
这里是在假设用户的使用场景,并且也仅适用于服务器中同时仅存在一种类型玩家的情况
如果你坚持拆分功能的话,那就拆分吧。这会拆分为多个rule。
或者可以通过让用户订阅不同的logger,让用户在不同的功能下被忽略(个人觉得不错)
(如:log ignoreMe natureSpawn
log ignoreMe catSpawnInVillage
)
或者也可以删去不常用的功能,仅保留第1条(如果你认为有必要的话,距离检测和实体碰撞检测还能进一步拆分)。
既然决定了拆分,那么以下的内容就不重要了,但是我还是想说一下
1、上下文是你在 #103 (comment) 里对功能解耦优点的说明,包括:
松耦合的模块设计机制。这是代码质量问题
松耦合仅仅只控制代码质量的
这些都是从代码实现上阐述解耦的优点。从功能上,适度的耦合可以提升用户体验。
2、学习成本这事属于公说公有理,我只是尝试说服你这种实现方便用户学习。如果你坚持的话,那就拆吧(或者删去不常用的功能)
3、可能我对此mod的总体定位理解有偏差。
我已经接受拆分功能了……
那么我提出的两个方案选哪个?
- 把上述功能放进一个rule,但是允许用户在订阅logger时选择自己被哪些刷怪算法忽略
- 删去不常用功能,只保留第一条(自然刷怪)
如果你认为有必要,距离和碰撞箱检查可以进一步拆分。
方案1:
新建一个rule(名字待定)
用户开启rule后,玩家需要进一步订阅logger,选择自己被哪些刷怪算法忽略。如:
/log ingoreMe natureSpawnDespawn
怪物生成时,不将订阅了该条目的玩家视为最近玩家进行距离检测,并不检查自身碰撞箱是否与玩家接触(如果你认为有必要,碰撞箱检测可以拆分,下同)。
怪物消失时,不考虑是否与该玩家过近(如果你认为有必要,亦可拆分)/log ignoreMe catSpawnInVillage
村庄刷猫时,将不会选中该玩家,并不检查自身碰撞箱是否与玩家接触
方案2
新建一个rule,名字类似于“natureMobSpawnDespawnIgnorePlayer”,用户开启此rule后需要订阅一个logger将自己加入忽略列表。
- 怪物生成时,不将订阅了该条目的玩家视为最近玩家进行距离检测,并不检查自身碰撞箱是否与玩家接触。
- 怪物消失时,不考虑是否与该玩家过近
当然还有一种更激进的方案:
方案3
新增一个游戏模式,名字类似“creativeSpectator”。在开启该模式后:
客户端
服务端会欺骗客户端正处于创造模式,客户端可以进行放置方块、放置实体等与世界交互的操作。如果客户端是兼容的客户端,在F3+F4中显示第五个模式。
服务端
服务端新增一个游戏模式“creativeSpectator”,玩家可以通过命令/gamemode creativeSpectator
进入该模式。
进入该模式后,服务端会将该玩家切换为旁观者模式,但是将PlayerEntity.ablility.allowModifyWorld
设置为true(可能还有其它地方麻将用的游戏模式来判断,需要单独处理)。服务端将该玩家渲染给其他玩家看。
如果玩家没有设置默认开启该规则,则在保存世界时将该玩家保存为创造模式。如果玩家默认开启该规则,则另外将该玩家所选的模式保存下来。
方案 1
该方案区分了“刷怪机制类型”的维度,而未区分“忽略的具体机制”这一维度,依然为解决“忽略”一词定位不清晰的问题。
方案 2
这个规则的影响范围足够清晰,若只添加这一个规则,是不错的选择。
不过,如果日后想要增加更多的相关规则,则需要考虑 logger 数量膨胀,“假 logger”过多的问题。这方面可以参考 #103 (comment) 的目标指定部分解决。
方案 3
原版 fabric 环境不支持为 GameMode
枚举类添加新成员,且做出相关修改后难保证原版兼容性,不予考虑。
如果需要完善地支持“玩家不影响生物生成/消失”国内,支持自定义开关“刷怪机制类型”、“忽略的具体机制”这两个维度的忽略机制,有一个更为完善的方案:创建一个专属命令,如 /spawn ignore_player
子命令,并在其中添加专属的订阅增删查改逻辑,如:
/spawn ignore_player:自述本条指令功能,列出所有可能的 mechanism 及其含义
/spawn ignore_player <mechanism>:解释此机制的功能
/spawn ignore_player <mechanism> [join|leave|list|clean]:增删查改此忽略机制的订阅数据
其中,mechanism
是一个字符串,代表某个刷怪相关的具体机制,结构为 "$type.$logic"
,如:
natual.min_distance
:自然刷怪,可刷在玩家 24m 内natual.collision
:自然刷怪,可刷在玩家配置箱中cat.targetting
:猫刷新,不选择当前玩家cat.collision
:猫刷怪,可刷在玩家碰撞箱中
当然,也可以使用通配符来进行批量指定:
natual.*
:自然刷怪的所有*.collision
:所有碰撞检测中都忽略玩家*
:所有涉及到的机制
这部分的数据储存在 ./config/carpettisaddition/spawn_ignore.json
中
最后,加个 commandSpawnIgnorePlayer
规则作为这条子命令的开关
优点:不依赖 logger 和 rule 来储存相关逻辑,提供了充足的订阅控制相关指令。后续拓展新机制容易,影响范围可控于该子命令下
缺点:工作量高,实现复杂
注:上述指令设计思路仅供参考,如果有更好的指令设计方案欢迎提出