/* * MusicMUD - Actions module * Copyright (C) 1998-2003 Abigail Brady * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include <string.h> #include <stdio.h> #include <sys/types.h> #include <dirent.h> #include <unistd.h> #include "musicmud.h" #include "verbs.h" #include "util.h" #include "misc.h" #include "Player.h" #include "pflags.h" #include "trap.h" #include "events.h" #include "paths.h" #include "hooks.h" #include "musictok.h" #include "emsg.h" #include "actions.h" namespace { //! A verb which is soft-coded, either coming from the files in the action or data/verbs dirs. class ActionVerb : public Verb { private : string filename; public: virtual bool invoke(MudObject *invoker, int argc, const char*argv[]); ActionVerb(const char *id, int minlen, const char *filename); virtual ~ActionVerb(); }; ActionVerb::ActionVerb(const char *id, int minlen, const char *filename) : Verb(id, minlen, 0, PFL_NONE, VFL_MAGICSPACE) { this->filename = filename; set("module", "action"); } ActionVerb::~ActionVerb() { } } #define GIVE_UP do { player->printf("giving up line %i \n", __LINE__ ); return true; } while(0) static int viewers_at(MudObject *where) { if (!where) return 0; int i; MudObject *o; int c = 0; foreach(where->children, o, i) { if (is_player(o)) c++; } return c; } static int viewers(MudObject *where) { if (!where) return 0; int c = viewers_at(where); if (where->get_flag(FL_LINKED)) { MudObject *obj; int i; foreach(where->children, obj, i) { c += viewers_at(linkedlink(obj)); } } return c; } static void actresponse(MudObject *obj, MudObject *player, const char *id, int needp=1) { char foo[1024]; char bar[1024]; sprintf(foo, "on_%s", id); sprintf(bar, "lua.act.%s", id); if (obj) { if (obj->get(foo)) { obj->set("!$1", player->id); itell(obj, obj->get(foo)); return; } if (dotrap(bar+4, player, obj)) /* ::: act.* o1==object or mobile an action has been done on */ return; if ((is_mobile(obj) && is_player(player))==needp) { MudObject *at = archetype(obj); if (at && at->get(foo)) { obj->set("!$1", player->id); itell(obj, at->get(foo)); } } } if (!obj || obj->owner == player->owner) dotrap(ssprintf("lua.act_in.%s", id).c_str(), player, player->owner, obj); } const char *nilifempty(const string &s) { if (s.length()==0) return 0; return s.c_str(); } void appendnewline(string &s) { if (s.length()) s += '\n'; } bool ActionVerb::invoke(MudObject *player, int argc, const char*argv[]) { if (streq(get("module"), "luaverb")) { if (LUA_VERB) LUA_VERB(player, argc, argv); else player->printf("Real lua verb - but lua not loaded.\n"); return true; } if (!viewers(player->owner)) { return true; } if (player->get_flag(FL_SLEEPING)) { player->printf("You toss and turn in your sleep.\n"); player->oprintf("%#M %[tosses/toss] and %[turns/turn] in %s sleep.\n", player, his_or_her(player)); return true; } try { parsedact resp = parse_action(player, argc, argv, 1); resp.who->action_to(resp.targ, resp.a_me.c_str(), nilifempty(resp.txt), resp.prop); resp.who->action (resp.targ, resp.a_rest.c_str(), nilifempty(resp.txt), resp.prop); if (resp.targ) { resp.targ->action_from(resp.who,resp.a_you.c_str(), nilifempty(resp.txt), NULL, resp.prop); } if (resp.targ && resp.r_me.length()) { resp.targ->action_to (resp.who, resp.r_me.c_str(), nilifempty(resp.txt), resp.rprop); resp.targ->action (resp.who, resp.r_rest.c_str(), nilifempty(resp.txt), resp.rprop); resp.who ->action_from(resp.targ,resp.r_you.c_str(), nilifempty(resp.txt), NULL, resp.prop); } actresponse(resp.targ, resp.who, argv[0]); /// XXX E_ONTHINK /// XXX Away messages /// done - sleeping } catch (emsg &e) { if (e.msg.length()) player->printf("%s\n", e.msg); } return true; } #define MODULE "action" static void do_dir(const char *name, const char *pr, const char *module) { char path[1024]; DIR *dir=opendir(name); if (!dir) return; struct dirent *de; while ((de=readdir(dir))!=NULL) { if (verbs->get(de->d_name)) continue; char name[256]; strcpy(name, de->d_name); name[strlen(de->d_name)] = 0; if (get_verb(name)) continue; if (de->d_name[0]=='.') continue; if (strchr(de->d_name, '~')) continue; if (de->d_name[0]=='#') continue; if (streq(de->d_name, "CVS")) continue; sprintf(path, pr, de->d_name); strcpy(name, de->d_name); ActionVerb *av=new ActionVerb(name, strlen(name), path); if (module) { av->set("module", module); FILE *f = xopen(".", path, "r"); if (f) { char buf[1000]; fgets(buf, 1000, f); av->pflag = PFL_NONE; if (char *s=strchr(buf, '\n')) *s = 0; StrTok st(buf); int i = 0; while (const char *a = st.next(" ")) { if (i==1 && strncmp(a, "PFL_", 4)==0) { av->pflag = find_priv(a); } if (i==2) { av->privneeded = atoi(a); } if (i==3) { av->minlen = atoi(a); } i++; } av->vflags |= VFL_OKNOOWNER; xclose(f); } } verbs->add(*av); } closedir(dir); } static bool verb_reloadactions(MudObject*who, int, const char **) { Verb *o; int i; set<string> had; foreach(verbs, o, i) { if (IS_OF(o, ActionVerb)) { had.insert(o->id); verbs->remove(*o); delete o; i--; } } do_dir(DATA_ACTIONS, DATA_ACTIONS "/%s", NULL); do_dir(DATA_VERBS, DATA_VERBS "/%s", "luaverb"); foreach(verbs, o, i) { if (IS_OF(o, ActionVerb)) if (had.find(o->id)==had.end()) { who->printf("%s: added\n", o->id); } } set<string>::iterator it = had.begin(); while (it != had.end()) { if (!verbs->get(it->c_str())) { who->printf("%s: removed\n", it->c_str()); } it++; } // who->interpret("actlist"); return true; } NativeVerb *reloadactions; extern "C" void register_verbs() { reloadactions = new NativeVerb("rescan", 4, 0, verb_reloadactions, PFL_ACTIONS); reloadactions->set("module","ActionVerb"); verbs->add(*reloadactions); do_dir(DATA_ACTIONS, DATA_ACTIONS "/%s", NULL); do_dir(DATA_VERBS, DATA_VERBS "/%s", "luaverb"); } extern "C" void remove_verbs() { verbs->remove(*reloadactions); delete reloadactions; Verb *o; int i; foreach(verbs, o, i) { Verb * v = (Verb *)o; if (IS_OF(v, ActionVerb)) { verbs->remove(*o); delete o; i--; } } }