Multiple fixes

* made sure Lua GarbageCollector gets rid of finished lua threads (or at
least I hope so)
* changed timed message to be stored in a struct as the list isn't safe
to use with char*
* changed parser and format for timedmessages.cfg
This commit is contained in:
Walter Julius Hennecke 2012-11-19 18:13:03 +01:00
parent 94ffb3ea61
commit 75f20c6eef
7 changed files with 167 additions and 33 deletions

View file

@ -512,6 +512,7 @@ list_iter_p iterTimedMessages;
*/
static char *TimedMessage( void ){
char* message;
timedMessage_t *msg;
if(!level.timedMessages->length) {
return "^1RPG-X ERROR: No messages to display";
@ -524,7 +525,8 @@ static char *TimedMessage( void ){
}
}
message = (char *)list_cycl_next(iterTimedMessages);
msg = (timedMessage_t *)list_cycl_next(iterTimedMessages);
message = msg->message;
return message;
}

View file

@ -7439,7 +7439,8 @@ static void Cmd_Camtest_f(gentity_t *ent) {
}
void Cmd_CamtestEnd_f(gentity_t *ent) {
Cinematic_DeactivateCameraMode(ent);
//Cinematic_DeactivateCameraMode(ent);
G_LuaNumThreads();
}
// END CCAM

View file

@ -1368,6 +1368,8 @@ qboolean LuaHook_G_EntityTrigger(char *function, int entnum, int othernum);
qboolean LuaHook_G_EntitySpawn(char *function, int entnum);
qboolean LuaHook_G_EntityReached(char *function, int entnum);
qboolean LuaHook_G_EntityReachedAngular(char *function, int entnum);
void G_LuaNumThreads(void);
void G_LuaCollectGarbage(void);
void G_LuaStatus(gentity_t * ent);
qboolean G_LuaInit(void);
@ -2099,5 +2101,10 @@ struct safeZone_s {
vec3_t mins;
} safeZone_s;
// timed messages
typedef struct timedMessage_s timedMessage_t;
struct timedMessage_s {
char* message;
} timedMessage_s;
#endif //_G_LOCAL_H_

View file

@ -172,7 +172,24 @@ qboolean G_LuaResume(lvm_t *vm, lua_State *T, char *func, int nargs) {
G_Printf(S_COLOR_YELLOW "Lua: traceback error ( %s )\n", vm->filename);
vm->error++;
return qfalse;
}
}
if(vm->L != T) { // this is a thread
int n = lua_gettop(vm->L);
int i;
lua_State *p;
for(i = 0; i <= n; i++) {
if(lua_isthread(vm->L, i)) {
p = lua_tothread(vm->L, i);
if(p == T) {
lua_remove(vm->L, i);
G_LuaCollectGarbage();
}
}
}
}
return qtrue;
}
@ -264,22 +281,22 @@ qboolean G_LuaStartVM(lvm_t * vm)
if(lua_istable(vm->L, -1))
{
lua_pushstring(vm->L, va("%s%s%s%s?.lua;%s%s%s%slualib%slua%s?.lua",
homepath, LUA_DIRSEP, gamepath, LUA_DIRSEP,
homepath, LUA_DIRSEP, gamepath, LUA_DIRSEP, LUA_DIRSEP, LUA_DIRSEP));
homepath, LUA_DIRSEP, gamepath, LUA_DIRSEP,
homepath, LUA_DIRSEP, gamepath, LUA_DIRSEP, LUA_DIRSEP, LUA_DIRSEP));
lua_setfield(vm->L, -2, "path");
lua_pushstring(vm->L, va("%s%s%s%s?.%s;%s%s%s%slualib%sclibs%s?.%s",
homepath, LUA_DIRSEP, gamepath, LUA_DIRSEP, EXTENSION,
homepath, LUA_DIRSEP, gamepath, LUA_DIRSEP, LUA_DIRSEP, LUA_DIRSEP, EXTENSION));
homepath, LUA_DIRSEP, gamepath, LUA_DIRSEP, EXTENSION,
homepath, LUA_DIRSEP, gamepath, LUA_DIRSEP, LUA_DIRSEP, LUA_DIRSEP, EXTENSION));
lua_setfield(vm->L, -2, "cpath");
}
lua_pop(vm->L, 1);
Lua_RegisterGlobal(vm->L, "LUA_PATH", va("%s%s%s%s?.lua;%s%s%s%slualib%slua%s?.lua",
homepath, LUA_DIRSEP, gamepath, LUA_DIRSEP,
homepath, LUA_DIRSEP, gamepath, LUA_DIRSEP, LUA_DIRSEP, LUA_DIRSEP));
homepath, LUA_DIRSEP, gamepath, LUA_DIRSEP,
homepath, LUA_DIRSEP, gamepath, LUA_DIRSEP, LUA_DIRSEP, LUA_DIRSEP));
Lua_RegisterGlobal(vm->L, "LUA_CPATH", va("%s%s%s%s?.%s;%s%s%s%slualib%sclibs%s?.%s",
homepath, LUA_DIRSEP, gamepath, LUA_DIRSEP, EXTENSION,
homepath, LUA_DIRSEP, gamepath, LUA_DIRSEP, LUA_DIRSEP, LUA_DIRSEP, EXTENSION));
homepath, LUA_DIRSEP, gamepath, LUA_DIRSEP, EXTENSION,
homepath, LUA_DIRSEP, gamepath, LUA_DIRSEP, LUA_DIRSEP, LUA_DIRSEP, EXTENSION));
Lua_RegisterGlobal(vm->L, "LUA_DIRSEP", LUA_DIRSEP);
lua_newtable(vm->L);
@ -588,6 +605,7 @@ qboolean LuaHook_G_EntityThink(char *function, int entnum)
continue;
}
} else {
t = vm->L;
if(!G_LuaGetFunctionT(t, function))
continue;
ent = &g_entities[entnum];
@ -1071,4 +1089,49 @@ qboolean LuaHook_G_EntitySpawn(char *function, int entnum)
return qfalse;
}
void G_LuaNumThreads(void) {
lvm_t* vm = lVM[0];
if(vm) {
lua_State *p;
int n = lua_gettop(vm->L);
int i, cnt = 0;
for(i = 0; i <= n; i++) {
if(lua_isthread(vm->L, i)) {
cnt++;
p = lua_tothread(vm->L, i);
if(lua_status(p) == LUA_YIELD) {
G_Printf("lua thread %d is YIELDED\n", i);
} else if(lua_status(vm->L) == 0) {
G_Printf("lua thread %d is RUNNING\n", i);
}
}
}
G_Printf("Total lua thread count: %d\n", cnt);
}
}
void G_LuaCollectGarbage(void) {
lvm_t *vm;
lua_State *p;
int i, n, m;
for(i = 0; i < NUM_VMS; i++) {
vm = lVM[i];
if(vm) {
n = lua_gettop(vm->L);
for(m = n; m > 0; m--) {
if(lua_isthread(vm->L, m)) {
p = lua_tothread(vm->L, m);
lua_gc(p, LUA_GCCOLLECT, 0);
}
}
lua_gc(vm->L, LUA_GCCOLLECT, 0);
}
}
}
#endif

View file

@ -906,10 +906,11 @@ void SP_target_location (gentity_t *ent);
static void G_LoadTimedMessages(void) {
fileHandle_t f;
char* buffer;
char* ptr;
char* message;
char* textPtr;
char* token;
int len;
int i, n;
int i;
timedMessage_t *msg;
len = trap_FS_FOpenFile("timedmessages.cfg", &f, FS_READ);
if(!len) return;
@ -930,26 +931,49 @@ static void G_LoadTimedMessages(void) {
}
trap_FS_Read(buffer, len, f);
ptr = buffer;
textPtr = buffer;
COM_BeginParseSession();
token = COM_Parse(&textPtr);
if(token[0] != '{') {
G_Printf("G_LoadTimedMessages - timedmessages.cfg not beginning with '{'\n");
trap_FS_FCloseFile(f);
free(buffer);
return;
}
for(i = 0; i < 10; i++) {
for(n = 0; ptr[n] != ';' && ptr[n] != 0; n++);
if(ptr[n] == 0) break;
message = (char *)malloc(sizeof(char)*(n+1));
if(!message) {
G_Printf(S_COLOR_RED "ERROR: Was unable to allocate %i byte.\n", (n+1) * sizeof(char) );
trap_FS_FCloseFile(f);
free(buffer);
if(level.timedMessages != NULL) {
destroy_list(level.timedMessages);
}
return;
token = COM_Parse(&textPtr);
if(!token[0]) {
break;
}
memset(message, 0, sizeof(message));
strncpy(message, ptr, n);
list_add(level.timedMessages, message, strlen(message));
if(!strcmp(token, "message")) {
if(COM_ParseString(&textPtr, &token)) {
G_Printf("G_LoadTimedMessages - invalid value '%s'\n", token);
SkipRestOfLine(&textPtr);
continue;
}
ptr += strlen(message)+1;
msg = (timedMessage_t *)malloc(sizeof(timedMessage_s));
if(msg == NULL) {
G_Printf("G_LoadTimedMessages - was unable to allocate timed message storage\n");
continue;
}
msg->message = strdup(token);
G_Printf("------------------------------------------------>'%s'\n", token);
list_add(level.timedMessages, msg, sizeof(timedMessage_s));
} else {
G_Printf("G_LoadTimedMessages - invalid token '%s'\n", token);
SkipRestOfLine(&textPtr);
continue;
}
if(token[0] == '}') {
break;
}
}
trap_FS_FCloseFile(f);

View file

@ -738,6 +738,35 @@ char* Q_strrchr( const char* string, int c )
return sp;
}
char* Q_strtok(char* str, const char *tok, int size) {
char *ptr;
char *result;
int i, l;
if(str == NULL || tok == NULL) {
return NULL;
}
ptr = (char *)str;
for(i = 0; i < strlen(str); i++) {
for(l = 0; l < size; l++) {
if(ptr[i] == tok[l]) {
result = (char *)malloc(sizeof(char)+(i+1));
if(result == NULL) {
return NULL;
}
strncpy(result, str, i);
result[i] = '\0';
return result;
}
}
}
return NULL;
}
/*
=============
Q_strncpyz

View file

@ -688,9 +688,17 @@ int Q_isalpha( int c );
int Q_stricmp (const char *s1, const char *s2);
int Q_strncmp (const char *s1, const char *s2, int n);
int Q_stricmpn (const char *s1, const char *s2, int n);
char *Q_strlwr( char *s1 );
char *Q_strupr( char *s1 );
char *Q_strrchr( const char* string, int c );
char* Q_strlwr( char *s1 );
char* Q_strupr( char *s1 );
char* Q_strrchr( const char* string, int c );
/**
* Goes through a given str searching for one of the given tokens.
* If it finds one it returns a new string containing everything
* from str until the found token (Note: remember to free the result
* if no longer needed). Returns NULL if no token is found. Make sure
* to adjust str for the next call yourself as this function won't do that.
*/
char* Q_strtok(char* str, const char *tok, int size);
// buffer size safe library replacements
void Q_strncpyz( char *dest, const char *src, int destsize );