Update game to use TOML format for persistent data

This commit is contained in:
kinther 2026-01-23 09:27:09 -08:00
parent 18c92e2357
commit 2dcf2d7311
209 changed files with 12983 additions and 1982 deletions

View file

@ -16,6 +16,8 @@ file(GLOB CIRCLE_SOURCES
)
add_executable(circle ${CIRCLE_SOURCES})
target_sources(circle PRIVATE ${CMAKE_SOURCE_DIR}/third_party/tomlc99/toml.c)
target_include_directories(circle PRIVATE ${CMAKE_SOURCE_DIR}/third_party/tomlc99)
if(MSVC)
target_link_libraries(circle wsock32.lib)
@ -23,4 +25,4 @@ if(MSVC)
set_target_properties(circle PROPERTIES
VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/.."
)
endif()
endif()

View file

@ -17,11 +17,11 @@ PROFILE =
BINDIR = ../bin
CFLAGS = -g -O2 $(MYFLAGS) $(PROFILE)
CFLAGS = -g -O2 $(MYFLAGS) $(PROFILE) -I../third_party/tomlc99
LIBS = -lcrypt
SRCFILES := $(shell ls *.c | sort)
SRCFILES := $(shell ls *.c | sort) ../third_party/tomlc99/toml.c
OBJFILES := $(patsubst %.c,%.o,$(SRCFILES))
default: all
@ -47,13 +47,14 @@ $%.o: %.c
clean:
rm -f *.o depend
rm -f ../third_party/tomlc99/toml.o
rm -f ./tests/*.o depend
# Dependencies for the object files (automagically generated with
# gcc -MM)
depend:
$(CC) -MM *.c > depend
$(CC) $(CFLAGS) -MM *.c > depend
-include depend

View file

@ -16,11 +16,11 @@ PROFILE =
BINDIR = ../bin
CFLAGS = @CFLAGS@ $(MYFLAGS) $(PROFILE)
CFLAGS = @CFLAGS@ $(MYFLAGS) $(PROFILE) -I../third_party/tomlc99
LIBS = @LIBS@ @CRYPTLIB@ @NETLIB@
SRCFILES := $(shell ls *.c | sort)
SRCFILES := $(shell ls *.c | sort) ../third_party/tomlc99/toml.c
OBJFILES := $(patsubst %.c,%.o,$(SRCFILES))
default: all
@ -46,6 +46,7 @@ $%.o: %.c
clean:
rm -f *.o depend
rm -f ../third_party/tomlc99/toml.o
rm -f ./tests/*.o depend
# Dependencies for the object files (automagically generated with

View file

@ -12,6 +12,8 @@
#include "utils.h"
#include "db.h"
#include "accounts.h"
#include "toml.h"
#include "toml_utils.h"
static void set_account_name(struct account_data *account, const char *name)
{
@ -28,6 +30,31 @@ static void set_account_name(struct account_data *account, const char *name)
account->name = strdup(tmp);
}
static char *toml_dup_string(toml_table_t *tab, const char *key)
{
toml_datum_t d = toml_string_in(tab, key);
if (!d.ok)
return NULL;
return d.u.s;
}
static void toml_set_account_pc_name(struct account_data *account, const char *value)
{
char tmp[MAX_INPUT_LENGTH];
if (!value || !*value)
return;
strlcpy(tmp, value, sizeof(tmp));
CAP(tmp);
if (account->pc_name)
free(account->pc_name);
account->pc_name = strdup(tmp);
}
int account_has_pc(const struct account_data *account, const char *pc_name)
{
int i;
@ -77,9 +104,11 @@ struct account_data *account_load(const char *name)
struct account_data *account;
FILE *fl;
char filename[PATH_MAX];
char line[MAX_INPUT_LENGTH + 1];
char tag[6];
int i;
char errbuf[256];
toml_table_t *tab = NULL;
toml_array_t *arr = NULL;
char *value = NULL;
int i, count;
if (!name || !*name)
return NULL;
@ -91,29 +120,55 @@ struct account_data *account_load(const char *name)
if (!fl)
return NULL;
tab = toml_parse_file(fl, errbuf, sizeof(errbuf));
fclose(fl);
if (!tab) {
log("SYSERR: Couldn't parse account file %s: %s.", filename, errbuf);
return NULL;
}
account = account_create(NULL);
while (get_line(fl, line)) {
tag_argument(line, tag);
value = toml_dup_string(tab, "name");
if (value) {
set_account_name(account, value);
free(value);
}
if (!strcmp(tag, "Name"))
set_account_name(account, line);
else if (!strcmp(tag, "Pass"))
strlcpy(account->passwd, line, sizeof(account->passwd));
else if (!strcmp(tag, "Mail")) {
if (account->email)
free(account->email);
account->email = strdup(line);
} else if (!strcmp(tag, "Char"))
account_add_pc(account, line);
else if (!strcmp(tag, "Curr")) {
if (account->pc_name)
free(account->pc_name);
account->pc_name = strdup(line);
value = toml_dup_string(tab, "password");
if (value) {
strlcpy(account->passwd, value, sizeof(account->passwd));
free(value);
}
value = toml_dup_string(tab, "email");
if (value) {
if (account->email)
free(account->email);
account->email = value;
}
value = toml_dup_string(tab, "current_pc");
if (value) {
toml_set_account_pc_name(account, value);
free(value);
}
arr = toml_array_in(tab, "pcs");
if (arr) {
count = toml_array_nelem(arr);
for (i = 0; i < count; i++) {
toml_datum_t d = toml_string_at(arr, i);
if (!d.ok) {
log("SYSERR: Invalid account character entry %d in %s.", i, filename);
continue;
}
account_add_pc(account, d.u.s);
free(d.u.s);
}
}
fclose(fl);
toml_free(tab);
if (!account->name)
set_account_name(account, name);
@ -151,14 +206,33 @@ int account_save(const struct account_data *account)
return 0;
}
fprintf(fl, "Name: %s\n", account->name);
fprintf(fl, "Pass: %s\n", account->passwd);
fprintf(fl, "name = ");
toml_write_string(fl, account->name);
fprintf(fl, "\n");
fprintf(fl, "password = ");
toml_write_string(fl, account->passwd);
fprintf(fl, "\n");
if (account->email && *account->email)
fprintf(fl, "Mail: %s\n", account->email);
{
fprintf(fl, "email = ");
toml_write_string(fl, account->email);
fprintf(fl, "\n");
}
if (account->pc_name && *account->pc_name)
fprintf(fl, "Curr: %s\n", account->pc_name);
for (i = 0; i < account->pc_count; i++)
fprintf(fl, "Char: %s\n", account->pc_list[i]);
{
fprintf(fl, "current_pc = ");
toml_write_string(fl, account->pc_name);
fprintf(fl, "\n");
}
if (account->pc_count > 0) {
fprintf(fl, "pcs = [\n");
for (i = 0; i < account->pc_count; i++) {
fprintf(fl, " ");
toml_write_string(fl, account->pc_list[i]);
fprintf(fl, "%s\n", (i + 1 < account->pc_count) ? "," : "");
}
fprintf(fl, "]\n");
}
fclose(fl);
return 1;

1437
src/db.c

File diff suppressed because it is too large Load diff

View file

@ -54,11 +54,11 @@
#error "Unknown path components."
#endif
#define SUF_OBJS "objs"
#define SUF_OBJS "objs.toml"
#define SUF_TEXT "text"
#define SUF_MEM "mem"
#define SUF_PLR "plr"
#define SUF_ACCT "acc"
#define SUF_MEM "mem.toml"
#define SUF_PLR "plr.toml"
#define SUF_ACCT "acc.toml"
#if defined(CIRCLE_AMIGA)
#define EXE_FILE "/bin/circle" /* maybe use argv[0] but it's not reliable */
@ -77,8 +77,8 @@
#endif
/* names of various files and directories */
#define INDEX_FILE "index" /* index of world files */
#define MINDEX_FILE "index.mini" /* ... and for mini-mud-mode */
#define INDEX_FILE "index.toml" /* index of world files */
#define MINDEX_FILE "index.mini.toml" /* ... and for mini-mud-mode */
#define WLD_PREFIX LIB_WORLD"wld"SLASH /* room definitions */
#define MOB_PREFIX LIB_WORLD"mob"SLASH /* monster prototypes */
#define OBJ_PREFIX LIB_WORLD"obj"SLASH /* object prototypes */

View file

@ -113,6 +113,7 @@ ACMD(do_oasis_trigedit)
void script_save_to_disk(FILE *fp, void *item, int type)
{
struct trig_proto_list *t;
int first = 1;
if (type==MOB_TRIGGER)
t = ((struct char_data *)item)->proto_script;
@ -125,11 +126,18 @@ void script_save_to_disk(FILE *fp, void *item, int type)
return;
}
while (t)
{
fprintf(fp,"T %d\n", t->vnum);
if (!t)
return;
fprintf(fp, "triggers = [");
while (t) {
if (!first)
fputs(", ", fp);
fprintf(fp, "%d", t->vnum);
first = 0;
t = t->next;
}
fputs("]\n", fp);
}
static void trigedit_setup_new(struct descriptor_data *d)
@ -852,9 +860,9 @@ void trigedit_save(struct descriptor_data *d)
fclose(trig_file);
#ifdef CIRCLE_MAC
snprintf(buf, sizeof(buf), "%s:%d.trg", TRG_PREFIX, zone);
snprintf(buf, sizeof(buf), "%s:%d.toml", TRG_PREFIX, zone);
#else
snprintf(buf, sizeof(buf), "%s/%d.trg", TRG_PREFIX, zone);
snprintf(buf, sizeof(buf), "%s/%d.toml", TRG_PREFIX, zone);
#endif
remove(buf);

View file

@ -29,6 +29,8 @@
#include "genzon.h" /* for real_zone_by_thing */
#include "act.h"
#include "modify.h"
#include "toml.h"
#include "toml_utils.h"
#define PULSES_PER_MUD_HOUR (SECS_PER_MUD_HOUR*PASSES_PER_SEC)
@ -2826,11 +2828,11 @@ static struct cmdlist_element *find_done(struct cmdlist_element *cl)
void read_saved_vars(struct char_data *ch)
{
FILE *file;
long context;
char fn[127];
char input_line[1024], *temp, *p;
char varname[32];
char context_str[16];
char errbuf[256];
toml_table_t *tab = NULL;
toml_array_t *arr = NULL;
int i, count;
/* If getting to the menu from inside the game, the vars aren't removed. So
* let's not allocate them again. */
@ -2851,22 +2853,44 @@ void read_saved_vars(struct char_data *ch)
log("%s had no variable file", GET_NAME(ch));
return;
}
/* walk through each line in the file parsing variables */
do {
if (get_line(file, input_line)>0) {
p = temp = strdup(input_line);
temp = any_one_arg(temp, varname);
temp = any_one_arg(temp, context_str);
skip_spaces(&temp); /* temp now points to the rest of the line */
context = atol(context_str);
add_var(&(SCRIPT(ch)->global_vars), varname, temp, context);
free(p); /* plug memory hole */
}
} while( !feof(file) );
/* close the file and return */
tab = toml_parse_file(file, errbuf, sizeof(errbuf));
fclose(file);
if (!tab) {
log("SYSERR: Could not parse variable file %s: %s", fn, errbuf);
return;
}
arr = toml_array_in(tab, "var");
if (!arr) {
toml_free(tab);
return;
}
count = toml_array_nelem(arr);
for (i = 0; i < count; i++) {
toml_table_t *var_tab = toml_table_at(arr, i);
toml_datum_t name;
toml_datum_t value;
toml_datum_t context;
if (!var_tab)
continue;
name = toml_string_in(var_tab, "name");
value = toml_string_in(var_tab, "value");
context = toml_int_in(var_tab, "context");
if (!name.ok || !value.ok)
continue;
add_var(&(SCRIPT(ch)->global_vars), name.u.s, value.u.s,
context.ok ? (long)context.u.i : 0);
free(name.u.s);
free(value.u.s);
}
toml_free(tab);
}
/* save a characters variables out to disk */
@ -2901,7 +2925,12 @@ void save_char_vars(struct char_data *ch)
* future. */
while (vars) {
if (*vars->name != '-') /* don't save if it begins with - */
fprintf(file, "%s %ld %s\n", vars->name, vars->context, vars->value);
{
fprintf(file, "[[var]]\n");
toml_write_kv_string(file, "name", vars->name);
fprintf(file, "context = %ld\n", vars->context);
toml_write_kv_string(file, "value", vars->value);
}
vars = vars->next;
}

View file

@ -17,6 +17,7 @@
#include "genzon.h"
#include "dg_olc.h"
#include "spells.h"
#include "toml_utils.h"
/* local functions */
static void extract_mobile_all(mob_vnum vnum);
@ -312,10 +313,9 @@ int save_mobiles(zone_rnum rznum)
if (write_mobile_record(i, &mob_proto[rmob], mobfd) < 0)
log("SYSERR: GenOLC: Error writing mobile #%d.", i);
}
fputs("$\n", mobfd);
written = ftell(mobfd);
fclose(mobfd);
snprintf(usedfname, sizeof(usedfname), "%s%d.mob", MOB_PREFIX, vznum);
snprintf(usedfname, sizeof(usedfname), "%s%d.toml", MOB_PREFIX, vznum);
remove(usedfname);
rename(mobfname, usedfname);
@ -407,7 +407,6 @@ int write_mobile_record(mob_vnum mvnum, struct char_data *mob, FILE *fd)
char ldesc[MAX_STRING_LENGTH];
char ddesc[MAX_STRING_LENGTH];
char bdesc[MAX_STRING_LENGTH];
char buf[MAX_STRING_LENGTH];
int has_bdesc = 0;
ldesc[MAX_STRING_LENGTH - 1] = '\0';
@ -429,94 +428,71 @@ int write_mobile_record(mob_vnum mvnum, struct char_data *mob, FILE *fd)
} else
bdesc[0] = '\0';
int n;
if (has_bdesc) {
n = snprintf(buf, MAX_STRING_LENGTH,
"#%d\n"
"%s%c\n"
"%s%c\n"
"%s%c\n"
"%s%c\n"
"%s%c\n"
"B\n"
"%s%c\n",
mvnum,
GET_NAME(mob), STRING_TERMINATOR,
GET_KEYWORDS(mob), STRING_TERMINATOR,
GET_SDESC(mob), STRING_TERMINATOR,
ldesc, STRING_TERMINATOR,
ddesc, STRING_TERMINATOR,
bdesc, STRING_TERMINATOR);
} else {
n = snprintf(buf, MAX_STRING_LENGTH,
"#%d\n"
"%s%c\n"
"%s%c\n"
"%s%c\n"
"%s%c\n"
"%s%c\n",
mvnum,
GET_NAME(mob), STRING_TERMINATOR,
GET_KEYWORDS(mob), STRING_TERMINATOR,
GET_SDESC(mob), STRING_TERMINATOR,
ldesc, STRING_TERMINATOR,
ddesc, STRING_TERMINATOR);
}
fprintf(fd, "[[mob]]\n");
fprintf(fd, "vnum = %d\n", mvnum);
toml_write_kv_string(fd, "name", GET_NAME(mob));
toml_write_kv_string(fd, "keywords", GET_KEYWORDS(mob));
toml_write_kv_string(fd, "short", GET_SDESC(mob));
toml_write_kv_string(fd, "long", ldesc);
toml_write_kv_string(fd, "description", ddesc);
if (has_bdesc)
toml_write_kv_string_opt(fd, "background", bdesc);
if (n >= MAX_STRING_LENGTH) {
mudlog(BRF, LVL_BUILDER, TRUE,
"SYSERR: Could not save mobile #%d due to size (%d > maximum of %d)",
mvnum, n, MAX_STRING_LENGTH);
return TRUE;
}
fprintf(fd, "%s", convert_from_tabs(buf));
/* --- FLAGS/AFFECT/ALIGN line --- */
fprintf(fd,
"%d %d %d %d %d %d %d %d %d E\n",
fprintf(fd, "flags = [%d, %d, %d, %d]\n",
MOB_FLAGS(mob)[0], MOB_FLAGS(mob)[1],
MOB_FLAGS(mob)[2], MOB_FLAGS(mob)[3],
MOB_FLAGS(mob)[2], MOB_FLAGS(mob)[3]);
fprintf(fd, "aff_flags = [%d, %d, %d, %d]\n",
AFF_FLAGS(mob)[0], AFF_FLAGS(mob)[1],
AFF_FLAGS(mob)[2], AFF_FLAGS(mob)[3],
GET_ALIGNMENT(mob));
AFF_FLAGS(mob)[2], AFF_FLAGS(mob)[3]);
fprintf(fd, "alignment = %d\n", GET_ALIGNMENT(mob));
toml_write_kv_string(fd, "mob_type", "enhanced");
/* --- Level, hitdice, mana, move --- */
fprintf(fd, "%d %dd%d+%d\n",
GET_LEVEL(mob),
GET_HIT(mob),
GET_MANA(mob),
GET_STAMINA(mob));
fprintf(fd, "\n[mob.simple]\n");
fprintf(fd, "level = %d\n", GET_LEVEL(mob));
fprintf(fd, "hit_dice = %d\n", GET_HIT(mob));
fprintf(fd, "mana_dice = %d\n", GET_MANA(mob));
fprintf(fd, "stamina_dice = %d\n", GET_STAMINA(mob));
fprintf(fd, "pos = %d\n", GET_POS(mob));
fprintf(fd, "default_pos = %d\n", GET_DEFAULT_POS(mob));
fprintf(fd, "sex = %d\n", GET_SEX(mob));
/* --- Position / default position / sex --- */
fprintf(fd, "%d %d %d\n",
GET_POS(mob),
GET_DEFAULT_POS(mob),
GET_SEX(mob));
fprintf(fd, "\n[mob.enhanced]\n");
fprintf(fd, "class = %d\n", GET_CLASS(mob));
fprintf(fd, "species = %d\n", GET_SPECIES(mob));
fprintf(fd, "age = %d\n", GET_ROLEPLAY_AGE(mob));
fprintf(fd, "attack_type = %d\n", mob->mob_specials.attack_type);
/* --- Enhanced (E-spec + Skills) --- */
if (write_mobile_espec(mvnum, mob, fd) < 0)
log("SYSERR: GenOLC: Error writing E-specs for mobile #%d.", mvnum);
fprintf(fd, "\n[mob.enhanced.abilities]\n");
fprintf(fd, "str = %d\n", GET_STR(mob));
fprintf(fd, "dex = %d\n", GET_DEX(mob));
fprintf(fd, "con = %d\n", GET_CON(mob));
fprintf(fd, "int = %d\n", GET_INT(mob));
fprintf(fd, "wis = %d\n", GET_WIS(mob));
fprintf(fd, "cha = %d\n", GET_CHA(mob));
fprintf(fd, "\n[mob.enhanced.saving_throws]\n");
fprintf(fd, "str = %d\n", GET_SAVE(mob, ABIL_STR));
fprintf(fd, "dex = %d\n", GET_SAVE(mob, ABIL_DEX));
fprintf(fd, "con = %d\n", GET_SAVE(mob, ABIL_CON));
fprintf(fd, "int = %d\n", GET_SAVE(mob, ABIL_INT));
fprintf(fd, "wis = %d\n", GET_SAVE(mob, ABIL_WIS));
fprintf(fd, "cha = %d\n", GET_SAVE(mob, ABIL_CHA));
/* Write NPC skills (if any set) */
for (int s = 0; s < MAX_SKILLS; s++) {
if (mob->mob_specials.skills[s] > 0)
fprintf(fd, "Skill %d %d\n", s, mob->mob_specials.skills[s]);
if (mob->mob_specials.skills[s] > 0) {
fprintf(fd, "\n[[mob.enhanced.skills]]\n");
fprintf(fd, "id = %d\n", s);
fprintf(fd, "level = %d\n", mob->mob_specials.skills[s]);
}
}
/* Write attack type (if set) */
if (mob->mob_specials.attack_type > 0)
fprintf(fd, "AtkT %d\n", mob->mob_specials.attack_type);
/* Single proper terminator */
fprintf(fd, "E\n");
/* --- Loadout lines --- */
/* --- Loadout entries --- */
for (struct mob_loadout *e = mob->proto_loadout; e; e = e->next) {
fprintf(fd, "L %d %d %d\n",
(int)e->wear_pos,
(int)e->vnum,
MAX(1, e->quantity));
fprintf(fd, "\n[[mob.loadout]]\n");
fprintf(fd, "wear_pos = %d\n", (int)e->wear_pos);
fprintf(fd, "vnum = %d\n", (int)e->vnum);
fprintf(fd, "quantity = %d\n", MAX(1, e->quantity));
}
/* --- DG Scripts --- */
@ -528,10 +504,11 @@ int write_mobile_record(mob_vnum mvnum, struct char_data *mob, FILE *fd)
struct skin_yield_entry *sy;
if (rmob != NOBODY && mob_index[rmob].skin_yields) {
fprintf(fd, "Y\n");
for (sy = mob_index[rmob].skin_yields; sy; sy = sy->next)
fprintf(fd, "%d %d\n", sy->obj_vnum, sy->dc);
fprintf(fd, "0 0\n");
for (sy = mob_index[rmob].skin_yields; sy; sy = sy->next) {
fprintf(fd, "\n[[mob.skin_yield]]\n");
fprintf(fd, "obj_vnum = %d\n", sy->obj_vnum);
fprintf(fd, "dc = %d\n", sy->dc);
}
}
}
@ -540,6 +517,7 @@ int write_mobile_record(mob_vnum mvnum, struct char_data *mob, FILE *fd)
log("SYSERR: GenOLC: Error writing MobProgs for mobile #%d.", mvnum);
#endif
fputc('\n', fd);
return TRUE;
}

View file

@ -19,6 +19,7 @@
#include "handler.h"
#include "interpreter.h"
#include "boards.h" /* for board_info */
#include "toml_utils.h"
/* local functions */
@ -178,10 +179,7 @@ obj_rnum index_object(struct obj_data *obj, obj_vnum ovnum, obj_rnum ornum)
int save_objects(zone_rnum zone_num)
{
char filename[128], buf[MAX_STRING_LENGTH], buf2[MAX_STRING_LENGTH];
char ebuf1[MAX_STRING_LENGTH], ebuf2[MAX_STRING_LENGTH], ebuf3[MAX_STRING_LENGTH], ebuf4[MAX_STRING_LENGTH];
char wbuf1[MAX_STRING_LENGTH], wbuf2[MAX_STRING_LENGTH], wbuf3[MAX_STRING_LENGTH], wbuf4[MAX_STRING_LENGTH];
char pbuf1[MAX_STRING_LENGTH], pbuf2[MAX_STRING_LENGTH], pbuf3[MAX_STRING_LENGTH], pbuf4[MAX_STRING_LENGTH];
char filename[128], buf[MAX_STRING_LENGTH];
int counter, counter2, realcounter;
FILE *fp;
struct obj_data *obj;
@ -210,54 +208,33 @@ int save_objects(zone_rnum zone_num)
} else
*buf = '\0';
int n = snprintf(buf2, MAX_STRING_LENGTH,
"#%d\n"
"%s~\n"
"%s~\n"
"%s~\n"
"%s~\n",
GET_OBJ_VNUM(obj),
(obj->name && *obj->name) ? obj->name : "undefined",
(obj->short_description && *obj->short_description) ? obj->short_description : "undefined",
(obj->description && *obj->description) ? obj->description : "undefined",
buf);
if(n >= MAX_STRING_LENGTH) {
mudlog(BRF,LVL_BUILDER,TRUE,
"SYSERR: Could not save object #%d due to size (%d > maximum of %d).",
GET_OBJ_VNUM(obj), n, MAX_STRING_LENGTH);
continue;
fprintf(fp, "[[object]]\n");
fprintf(fp, "vnum = %d\n", GET_OBJ_VNUM(obj));
toml_write_kv_string(fp, "name", (obj->name && *obj->name) ? obj->name : "undefined");
toml_write_kv_string(fp, "short", (obj->short_description && *obj->short_description) ? obj->short_description : "undefined");
toml_write_kv_string(fp, "description", (obj->description && *obj->description) ? obj->description : "undefined");
toml_write_kv_string(fp, "main_description", buf);
fprintf(fp, "type = %d\n", GET_OBJ_TYPE(obj));
fprintf(fp, "extra_flags = [%d, %d, %d, %d]\n",
GET_OBJ_EXTRA(obj)[0], GET_OBJ_EXTRA(obj)[1],
GET_OBJ_EXTRA(obj)[2], GET_OBJ_EXTRA(obj)[3]);
fprintf(fp, "wear_flags = [%d, %d, %d, %d]\n",
GET_OBJ_WEAR(obj)[0], GET_OBJ_WEAR(obj)[1],
GET_OBJ_WEAR(obj)[2], GET_OBJ_WEAR(obj)[3]);
fprintf(fp, "affect_flags = [%d, %d, %d, %d]\n",
GET_OBJ_AFFECT(obj)[0], GET_OBJ_AFFECT(obj)[1],
GET_OBJ_AFFECT(obj)[2], GET_OBJ_AFFECT(obj)[3]);
fprintf(fp, "values = [");
for (counter2 = 0; counter2 < NUM_OBJ_VAL_POSITIONS; counter2++) {
if (counter2)
fputs(", ", fp);
fprintf(fp, "%d", GET_OBJ_VAL(obj, counter2));
}
fprintf(fp, "%s", convert_from_tabs(buf2));
sprintascii(ebuf1, GET_OBJ_EXTRA(obj)[0]);
sprintascii(ebuf2, GET_OBJ_EXTRA(obj)[1]);
sprintascii(ebuf3, GET_OBJ_EXTRA(obj)[2]);
sprintascii(ebuf4, GET_OBJ_EXTRA(obj)[3]);
sprintascii(wbuf1, GET_OBJ_WEAR(obj)[0]);
sprintascii(wbuf2, GET_OBJ_WEAR(obj)[1]);
sprintascii(wbuf3, GET_OBJ_WEAR(obj)[2]);
sprintascii(wbuf4, GET_OBJ_WEAR(obj)[3]);
sprintascii(pbuf1, GET_OBJ_AFFECT(obj)[0]);
sprintascii(pbuf2, GET_OBJ_AFFECT(obj)[1]);
sprintascii(pbuf3, GET_OBJ_AFFECT(obj)[2]);
sprintascii(pbuf4, GET_OBJ_AFFECT(obj)[3]);
fprintf(fp, "%d %s %s %s %s %s %s %s %s %s %s %s %s\n"
"%d %d %d %d\n"
"%d %d %d %d %d\n",
GET_OBJ_TYPE(obj),
ebuf1, ebuf2, ebuf3, ebuf4,
wbuf1, wbuf2, wbuf3, wbuf4,
pbuf1, pbuf2, pbuf3, pbuf4,
GET_OBJ_VAL(obj, 0), GET_OBJ_VAL(obj, 1),
GET_OBJ_VAL(obj, 2), GET_OBJ_VAL(obj, 3),
GET_OBJ_WEIGHT(obj), GET_OBJ_COST(obj),
GET_OBJ_COST_PER_DAY(obj), GET_OBJ_LEVEL(obj), GET_OBJ_TIMER(obj)
);
fputs("]\n", fp);
fprintf(fp, "weight = %d\n", GET_OBJ_WEIGHT(obj));
fprintf(fp, "cost = %d\n", GET_OBJ_COST(obj));
fprintf(fp, "level = %d\n", GET_OBJ_LEVEL(obj));
fprintf(fp, "timer = %d\n", GET_OBJ_TIMER(obj));
/* Do we have script(s) attached? */
script_save_to_disk(fp, obj, OBJ_TRIGGER);
@ -272,24 +249,25 @@ int save_objects(zone_rnum zone_num)
}
strncpy(buf, ex_desc->description, sizeof(buf) - 1);
strip_cr(buf);
fprintf(fp, "E\n"
"%s~\n"
"%s~\n", ex_desc->keyword, buf);
fprintf(fp, "\n[[object.extra_desc]]\n");
toml_write_kv_string(fp, "keyword", ex_desc->keyword);
toml_write_kv_string(fp, "description", buf);
}
}
/* Do we have affects? */
for (counter2 = 0; counter2 < MAX_OBJ_AFFECT; counter2++)
if (obj->affected[counter2].modifier)
fprintf(fp, "A\n"
"%d %d\n", obj->affected[counter2].location,
obj->affected[counter2].modifier);
for (counter2 = 0; counter2 < MAX_OBJ_AFFECT; counter2++) {
if (obj->affected[counter2].modifier) {
fprintf(fp, "\n[[object.affect]]\n");
fprintf(fp, "location = %d\n", obj->affected[counter2].location);
fprintf(fp, "modifier = %d\n", obj->affected[counter2].modifier);
}
}
fputc('\n', fp);
}
}
/* Write the final line, close the file. */
fprintf(fp, "$~\n");
fclose(fp);
snprintf(buf, sizeof(buf), "%s/%d.obj", OBJ_PREFIX, zone_table[zone_num].number);
snprintf(buf, sizeof(buf), "%s/%d.toml", OBJ_PREFIX, zone_table[zone_num].number);
remove(buf);
rename(filename, buf);
@ -615,4 +593,4 @@ void clamp_armor_values(struct obj_data *obj) {
GET_OBJ_VAL(obj, VAL_ARMOR_MAGIC_BONUS) = v;
/* flags are a bitvector; leave as-is (OLC will manage legal bits) */
}
}

View file

@ -313,7 +313,7 @@ ACMD(do_export_zone)
#else /* all other configurations */
zone_rnum zrnum;
zone_vnum zvnum;
char sysbuf[MAX_INPUT_LENGTH];
char sysbuf[MAX_STRING_LENGTH];
char zone_name[READ_SIZE], fixed_file_name[READ_SIZE];
int success, errorcode = 0;
@ -384,7 +384,7 @@ ACMD(do_export_zone)
/* Tar the new copy. */
snprintf(sysbuf, sizeof(sysbuf), "tar -cf %s%s.tar %sqq.info %sqq.wld %sqq.zon %sqq.mob %sqq.obj %sqq.trg %sqq.shp", path, fixed_file_name, path, path, path, path, path, path, path);
snprintf(sysbuf, sizeof(sysbuf), "tar -cf %s%s.tar %sqq.info %sqq.wld.toml %sqq.zon.toml %sqq.mob.toml %sqq.obj.toml %sqq.trg.toml %sqq.shp.toml %sqq.qst.toml", path, fixed_file_name, path, path, path, path, path, path, path, path);
errorcode = system(sysbuf);
if (errorcode) {
send_to_char(ch, "Failed to tar files.\r\n");
@ -425,8 +425,8 @@ static int export_info_file(zone_rnum zrnum)
fprintf(info_file, "Implementation:\n");
fprintf(info_file, "1. All the files have been QQ'ed. This means all occurences of the zone number\n");
fprintf(info_file, " have been changed to QQ. In other words, if you decide to have this zone as\n");
fprintf(info_file, " zone 123, replace all occurences of QQ with 123 and rename the qq.zon file\n");
fprintf(info_file, " to 123.zon (etc.). And of course add 123.zon to the respective index file.\n");
fprintf(info_file, " zone 123, replace all occurences of QQ with 123 and rename the qq.wld.toml file\n");
fprintf(info_file, " to 123.toml (etc.). And of course add 123.toml to the respective index file.\n");
if (zone_exits) {
fprintf(info_file, "2. Exits out of this zone have been ZZ'd. So all doors leading out have ZZ??\n");
fprintf(info_file, " instead of the room vnum (?? are numbers 00 - 99).\n");
@ -481,7 +481,7 @@ static int export_save_shops(zone_rnum zrnum)
FILE *shop_file;
struct shop_data *shop;
if (!(shop_file = fopen("world/export/qq.shp", "w"))) {
if (!(shop_file = fopen("world/export/qq.shp.toml", "w"))) {
mudlog(BRF, LVL_GOD, TRUE, "SYSERR: export_save_shops : Cannot open shop file!");
return FALSE;
} else if (fprintf(shop_file, "CircleMUD v3.0 Shop File~\n") < 0) {
@ -571,7 +571,7 @@ static int export_save_mobiles(zone_rnum rznum)
mob_vnum i;
mob_rnum rmob;
if (!(mob_file = fopen("world/export/qq.mob", "w"))) {
if (!(mob_file = fopen("world/export/qq.mob.toml", "w"))) {
mudlog(BRF, LVL_GOD, TRUE, "SYSERR: export_save_mobiles : Cannot open file!");
return FALSE;
}
@ -648,7 +648,7 @@ static int export_save_zone(zone_rnum zrnum)
int subcmd;
FILE *zone_file;
if (!(zone_file = fopen("world/export/qq.zon", "w"))) {
if (!(zone_file = fopen("world/export/qq.zon.toml", "w"))) {
mudlog(BRF, LVL_GOD, TRUE, "SYSERR: export_save_zone : Cannot open file!");
return FALSE;
}
@ -783,7 +783,7 @@ static int export_save_objects(zone_rnum zrnum)
struct obj_data *obj;
struct extra_descr_data *ex_desc;
if (!(obj_file = fopen("world/export/qq.obj", "w"))) {
if (!(obj_file = fopen("world/export/qq.obj.toml", "w"))) {
mudlog(BRF, LVL_GOD, TRUE, "SYSERR: export_save_objects : Cannot open file!");
return FALSE;
}
@ -889,7 +889,7 @@ static int export_save_rooms(zone_rnum zrnum)
char buf[MAX_STRING_LENGTH];
char buf1[MAX_STRING_LENGTH];
if (!(room_file = fopen("world/export/qq.wld", "w"))) {
if (!(room_file = fopen("world/export/qq.wld.toml", "w"))) {
mudlog(BRF, LVL_GOD, TRUE, "SYSERR: export_save_rooms : Cannot open file!");
return FALSE;
}
@ -1028,7 +1028,7 @@ static int export_save_triggers(zone_rnum zrnum)
FILE *trig_file;
char bitBuf[MAX_INPUT_LENGTH];
if (!(trig_file = fopen("world/export/qq.trg", "w"))) {
if (!(trig_file = fopen("world/export/qq.trg.toml", "w"))) {
mudlog(BRF, LVL_GOD, TRUE, "SYSERR: export_save_triggers : Cannot open file!");
return FALSE;
}

View file

@ -16,6 +16,7 @@
#include "quest.h"
#include "genolc.h"
#include "genzon.h" /* for create_world_index */
#include "toml_utils.h"
/*-------------------------------------------------------------------*/
@ -176,10 +177,9 @@ int delete_quest(qst_rnum rnum)
int save_quests(zone_rnum zone_num)
{
FILE *sf;
char filename[128], oldname[128], quest_flags[MAX_STRING_LENGTH];
char filename[128], oldname[128];
char quest_desc[MAX_STRING_LENGTH], quest_info[MAX_STRING_LENGTH];
char quest_done[MAX_STRING_LENGTH], quest_quit[MAX_STRING_LENGTH];
char buf[MAX_STRING_LENGTH];
int i, num_quests = 0;
#if CIRCLE_UNSIGNED_INDEX
@ -219,53 +219,37 @@ int save_quests(zone_rnum zone_num)
strip_cr(quest_done);
strip_cr(quest_quit);
/* Save the quest details to the file. */
sprintascii(quest_flags, QST_FLAGS(rnum));
int n = snprintf(buf, MAX_STRING_LENGTH,
"#%d\n"
"%s%c\n"
"%s%c\n"
"%s%c\n"
"%s%c\n"
"%s%c\n"
"%d %d %s %d %d %d %d\n"
"%d %d %d %d %d %d %d\n"
"%d %d %d\n"
"S\n",
QST_NUM(rnum),
QST_NAME(rnum) ? QST_NAME(rnum) : "Untitled", STRING_TERMINATOR,
quest_desc, STRING_TERMINATOR,
quest_info, STRING_TERMINATOR,
quest_done, STRING_TERMINATOR,
quest_quit, STRING_TERMINATOR,
QST_TYPE(rnum),
QST_MASTER(rnum) == NOBODY ? -1 : QST_MASTER(rnum),
quest_flags,
QST_TARGET(rnum) == NOTHING ? -1 : QST_TARGET(rnum),
QST_PREV(rnum) == NOTHING ? -1 : QST_PREV(rnum),
QST_NEXT(rnum) == NOTHING ? -1 : QST_NEXT(rnum),
QST_PREREQ(rnum) == NOTHING ? -1 : QST_PREREQ(rnum),
QST_POINTS(rnum), QST_PENALTY(rnum), QST_MINLEVEL(rnum),
QST_MAXLEVEL(rnum), QST_TIME(rnum),
QST_RETURNMOB(rnum) == NOBODY ? -1 : QST_RETURNMOB(rnum),
QST_QUANTITY(rnum), QST_COINS(rnum), QST_EXP(rnum), QST_OBJ(rnum)
);
if(n < MAX_STRING_LENGTH) {
fprintf(sf, "%s", convert_from_tabs(buf));
num_quests++;
} else {
mudlog(BRF,LVL_BUILDER,TRUE,
"SYSERR: Could not save quest #%d due to size (%d > maximum of %d).",
QST_NUM(rnum), n, MAX_STRING_LENGTH);
}
fprintf(sf, "[[quest]]\n");
fprintf(sf, "vnum = %d\n", QST_NUM(rnum));
toml_write_kv_string(sf, "name", QST_NAME(rnum) ? QST_NAME(rnum) : "Untitled");
toml_write_kv_string(sf, "description", quest_desc);
toml_write_kv_string(sf, "info", quest_info);
toml_write_kv_string(sf, "done", quest_done);
toml_write_kv_string(sf, "quit", quest_quit);
fprintf(sf, "type = %d\n", QST_TYPE(rnum));
fprintf(sf, "quest_master = %d\n", QST_MASTER(rnum) == NOBODY ? -1 : QST_MASTER(rnum));
fprintf(sf, "flags = %d\n", (int)QST_FLAGS(rnum));
fprintf(sf, "target = %d\n", QST_TARGET(rnum) == NOTHING ? -1 : QST_TARGET(rnum));
fprintf(sf, "prev_quest = %d\n", QST_PREV(rnum) == NOTHING ? -1 : QST_PREV(rnum));
fprintf(sf, "next_quest = %d\n", QST_NEXT(rnum) == NOTHING ? -1 : QST_NEXT(rnum));
fprintf(sf, "prereq = %d\n", QST_PREREQ(rnum) == NOTHING ? -1 : QST_PREREQ(rnum));
fprintf(sf, "values = [%d, %d, %d, %d, %d, %d, %d]\n",
QST_POINTS(rnum), QST_PENALTY(rnum), QST_MINLEVEL(rnum),
QST_MAXLEVEL(rnum), QST_TIME(rnum),
QST_RETURNMOB(rnum) == NOBODY ? -1 : QST_RETURNMOB(rnum),
QST_QUANTITY(rnum));
fprintf(sf, "[quest.rewards]\n");
fprintf(sf, "coins = %d\n", QST_COINS(rnum));
fprintf(sf, "exp = %d\n", QST_EXP(rnum));
fprintf(sf, "obj_vnum = %d\n", QST_OBJ(rnum) == NOTHING ? -1 : QST_OBJ(rnum));
fputc('\n', sf);
num_quests++;
}
}
/* Write the final line and close it. */
fprintf(sf, "$~\n");
fclose(sf);
/* Old file we're replacing. */
snprintf(oldname, sizeof(oldname), "%s/%d.qst",
snprintf(oldname, sizeof(oldname), "%s/%d.toml",
QST_PREFIX, zone_table[zone_num].number);
remove(oldname);
rename(filename, oldname);

View file

@ -14,6 +14,7 @@
#include "genolc.h"
#include "genshp.h"
#include "genzon.h"
#include "toml_utils.h"
/* NOTE (gg): Didn't modify sedit much. Don't consider it as 'recent' as the
* other editors with regard to updates or style. */
@ -345,7 +346,7 @@ int save_shops(zone_rnum zone_num)
{
int i, j, rshop, num_shops = 0;
FILE *shop_file;
char fname[128], oldname[128], buf[MAX_STRING_LENGTH];
char fname[128], oldname[128];
struct shop_data *shop;
#if CIRCLE_UNSIGNED_INDEX
@ -361,77 +362,68 @@ int save_shops(zone_rnum zone_num)
if (!(shop_file = fopen(fname, "w"))) {
mudlog(BRF, LVL_GOD, TRUE, "SYSERR: OLC: Cannot open shop file!");
return FALSE;
} else if (fprintf(shop_file, "CircleMUD v3.0 Shop File~\n") < 0) {
mudlog(BRF, LVL_GOD, TRUE, "SYSERR: OLC: Cannot write to shop file!");
fclose(shop_file);
return FALSE;
}
/* Search database for shops in this zone. */
for (i = genolc_zone_bottom(zone_num); i <= zone_table[zone_num].top; i++) {
if ((rshop = real_shop(i)) != NOWHERE) {
fprintf(shop_file, "#%d~\n", i);
shop = shop_index + rshop;
/* Save the products. */
for (j = 0; S_PRODUCT(shop, j) != NOTHING; j++)
fprintf(shop_file, "%d\n", obj_index[S_PRODUCT(shop, j)].vnum);
fprintf(shop_file, "-1\n");
fprintf(shop_file, "[[shop]]\n");
fprintf(shop_file, "vnum = %d\n", i);
/* Save the rates. */
fprintf(shop_file, "%1.2f\n"
"%1.2f\n",
S_BUYPROFIT(shop),
S_SELLPROFIT(shop));
fprintf(shop_file, "products = [");
for (j = 0; S_PRODUCT(shop, j) != NOTHING; j++) {
if (j)
fputs(", ", shop_file);
fprintf(shop_file, "%d", obj_index[S_PRODUCT(shop, j)].vnum);
}
fputs("]\n", shop_file);
/* Save the buy types and namelists. */
for (j = 0;S_BUYTYPE(shop, j) != NOTHING; j++)
fprintf(shop_file, "%d%s\n",
S_BUYTYPE(shop, j),
S_BUYWORD(shop, j) ? S_BUYWORD(shop, j) : "");
fprintf(shop_file, "-1\n");
fprintf(shop_file, "buy_profit = %1.2f\n", S_BUYPROFIT(shop));
fprintf(shop_file, "sell_profit = %1.2f\n", S_SELLPROFIT(shop));
/* Save messages. Added some defaults as sanity checks. */
sprintf(buf,
"%s~\n"
"%s~\n"
"%s~\n"
"%s~\n"
"%s~\n"
"%s~\n"
"%s~\n"
"%d\n"
"%ld\n"
"%d\n"
"%d\n",
S_NOITEM1(shop) ? S_NOITEM1(shop) : "%s Ke?!",
S_NOITEM2(shop) ? S_NOITEM2(shop) : "%s Ke?!",
S_NOBUY(shop) ? S_NOBUY(shop) : "%s Ke?!",
S_NOCASH1(shop) ? S_NOCASH1(shop) : "%s Ke?!",
S_NOCASH2(shop) ? S_NOCASH2(shop) : "%s Ke?!",
S_BUY(shop) ? S_BUY(shop) : "%s Ke?! %d?",
S_SELL(shop) ? S_SELL(shop) : "%s Ke?! %d?",
S_BROKE_TEMPER(shop),
S_BITVECTOR(shop),
S_KEEPER(shop) == NOBODY ? -1 : mob_index[S_KEEPER(shop)].vnum,
S_NOTRADE(shop)
);
fputs(convert_from_tabs(buf), shop_file);
for (j = 0; S_BUYTYPE(shop, j) != NOTHING; j++) {
fprintf(shop_file, "\n[[shop.buy_type]]\n");
fprintf(shop_file, "type = %d\n", S_BUYTYPE(shop, j));
toml_write_kv_string_opt(shop_file, "keyword", S_BUYWORD(shop, j));
}
/* Save the rooms. */
for (j = 0;S_ROOM(shop, j) != NOWHERE; j++)
fprintf(shop_file, "%d\n", S_ROOM(shop, j));
fprintf(shop_file, "-1\n");
fprintf(shop_file, "\n[shop.messages]\n");
toml_write_kv_string(shop_file, "no_such_item1", S_NOITEM1(shop) ? S_NOITEM1(shop) : "");
toml_write_kv_string(shop_file, "no_such_item2", S_NOITEM2(shop) ? S_NOITEM2(shop) : "");
toml_write_kv_string(shop_file, "do_not_buy", S_NOBUY(shop) ? S_NOBUY(shop) : "");
toml_write_kv_string(shop_file, "missing_cash1", S_NOCASH1(shop) ? S_NOCASH1(shop) : "");
toml_write_kv_string(shop_file, "missing_cash2", S_NOCASH2(shop) ? S_NOCASH2(shop) : "");
toml_write_kv_string(shop_file, "message_buy", S_BUY(shop) ? S_BUY(shop) : "");
toml_write_kv_string(shop_file, "message_sell", S_SELL(shop) ? S_SELL(shop) : "");
/* Save open/closing times. */
fprintf(shop_file, "%d\n%d\n%d\n%d\n", S_OPEN1(shop), S_CLOSE1(shop),
S_OPEN2(shop), S_CLOSE2(shop));
fprintf(shop_file, "broke_temper = %d\n", S_BROKE_TEMPER(shop));
fprintf(shop_file, "bitvector = %ld\n", S_BITVECTOR(shop));
fprintf(shop_file, "keeper = %d\n",
S_KEEPER(shop) == NOBODY ? -1 : mob_index[S_KEEPER(shop)].vnum);
fprintf(shop_file, "trade_with = %d\n", S_NOTRADE(shop));
fprintf(shop_file, "rooms = [");
for (j = 0; S_ROOM(shop, j) != NOWHERE; j++) {
if (j)
fputs(", ", shop_file);
fprintf(shop_file, "%d", S_ROOM(shop, j));
}
fputs("]\n", shop_file);
fprintf(shop_file, "open1 = %d\n", S_OPEN1(shop));
fprintf(shop_file, "close1 = %d\n", S_CLOSE1(shop));
fprintf(shop_file, "open2 = %d\n", S_OPEN2(shop));
fprintf(shop_file, "close2 = %d\n", S_CLOSE2(shop));
fprintf(shop_file, "bank = %d\n", S_BANK(shop));
fprintf(shop_file, "sort = %d\n", S_SORT(shop));
fputc('\n', shop_file);
num_shops++;
}
}
fprintf(shop_file, "$~\n");
fclose(shop_file);
snprintf(oldname, sizeof(oldname), "%s/%d.shp", SHP_PREFIX, zone_table[zone_num].number);
snprintf(oldname, sizeof(oldname), "%s/%d.toml", SHP_PREFIX, zone_table[zone_num].number);
remove(oldname);
rename(fname, oldname);

View file

@ -18,6 +18,7 @@
#include "shop.h"
#include "dg_olc.h"
#include "mud_event.h"
#include "toml_utils.h"
/* This function will copy the strings so be sure you free your own copies of
@ -269,7 +270,6 @@ int save_rooms(zone_rnum rzone)
char filename[128];
char buf[MAX_STRING_LENGTH];
char buf1[MAX_STRING_LENGTH];
char buf2[MAX_STRING_LENGTH];
#if CIRCLE_UNSIGNED_INDEX
if (rzone == NOWHERE || rzone > top_of_zone_table) {
@ -301,96 +301,70 @@ int save_rooms(zone_rnum rzone)
strncpy(buf, room->description ? room->description : "Empty room.", sizeof(buf)-1 );
strip_cr(buf);
/* Save the numeric and string section of the file. */
int n = snprintf(buf2, MAX_STRING_LENGTH, "#%d\n"
"%s%c\n"
"%s%c\n"
"%d %d %d %d %d %d\n",
room->number,
room->name ? room->name : "Untitled", STRING_TERMINATOR,
buf, STRING_TERMINATOR,
zone_table[room->zone].number, room->room_flags[0], room->room_flags[1], room->room_flags[2],
room->room_flags[3], room->sector_type
);
if(n >= MAX_STRING_LENGTH) {
mudlog(BRF,LVL_BUILDER,TRUE,
"SYSERR: Could not save room #%d due to size (%d > maximum of %d).",
room->number, n, MAX_STRING_LENGTH);
continue;
}
fprintf(sf, "[[room]]\n");
fprintf(sf, "vnum = %d\n", room->number);
toml_write_kv_string(sf, "name", room->name ? convert_from_tabs(room->name) : "Untitled");
toml_write_kv_string(sf, "description", convert_from_tabs(buf));
fprintf(sf, "flags = [%d, %d, %d, %d]\n",
room->room_flags[0], room->room_flags[1],
room->room_flags[2], room->room_flags[3]);
fprintf(sf, "sector = %d\n", room->sector_type);
fprintf(sf, "%s", convert_from_tabs(buf2));
/* Now you write out the exits for the room. */
for (j = 0; j < DIR_COUNT; j++) {
if (R_EXIT(room, j)) {
int dflag;
if (R_EXIT(room, j)->general_description) {
strncpy(buf, R_EXIT(room, j)->general_description, sizeof(buf)-1);
strip_cr(buf);
} else
*buf = '\0';
if (R_EXIT(room, j)) {
if (R_EXIT(room, j)->general_description) {
strncpy(buf, R_EXIT(room, j)->general_description, sizeof(buf)-1);
strip_cr(buf);
} else
*buf = '\0';
/* Figure out door flag. */
if (IS_SET(R_EXIT(room, j)->exit_info, EX_ISDOOR)) {
if (IS_SET(R_EXIT(room, j)->exit_info, EX_PICKPROOF))
dflag = 2;
else
dflag = 1;
if (IS_SET(R_EXIT(room, j)->exit_info, EX_HIDDEN))
dflag += 2;
} else
dflag = 0;
if (R_EXIT(room, j)->keyword)
strncpy(buf1, R_EXIT(room, j)->keyword, sizeof(buf1)-1 );
else
*buf1 = '\0';
if (R_EXIT(room, j)->keyword)
strncpy(buf1, R_EXIT(room, j)->keyword, sizeof(buf1)-1 );
else
*buf1 = '\0';
/* Now write the exit to the file. */
fprintf(sf, "D%d\n"
"%s~\n"
"%s~\n"
"%d %d %d\n", j, buf, buf1, dflag,
R_EXIT(room, j)->key != NOTHING ? R_EXIT(room, j)->key : -1,
R_EXIT(room, j)->to_room != NOWHERE ? world[R_EXIT(room, j)->to_room].number : -1);
}
fprintf(sf, "\n[[room.exit]]\n");
fprintf(sf, "dir = %d\n", j);
toml_write_kv_string(sf, "description", convert_from_tabs(buf));
toml_write_kv_string(sf, "keyword", buf1);
fprintf(sf, "exit_info = %d\n", R_EXIT(room, j)->exit_info);
fprintf(sf, "key = %d\n",
R_EXIT(room, j)->key != NOTHING ? R_EXIT(room, j)->key : -1);
fprintf(sf, "to_room = %d\n",
R_EXIT(room, j)->to_room != NOWHERE ? world[R_EXIT(room, j)->to_room].number : -1);
}
}
if (room->ex_description) {
struct extra_descr_data *xdesc;
for (xdesc = room->ex_description; xdesc; xdesc = xdesc->next) {
strncpy(buf, xdesc->description, sizeof(buf) - 1);
buf[sizeof(buf) - 1] = '\0';
strip_cr(buf);
fprintf(sf, "E\n"
"%s~\n"
"%s~\n", xdesc->keyword, buf);
}
for (xdesc = room->ex_description; xdesc; xdesc = xdesc->next) {
strncpy(buf, xdesc->description, sizeof(buf) - 1);
buf[sizeof(buf) - 1] = '\0';
strip_cr(buf);
fprintf(sf, "\n[[room.extra_desc]]\n");
toml_write_kv_string(sf, "keyword", xdesc->keyword);
toml_write_kv_string(sf, "description", convert_from_tabs(buf));
}
}
if (room->forage) {
struct forage_entry *entry;
fprintf(sf, "F\n");
for (entry = room->forage; entry; entry = entry->next)
fprintf(sf, "%d %d\n", entry->obj_vnum, entry->dc);
fprintf(sf, "0 0\n");
for (entry = room->forage; entry; entry = entry->next) {
fprintf(sf, "\n[[room.forage]]\n");
fprintf(sf, "obj_vnum = %d\n", entry->obj_vnum);
fprintf(sf, "dc = %d\n", entry->dc);
}
}
fprintf(sf, "S\n");
script_save_to_disk(sf, room, WLD_TRIGGER);
fputc('\n', sf);
}
}
/* Write the final line and close it. */
fprintf(sf, "$~\n");
fclose(sf);
/* Old file we're replacing. */
snprintf(buf, sizeof(buf), "%s/%d.wld", WLD_PREFIX, zone_table[rzone].number);
snprintf(buf, sizeof(buf), "%s/%d.toml", WLD_PREFIX, zone_table[rzone].number);
remove(buf);
rename(filename, buf);

View file

@ -11,6 +11,8 @@
#include "utils.h"
#include "db.h"
#include "genolc.h"
#include "toml.h"
#include "toml_utils.h"
#include "genzon.h"
#include "dg_scripts.h"
@ -89,7 +91,7 @@ zone_rnum create_new_zone(zone_vnum vzone_num, room_vnum bottom, room_vnum top,
}
/* Create the zone file. */
snprintf(buf, sizeof(buf), "%s/%d.zon", ZON_PREFIX, vzone_num);
snprintf(buf, sizeof(buf), "%s/%d.toml", ZON_PREFIX, vzone_num);
if (!(fp = fopen(buf, "w"))) {
mudlog(BRF, LVL_IMPL, TRUE, "SYSERR: OLC: Can't write new zone file.");
*error = "Could not write zone file.\r\n";
@ -99,7 +101,7 @@ zone_rnum create_new_zone(zone_vnum vzone_num, room_vnum bottom, room_vnum top,
fclose(fp);
/* Create the room file. */
snprintf(buf, sizeof(buf), "%s/%d.wld", WLD_PREFIX, vzone_num);
snprintf(buf, sizeof(buf), "%s/%d.toml", WLD_PREFIX, vzone_num);
if (!(fp = fopen(buf, "w"))) {
mudlog(BRF, LVL_IMPL, TRUE, "SYSERR: OLC: Can't write new world file.");
*error = "Could not write world file.\r\n";
@ -109,7 +111,7 @@ zone_rnum create_new_zone(zone_vnum vzone_num, room_vnum bottom, room_vnum top,
fclose(fp);
/* Create the mobile file. */
snprintf(buf, sizeof(buf), "%s/%d.mob", MOB_PREFIX, vzone_num);
snprintf(buf, sizeof(buf), "%s/%d.toml", MOB_PREFIX, vzone_num);
if (!(fp = fopen(buf, "w"))) {
mudlog(BRF, LVL_IMPL, TRUE, "SYSERR: OLC: Can't write new mob file.");
*error = "Could not write mobile file.\r\n";
@ -119,7 +121,7 @@ zone_rnum create_new_zone(zone_vnum vzone_num, room_vnum bottom, room_vnum top,
fclose(fp);
/* Create the object file. */
snprintf(buf, sizeof(buf), "%s/%d.obj", OBJ_PREFIX, vzone_num);
snprintf(buf, sizeof(buf), "%s/%d.toml", OBJ_PREFIX, vzone_num);
if (!(fp = fopen(buf, "w"))) {
mudlog(BRF, LVL_IMPL, TRUE, "SYSERR: OLC: Can't write new obj file.");
*error = "Could not write object file.\r\n";
@ -129,7 +131,7 @@ zone_rnum create_new_zone(zone_vnum vzone_num, room_vnum bottom, room_vnum top,
fclose(fp);
/* Create the shop file. */
snprintf(buf, sizeof(buf), "%s/%d.shp", SHP_PREFIX, vzone_num);
snprintf(buf, sizeof(buf), "%s/%d.toml", SHP_PREFIX, vzone_num);
if (!(fp = fopen(buf, "w"))) {
mudlog(BRF, LVL_IMPL, TRUE, "SYSERR: OLC: Can't write new shop file.");
*error = "Could not write shop file.\r\n";
@ -139,7 +141,7 @@ zone_rnum create_new_zone(zone_vnum vzone_num, room_vnum bottom, room_vnum top,
fclose(fp);
/* Create the quests file */
snprintf(buf, sizeof(buf), "%s/%d.qst", QST_PREFIX, vzone_num);
snprintf(buf, sizeof(buf), "%s/%d.toml", QST_PREFIX, vzone_num);
if (!(fp = fopen(buf, "w"))) {
mudlog(BRF, LVL_IMPL, TRUE, "SYSERR: OLC: Can't write new quest file");
*error = "Could not write quest file.\r\n";
@ -149,7 +151,7 @@ zone_rnum create_new_zone(zone_vnum vzone_num, room_vnum bottom, room_vnum top,
fclose(fp);
/* Create the trigger file. */
snprintf(buf, sizeof(buf), "%s/%d.trg", TRG_PREFIX, vzone_num);
snprintf(buf, sizeof(buf), "%s/%d.toml", TRG_PREFIX, vzone_num);
if (!(fp = fopen(buf, "w"))) {
mudlog(BRF, LVL_IMPL, TRUE, "SYSERR: OLC: Can't write new trigger file");
*error = "Could not write trigger file.\r\n";
@ -219,9 +221,12 @@ void create_world_index(int znum, const char *type)
{
FILE *newfile, *oldfile;
char new_name[32], old_name[32], *prefix;
int num, found = FALSE;
char buf[MAX_STRING_LENGTH];
char buf1[MAX_STRING_LENGTH];
char **files = NULL;
char errbuf[256];
char file_name[32];
toml_table_t *tab = NULL;
toml_array_t *arr = NULL;
int i, num, count, insert_at;
switch (*type) {
case 'z':
@ -250,44 +255,98 @@ void create_world_index(int znum, const char *type)
return;
}
snprintf(old_name, sizeof(old_name), "%s/index", prefix);
snprintf(new_name, sizeof(new_name), "%s/newindex", prefix);
snprintf(old_name, sizeof(old_name), "%s/index.toml", prefix);
snprintf(new_name, sizeof(new_name), "%s/newindex.toml", prefix);
snprintf(file_name, sizeof(file_name), "%d.toml", znum);
if (!(oldfile = fopen(old_name, "r"))) {
mudlog(BRF, LVL_IMPL, TRUE, "SYSERR: OLC: Failed to open %s.", old_name);
return;
} else if (!(newfile = fopen(new_name, "w"))) {
mudlog(BRF, LVL_IMPL, TRUE, "SYSERR: OLC: Failed to open %s.", new_name);
fclose(oldfile);
}
tab = toml_parse_file(oldfile, errbuf, sizeof(errbuf));
fclose(oldfile);
if (!tab) {
mudlog(BRF, LVL_IMPL, TRUE, "SYSERR: OLC: Failed to parse %s: %s.", old_name, errbuf);
return;
}
/* Index contents must be in order: search through the old file for the right
* place, insert the new file, then copy the rest over. */
snprintf(buf1, sizeof(buf1), "%d.%s", znum, type);
while (get_line(oldfile, buf)) {
if (*buf == '$') {
/* The following used to add a blank line, thanks to Brian Taylor for the fix. */
fprintf(newfile, "%s", (!found ? strncat(buf1, "\n$\n", sizeof(buf1) - strlen(buf1) - 1) : "$\n"));
break;
} else if (!found) {
sscanf(buf, "%d", &num);
if (num > znum) {
found = TRUE;
fprintf(newfile, "%s\n", buf1);
} else if (num == znum) {
/* index file already had an entry for this zone. */
fclose(oldfile);
fclose(newfile);
remove(new_name);
return;
}
}
fprintf(newfile, "%s\n", buf);
arr = toml_array_in(tab, "files");
if (!arr) {
mudlog(BRF, LVL_IMPL, TRUE, "SYSERR: OLC: %s missing 'files' array.", old_name);
toml_free(tab);
return;
}
count = toml_array_nelem(arr);
CREATE(files, char *, count + 1);
for (i = 0; i < count; i++) {
toml_datum_t d = toml_string_at(arr, i);
if (!d.ok) {
mudlog(BRF, LVL_IMPL, TRUE, "SYSERR: OLC: %s has invalid 'files' entry at %d.", old_name, i);
toml_free(tab);
while (i-- > 0)
free(files[i]);
free(files);
return;
}
files[i] = d.u.s;
}
for (i = 0; i < count; i++) {
if (!strcmp(files[i], file_name)) {
toml_free(tab);
for (i = 0; i < count; i++)
free(files[i]);
free(files);
return;
}
if (sscanf(files[i], "%d", &num) == 1 && num == znum) {
toml_free(tab);
for (i = 0; i < count; i++)
free(files[i]);
free(files);
return;
}
}
insert_at = count;
for (i = 0; i < count; i++) {
if (sscanf(files[i], "%d", &num) == 1 && num > znum) {
insert_at = i;
break;
}
}
RECREATE(files, char *, count + 2);
if (insert_at < count)
memmove(&files[insert_at + 1], &files[insert_at], sizeof(char *) * (count - insert_at));
files[insert_at] = strdup(file_name);
count++;
if (!(newfile = fopen(new_name, "w"))) {
mudlog(BRF, LVL_IMPL, TRUE, "SYSERR: OLC: Failed to open %s.", new_name);
toml_free(tab);
for (i = 0; i < count; i++)
free(files[i]);
free(files);
return;
}
fprintf(newfile, "files = [\n");
for (i = 0; i < count; i++) {
fprintf(newfile, " ");
toml_write_string(newfile, files[i]);
fprintf(newfile, "%s\n", (i + 1 < count) ? "," : "");
}
fprintf(newfile, "]\n");
fclose(newfile);
fclose(oldfile);
toml_free(tab);
for (i = 0; i < count; i++)
free(files[i]);
free(files);
/* Out with the old, in with the new. */
remove(old_name);
rename(new_name, old_name);
@ -326,12 +385,9 @@ void remove_room_zone_commands(zone_rnum zone, room_rnum room_num)
* field is also there. */
int save_zone(zone_rnum zone_num)
{
int subcmd, arg1 = -1, arg2 = -1, arg3 = -1, flag_tot=0, i;
int subcmd, arg1 = -1, arg2 = -1, arg3 = -1;
char fname[128], oldname[128];
const char *comment = NULL;
FILE *zfile;
char zbuf1[MAX_STRING_LENGTH], zbuf2[MAX_STRING_LENGTH];
char zbuf3[MAX_STRING_LENGTH], zbuf4[MAX_STRING_LENGTH];
#if CIRCLE_UNSIGNED_INDEX
if (zone_num == NOWHERE || zone_num > top_of_zone_table) {
@ -348,67 +404,25 @@ int save_zone(zone_rnum zone_num)
return FALSE;
}
for (i=0; i<ZN_ARRAY_MAX; i++)
flag_tot += zone_table[zone_num].zone_flags[(i)];
/* If zone flags or levels aren't set, there is no reason to save them! */
if (flag_tot == 0 && zone_table[zone_num].min_level == -1 && zone_table[zone_num].max_level == -1)
{
/* Print zone header to file. */
fprintf(zfile, "#%d\n"
"%s~\n"
"%s~\n"
"%d %d %d %d\n",
zone_table[zone_num].number,
(zone_table[zone_num].builders && *zone_table[zone_num].builders)
? zone_table[zone_num].builders : "None.",
(zone_table[zone_num].name && *zone_table[zone_num].name)
? convert_from_tabs(zone_table[zone_num].name) : "undefined",
genolc_zone_bottom(zone_num),
zone_table[zone_num].top,
zone_table[zone_num].lifespan,
zone_table[zone_num].reset_mode
);
} else {
sprintascii(zbuf1, zone_table[zone_num].zone_flags[0]);
sprintascii(zbuf2, zone_table[zone_num].zone_flags[1]);
sprintascii(zbuf3, zone_table[zone_num].zone_flags[2]);
sprintascii(zbuf4, zone_table[zone_num].zone_flags[3]);
/* Print zone header to file. */
fprintf(zfile, "#%d\n"
"%s~\n"
"%s~\n"
"%d %d %d %d %s %s %s %s %d %d\n", /* New tbaMUD data line */
zone_table[zone_num].number,
(zone_table[zone_num].builders && *zone_table[zone_num].builders)
? zone_table[zone_num].builders : "None.",
(zone_table[zone_num].name && *zone_table[zone_num].name)
? convert_from_tabs(zone_table[zone_num].name) : "undefined",
genolc_zone_bottom(zone_num),
zone_table[zone_num].top,
zone_table[zone_num].lifespan,
zone_table[zone_num].reset_mode,
zbuf1, zbuf2, zbuf3, zbuf4,
zone_table[zone_num].min_level,
zone_table[zone_num].max_level
);
}
/* Handy Quick Reference Chart for Zone Values.
*
* Field #1 Field #3 Field #4 Field #5
* -------------------------------------------------
* M (Mobile) Mob-Vnum Wld-Max Room-Vnum
* O (Object) Obj-Vnum Wld-Max Room-Vnum
* G (Give) Obj-Vnum Wld-Max Unused
* E (Equip) Obj-Vnum Wld-Max EQ-Position
* P (Put) Obj-Vnum Wld-Max Target-Obj-Vnum
* D (Door) Room-Vnum Door-Dir Door-State
* R (Remove) Room-Vnum Obj-Vnum Unused
* T (Trigger) Trig-type Trig-Vnum Room-Vnum
* V (var) Trig-type Context Room-Vnum Varname Value
* ------------------------------------------------- */
fprintf(zfile, "[[zone]]\n");
fprintf(zfile, "vnum = %d\n", zone_table[zone_num].number);
toml_write_kv_string(zfile, "builders",
(zone_table[zone_num].builders && *zone_table[zone_num].builders)
? zone_table[zone_num].builders : "None.");
toml_write_kv_string(zfile, "name",
(zone_table[zone_num].name && *zone_table[zone_num].name)
? convert_from_tabs(zone_table[zone_num].name) : "undefined");
fprintf(zfile, "bot = %d\n", genolc_zone_bottom(zone_num));
fprintf(zfile, "top = %d\n", zone_table[zone_num].top);
fprintf(zfile, "lifespan = %d\n", zone_table[zone_num].lifespan);
fprintf(zfile, "reset_mode = %d\n", zone_table[zone_num].reset_mode);
fprintf(zfile, "flags = [%d, %d, %d, %d]\n",
zone_table[zone_num].zone_flags[0],
zone_table[zone_num].zone_flags[1],
zone_table[zone_num].zone_flags[2],
zone_table[zone_num].zone_flags[3]);
fprintf(zfile, "min_level = %d\n", zone_table[zone_num].min_level);
fprintf(zfile, "max_level = %d\n", zone_table[zone_num].max_level);
for (subcmd = 0; ZCMD(zone_num, subcmd).command != 'S'; subcmd++) {
switch (ZCMD(zone_num, subcmd).command) {
@ -416,49 +430,41 @@ int save_zone(zone_rnum zone_num)
arg1 = mob_index[ZCMD(zone_num, subcmd).arg1].vnum;
arg2 = ZCMD(zone_num, subcmd).arg2;
arg3 = world[ZCMD(zone_num, subcmd).arg3].number;
comment = mob_proto[ZCMD(zone_num, subcmd).arg1].player.short_descr;
break;
case 'O':
arg1 = obj_index[ZCMD(zone_num, subcmd).arg1].vnum;
arg2 = ZCMD(zone_num, subcmd).arg2;
arg3 = world[ZCMD(zone_num, subcmd).arg3].number;
comment = obj_proto[ZCMD(zone_num, subcmd).arg1].short_description;
break;
case 'G':
arg1 = obj_index[ZCMD(zone_num, subcmd).arg1].vnum;
arg2 = ZCMD(zone_num, subcmd).arg2;
arg3 = -1;
comment = obj_proto[ZCMD(zone_num, subcmd).arg1].short_description;
break;
case 'E':
arg1 = obj_index[ZCMD(zone_num, subcmd).arg1].vnum;
arg2 = ZCMD(zone_num, subcmd).arg2;
arg3 = ZCMD(zone_num, subcmd).arg3;
comment = obj_proto[ZCMD(zone_num, subcmd).arg1].short_description;
break;
case 'P':
arg1 = obj_index[ZCMD(zone_num, subcmd).arg1].vnum;
arg2 = ZCMD(zone_num, subcmd).arg2;
arg3 = obj_index[ZCMD(zone_num, subcmd).arg3].vnum;
comment = obj_proto[ZCMD(zone_num, subcmd).arg1].short_description;
break;
case 'D':
arg1 = world[ZCMD(zone_num, subcmd).arg1].number;
arg2 = ZCMD(zone_num, subcmd).arg2;
arg3 = ZCMD(zone_num, subcmd).arg3;
comment = world[ZCMD(zone_num, subcmd).arg1].name;
break;
case 'R':
arg1 = world[ZCMD(zone_num, subcmd).arg1].number;
arg2 = obj_index[ZCMD(zone_num, subcmd).arg2].vnum;
comment = obj_proto[ZCMD(zone_num, subcmd).arg2].short_description;
arg3 = -1;
break;
case 'T':
arg1 = ZCMD(zone_num, subcmd).arg1; /* trigger type */
arg2 = trig_index[ZCMD(zone_num, subcmd).arg2]->vnum; /* trigger vnum */
arg3 = world[ZCMD(zone_num, subcmd).arg3].number; /* room num */
comment = GET_TRIG_NAME(trig_index[real_trigger(arg2)]->proto);
break;
case 'V':
arg1 = ZCMD(zone_num, subcmd).arg1; /* trigger type */
@ -472,17 +478,20 @@ int save_zone(zone_rnum zone_num)
mudlog(BRF, LVL_BUILDER, TRUE, "SYSERR: OLC: z_save_to_disk(): Unknown cmd '%c' - NOT saving", ZCMD(zone_num, subcmd).command);
continue;
}
if (ZCMD(zone_num, subcmd).command != 'V')
fprintf(zfile, "%c %d %d %d %d \t(%s)\n",
ZCMD(zone_num, subcmd).command, ZCMD(zone_num, subcmd).if_flag, arg1, arg2, arg3, comment);
else
fprintf(zfile, "%c %d %d %d %d %s %s\n",
ZCMD(zone_num, subcmd).command, ZCMD(zone_num, subcmd).if_flag, arg1, arg2, arg3,
ZCMD(zone_num, subcmd).sarg1, ZCMD(zone_num, subcmd).sarg2);
fprintf(zfile, "\n[[zone.command]]\n");
fprintf(zfile, "command = \"%c\"\n", ZCMD(zone_num, subcmd).command);
fprintf(zfile, "if_flag = %d\n", ZCMD(zone_num, subcmd).if_flag);
fprintf(zfile, "arg1 = %d\n", arg1);
fprintf(zfile, "arg2 = %d\n", arg2);
fprintf(zfile, "arg3 = %d\n", arg3);
if (ZCMD(zone_num, subcmd).command == 'V') {
toml_write_kv_string(zfile, "sarg1", ZCMD(zone_num, subcmd).sarg1 ? ZCMD(zone_num, subcmd).sarg1 : "");
toml_write_kv_string(zfile, "sarg2", ZCMD(zone_num, subcmd).sarg2 ? ZCMD(zone_num, subcmd).sarg2 : "");
}
fprintf(zfile, "line = %d\n", ZCMD(zone_num, subcmd).line);
}
fputs("S\n$\n", zfile);
fclose(zfile);
snprintf(oldname, sizeof(oldname), "%s/%d.zon", ZON_PREFIX, zone_table[zone_num].number);
snprintf(oldname, sizeof(oldname), "%s/%d.toml", ZON_PREFIX, zone_table[zone_num].number);
remove(oldname);
rename(fname, oldname);
@ -586,4 +595,3 @@ void delete_zone_command(struct zone_data *zone, int pos)
/* Ok, let's zap it. */
remove_cmd_from_list(&zone->cmd, pos);
}

View file

@ -48,7 +48,7 @@ static int House_get_filename(room_vnum vnum, char *filename, size_t maxlen)
if (vnum == NOWHERE)
return (0);
snprintf(filename, maxlen, LIB_HOUSE"%d.house", vnum);
snprintf(filename, maxlen, LIB_HOUSE"%d.house.toml", vnum);
return (1);
}
@ -710,8 +710,6 @@ static int ascii_convert_house(struct char_data *ch, obj_vnum vnum)
}
}
fprintf(out, "$~\n");
fclose(in);
fclose(out);

View file

@ -22,6 +22,8 @@
#include "config.h"
#include "modify.h"
#include "genolc.h" /* for strip_cr and sprintascii */
#include "toml.h"
#include "toml_utils.h"
/* these factors should be unique integers */
#define CRYO_FACTOR 4
@ -37,106 +39,84 @@ static int Crash_load_objs(struct char_data *ch);
static int handle_obj(struct obj_data *obj, struct char_data *ch, int locate, struct obj_data **cont_rows);
static void Crash_write_header(struct char_data *ch, FILE *fp, int savecode);
static int toml_get_int_default(toml_table_t *tab, const char *key, int def)
{
toml_datum_t d = toml_int_in(tab, key);
if (!d.ok)
return def;
return (int)d.u.i;
}
static char *toml_get_string_dup(toml_table_t *tab, const char *key)
{
toml_datum_t d = toml_string_in(tab, key);
if (!d.ok)
return NULL;
return d.u.s;
}
static void toml_read_int_array(toml_array_t *arr, int *out, int out_count, int def)
{
int i;
for (i = 0; i < out_count; i++)
out[i] = def;
if (!arr)
return;
for (i = 0; i < out_count; i++) {
toml_datum_t d = toml_int_at(arr, i);
if (d.ok)
out[i] = (int)d.u.i;
}
}
/* Writes one object record to FILE. Old name: Obj_to_store().
* Updated to save all NUM_OBJ_VAL_POSITIONS values instead of only 4. */
int objsave_save_obj_record(struct obj_data *obj, FILE *fp, int locate)
{
int i;
char buf1[MAX_STRING_LENGTH + 1];
struct obj_data *temp = NULL;
int out_locate = (locate > 0) ? locate : 0;
int nest = (locate < 0) ? -locate : 0;
/* Build a prototype baseline to diff against so we only emit changed fields */
if (GET_OBJ_VNUM(obj) != NOTHING)
temp = read_object(GET_OBJ_VNUM(obj), VIRTUAL);
else {
temp = create_obj();
temp->item_number = NOWHERE;
fprintf(fp, "\n[[object]]\n");
fprintf(fp, "vnum = %d\n", GET_OBJ_VNUM(obj));
fprintf(fp, "locate = %d\n", out_locate);
fprintf(fp, "nest = %d\n", nest);
fprintf(fp, "values = [");
for (i = 0; i < NUM_OBJ_VAL_POSITIONS; i++) {
if (i > 0)
fputs(", ", fp);
fprintf(fp, "%d", GET_OBJ_VAL(obj, i));
}
fprintf(fp, "]\n");
if (obj->main_description) {
strcpy(buf1, obj->main_description);
fprintf(fp, "extra_flags = [%d, %d, %d, %d]\n",
GET_OBJ_EXTRA(obj)[0], GET_OBJ_EXTRA(obj)[1],
GET_OBJ_EXTRA(obj)[2], GET_OBJ_EXTRA(obj)[3]);
fprintf(fp, "wear_flags = [%d, %d, %d, %d]\n",
GET_OBJ_WEAR(obj)[0], GET_OBJ_WEAR(obj)[1],
GET_OBJ_WEAR(obj)[2], GET_OBJ_WEAR(obj)[3]);
toml_write_kv_string_opt(fp, "name", obj->name);
toml_write_kv_string_opt(fp, "short", obj->short_description);
toml_write_kv_string_opt(fp, "description", obj->description);
if (obj->main_description && *obj->main_description) {
strlcpy(buf1, obj->main_description, sizeof(buf1));
strip_cr(buf1);
} else
*buf1 = 0;
/* Header and placement */
fprintf(fp, "#%d\n", GET_OBJ_VNUM(obj));
/* Top-level worn slots are positive (1..NUM_WEARS); inventory is 0.
* Children use negative numbers from Crash_save recursion (,-1,-2,) we map that to Nest. */
if (locate > 0)
fprintf(fp, "Loc : %d\n", locate);
if (locate < 0) {
int nest = -locate; /* e.g. -1 => Nest:1, -2 => Nest:2, etc. */
fprintf(fp, "Nest: %d\n", nest);
} else {
fprintf(fp, "Nest: %d\n", 0); /* top-level object (inventory or worn) */
toml_write_kv_string(fp, "main_description", buf1);
}
/* Save all object values (diffed against proto) */
{
bool diff = FALSE;
for (i = 0; i < NUM_OBJ_VAL_POSITIONS; i++) {
if (GET_OBJ_VAL(obj, i) != GET_OBJ_VAL(temp, i)) {
diff = TRUE;
break;
}
}
if (diff) {
fprintf(fp, "Vals:");
for (i = 0; i < NUM_OBJ_VAL_POSITIONS; i++)
fprintf(fp, " %d", GET_OBJ_VAL(obj, i));
fprintf(fp, "\n");
}
}
/* Extra flags (array words) */
if (GET_OBJ_EXTRA(obj) != GET_OBJ_EXTRA(temp))
fprintf(fp, "Flag: %d %d %d %d\n",
GET_OBJ_EXTRA(obj)[0], GET_OBJ_EXTRA(obj)[1],
GET_OBJ_EXTRA(obj)[2], GET_OBJ_EXTRA(obj)[3]);
/* Names/descriptions */
if (obj->name && (!temp->name || strcmp(obj->name, temp->name)))
fprintf(fp, "Name: %s\n", obj->name);
if (obj->short_description && (!temp->short_description ||
strcmp(obj->short_description, temp->short_description)))
fprintf(fp, "Shrt: %s\n", obj->short_description);
if (obj->description && (!temp->description ||
strcmp(obj->description, temp->description)))
fprintf(fp, "Desc: %s\n", obj->description);
if (obj->main_description && (!temp->main_description ||
strcmp(obj->main_description, temp->main_description)))
fprintf(fp, "ADes:\n%s~\n", buf1);
/* Core fields */
if (GET_OBJ_TYPE(obj) != GET_OBJ_TYPE(temp))
fprintf(fp, "Type: %d\n", GET_OBJ_TYPE(obj));
if (GET_OBJ_WEIGHT(obj) != GET_OBJ_WEIGHT(temp))
fprintf(fp, "Wght: %d\n", GET_OBJ_WEIGHT(obj));
if (GET_OBJ_COST(obj) != GET_OBJ_COST(temp))
fprintf(fp, "Cost: %d\n", GET_OBJ_COST(obj));
/* Permanent affects (array words) */
if (GET_OBJ_AFFECT(obj)[0] != GET_OBJ_AFFECT(temp)[0] ||
GET_OBJ_AFFECT(obj)[1] != GET_OBJ_AFFECT(temp)[1] ||
GET_OBJ_AFFECT(obj)[2] != GET_OBJ_AFFECT(temp)[2] ||
GET_OBJ_AFFECT(obj)[3] != GET_OBJ_AFFECT(temp)[3])
fprintf(fp, "Perm: %d %d %d %d\n",
GET_OBJ_AFFECT(obj)[0], GET_OBJ_AFFECT(obj)[1],
GET_OBJ_AFFECT(obj)[2], GET_OBJ_AFFECT(obj)[3]);
/* Wear flags (array words) */
if (GET_OBJ_WEAR(obj)[0] != GET_OBJ_WEAR(temp)[0] ||
GET_OBJ_WEAR(obj)[1] != GET_OBJ_WEAR(temp)[1] ||
GET_OBJ_WEAR(obj)[2] != GET_OBJ_WEAR(temp)[2] ||
GET_OBJ_WEAR(obj)[3] != GET_OBJ_WEAR(temp)[3])
fprintf(fp, "Wear: %d %d %d %d\n",
GET_OBJ_WEAR(obj)[0], GET_OBJ_WEAR(obj)[1],
GET_OBJ_WEAR(obj)[2], GET_OBJ_WEAR(obj)[3]);
/* (If you also persist applies, extra descs, scripts, etc., keep that code here unchanged) */
fprintf(fp, "type = %d\n", GET_OBJ_TYPE(obj));
fprintf(fp, "weight = %d\n", GET_OBJ_WEIGHT(obj));
fprintf(fp, "cost = %d\n", GET_OBJ_COST(obj));
return 1;
}
@ -266,10 +246,11 @@ int Crash_delete_file(char *name)
int Crash_delete_crashfile(struct char_data *ch)
{
char filename[MAX_INPUT_LENGTH];
int numread;
FILE *fl;
char errbuf[256];
toml_table_t *tab = NULL;
toml_table_t *header = NULL;
int savecode;
char line[READ_SIZE];
if (!get_filename(filename, sizeof(filename), CRASH_FILE, GET_NAME(ch)))
return FALSE;
@ -279,12 +260,19 @@ int Crash_delete_crashfile(struct char_data *ch)
log("SYSERR: checking for crash file %s (3): %s", filename, strerror(errno));
return FALSE;
}
numread = get_line(fl,line);
tab = toml_parse_file(fl, errbuf, sizeof(errbuf));
fclose(fl);
if (numread == FALSE)
if (!tab)
return FALSE;
sscanf(line,"%d ",&savecode);
header = toml_table_in(tab, "header");
if (!header) {
toml_free(tab);
return FALSE;
}
savecode = toml_get_int_default(header, "save_code", SAVE_UNDEF);
toml_free(tab);
if (savecode == SAVE_CRASH)
Crash_delete_file(GET_NAME(ch));
@ -295,10 +283,11 @@ int Crash_delete_crashfile(struct char_data *ch)
int Crash_clean_file(char *name)
{
char filename[MAX_INPUT_LENGTH], filetype[20];
int numread;
FILE *fl;
int savecode, timed, netcost, coins, account, nitems;
char line[READ_SIZE];
char errbuf[256];
toml_table_t *tab = NULL;
toml_table_t *header = NULL;
int savecode, timed;
if (!get_filename(filename, sizeof(filename), CRASH_FILE, name))
return FALSE;
@ -310,13 +299,20 @@ int Crash_clean_file(char *name)
return FALSE;
}
numread = get_line(fl,line);
tab = toml_parse_file(fl, errbuf, sizeof(errbuf));
fclose(fl);
if (numread == FALSE)
if (!tab)
return FALSE;
sscanf(line, "%d %d %d %d %d %d",&savecode,&timed,&netcost,
&coins,&account,&nitems);
header = toml_table_in(tab, "header");
if (!header) {
toml_free(tab);
return FALSE;
}
savecode = toml_get_int_default(header, "save_code", SAVE_UNDEF);
timed = toml_get_int_default(header, "timed", 0);
toml_free(tab);
if ((savecode == SAVE_CRASH) ||
(savecode == SAVE_LOGOUT) ||
@ -403,7 +399,13 @@ static void Crash_write_header(struct char_data *ch, FILE *fp, int savecode)
int account = ch ? GET_BANK_COINS(ch) : 0;
int nitems = 0;
fprintf(fp, "%d %d %d %d %d %d\n", savecode, timed, netcost, coins, account, nitems);
fprintf(fp, "[header]\n");
fprintf(fp, "save_code = %d\n", savecode);
fprintf(fp, "timed = %d\n", timed);
fprintf(fp, "net_cost = %d\n", netcost);
fprintf(fp, "coins = %d\n", coins);
fprintf(fp, "account = %d\n", account);
fprintf(fp, "item_count = %d\n", nitems);
}
void Crash_crashsave(struct char_data *ch)
@ -438,7 +440,6 @@ void Crash_crashsave(struct char_data *ch)
}
Crash_restore_weight(ch->carrying);
fprintf(fp, "$~\n");
fclose(fp);
REMOVE_BIT_AR(PLR_FLAGS(ch), PLR_CRASH);
}
@ -476,7 +477,6 @@ void Crash_idlesave(struct char_data *ch)
}
Crash_restore_weight(ch->carrying);
fprintf(fp, "$~\n");
fclose(fp);
REMOVE_BIT_AR(PLR_FLAGS(ch), PLR_CRASH);
}
@ -514,7 +514,6 @@ void Crash_rentsave(struct char_data *ch, int cost)
}
Crash_restore_weight(ch->carrying);
fprintf(fp, "$~\n");
fclose(fp);
REMOVE_BIT_AR(PLR_FLAGS(ch), PLR_CRASH);
}
@ -553,100 +552,32 @@ void Crash_save_all(void)
}
}
/* Load all objects from file into memory. Updated to load NUM_OBJ_VAL_POSITIONS values. */
obj_save_data *objsave_parse_objects(FILE *fl)
/* Load all objects from TOML into memory. */
static obj_save_data *objsave_parse_objects_from_toml(toml_table_t *tab, const char *filename)
{
char line[MAX_STRING_LENGTH];
obj_save_data *head = NULL, *tail = NULL;
toml_array_t *arr = NULL;
int count, i;
/* State for the object were currently assembling */
struct obj_data *temp = NULL;
int pending_locate = 0; /* 0 = inventory, 1..NUM_WEARS = worn slot */
int pending_nest = 0; /* 0 = top-level; >0 = inside container at level-1 */
arr = toml_array_in(tab, "object");
if (!arr)
return NULL;
/* --- helpers (GCC nested functions OK in tbaMUD build) ---------------- */
count = toml_array_nelem(arr);
for (i = 0; i < count; i++) {
toml_table_t *obj_tab = toml_table_at(arr, i);
struct obj_data *temp = NULL;
int locate, nest;
int values[NUM_OBJ_VAL_POSITIONS];
int flags[4];
char *str = NULL;
/* append current object to the result list with proper locate */
void commit_current(void) {
if (!temp) return;
if (!obj_tab)
continue;
if (GET_OBJ_TYPE(temp) == ITEM_MONEY)
update_money_obj(temp);
/* sanitize top-level locate range only; children will be negative later */
int loc = pending_locate;
if (pending_nest <= 0) {
if (loc < 0 || loc > NUM_WEARS) {
mudlog(NRM, LVL_IMMORT, TRUE,
"SAVE-LOAD: bad locate %d for vnum %d; defaulting to inventory.",
loc, GET_OBJ_VNUM(temp));
loc = 0;
}
}
/* convert Nest>0 into negative locate for handle_obj()/cont_row */
int effective_loc = (pending_nest > 0) ? -pending_nest : loc;
obj_save_data *node = NULL;
CREATE(node, obj_save_data, 1);
node->obj = temp;
node->locate = effective_loc;
node->next = NULL;
if (!head) head = node, tail = node;
else tail->next = node, tail = node;
temp = NULL;
pending_locate = 0;
pending_nest = 0;
}
/* split a line into normalized tag (no colon) and payload pointer */
void split_tag_line(const char *src, char tag_out[6], const char **payload_out) {
const char *s = src;
while (*s && isspace((unsigned char)*s)) s++; /* skip leading ws */
const char *te = s;
while (*te && !isspace((unsigned char)*te) && *te != ':') te++;
size_t tlen = (size_t)(te - s);
if (tlen > 5) tlen = 5;
memcpy(tag_out, s, tlen);
tag_out[tlen] = '\0';
const char *p = te;
while (*p && isspace((unsigned char)*p)) p++;
if (*p == ':') {
p++;
while (*p && isspace((unsigned char)*p)) p++;
}
*payload_out = p;
}
/* ---------------------------------------------------------------------- */
while (get_line(fl, line)) {
if (!*line) continue;
/* New object header: "#<vnum>" (commit any previous one first) */
if (*line == '#') {
if (temp) commit_current();
long vnum = -1L;
vnum = strtol(line + 1, NULL, 10);
if (vnum <= 0 && vnum != -1L) {
mudlog(NRM, LVL_IMMORT, TRUE, "SAVE-LOAD: bad vnum header: '%s'", line);
temp = NULL;
pending_locate = 0;
pending_nest = 0;
continue;
}
/* Instantiate from prototype if available, else create a blank */
if (vnum == -1L) {
{
int vnum = toml_get_int_default(obj_tab, "vnum", -1);
if (vnum == -1) {
temp = create_obj();
temp->item_number = NOTHING;
if (!temp->name) temp->name = strdup("object");
@ -658,133 +589,122 @@ obj_save_data *objsave_parse_objects(FILE *fl)
temp = read_object(rnum, REAL);
} else {
temp = create_obj();
/* Do NOT assign GET_OBJ_VNUM(temp); item_number derives vnum. */
if (!temp->name) temp->name = strdup("object");
if (!temp->short_description) temp->short_description = strdup("an object");
if (!temp->description) temp->description = strdup("An object lies here.");
}
}
pending_locate = 0;
pending_nest = 0;
continue;
}
/* Normal data line: TAG [ : ] payload */
char tag[6];
const char *payload = NULL;
split_tag_line(line, tag, &payload);
locate = toml_get_int_default(obj_tab, "locate", 0);
if (locate < 0 || locate > NUM_WEARS)
locate = 0;
if (!*tag) continue;
if (!temp) {
mudlog(NRM, LVL_IMMORT, TRUE, "SAVE-LOAD: data before header ignored: '%s'", line);
continue;
}
if (!strcmp(tag, "Loc")) {
pending_locate = (int)strtol(payload, NULL, 10);
}
else if (!strcmp(tag, "Nest")) {
pending_nest = (int)strtol(payload, NULL, 10);
if (pending_nest < 0) pending_nest = 0;
if (pending_nest > MAX_BAG_ROWS) {
nest = toml_get_int_default(obj_tab, "nest", 0);
if (nest < 0)
nest = 0;
if (nest > MAX_BAG_ROWS) {
if (filename)
mudlog(NRM, LVL_IMMORT, TRUE,
"SAVE-LOAD: nest level %d too deep in %s; clamping to %d.",
nest, filename, MAX_BAG_ROWS);
else
mudlog(NRM, LVL_IMMORT, TRUE,
"SAVE-LOAD: nest level %d too deep; clamping to %d.",
pending_nest, MAX_BAG_ROWS);
pending_nest = MAX_BAG_ROWS;
}
nest, MAX_BAG_ROWS);
nest = MAX_BAG_ROWS;
}
else if (!strcmp(tag, "Vals")) {
const char *p = payload;
for (int i = 0; i < NUM_OBJ_VAL_POSITIONS; i++) {
if (!*p) { GET_OBJ_VAL(temp, i) = 0; continue; }
GET_OBJ_VAL(temp, i) = (int)strtol(p, (char **)&p, 10);
}
}
else if (!strcmp(tag, "Wght")) {
GET_OBJ_WEIGHT(temp) = (int)strtol(payload, NULL, 10);
}
else if (!strcmp(tag, "Cost")) {
GET_OBJ_COST(temp) = (int)strtol(payload, NULL, 10);
}
else if (!strcmp(tag, "Rent")) {
/* Legacy tag ignored (cost-per-day no longer used). */
}
else if (!strcmp(tag, "Type")) {
GET_OBJ_TYPE(temp) = (int)strtol(payload, NULL, 10);
}
else if (!strcmp(tag, "Wear")) {
unsigned long words[4] = {0,0,0,0};
const char *p = payload;
for (int i = 0; i < 4 && *p; i++) words[i] = strtoul(p, (char **)&p, 10);
#if defined(TW_ARRAY_MAX) && defined(GET_OBJ_WEAR_AR)
for (int i = 0; i < 4; i++) {
if (i < TW_ARRAY_MAX) GET_OBJ_WEAR_AR(temp, i) = (bitvector_t)words[i];
else if (words[i])
mudlog(NRM, LVL_IMMORT, TRUE,
"SAVE-LOAD: Wear word %d (%lu) truncated (TW_ARRAY_MAX=%d).",
i, words[i], TW_ARRAY_MAX);
}
#elif defined(GET_OBJ_WEAR_AR)
for (int i = 0; i < 4; i++) GET_OBJ_WEAR_AR(temp, i) = (bitvector_t)words[i];
#endif
}
else if (!strcmp(tag, "Flag")) {
unsigned long words[4] = {0,0,0,0};
const char *p = payload;
for (int i = 0; i < 4 && *p; i++) words[i] = strtoul(p, (char **)&p, 10);
toml_read_int_array(toml_array_in(obj_tab, "values"), values, NUM_OBJ_VAL_POSITIONS, 0);
for (int j = 0; j < NUM_OBJ_VAL_POSITIONS; j++)
GET_OBJ_VAL(temp, j) = values[j];
#if defined(EF_ARRAY_MAX) && defined(GET_OBJ_EXTRA_AR)
for (int i = 0; i < 4; i++) {
if (i < EF_ARRAY_MAX) GET_OBJ_EXTRA_AR(temp, i) = (bitvector_t)words[i];
else if (words[i])
mudlog(NRM, LVL_IMMORT, TRUE,
"SAVE-LOAD: Extra word %d (%lu) truncated (EF_ARRAY_MAX=%d).",
i, words[i], EF_ARRAY_MAX);
}
#elif defined(GET_OBJ_EXTRA_AR)
for (int i = 0; i < 4; i++) GET_OBJ_EXTRA_AR(temp, i) = (bitvector_t)words[i];
#endif
toml_read_int_array(toml_array_in(obj_tab, "extra_flags"), flags, 4, 0);
for (int j = 0; j < 4; j++)
GET_OBJ_EXTRA(temp)[j] = flags[j];
toml_read_int_array(toml_array_in(obj_tab, "wear_flags"), flags, 4, 0);
for (int j = 0; j < 4; j++)
GET_OBJ_WEAR(temp)[j] = flags[j];
str = toml_get_string_dup(obj_tab, "name");
if (str) {
if (temp->name)
free(temp->name);
temp->name = str;
}
else if (!strcmp(tag, "Name")) {
if (temp->name) free(temp->name);
temp->name = *payload ? strdup(payload) : strdup("object");
str = toml_get_string_dup(obj_tab, "short");
if (str) {
if (temp->short_description)
free(temp->short_description);
temp->short_description = str;
}
else if (!strcmp(tag, "Shrt")) {
if (temp->short_description) free(temp->short_description);
temp->short_description = *payload ? strdup(payload) : strdup("an object");
str = toml_get_string_dup(obj_tab, "description");
if (str) {
if (temp->description)
free(temp->description);
temp->description = str;
}
else if (!strcmp(tag, "Desc")) {
if (temp->description) free(temp->description);
temp->description = *payload ? strdup(payload) : strdup("An object lies here.");
str = toml_get_string_dup(obj_tab, "main_description");
if (str) {
if (temp->main_description)
free(temp->main_description);
temp->main_description = str;
}
else if (!strcmp(tag, "ADes")) {
if (temp->main_description) free(temp->main_description);
temp->main_description = *payload ? strdup(payload) : NULL;
}
else if (!strcmp(tag, "End")) {
commit_current();
}
else {
mudlog(NRM, LVL_IMMORT, TRUE, "SAVE-LOAD: unknown tag '%s'", tag);
GET_OBJ_TYPE(temp) = toml_get_int_default(obj_tab, "type", GET_OBJ_TYPE(temp));
GET_OBJ_WEIGHT(temp) = toml_get_int_default(obj_tab, "weight", GET_OBJ_WEIGHT(temp));
GET_OBJ_COST(temp) = toml_get_int_default(obj_tab, "cost", GET_OBJ_COST(temp));
if (GET_OBJ_TYPE(temp) == ITEM_MONEY)
update_money_obj(temp);
{
int effective_loc = (nest > 0) ? -nest : locate;
obj_save_data *node = NULL;
CREATE(node, obj_save_data, 1);
node->obj = temp;
node->locate = effective_loc;
node->next = NULL;
if (!head)
head = node, tail = node;
else
tail->next = node, tail = node;
}
}
if (temp) commit_current();
return head;
}
obj_save_data *objsave_parse_objects(FILE *fl)
{
char errbuf[256];
toml_table_t *tab = toml_parse_file(fl, errbuf, sizeof(errbuf));
obj_save_data *list = NULL;
if (!tab)
return NULL;
list = objsave_parse_objects_from_toml(tab, NULL);
toml_free(tab);
return list;
}
static int Crash_load_objs(struct char_data *ch) {
FILE *fl;
char filename[PATH_MAX];
char line[READ_SIZE];
char buf[MAX_STRING_LENGTH];
int i, orig_save_code, num_objs=0;
struct obj_data *cont_row[MAX_BAG_ROWS];
int savecode = SAVE_UNDEF;
int timed=0,netcost=0,coins,account,nitems;
int timed=0,netcost=0,coins=0,account=0,nitems=0;
char errbuf[256];
toml_table_t *tab = NULL;
toml_table_t *header = NULL;
obj_save_data *loaded, *current;
if (!get_filename(filename, sizeof(filename), CRASH_FILE, GET_NAME(ch)))
@ -810,10 +730,28 @@ static int Crash_load_objs(struct char_data *ch) {
return 1;
}
if (!get_line(fl, line))
mudlog(NRM, MAX(LVL_IMMORT, GET_INVIS_LEV(ch)), TRUE, "Failed to read player's save code: %s.", GET_NAME(ch));
else
sscanf(line,"%d %d %d %d %d %d",&savecode, &timed, &netcost,&coins,&account,&nitems);
tab = toml_parse_file(fl, errbuf, sizeof(errbuf));
fclose(fl);
if (!tab) {
mudlog(NRM, MAX(LVL_IMMORT, GET_INVIS_LEV(ch)), TRUE,
"Failed to parse player's object file %s: %s.", filename, errbuf);
return 1;
}
header = toml_table_in(tab, "header");
if (!header) {
mudlog(NRM, MAX(LVL_IMMORT, GET_INVIS_LEV(ch)), TRUE,
"Player object file %s missing header.", filename);
toml_free(tab);
return 1;
}
savecode = toml_get_int_default(header, "save_code", SAVE_UNDEF);
timed = toml_get_int_default(header, "timed", 0);
netcost = toml_get_int_default(header, "net_cost", 0);
coins = toml_get_int_default(header, "coins", 0);
account = toml_get_int_default(header, "account", 0);
nitems = toml_get_int_default(header, "item_count", 0);
if (savecode == SAVE_LOGOUT || savecode == SAVE_TIMEDOUT) {
mudlog(NRM, MAX(LVL_IMMORT, GET_INVIS_LEV(ch)), TRUE,
@ -844,7 +782,8 @@ static int Crash_load_objs(struct char_data *ch) {
break;
}
loaded = objsave_parse_objects(fl);
loaded = objsave_parse_objects_from_toml(tab, filename);
toml_free(tab);
for (current = loaded; current != NULL; current=current->next)
num_objs += handle_obj(current->obj, ch, current->locate, cont_row);
@ -874,8 +813,6 @@ static int Crash_load_objs(struct char_data *ch) {
mudlog(NRM, MAX(LVL_GOD, GET_INVIS_LEV(ch)), TRUE, "%s (level %d) has %d object%s.",
GET_NAME(ch), GET_LEVEL(ch), num_objs, num_objs != 1 ? "s" : "");
fclose(fl);
if ((orig_save_code == SAVE_LOGOUT) || (orig_save_code == SAVE_CRYO))
return 0;
else

File diff suppressed because it is too large Load diff

1346
src/set.c

File diff suppressed because it is too large Load diff

View file

@ -25,6 +25,17 @@
#include "modify.h"
#include "spells.h" /* for skill_name() */
#include "screen.h"
#include "toml.h"
static char *toml_get_string_dup(toml_table_t *tab, const char *key)
{
toml_datum_t d = toml_string_in(tab, key);
if (!d.ok)
return NULL;
return d.u.s;
}
/* Global variables definitions used externally */
/* Constant list for printing out who we sell to */
@ -57,9 +68,11 @@ static int top(struct stack_data *stack); /**< @todo Move to utils.c */
static int pop(struct stack_data *stack); /**< @todo Move to utils.c */
static char *list_object(struct obj_data *obj, int cnt, int oindex, int shop_nr, struct char_data *keeper, struct char_data *seller);
static void sort_keeper_objs(struct char_data *keeper, int shop_nr);
#if 0
static char *read_shop_message(int mnum, room_vnum shr, FILE *shop_f, const char *why);
static int read_type_list(FILE *shop_f, struct shop_buy_data *list, int new_format, int max);
static int read_list(FILE *shop_f, struct shop_buy_data *list, int new_format, int max, int type);
#endif
static void shopping_list(char *arg, struct char_data *ch, struct char_data *keeper, int shop_nr);
static void shopping_value(char *arg, struct char_data *ch, struct char_data *keeper, int shop_nr);
static void shopping_sell(char *arg, struct char_data *ch, struct char_data *keeper, int shop_nr);
@ -78,6 +91,22 @@ static int is_ok(struct char_data *keeper, struct char_data *ch, int shop_nr);
static void evaluate_operation(struct stack_data *ops, struct stack_data *vals);
static int find_oper_num(char token);
static int evaluate_expression(struct obj_data *obj, char *expr);
static float toml_get_float_default(toml_table_t *tab, const char *key, float def)
{
toml_datum_t v = toml_double_in(tab, key);
if (!v.ok)
return def;
return (float)v.u.d;
}
static int toml_get_int_default(toml_table_t *tab, const char *key, int def)
{
toml_datum_t v = toml_int_in(tab, key);
if (!v.ok)
return def;
return (int)v.u.i;
}
static int trade_with(struct obj_data *item, int shop_nr);
static int same_obj(struct obj_data *obj1, struct obj_data *obj2);
static int shop_producing(struct obj_data *item, int shop_nr);
@ -86,9 +115,11 @@ static char *times_message(struct obj_data *obj, char *name, int num);
static int buy_price(struct obj_data *obj, int shop_nr, struct char_data *keeper, struct char_data *buyer);
static int sell_price(struct obj_data *obj, int shop_nr, struct char_data *keeper, struct char_data *seller);
static int ok_shop_room(int shop_nr, room_vnum room);
#if 0
static int add_to_shop_list(struct shop_buy_data *list, int type, int *len, int *val);
static int end_read_list(struct shop_buy_data *list, int len, int error);
static void read_line(FILE *shop_f, const char *string, void *data);
#endif
/* Local file scope only variables */
static int cmd_say;
@ -1104,6 +1135,7 @@ int ok_damage_shopkeeper(struct char_data *ch, struct char_data *victim)
}
/* val == obj_vnum and obj_rnum (?) */
#if 0
static int add_to_shop_list(struct shop_buy_data *list, int type, int *len, int *val)
{
if (*val != NOTHING && *val >= 0) { /* necessary after changing to unsigned v/rnums -- Welcor */
@ -1140,7 +1172,9 @@ static void read_line(FILE *shop_f, const char *string, void *data)
exit(1);
}
}
#endif
#if 0
static int read_list(FILE *shop_f, struct shop_buy_data *list, int new_format,
int max, int type)
{
@ -1160,7 +1194,9 @@ static int read_list(FILE *shop_f, struct shop_buy_data *list, int new_format,
}
return (end_read_list(list, len, error));
}
#endif
#if 0
/* END_OF inefficient. */
static int read_type_list(FILE *shop_f, struct shop_buy_data *list,
int new_format, int max)
@ -1251,76 +1287,172 @@ static char *read_shop_message(int mnum, room_vnum shr, FILE *shop_f, const char
}
return (tbuf);
}
#endif
static char *dup_shop_message(int mnum, room_vnum shr, const char *msg)
{
int cht, ss = 0, ds = 0, err = 0;
char *tbuf;
if (!msg || !*msg)
return NULL;
tbuf = strdup(msg);
for (cht = 0; tbuf[cht]; cht++) {
if (tbuf[cht] != '%')
continue;
if (tbuf[cht + 1] == 's')
ss++;
else if (tbuf[cht + 1] == 'd' && (mnum == 5 || mnum == 6)) {
if (ss == 0) {
log("SYSERR: Shop #%d has %%d before %%s, message #%d.", shr, mnum);
err++;
}
ds++;
} else if (tbuf[cht + 1] != '%') {
log("SYSERR: Shop #%d has invalid format '%%%c' in message #%d.", shr, tbuf[cht + 1], mnum);
err++;
}
}
if (ss > 1 || ds > 1) {
log("SYSERR: Shop #%d has too many specifiers for message #%d. %%s=%d %%d=%d", shr, mnum, ss, ds);
err++;
}
if (err) {
free(tbuf);
return NULL;
}
return (tbuf);
}
void boot_the_shops(FILE *shop_f, char *filename, int rec_count)
{
char *buf, buf2[256];
int temp, count, new_format = FALSE;
struct shop_buy_data list[MAX_SHOP_OBJ + 1];
int done = FALSE;
FILE *fp;
toml_table_t *tab;
toml_array_t *shops;
char errbuf[200];
int i;
snprintf(buf2, sizeof(buf2), "beginning of shop file %s", filename);
(void)shop_f;
while (!done) {
buf = fread_string(shop_f, buf2);
if (*buf == '#') { /* New shop */
sscanf(buf, "#%d\n", &temp);
snprintf(buf2, sizeof(buf2), "shop #%d in shop file %s", temp, filename);
free(buf); /* Plug memory leak! */
top_shop++;
if (!top_shop)
CREATE(shop_index, struct shop_data, rec_count);
SHOP_NUM(top_shop) = temp;
temp = read_list(shop_f, list, new_format, MAX_PROD, LIST_PRODUCE);
CREATE(shop_index[top_shop].producing, obj_vnum, temp);
for (count = 0; count < temp; count++)
SHOP_PRODUCT(top_shop, count) = BUY_TYPE(list[count]);
read_line(shop_f, "%f", &SHOP_BUYPROFIT(top_shop));
read_line(shop_f, "%f", &SHOP_SELLPROFIT(top_shop));
temp = read_type_list(shop_f, list, new_format, MAX_TRADE);
CREATE(shop_index[top_shop].type, struct shop_buy_data, temp);
for (count = 0; count < temp; count++) {
SHOP_BUYTYPE(top_shop, count) = BUY_TYPE(list[count]);
SHOP_BUYWORD(top_shop, count) = BUY_WORD(list[count]);
}
shop_index[top_shop].no_such_item1 = read_shop_message(0, SHOP_NUM(top_shop), shop_f, buf2);
shop_index[top_shop].no_such_item2 = read_shop_message(1, SHOP_NUM(top_shop), shop_f, buf2);
shop_index[top_shop].do_not_buy = read_shop_message(2, SHOP_NUM(top_shop), shop_f, buf2);
shop_index[top_shop].missing_cash1 = read_shop_message(3, SHOP_NUM(top_shop), shop_f, buf2);
shop_index[top_shop].missing_cash2 = read_shop_message(4, SHOP_NUM(top_shop), shop_f, buf2);
shop_index[top_shop].message_buy = read_shop_message(5, SHOP_NUM(top_shop), shop_f, buf2);
shop_index[top_shop].message_sell = read_shop_message(6, SHOP_NUM(top_shop), shop_f, buf2);
read_line(shop_f, "%d", &SHOP_BROKE_TEMPER(top_shop));
read_line(shop_f, "%ld", &SHOP_BITVECTOR(top_shop));
read_line(shop_f, "%d", &SHOP_KEEPER(top_shop));
SHOP_KEEPER(top_shop) = real_mobile(SHOP_KEEPER(top_shop));
read_line(shop_f, "%d", &SHOP_TRADE_WITH(top_shop));
temp = read_list(shop_f, list, new_format, 1, LIST_ROOM);
CREATE(shop_index[top_shop].in_room, room_vnum, temp);
for (count = 0; count < temp; count++)
SHOP_ROOM(top_shop, count) = BUY_TYPE(list[count]);
read_line(shop_f, "%d", &SHOP_OPEN1(top_shop));
read_line(shop_f, "%d", &SHOP_CLOSE1(top_shop));
read_line(shop_f, "%d", &SHOP_OPEN2(top_shop));
read_line(shop_f, "%d", &SHOP_CLOSE2(top_shop));
SHOP_BANK(top_shop) = 0;
SHOP_SORT(top_shop) = 0;
SHOP_FUNC(top_shop) = NULL;
} else {
if (*buf == '$') /* EOF */
done = TRUE;
else if (strstr(buf, VERSION3_TAG)) /* New format marker */
new_format = TRUE;
free(buf); /* Plug memory leak! */
}
fp = fopen(filename, "r");
if (!fp) {
log("SYSERR: %s: %s", filename, strerror(errno));
exit(1);
}
tab = toml_parse_file(fp, errbuf, sizeof(errbuf));
fclose(fp);
if (!tab) {
log("SYSERR: parsing file '%s': %s", filename, errbuf);
exit(1);
}
shops = toml_array_in(tab, "shop");
if (!shops) {
toml_free(tab);
log("SYSERR: TOML file '%s' missing 'shop' array.", filename);
exit(1);
}
for (i = 0; i < toml_array_nelem(shops); i++) {
toml_table_t *shop_tab = toml_table_at(shops, i);
toml_array_t *arr;
toml_table_t *msgs;
int count, temp;
if (!shop_tab)
continue;
top_shop++;
if (!top_shop)
CREATE(shop_index, struct shop_data, rec_count);
SHOP_NUM(top_shop) = toml_get_int_default(shop_tab, "vnum", 0);
arr = toml_array_in(shop_tab, "products");
temp = arr ? toml_array_nelem(arr) : 0;
CREATE(shop_index[top_shop].producing, obj_vnum, temp + 1);
for (count = 0; count < temp; count++) {
toml_datum_t v = toml_int_at(arr, count);
SHOP_PRODUCT(top_shop, count) = v.ok ? (obj_vnum)v.u.i : NOTHING;
}
SHOP_PRODUCT(top_shop, temp) = NOTHING;
SHOP_BUYPROFIT(top_shop) = toml_get_float_default(shop_tab, "buy_profit", 0.0f);
SHOP_SELLPROFIT(top_shop) = toml_get_float_default(shop_tab, "sell_profit", 0.0f);
arr = toml_array_in(shop_tab, "buy_type");
temp = arr ? toml_array_nelem(arr) : 0;
CREATE(shop_index[top_shop].type, struct shop_buy_data, temp + 1);
for (count = 0; count < temp; count++) {
toml_table_t *bt_tab = toml_table_at(arr, count);
int t = NOTHING;
char *word = NULL;
if (bt_tab) {
t = toml_get_int_default(bt_tab, "type", NOTHING);
word = toml_get_string_dup(bt_tab, "keyword");
}
SHOP_BUYTYPE(top_shop, count) = t;
SHOP_BUYWORD(top_shop, count) = word;
}
SHOP_BUYTYPE(top_shop, temp) = NOTHING;
SHOP_BUYWORD(top_shop, temp) = NULL;
msgs = toml_table_in(shop_tab, "messages");
if (msgs) {
char *msg;
msg = toml_get_string_dup(msgs, "no_such_item1");
shop_index[top_shop].no_such_item1 = dup_shop_message(0, SHOP_NUM(top_shop), msg);
if (msg) free(msg);
msg = toml_get_string_dup(msgs, "no_such_item2");
shop_index[top_shop].no_such_item2 = dup_shop_message(1, SHOP_NUM(top_shop), msg);
if (msg) free(msg);
msg = toml_get_string_dup(msgs, "do_not_buy");
shop_index[top_shop].do_not_buy = dup_shop_message(2, SHOP_NUM(top_shop), msg);
if (msg) free(msg);
msg = toml_get_string_dup(msgs, "missing_cash1");
shop_index[top_shop].missing_cash1 = dup_shop_message(3, SHOP_NUM(top_shop), msg);
if (msg) free(msg);
msg = toml_get_string_dup(msgs, "missing_cash2");
shop_index[top_shop].missing_cash2 = dup_shop_message(4, SHOP_NUM(top_shop), msg);
if (msg) free(msg);
msg = toml_get_string_dup(msgs, "message_buy");
shop_index[top_shop].message_buy = dup_shop_message(5, SHOP_NUM(top_shop), msg);
if (msg) free(msg);
msg = toml_get_string_dup(msgs, "message_sell");
shop_index[top_shop].message_sell = dup_shop_message(6, SHOP_NUM(top_shop), msg);
if (msg) free(msg);
}
SHOP_BROKE_TEMPER(top_shop) = toml_get_int_default(shop_tab, "broke_temper", 0);
SHOP_BITVECTOR(top_shop) = (long)toml_get_int_default(shop_tab, "bitvector", 0);
SHOP_KEEPER(top_shop) = toml_get_int_default(shop_tab, "keeper", NOBODY);
SHOP_KEEPER(top_shop) = real_mobile(SHOP_KEEPER(top_shop));
SHOP_TRADE_WITH(top_shop) = toml_get_int_default(shop_tab, "trade_with", 0);
arr = toml_array_in(shop_tab, "rooms");
temp = arr ? toml_array_nelem(arr) : 0;
CREATE(shop_index[top_shop].in_room, room_vnum, temp + 1);
for (count = 0; count < temp; count++) {
toml_datum_t v = toml_int_at(arr, count);
SHOP_ROOM(top_shop, count) = v.ok ? (room_vnum)v.u.i : NOWHERE;
}
SHOP_ROOM(top_shop, temp) = NOWHERE;
SHOP_OPEN1(top_shop) = toml_get_int_default(shop_tab, "open1", 0);
SHOP_CLOSE1(top_shop) = toml_get_int_default(shop_tab, "close1", 0);
SHOP_OPEN2(top_shop) = toml_get_int_default(shop_tab, "open2", 0);
SHOP_CLOSE2(top_shop) = toml_get_int_default(shop_tab, "close2", 0);
SHOP_BANK(top_shop) = toml_get_int_default(shop_tab, "bank", 0);
SHOP_SORT(top_shop) = toml_get_int_default(shop_tab, "sort", 0);
SHOP_FUNC(top_shop) = NULL;
}
toml_free(tab);
}
void assign_the_shopkeepers(void)

58
src/toml_utils.c Normal file
View file

@ -0,0 +1,58 @@
#include "conf.h"
#include "sysdep.h"
#include "toml_utils.h"
static void toml_write_escaped(FILE *fp, const char *value)
{
const unsigned char *p = (const unsigned char *)value;
while (p && *p) {
switch (*p) {
case '\\':
fputs("\\\\", fp);
break;
case '"':
fputs("\\\"", fp);
break;
case '\n':
fputs("\\n", fp);
break;
case '\r':
fputs("\\r", fp);
break;
case '\t':
fputs("\\t", fp);
break;
default:
if (*p < 0x20) {
fprintf(fp, "\\u%04x", (unsigned int)*p);
} else {
fputc(*p, fp);
}
break;
}
p++;
}
}
void toml_write_string(FILE *fp, const char *value)
{
fputc('"', fp);
if (value && *value)
toml_write_escaped(fp, value);
fputc('"', fp);
}
void toml_write_kv_string(FILE *fp, const char *key, const char *value)
{
fprintf(fp, "%s = ", key);
toml_write_string(fp, value);
fputc('\n', fp);
}
void toml_write_kv_string_opt(FILE *fp, const char *key, const char *value)
{
if (!value || !*value)
return;
toml_write_kv_string(fp, key, value);
}

10
src/toml_utils.h Normal file
View file

@ -0,0 +1,10 @@
#ifndef TOML_UTILS_H
#define TOML_UTILS_H
#include <stdio.h>
void toml_write_string(FILE *fp, const char *value);
void toml_write_kv_string(FILE *fp, const char *key, const char *value);
void toml_write_kv_string_opt(FILE *fp, const char *key, const char *value);
#endif