//*****************************************************************************
//
// iedit.c
//
// Although it is not core to the functioning of items, we will more likely
// than not want to be able to edit their type information in OLC. This will
// require a parser, a chooser, and a menu for editing the type information.
// Item types can add in their OLC functions via this framework. iedit uses
// the OLC2 framework. For more detailed instructions on how to set up an OLC,
// users should refer to the OLC2 source headers.
//
// NOTE: the menu, chooser, and parser should only take the item-specific data,
// and not the WHOLE object! It has been set up this way to encourage
// people to localize all of the data associated with one item type.
//
//*****************************************************************************
#include "../mud.h"
#include "../utils.h"
#include "../socket.h"
#include "items.h"
#include "iedit.h"
//*****************************************************************************
// mandatory modules
//*****************************************************************************
#include "../scripts/scripts.h"
#include "../olc2/olc.h"
#include "../olc2/olc_extender.h"
//*****************************************************************************
// local functions, variables, and datastructures
//*****************************************************************************
// used to store the different sub-olc functions for different item types
HASHTABLE *item_olc_table = NULL;
typedef struct item_olc_data {
void (* menu)(SOCKET_DATA *sock, void *data);
int (* chooser)(SOCKET_DATA *sock, void *data, const char *option);
bool (* parser)(SOCKET_DATA *sock, void *data,int choice,const char *arg);
void (* from_proto)(void *data);
void (* to_proto)(void *data, BUFFER *buf);
} ITEM_OLC_DATA;
ITEM_OLC_DATA *newItemOLC(void *menu, void *chooser, void *parser,
void *from_proto, void *to_proto) {
ITEM_OLC_DATA *data = calloc(1, sizeof(ITEM_OLC_DATA));
data->menu = menu;
data->chooser = chooser;
data->parser = parser;
data->from_proto = from_proto;
data->to_proto = to_proto;
return data;
}
void deleteItemOLC(ITEM_OLC_DATA *data) {
free(data);
}
//*****************************************************************************
// implementation of iedit.h
//*****************************************************************************
#define IEDIT_EDIT 1
#define IEDIT_DELETE 2
//
// list off all the item types available for editing. Print the type in green
// if the item currently is not of that type. Print the type in yellow if the
// item is of that type.
void iedit_show_types(SOCKET_DATA *sock, OBJ_DATA *obj) {
LIST *list = itemTypeList();
LIST_ITERATOR *list_i = newListIterator(list);
char *type = NULL;
int col = 0;
text_to_buffer(sock, "{wEditable item types:{g\r\n");
ITERATE_LIST(type, list_i) {
col++;
send_to_socket(sock, " %s%-14s%s", (objIsType(obj, type) ? "{y" : "{g"),
type, ((col != 0 && col % 4 == 0) ? "\r\n": " "));
}
deleteListIterator(list_i);
deleteListWith(list, free);
if(col % 4 != 0) text_to_buffer(sock, "\r\n");
}
void item_add_olc(const char *type, void *menu, void *chooser, void *parser,
void *from_proto, void *to_proto) {
ITEM_OLC_DATA *data = NULL;
// check to see if we already have functions for this item type installed
if( (data = hashRemove(item_olc_table, type)) != NULL)
deleteItemOLC(data);
data = newItemOLC(menu, chooser, parser, from_proto, to_proto);
hashPut(item_olc_table, type, data);
}
void iedit_menu(SOCKET_DATA *sock, OBJ_DATA *obj) {
iedit_show_types(sock, obj);
text_to_buffer(sock,
"\r\n"
" {gE) edit type\r\n"
" D) delete type\r\n");
}
int iedit_chooser(SOCKET_DATA *sock, OBJ_DATA *obj, const char *option) {
switch(toupper(*option)) {
case 'E':
text_to_buffer(sock, "Which item type would you like to edit: ");
return IEDIT_EDIT;
case 'D':
text_to_buffer(sock, "Which item type would you like to delete: ");
return IEDIT_DELETE;
default: return MENU_CHOICE_INVALID;
}
}
bool iedit_parser(SOCKET_DATA *sock, OBJ_DATA *obj,int choice, const char *arg){
switch(choice) {
case IEDIT_EDIT: {
ITEM_OLC_DATA *funcs = NULL;
if(!objIsType(obj, arg))
objSetType(obj, arg);
// pull up the OLC functions and see if we can edit the type
if((funcs = hashGet(item_olc_table, arg)) != NULL) {
void *item_data = objGetTypeData(obj, arg);
do_olc(sock, funcs->menu, funcs->chooser, funcs->parser,
NULL, NULL, NULL, NULL, item_data);
}
return TRUE;
}
case IEDIT_DELETE:
objDeleteType(obj, arg);
return TRUE;
default: return FALSE;
}
}
void item_from_proto(const char *type, void *data) {
ITEM_OLC_DATA *funcs = hashGet(item_olc_table, type);
if(funcs != NULL && funcs->from_proto != NULL)
funcs->from_proto(data);
}
void item_to_proto(const char *type, void *data, BUFFER *buf) {
ITEM_OLC_DATA *funcs = hashGet(item_olc_table, type);
if(funcs != NULL && funcs->to_proto != NULL)
return funcs->to_proto(data, buf);
}
//*****************************************************************************
// functions for extending oedit
//*****************************************************************************
void oedit_item_menu(SOCKET_DATA *sock, OBJ_DATA *obj) {
send_to_socket(sock, "Edit item types: {c%s\r\n", objGetTypes(obj));
}
int oedit_item_choose(SOCKET_DATA *sock, OBJ_DATA *obj) {
do_olc(sock, iedit_menu, iedit_chooser, iedit_parser, NULL, NULL, NULL,
NULL, obj);
return MENU_NOCHOICE;
}
void oedit_item_to_proto(OBJ_DATA *obj, BUFFER *buf) {
// item types
LIST *item_types = itemTypeList();
LIST_ITERATOR *type_i = newListIterator(item_types);
char *type = NULL;
ITERATE_LIST(type, type_i) {
if(objIsType(obj, type)) {
void *data = objGetTypeData(obj, type);
bprintf(buf, "\n### item type: %s\n", type);
bprintf(buf, "me.settype(\"%s\")\n", type);
item_to_proto(type, data, buf);
//item_to_proto_func(type)(data, buf);
bprintf(buf, "### end type\n");
}
} deleteListIterator(type_i);
deleteListWith(item_types, free);
}
void oedit_item_from_proto(OBJ_DATA *obj) {
// item types
LIST *item_types = itemTypeList();
LIST_ITERATOR *type_i = newListIterator(item_types);
char *type = NULL;
ITERATE_LIST(type, type_i) {
if(objIsType(obj, type))
item_from_proto(type, obj);
} deleteListIterator(type_i);
deleteListWith(item_types, free);
}
//*****************************************************************************
// initialization of item olc
//*****************************************************************************
void init_item_olc() {
item_olc_table = newHashtable();
// add our OLC extension
extenderRegisterOpt(oedit_extend, 'I',
oedit_item_menu, oedit_item_choose, NULL,
oedit_item_from_proto, oedit_item_to_proto);
}