#include <kernel/kernel.h> #include <phantasmal/log.h> #include <phantasmal/lpc_names.h> #include <type.h> inherit COMMON_AUTO; /* User-state processing stack */ private object* state_stack; private object scroll_state; /* Saved by save_object? */ int num_lines; /* how many lines on terminal */ /* Prototypes */ void push_state(object state); void upgraded(varargs int clone); /* Macros */ #define NEW_PHRASE(x) PHRASED->new_simple_english_phrase(x) static void create(void) { state_stack = ({ }); /* More defaults */ num_lines = 20; upgraded(); } void upgraded(varargs int clone) { if(SYSTEM()) { if(!find_object(US_SCROLL_TEXT)) { compile_object(US_SCROLL_TEXT); } } else error("Non-System code called upgraded!"); } int get_num_lines(void) { if(!SYSTEM() && !COMMON() && !GAME()) error("Only privileged code can call get_num_lines!"); return num_lines; } static void set_num_lines(int new_num) { num_lines = new_num; } /****** USER_STATE stack implementation ********/ void to_state_stack(string str) { if(SYSTEM() || COMMON() || GAME()) { state_stack[0]->to_user(str); } } void message_scroll(string str) { if(!SYSTEM() && !COMMON() && !GAME()) error("Only privileged code can call message_scroll!"); if(scroll_state) { scroll_state->to_user(str); } else { scroll_state = clone_object(US_SCROLL_TEXT); if(scroll_state) { scroll_state->add_text(str); push_state(scroll_state); } else { LOGD->write_syslog("Couldn't clone US_SCROLL_TEXT state object!", LOG_ERROR); } } } void notify_done_scrolling(void) { if(previous_object() != scroll_state) error("Only our own scrolling state can notify a user it's done!"); scroll_state = nil; } void pop_state(object state) { int first_state; /* This is a boolean value */ int ctr; object prev_state, next_state; if(!SYSTEM() && !COMMON() && !GAME()) return; if(!state_stack || !sizeof(state_stack)) { destruct_object(state); error("Popping empty stack!"); } if(!(state_stack && ({ state }))) error("Popping state not in stack!"); if(state_stack[0] == state) first_state = 1; else { first_state = 0; for(ctr = 1; ; ctr++) { if(state_stack[ctr] == state) { prev_state = state_stack[ctr - 1]; if(ctr + 1 < sizeof(state_stack)) next_state = state_stack[ctr + 1]; break; } } } state_stack = state_stack - ({ state }); if(first_state) { state->switch_from(1); /* 1 because popp is true */ if(sizeof(state_stack)) { state_stack[0]->switch_to(0); /* 0 because pushp is false */ } /* No longer print prompt here, that's handled in receive_message. */ } else { /* Make sure that the next_state values are correct in user state. */ prev_state->init(this_object(), next_state); } destruct_object(state); } void push_state(object state) { if(!SYSTEM() && previous_program() != USER_STATE) error("Only privileged code can call push_state()!"); if(!SYSTEM() && !COMMON() && !GAME()) return; if(!state_stack) { state_stack = ({ }); } if(sizeof(state_stack)) { state->init(this_object(), state_stack[0]); state_stack[0]->switch_from(0); /* 0 because popp is false */ } else { state->init(this_object(), nil); } state_stack = ({ state }) + state_stack; /* Call switch_to() after adding the new state to the stack -- 'cause it can pop the state right back off in some cases... */ state->switch_to(1); /* 1 because pushp is true */ } void push_new_state(mixed state_type, mixed params...) { object new_state; new_state = clone_object(state_type); if(!new_state) error("Can't create new state to push in push_new_state()!"); new_state->set_up_func(params...); push_state(new_state); } object peek_state(void) { if(!SYSTEM() && !COMMON() && !GAME()) error("Only privileged code can call peek_state!"); if(!state_stack || !sizeof(state_stack)) return nil; return state_stack[0]; } /****************/ /* * NAME: message_all_users() * DESCRIPTION: send message to listening users */ static void message_all_users(string str) { object *users, user; int i; if(!SYSTEM() && !COMMON() && !GAME()) return; users = users(); for (i = sizeof(users); --i >= 0; ) { user = users[i]; if (user && user != this_object()) { user->message(str); } } } /* * NAME: system_phrase_all_users() * DESCRIPTION: send message to listening users */ static void system_phrase_all_users(string str) { object *users, user; int i; if(!SYSTEM() && !COMMON() && !GAME()) return; users = users(); for (i = sizeof(users); --i >= 0; ) { user = users[i]; if (user != this_object()) { user->send_system_phrase(str); } } } mixed state_receive_message(string str) { if(!SYSTEM() && !COMMON() && !GAME()) return nil; return state_stack[0]->from_user(str); }