[Add] mission/hook save disabled right now - Pluto is still being a bitch!
This commit is contained in:
parent
2bd4edfa09
commit
304bc81ea1
@ -291,11 +291,8 @@ static void persistfunction(PersistInfo *pi)
|
||||
/* It's a C function. For now, we aren't going to allow
|
||||
* persistence of C closures, even if the "C proto" is
|
||||
* already in the permanents table. */
|
||||
/*
|
||||
lua_pushstring(pi->L, "Attempt to persist a C function");
|
||||
lua_error(pi->L);
|
||||
*/
|
||||
return; /* we don't save C closures, they'll have to get repushed */
|
||||
} else {
|
||||
/* It's a Lua closure. */
|
||||
{
|
||||
|
109
src/hook.c
109
src/hook.c
@ -3,11 +3,12 @@
|
||||
|
||||
#include "log.h"
|
||||
#include "lephisto.h"
|
||||
#include "xml.h"
|
||||
#include "hook.h"
|
||||
|
||||
// The hook.
|
||||
typedef struct Hook_ {
|
||||
int id; // Unique id.
|
||||
unsigned int id; // Unique id.
|
||||
unsigned int parent; // Mission it's connected to.
|
||||
char* func; // Function returned.
|
||||
char* stack; // Stack it's a part of.
|
||||
@ -26,6 +27,9 @@ static int hook_runningstack = 0; // Check if stack is running.
|
||||
extern int misn_run(Mission* misn, char* func);
|
||||
// Intern.
|
||||
static int hook_run(Hook* hook);
|
||||
static void hook_free(Hook* h);
|
||||
static int hook_needSave(Hook* h);
|
||||
static int hook_parse(xmlNodePtr base);
|
||||
|
||||
static int hook_run(Hook* hook) {
|
||||
int i;
|
||||
@ -52,7 +56,7 @@ static int hook_run(Hook* hook) {
|
||||
}
|
||||
|
||||
// Add/Remove hooks.
|
||||
int hook_add(unsigned int parent, char* func, char* stack) {
|
||||
unsigned int hook_add(unsigned int parent, char* func, char* stack) {
|
||||
Hook* new_hook;
|
||||
|
||||
// If the memory must grow.
|
||||
@ -65,8 +69,8 @@ int hook_add(unsigned int parent, char* func, char* stack) {
|
||||
new_hook = &hook_stack[hook_nstack];
|
||||
new_hook->id = ++hook_id;
|
||||
new_hook->parent = parent;
|
||||
new_hook->func = func;
|
||||
new_hook->stack = stack;
|
||||
new_hook->func = strdup(func);
|
||||
new_hook->stack = strdup(stack);
|
||||
new_hook->delete = 0;
|
||||
|
||||
hook_nstack++;
|
||||
@ -74,7 +78,7 @@ int hook_add(unsigned int parent, char* func, char* stack) {
|
||||
return new_hook->id;
|
||||
}
|
||||
|
||||
void hook_rm(int id) {
|
||||
void hook_rm(unsigned int id) {
|
||||
int l, m, h;
|
||||
l = 0;
|
||||
h = hook_nstack-1;
|
||||
@ -93,12 +97,13 @@ void hook_rm(int id) {
|
||||
|
||||
// Last hook, just clip the stack.
|
||||
if(m == (hook_nstack-1)) {
|
||||
hook_free(&hook_stack[m]);
|
||||
hook_nstack--;
|
||||
return;
|
||||
}
|
||||
|
||||
// Move it!
|
||||
memmove(&hook_stack[m], &hook_stack[m], sizeof(Hook)*(hook_nstack-(m+1)));
|
||||
memmove(&hook_stack[m], &hook_stack[m+1], sizeof(Hook)*(hook_nstack-(m+1)));
|
||||
hook_nstack--;
|
||||
}
|
||||
|
||||
@ -132,7 +137,7 @@ int hooks_run(char* stack) {
|
||||
}
|
||||
|
||||
// Run a single hook by id.
|
||||
void hook_runID(int id) {
|
||||
void hook_runID(unsigned int id) {
|
||||
int i;
|
||||
|
||||
for(i = 0; i < hook_nstack; i++)
|
||||
@ -143,8 +148,18 @@ void hook_runID(int id) {
|
||||
DEBUG("Attempting to run hook of id '%d' which is not in the stack", id);
|
||||
}
|
||||
|
||||
// Free a hook.
|
||||
static void hook_free(Hook* h) {
|
||||
if(h->func != NULL) free(h->func);
|
||||
if(h->stack != NULL) free(h->stack);
|
||||
}
|
||||
|
||||
// Clean upi after ourselves.
|
||||
void hook_cleanup(void) {
|
||||
int i;
|
||||
|
||||
for(i = 0; i < hook_nstack; i++)
|
||||
hook_free(&hook_stack[i]);
|
||||
free(hook_stack);
|
||||
hook_stack = NULL;
|
||||
// Sane defaults just in case.
|
||||
@ -152,3 +167,83 @@ void hook_cleanup(void) {
|
||||
hook_mstack = 0;
|
||||
}
|
||||
|
||||
// Save the hooks.
|
||||
static int hook_needSave(Hook* h) {
|
||||
int i;
|
||||
char* nosave[] = { "death", "end" };
|
||||
|
||||
for(i = 0; strcmp(nosave[i], "end") != 0; i++)
|
||||
if(strcmp(nosave[i], h->stack)==0) return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int hook_save(xmlTextWriterPtr writer) {
|
||||
int i;
|
||||
Hook* h;
|
||||
|
||||
xmlw_startElem(writer, "hooks");
|
||||
for(i = 0; i < hook_nstack; i++) {
|
||||
h = &hook_stack[i];
|
||||
|
||||
if(!hook_needSave(h)) continue; // No need to save it.
|
||||
|
||||
xmlw_startElem(writer, "hook");
|
||||
|
||||
//xmlw_attr(writer, "id", "%u", h->id); // I don't think it's needed.
|
||||
xmlw_elem(writer, "parent", "%u", h->parent);
|
||||
xmlw_elem(writer, "func", "%s", h->func);
|
||||
xmlw_elem(writer, "stack", "%s", h->stack);
|
||||
|
||||
xmlw_endElem(writer); // Hook.
|
||||
}
|
||||
xmlw_endElem(writer); // Hooks.
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Load hooks for a player.
|
||||
int hook_load(xmlNodePtr parent) {
|
||||
xmlNodePtr node;
|
||||
|
||||
hook_cleanup();
|
||||
|
||||
node = parent->xmlChildrenNode;
|
||||
do {
|
||||
if(xml_isNode(node, "hooks"))
|
||||
hook_parse(node);
|
||||
} while(xml_nextNode(node));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hook_parse(xmlNodePtr base) {
|
||||
xmlNodePtr node, cur;
|
||||
char* func, *stack;
|
||||
unsigned int parent;
|
||||
|
||||
node = base->xmlChildrenNode;
|
||||
do {
|
||||
if(xml_isNode(node, "hook")) {
|
||||
parent = 0;
|
||||
func = NULL;
|
||||
stack = NULL;
|
||||
|
||||
cur = node->xmlChildrenNode;
|
||||
do {
|
||||
xmlr_long(cur, "parent", parent);
|
||||
xmlr_str(cur, "func", func);
|
||||
xmlr_str(cur, "stack", stack);
|
||||
} while(xml_nextNode(cur));
|
||||
|
||||
if((parent == 0) || (func == NULL) || (stack == NULL)) {
|
||||
WARN("Invalid hook.");
|
||||
return -1;
|
||||
}
|
||||
hook_add(parent, func, stack);
|
||||
}
|
||||
} while(xml_nextNode(node));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2,8 +2,8 @@
|
||||
#include "mission.h"
|
||||
|
||||
// Add/Run hooks.
|
||||
int hook_add(unsigned int parent, char* func, char* stack);
|
||||
void hook_rm(int id);
|
||||
unsigned int hook_add(unsigned int parent, char* func, char* stack);
|
||||
void hook_rm(unsigned int id);
|
||||
void hook_rmParent(unsigned int parent);
|
||||
|
||||
// ========================================================
|
||||
@ -18,7 +18,7 @@ void hook_rmParent(unsigned int parent);
|
||||
// ========================================================
|
||||
|
||||
int hooks_run(char* stack);
|
||||
void hook_runID(int id); // Runs hook of specific id.
|
||||
void hook_runID(unsigned int id); // Runs hook of specific id.
|
||||
|
||||
// Destroy hook.
|
||||
void hook_cleanup(void);
|
||||
|
@ -55,7 +55,7 @@ static int misn_delete = 0; // If 1 delete current mission.
|
||||
|
||||
static int var_add(misn_var* var);
|
||||
static void var_free(misn_var* var);
|
||||
static int hook_generic(lua_State* L, char* stack);
|
||||
static unsigned int hook_generic(lua_State* L, char* stack);
|
||||
|
||||
// -- Libraries. --
|
||||
|
||||
@ -872,7 +872,7 @@ static int tk_input(lua_State* L) {
|
||||
}
|
||||
|
||||
// -- HOOK --
|
||||
static int hook_generic(lua_State* L, char* stack) {
|
||||
static unsigned int hook_generic(lua_State* L, char* stack) {
|
||||
int i;
|
||||
char* func;
|
||||
|
||||
@ -893,8 +893,7 @@ static int hook_generic(lua_State* L, char* stack) {
|
||||
cur_mission->data->name);
|
||||
return 0;
|
||||
}
|
||||
i = hook_add(cur_mission->id, func, stack);
|
||||
return i;
|
||||
return hook_add(cur_mission->id, func, stack);
|
||||
}
|
||||
|
||||
static int hook_land(lua_State* L) {
|
||||
@ -919,8 +918,7 @@ static int hook_enter(lua_State* L) {
|
||||
|
||||
static int hook_pilotDeath(lua_State* L) {
|
||||
MIN_ARGS(2);
|
||||
int h;
|
||||
unsigned int p;
|
||||
unsigned int h, p;
|
||||
|
||||
if(lua_isnumber(L, -2)) p = (unsigned int) lua_tonumber(L, -2);
|
||||
else MISN_INVALID_PARAMETER();
|
||||
|
142
src/mission.c
142
src/mission.c
@ -48,6 +48,8 @@ static int mission_matchFaction(MissionData* misn, int faction);
|
||||
static int mission_location(char* loc);
|
||||
static MissionData* mission_parse(const xmlNodePtr parent);
|
||||
static int missions_parseActive(xmlNodePtr parent);
|
||||
static int mission_persistTable(lua_State* L);
|
||||
static int mission_unpersistTable(lua_State* L);
|
||||
|
||||
// Generate a new id for the mission.
|
||||
static unsigned int mission_genID(void) {
|
||||
@ -104,7 +106,7 @@ static int mission_init(Mission* mission, MissionData* misn) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
luaopen_base(mission->L); // Can be useful.
|
||||
//luaopen_base(mission->L); // Can be useful.
|
||||
luaopen_string(mission->L); // string.format can be very useful.
|
||||
misn_loadLibs(mission->L); // Load our custom libraries.
|
||||
|
||||
@ -224,18 +226,33 @@ void mission_unlinkCargo(Mission* misn, unsigned int cargo_id) {
|
||||
// Clean up a mission.
|
||||
void mission_cleanup(Mission* misn) {
|
||||
int i;
|
||||
if(misn->id) hook_rmParent(misn->id); // Remove existing hooks.
|
||||
if(misn->title) free(misn->title);
|
||||
if(misn->desc) free(misn->desc);
|
||||
if(misn->reward) free(misn->reward);
|
||||
if(misn->id != 0) {
|
||||
hook_rmParent(misn->id); // Remove existing hooks.
|
||||
misn->id = 0;
|
||||
}
|
||||
if(misn->title != NULL) {
|
||||
free(misn->title);
|
||||
misn->title = NULL;
|
||||
}
|
||||
if(misn->desc != NULL) {
|
||||
free(misn->desc);
|
||||
misn->desc = NULL;
|
||||
}
|
||||
if(misn->reward) {
|
||||
free(misn->reward);
|
||||
misn->reward = NULL;
|
||||
}
|
||||
if(misn->cargo) {
|
||||
for(i = 0; i < misn->ncargo; i++)
|
||||
mission_unlinkCargo(misn, misn->cargo[i]);
|
||||
free(misn->cargo);
|
||||
misn->cargo = NULL;
|
||||
misn->ncargo = 0;
|
||||
}
|
||||
if(misn->L) lua_close(misn->L);
|
||||
memset(misn, 0, sizeof(Mission));
|
||||
if(misn->L) {
|
||||
lua_close(misn->L);
|
||||
misn->L = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Free a mission.
|
||||
@ -432,6 +449,7 @@ void missions_cleanup(void) {
|
||||
mission_cleanup(&player_missions[i]);
|
||||
}
|
||||
|
||||
// Memory buffer structure to handle lua writers/readers.
|
||||
typedef struct MBuf_ {
|
||||
char* data;
|
||||
ssize_t len, alloc; // Size of each data chunk, chunks to alloc when growing.
|
||||
@ -482,6 +500,53 @@ static int mission_writeLua(lua_State* L, const void* p, size_t sz, void* ud) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mission_persistTable(lua_State* L) {
|
||||
lua_newtable(L);
|
||||
// Table.
|
||||
lua_pushnil(L);
|
||||
// table, nil.
|
||||
while(lua_next(L, LUA_GLOBALSINDEX) != 0) {
|
||||
// table, key, value.
|
||||
switch(lua_type(L, -1)) {
|
||||
case LUA_TNUMBER:
|
||||
case LUA_TBOOLEAN:
|
||||
case LUA_TSTRING:
|
||||
lua_pushvalue(L, -2); // Copy key.
|
||||
// table, key, value, key.
|
||||
lua_insert(L, -3); // key << 2.
|
||||
// table, key, key, value.
|
||||
lua_settable(L, -4); // table[key] = value.
|
||||
// table, key.
|
||||
break;
|
||||
default:
|
||||
lua_pop(L, 1);
|
||||
// table, key.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// table.
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mission_unpersistTable(lua_State* L) {
|
||||
// Table.
|
||||
lua_pushnil(L);
|
||||
// Table, Nil.
|
||||
while(lua_next(L, -2) != 0) {
|
||||
// Table, key, value.
|
||||
lua_pushvalue(L, -2); // Copy key.
|
||||
// Table, key, value, key.
|
||||
lua_insert(L, -3); // key << 2.
|
||||
// table, key, key, value.
|
||||
lua_settable(L, LUA_GLOBALSINDEX);
|
||||
// table, key.
|
||||
}
|
||||
// Table.
|
||||
lua_pop(L, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int missions_saveActive(xmlTextWriterPtr writer) {
|
||||
MBuf* buf;
|
||||
char* data;
|
||||
@ -494,8 +559,9 @@ int missions_saveActive(xmlTextWriterPtr writer) {
|
||||
if(player_missions[i].id != 0) {
|
||||
xmlw_startElem(writer, "mission");
|
||||
|
||||
xmlw_elem(writer, "data", player_missions[i].data->name);
|
||||
xmlw_elem(writer, "id", "%u", player_missions[i].id);
|
||||
// Data and id are attributes because they must be loaded first.
|
||||
xmlw_attr(writer, "data", player_missions[i].data->name);
|
||||
xmlw_attr(writer, "id", "%u", player_missions[i].id);
|
||||
|
||||
xmlw_elem(writer, "title", player_missions[i].title);
|
||||
xmlw_elem(writer, "desc", player_missions[i].desc);
|
||||
@ -506,14 +572,25 @@ int missions_saveActive(xmlTextWriterPtr writer) {
|
||||
xmlw_elem(writer, "cargo", "%u", player_missions[i].cargo[j]);
|
||||
xmlw_endElem(writer); // Cargo.
|
||||
|
||||
// Write lua magic.
|
||||
xmlw_startElem(writer, "lua");
|
||||
|
||||
// We need to use a special data struct.
|
||||
buf = mbuf_create(1, 128);
|
||||
lua_pushvalue(player_missions[i].L, LUA_GLOBALSINDEX);
|
||||
|
||||
// Prepare the data.
|
||||
lua_pushnil(player_missions[i].L);
|
||||
mission_persistTable(player_missions[i].L); // We don't save it all.
|
||||
pluto_persist(player_missions[i].L, mission_writeLua, buf);
|
||||
|
||||
// Now process it to save it.
|
||||
data = base64_encode(&sz, buf->data, buf->ndata);
|
||||
mbuf_free(buf);
|
||||
xmlw_raw(writer, data, sz);
|
||||
|
||||
// Cleanup.
|
||||
mbuf_free(buf);
|
||||
free(data);
|
||||
|
||||
xmlw_endElem(writer); // Lua.
|
||||
|
||||
xmlw_endElem(writer); // Mission.
|
||||
@ -529,21 +606,23 @@ const char* mission_readLua(lua_State* L, void* data, size_t* size) {
|
||||
MBuf* dat;
|
||||
char* pos;
|
||||
char* buf;
|
||||
size_t len;
|
||||
|
||||
dat = (MBuf*) data;
|
||||
len = dat->alloc * dat->len;
|
||||
pos = dat->data;
|
||||
|
||||
buf = &pos[dat->ndata];
|
||||
if(dat->mdata >= dat->ndata) {
|
||||
if(dat->ndata >= dat->mdata) {
|
||||
(*size) = 0;
|
||||
return NULL;
|
||||
}
|
||||
if(dat->mdata < (dat->ndata + dat->alloc * dat->len)) { // Last chunk.
|
||||
if(dat->mdata < (dat->ndata + len)) { // Last chunk.
|
||||
(*size) = dat->mdata - dat->ndata;
|
||||
dat->ndata = dat->mdata;
|
||||
} else {
|
||||
(*size) = dat->alloc * dat->len;
|
||||
dat->ndata += dat->alloc * dat->len;
|
||||
(*size) = len;
|
||||
dat->ndata += len;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
@ -566,7 +645,7 @@ int missions_loadActive(xmlNodePtr parent) {
|
||||
static int missions_parseActive(xmlNodePtr parent) {
|
||||
Mission* misn;
|
||||
int m;
|
||||
char* buf;
|
||||
char* buf, *str;
|
||||
MBuf dat;
|
||||
|
||||
xmlNodePtr node, cur, nest;
|
||||
@ -576,16 +655,19 @@ static int missions_parseActive(xmlNodePtr parent) {
|
||||
do {
|
||||
if(xml_isNode(node, "mission")) {
|
||||
misn = &player_missions[m];
|
||||
mission_init(misn, NULL); // Won't set data nor id.
|
||||
|
||||
// Process the attributes to create the mission.
|
||||
xmlr_attr(node, "data", buf);
|
||||
mission_init(misn, mission_get(mission_getID(buf)));
|
||||
free(buf);
|
||||
|
||||
// This will orphan an identifier.
|
||||
xmlr_attr(node, "id", buf);
|
||||
misn->id = atol(buf);
|
||||
free(buf);
|
||||
|
||||
cur = node->xmlChildrenNode;
|
||||
do {
|
||||
if(xml_isNode(cur, "data")) {
|
||||
buf = xml_get(cur);
|
||||
misn->data = mission_get(mission_getID(buf));
|
||||
}
|
||||
xmlr_long(cur, "id", misn->id);
|
||||
|
||||
xmlr_strd(cur, "title", misn->title);
|
||||
xmlr_strd(cur, "desc", misn->desc);
|
||||
xmlr_strd(cur, "reward", misn->reward);
|
||||
@ -599,12 +681,20 @@ static int missions_parseActive(xmlNodePtr parent) {
|
||||
}
|
||||
|
||||
if(xml_isNode(cur, "lua")) {
|
||||
buf = xml_get(cur);
|
||||
// Prepare the data.
|
||||
str = xml_get(cur);
|
||||
dat.ndata = 0;
|
||||
dat.len = 1;
|
||||
dat.len = 1024;
|
||||
dat.alloc = 128;
|
||||
dat.data = base64_decode(&dat.mdata, buf, strlen(buf));
|
||||
dat.data = base64_decode(&dat.mdata, str, strlen(str));
|
||||
|
||||
// Start the unpersist routine.
|
||||
lua_pushnil(misn->L);
|
||||
pluto_unpersist(misn->L, mission_readLua, &dat);
|
||||
mission_unpersistTable(misn->L);
|
||||
|
||||
// Cleanup.
|
||||
free(dat.data);
|
||||
}
|
||||
} while(xml_nextNode(cur));
|
||||
|
||||
|
@ -22,6 +22,8 @@ extern int var_save(xmlTextWriterPtr writer); // misn var.
|
||||
extern int var_load(xmlNodePtr parent);
|
||||
extern int pfaction_save(xmlTextWriterPtr writer); // Faction data.
|
||||
extern int pfaction_load(xmlNodePtr parent);
|
||||
extern int hook_save(xmlTextWriterPtr writer); // Hooks.
|
||||
extern int hook_load(xmlNodePtr parent);
|
||||
extern void menu_main_close(void);
|
||||
// Static.
|
||||
static int save_data(xmlTextWriterPtr writer);
|
||||
@ -33,9 +35,9 @@ static int load_game(char* file);
|
||||
static int save_data(xmlTextWriterPtr writer) {
|
||||
// The data itself.
|
||||
if(player_save(writer) < 0) return -1;
|
||||
if(missions_saveActive(writer) < 0) return -1;
|
||||
//if(missions_saveActive(writer) < 0) return -1;
|
||||
if(var_save(writer) < 0) return -1;
|
||||
if(pfaction_save(writer) < 0) return -1;
|
||||
//if(pfaction_save(writer) < 0) return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -171,8 +173,9 @@ static int load_game(char* file) {
|
||||
|
||||
player_load(node);
|
||||
var_load(node);
|
||||
missions_loadActive(node);
|
||||
//missions_loadActive(node);
|
||||
pfaction_load(node);
|
||||
//hook_load(node);
|
||||
|
||||
xmlFreeDoc(doc);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user