|
首先让我们找到移动的代码,这个我熟悉,cmd/std/go.c
把拉巴拉一段战斗逃跑的判断,然后
恩,好理解,把当前对象移动到dest下。
这里mudos是这样的,所有的东西都是obejct,都是平级。obecjt下可以有子元素,就是道具。这样,一个道具即可以在room里,也可以在玩家身上,也可以在玩家身上的容器里,也可以在房间的容器里。大家都是对象,平级,都能装。
然后找move方法的定义
恩,在feature/move.c里
一堆负重的判断,然后调用了一个 代码
恩,这个我看文档看到过,是一个efun(官方api),让我们打开页面看看,继续水一点
https://www.fluffos.info/zh-CN/efun/move_object.html
移动当前对象到环境 `dest`,移动后会触发当前对象和目标环境及其中对象的 init() 方法。继续水,但是init不是初始化么,为啥移动会初始化一下?不管了,继续爬文档。
熟练的打开文档https://www.fluffos.info/zh-CN/apply/object/init.html
然后,然后,然后,我被硬控了几秒
当 MUDLIB 移动对象 `A` 进入对象 `B`时,游戏驱动的 move_object() 外部函数会做以下行为:1. 如果 `A` 是生物(living),让 `A` 呼叫 `B` 的 init() 方法。2. 不管 `A` 是否是生物,让 `B` 中的所有生物呼叫 `A` 的 init() 方法。3. 如果 `A 是生物,让 `A 呼叫 `B` 中所有对象的 init() 方法。1.我还能理解,让移动入的元素和房间/容器交互下。2和3是什么鬼?和房间/容器所有的容器都交互下,然后再被房间里所有的容器交互下?这是啥,连还尸爆么?
看的我一脸蒙蔽,爬下源代码
efun我知道,直接搜f_move_object()就行
调用的是src/package/core/efuns_main.cc里的- #ifdef F_MOVE_OBJECT
- void f_move_object() {
- object_t *o1, *o2;
- /* get destination */
- if (sp->type == T_OBJECT) {
- o2 = sp->u.ob;
- } else {
- if (!(o2 = find_object(sp->u.string)) || !object_visible(o2)) {
- error("move_object failed: could not find destination\n");
- }
- }
- if ((o1 = current_object)->flags & O_DESTRUCTED) {
- error("move_object(): can't move a destructed object\n");
- }
- move_object(o1, o2);
- pop_stack();
- }
复制代码 然后move_object方法是src/internal/base/simulate.cc里- void move_object(object_t *item, object_t *dest) {
- object_t **pp, *ob;
- save_command_giver(command_giver);
- /* Recursive moves are not allowed. */
- for (ob = dest; ob; ob = ob->super) {
- if (ob == item) {
- error("Can't move object inside itself.\n");
- }
- }
- #ifndef NO_SHADOWS
- if (item->shadowing) {
- error("Can't move an object that is shadowing.\n");
- }
- #endif
- if (!CONFIG_INT(__RC_NO_RESETS__) && CONFIG_INT(__RC_LAZY_RESETS__)) {
- try_reset(dest);
- }
- #ifndef NO_LIGHT
- add_light(dest, item->total_light);
- #endif
- if (item->super) {
- int okay = 0;
- remove_sent(item->super, item);
- remove_sent(item, item->super);
- #ifndef NO_LIGHT
- add_light(item->super, -item->total_light);
- #endif
- for (pp = &item->super->contains; *pp;) {
- if (*pp != item) {
- remove_sent(item, *pp);
- remove_sent(*pp, item);
- pp = &(*pp)->next_inv;
- continue;
- }
- /*
- * unlink object from original inventory list
- */
- *pp = item->next_inv;
- okay = 1;
- }
- #ifdef DEBUG
- if (!okay) {
- fatal("Failed to find object /%s in super list of /%s.\n", item->obname, item->super->obname);
- }
- #endif
- }
- /*
- * link object into target's inventory list
- */
- item->next_inv = dest->contains;
- dest->contains = item;
- item->super = dest;
- setup_new_commands(dest, item);
- restore_command_giver();
- }
复制代码
恩,明显道具是个链表,里面有个不起眼的 setup_new_commands
让我再找一下,在src/packages/core/add_action里(话说从内部包引用efun包,这合理么?):- void setup_new_commands(object_t *dest, object_t *item) {
- object_t *next_ob, *ob;
- /*
- * Setup the new commands. The order is very important, as commands in
- * the room should override commands defined by the room. Beware that
- * init() in the room may have moved 'item' !
- *
- * The call of init() should really be done by the object itself (except in
- * the -o mode). It might be too slow, though :-(
- */
- if (item->flags & O_ENABLE_COMMANDS) {
- save_command_giver(item);
- (void)apply(APPLY_INIT, dest, 0, ORIGIN_DRIVER);
- restore_command_giver();
- if (item->super != dest) {
- return;
- }
- }
- /*
- * Run init of the item once for every present user, and for the
- * environment (which can be a user).
- */
- for (ob = dest->contains; ob; ob = next_ob) {
- next_ob = ob->next_inv;
- if (ob == item) {
- continue;
- }
- if (ob->flags & O_DESTRUCTED) {
- error("An object was destructed at call of " APPLY_INIT "()\n");
- }
- if (dest != ob->super) {
- error("An object was moved at call of " APPLY_INIT "()\n");
- }
- if (ob->flags & O_ENABLE_COMMANDS) {
- save_command_giver(ob);
- (void)apply(APPLY_INIT, item, 0, ORIGIN_DRIVER);
- restore_command_giver();
- if (dest != item->super) {
- return;
- }
- }
- if (item->flags & O_DESTRUCTED) { /* marion */
- error("The object to be moved was destructed at call of " APPLY_INIT "()\n");
- }
- if (ob->flags & O_DESTRUCTED) { /* Alaron */
- error("An object was destructed at call of " APPLY_INIT "()\n");
- }
- if (item->flags & O_ENABLE_COMMANDS) {
- save_command_giver(item);
- (void)apply(APPLY_INIT, ob, 0, ORIGIN_DRIVER);
- restore_command_giver();
- if (dest != item->super) {
- return;
- }
- }
- }
- if (dest->flags & O_DESTRUCTED) { /* marion */
- error("The destination to move to was destructed at call of " APPLY_INIT "()\n");
- }
- if (item->flags & O_DESTRUCTED) { /* Alaron */
- error("The object to be moved was destructed at call of " APPLY_INIT "()\n");
- }
- if (dest->flags & O_ENABLE_COMMANDS) {
- save_command_giver(dest);
- (void)apply(APPLY_INIT, item, 0, ORIGIN_DRIVER);
- restore_command_giver();
- }
- }
复制代码 还真是互相交互两边啊,这不是性能炸弹么。
再让我们找个文件看看init()一般是干什么的。
- void init()
- {
- object me;
-
- ::init();
- if (interactive(me = this_player()))
- {
- remove_call_out("greeting");
- call_out("greeting", 1, me);
- }
- me->delete_temp("decide_withdraw");
- me->delete_temp("demolish_room");
- add_action("do_stop", "stop");
- add_action("do_answer", "answer");
- add_action("do_desc", "desc");
- add_action("do_show", "show");
- add_action("do_changename", "changename");
- add_action("do_changeid", "changeid");
- add_action("do_changetype", "changetype");
- add_action("do_changedesc", "changedesc");
- add_action("do_finish", "finish");
- add_action("do_finish", "ok");
- add_action("do_withdraw", "withdraw");
- add_action("do_withdraw", "chexiao");
- add_action("decide_withdraw", "decide");
- add_action("do_demolish", "demolish");
- // 如果来的是有资格处理表单的巫师就增加处理表单的命令
- if (wizardp(me) && wiz_level(me) >= WIZLEVEL)
- {
- add_action("do_help", "help");
- add_action("do_list", "list");
- add_action("do_type", "type");
- add_action("do_agree", "agree");
- add_action("do_reject", "reject");
- add_action("do_delete", "delete");
- }
- }
复制代码
好家伙,是为了绑临时指令啊。
话说每走一步,捡个东西,丢个东西/放个东西到包裹里,都要这样来一圈,好扯啊。
这init()函数,不是正常应该都为空,不正常情况采取使用么。
我深度怀疑,北侠的移动指令这么容易上榜,可能就是和init优点重,或者addaction部分太重可能优点关系。
|
|