diff --git a/include/rua_internal.h b/include/rua_internal.h index f80fe64e9..a134a49ad 100644 --- a/include/rua_internal.h +++ b/include/rua_internal.h @@ -33,10 +33,6 @@ #define __rua_internal_h #include "QF/quakeio.h" -#define QFILE_MAX_HANDLES 20 -typedef struct { - QFile *handles[QFILE_MAX_HANDLES]; -} qfile_resources_t; void RUA_Cbuf_Init (struct progs_s *pr, int secure); @@ -54,6 +50,7 @@ void RUA_Obj_Init (struct progs_s *pr, int secure); void RUA_Plist_Init (struct progs_s *pr, int secure); +void RUA_Script_Init (progs_t *pr, int secure); void RUA_String_Init (struct progs_s *pr, int secure); void RUA_QFile_Init (struct progs_s *pr, int secure); diff --git a/libs/ruamoko/Makefile.am b/libs/ruamoko/Makefile.am index c1a09a864..451cb3f0f 100644 --- a/libs/ruamoko/Makefile.am +++ b/libs/ruamoko/Makefile.am @@ -9,5 +9,5 @@ libQFruamoko_la_LDFLAGS= -version-info 1:0:0 -no-undefined libQFruamoko_la_LIBADD= $(top_builddir)/libs/gamecode/engine/libQFgamecode.la $(top_builddir)/libs/util/libQFutil.la libQFruamoko_la_SOURCES= \ rua_cbuf.c rua_cmd.c rua_cvar.c rua_file.c rua_hash.c rua_init.c \ - rua_obj.c rua_plist.c rua_qfile.c rua_qfs.c rua_string.c \ - rua_math.c + rua_math.c rua_obj.c rua_plist.c rua_qfile.c rua_qfs.c rua_script.c \ + rua_string.c diff --git a/libs/ruamoko/rua_init.c b/libs/ruamoko/rua_init.c index 6fa0e9912..1b19772df 100644 --- a/libs/ruamoko/rua_init.c +++ b/libs/ruamoko/rua_init.c @@ -48,6 +48,7 @@ static void (*init_funcs[])(progs_t *, int) = { RUA_Plist_Init, RUA_QFile_Init, RUA_QFS_Init, + RUA_Script_Init, RUA_String_Init, }; diff --git a/libs/ruamoko/rua_script.c b/libs/ruamoko/rua_script.c new file mode 100644 index 000000000..bfcb821fe --- /dev/null +++ b/libs/ruamoko/rua_script.c @@ -0,0 +1,222 @@ +/* + rua_script.c + + Script api for ruamoko + + Copyright (C) 2004 Bill Currie + + Author: Bill Currie + Date: 2002/11/11 + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +static __attribute__ ((unused)) const char rcsid[] = + "$Id$"; + +#include +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/progs.h" +#include "QF/script.h" + +#include "rua_internal.h" + +typedef struct { + script_t script; + string_t dstr; + progs_t *pr; + string_t err_msg; +} rua_script_t; + +typedef struct { + PR_RESMAP(rua_script_t) scripts; +} script_resources_t; + +static rua_script_t * +script_new (script_resources_t *res) +{ + PR_RESNEW (rua_script_t, res->scripts); +} + +static void +script_free (script_resources_t *res, rua_script_t *script) +{ + PR_RESFREE (rua_script_t, res->scripts, script); +} + +static void +script_reset (script_resources_t *res) +{ + PR_RESRESET (rua_script_t, res->scripts); +} + +static inline rua_script_t * +script_get (script_resources_t *res, int index) +{ + PR_RESGET(res->scripts, index); +} + +static inline int +script_index (script_resources_t *res, rua_script_t *script) +{ + PR_RESINDEX(res->scripts, script); +} + +static void +bi_script_clear (progs_t *pr, void *data) +{ + script_resources_t *res = (script_resources_t *) data; + script_reset (res); +} + +static void +bi_script_error (script_t *_script, const char *msg) +{ + rua_script_t *script = (rua_script_t *)_script; + script->err_msg = PR_SetString (script->pr, msg); +} + +static void +bi_Script_New (progs_t *pr) +{ + script_resources_t *res = PR_Resources_Find (pr, "Script"); + rua_script_t *script = script_new (res); + + if (!script) + PR_RunError (pr, "out of memory"); + + script->dstr = PR_NewMutableString (pr); + script->script.token = PR_GetMutableString (pr, script->dstr); + script->script.error = bi_script_error; + script->pr = pr; + R_INT (pr) = script_index (res, script); +} + +static void +bi_Script_Delete (progs_t *pr) +{ + script_resources_t *res = PR_Resources_Find (pr, "Script"); + rua_script_t *script = script_get (res, P_INT (pr, 0)); + + if (!script) + PR_RunError (pr, "invalid script handle"); + PR_FreeString (pr, script->dstr); + script_free (res, script); +} + +static void +bi_Script_Start (progs_t *pr) +{ + script_resources_t *res = PR_Resources_Find (pr, "Script"); + rua_script_t *script = script_get (res, P_INT (pr, 0)); + + if (!script) + PR_RunError (pr, "invalid script handle"); + Script_Start (&script->script, P_GSTRING (pr, 1), P_GSTRING (pr, 2)); + R_STRING (pr) = script->dstr; +} + +static void +bi_Script_TokenAvailable (progs_t *pr) +{ + script_resources_t *res = PR_Resources_Find (pr, "Script"); + rua_script_t *script = script_get (res, P_INT (pr, 0)); + + if (!script) + PR_RunError (pr, "invalid script handle"); + R_INT (pr) = Script_TokenAvailable (&script->script, P_INT (pr, 1)); +} + +static void +bi_Script_GetToken (progs_t *pr) +{ + script_resources_t *res = PR_Resources_Find (pr, "Script"); + rua_script_t *script = script_get (res, P_INT (pr, 0)); + + if (!script) + PR_RunError (pr, "invalid script handle"); + R_INT (pr) = Script_GetToken (&script->script, P_INT (pr, 1)); +} + +static void +bi_Script_UngetToken (progs_t *pr) +{ + script_resources_t *res = PR_Resources_Find (pr, "Script"); + rua_script_t *script = script_get (res, P_INT (pr, 0)); + + if (!script) + PR_RunError (pr, "invalid script handle"); + Script_UngetToken (&script->script); +} + +static void +bi_Script_Error (progs_t *pr) +{ + script_resources_t *res = PR_Resources_Find (pr, "Script"); + rua_script_t *script = script_get (res, P_INT (pr, 0)); + + if (!script) + PR_RunError (pr, "invalid script handle"); + R_STRING (pr) = script->err_msg; + script->err_msg = 0; +} + +static void +bi_Script_NoQuoteLines (progs_t *pr) +{ + script_resources_t *res = PR_Resources_Find (pr, "Script"); + rua_script_t *script = script_get (res, P_INT (pr, 0)); + + if (!script) + PR_RunError (pr, "invalid script handle"); + R_INT (pr) = script->script.no_quote_lines; + script->script.no_quote_lines = P_INT (pr, 1); +} + +static builtin_t builtins[] = { + {"Script_New", bi_Script_New, -1}, + {"Script_Delete", bi_Script_Delete, -1}, + {"Script_Start", bi_Script_Start, -1}, + {"Script_TokenAvailable", bi_Script_TokenAvailable, -1}, + {"Script_GetToken", bi_Script_GetToken, -1}, + {"Script_UngetToken", bi_Script_UngetToken, -1}, + {"Script_Error", bi_Script_Error, -1}, + {"Script_NoQuoteLines", bi_Script_NoQuoteLines, -1}, + {0} +}; + +void +RUA_Script_Init (progs_t *pr, int secure) +{ + script_resources_t *res = calloc (1, sizeof (script_resources_t)); + + PR_Resources_Register (pr, "Script", res, bi_script_clear); + + PR_RegisterBuiltins (pr, builtins); +} diff --git a/ruamoko/include/Makefile.am b/ruamoko/include/Makefile.am index 1df02b09a..bd5534864 100644 --- a/ruamoko/include/Makefile.am +++ b/ruamoko/include/Makefile.am @@ -3,7 +3,7 @@ pkgincludedir= $(includedir)/QF/ruamoko nobase_pkginclude_HEADERS= \ crudefile.h debug.h entities.h infokey.h math.h message.h nq_message.h \ physics.h qfile.h qfs.h qw_message.h qw_physics.h qw_sys.h server.h \ - sound.h string.h system.h \ + sound.h script.h string.h system.h \ \ draw.h key.h \ \ diff --git a/ruamoko/include/script.h b/ruamoko/include/script.h new file mode 100644 index 000000000..53b986639 --- /dev/null +++ b/ruamoko/include/script.h @@ -0,0 +1,16 @@ +#ifndef __ruamoko_script_h +#define __ruamoko_script_h + +typedef struct rua_script [] script_t; + +@extern script_t Script_New (void); +@extern void Script_Delete (script_t script); +// returns the token string +@extern string Script_Start (script_t script, string file, string data); +@extern integer Script_TokenAvailable (script_t script, integer crossline); +@extern integer Script_GetToken (script_t script, integer crossline); +@extern void Script_UngetToken (script_t script); +@extern string Script_Error (script_t script); +@extern integer Script_NoQuoteLines (script_t script); + +#endif//__ruamoko_script_h diff --git a/ruamoko/lib/Entity.r b/ruamoko/lib/Entity.r index 322d2bb01..15aaa563f 100644 --- a/ruamoko/lib/Entity.r +++ b/ruamoko/lib/Entity.r @@ -1,7 +1,25 @@ #include "Entity.h" +#include "debug.h" +#include "entities.h" +#include "plist.h" +#include "script.h" +#include "string.h" + +typedef void () void_function; + +integer PR_SetField (entity ent, string field, string value) = #0; +function PR_FindFunction (string func) = #0; + +@static void ParseEntities (string ent_data); + @implementation Entity +- (void) own +{ + own = 1; +} + - (id) init { return [self initWithEntity: spawn ()]; @@ -14,15 +32,117 @@ return self; } -- (void) free +- (void) dealloc { - remove (ent); - [super free]; + if (own) + remove (ent); + [super dealloc]; } - (entity) ent { - return self.ent; + return ent; +} + ++ (void) load +{ + //XXX EntityParseFunction (ParseEntities); +} + ++ createFromPlist:(plitem_t) dict +{ + local string classname; + local Class class; + local entity ent; + local integer count; + local string field, value; + local plitem_t keys; + local function func; + local Entity e; + + classname = PL_String (PL_ObjectForKey (dict, "classname")); + if (classname == "worldspawn") + ent = NIL; + else + ent = spawn (); + if ((class = obj_lookup_class (classname))) { + e = [[class alloc] initWithEntity:ent fromPlist:dict]; + } else { + e = [[Entity alloc] initWithEntity:ent]; + keys = PL_D_AllKeys (dict); + count = PL_A_NumObjects (keys); + while (count--) { + field = PL_String (PL_ObjectAtIndex (keys, count)); + value = PL_String (PL_ObjectForKey (dict, field)); + PR_SetField (ent, field, value); + } + PL_Free (keys); + if ((func = PR_FindFunction (classname))) { + //dprint ("calling " + classname + "\n"); + @self = ent; + func (); + } else { + //dprint ("no spawn function for " + classname + "\n"); + } + } + if (ent) + [e own]; } @end + +@static void ParseEntities (string ent_data) +{ + local script_t script; + local plitem_t plist, ent, key, value; + local string token; + local integer anglehack, i, count; + + script = Script_New (); + token = Script_Start (script, "ent data", ent_data); + if (Script_GetToken (script, 1)) { + if (token == "(") { + plist = PL_GetPropertyList (ent_data); + } else { + Script_UngetToken (script); + plist = PL_NewArray (); + while (Script_GetToken (script, 1)) { + if (token != "{") + return; // abort, bad ent data + ent = PL_NewDictionary (); + while (1) { + if (!Script_GetToken (script, 1)) + return; // abort, bad ent data + if (token == "}") + break; + anglehack = 0; + if (token == "angle") { + key = PL_NewString ("angles"); + anglehack = 1; + } else if (token == "light") { + key = PL_NewString ("light_lev"); + } else { + key = PL_NewString (token); + } + if (!Script_GetToken (script, 0)) + return; // abort, bad ent data + if (token == "}") + return; // abort, bad ent data + if (anglehack) + value = PL_NewString ("0 " + token + " 0"); + else + value = PL_NewString (token); + PL_D_AddObject (ent, key, value); + } + PL_A_AddObject (plist, ent); + } + } + //dprint (PL_WritePropertyList (plist)); + count = PL_A_NumObjects (plist); + for (i = 0; i < count; i++) { + ent = PL_ObjectAtIndex (plist, i); + [Entity createFromPlist:ent]; + } + } + Script_Delete (script); +} diff --git a/ruamoko/lib/List.r b/ruamoko/lib/List.r index 528e2dab0..6b32e5a2f 100644 --- a/ruamoko/lib/List.r +++ b/ruamoko/lib/List.r @@ -17,16 +17,16 @@ typedef struct list_bucket_s list_bucket_t; return self; } -- (void) free +- (void) dealloc { local list_bucket_t [] e, t = NIL; //FIXME t uninitialized for (e = head; e; e = t) { t = e.next; - [e.obj free]; + [e.obj release]; obj_free (e); } - [super free]; + [super dealloc]; } - (id) getItemAt: (integer) index diff --git a/ruamoko/lib/script.r b/ruamoko/lib/script.r new file mode 100644 index 000000000..4b88fb65e --- /dev/null +++ b/ruamoko/lib/script.r @@ -0,0 +1,11 @@ +#include "script.h" + +script_t Script_New (void) = #0; +void Script_Delete (script_t script) = #0; +// returns the token string +string Script_Start (script_t script, string file, string data) = #0; +integer Script_TokenAvailable (script_t script, integer crossline) = #0; +integer Script_GetToken (script_t script, integer crossline) = #0; +void Script_UngetToken (script_t script) = #0; +string Script_Error (script_t script) = #0; +integer Script_NoQuoteLines (script_t script) = #0; diff --git a/tools/qwaq/main.qc b/tools/qwaq/main.qc index 39635c20e..112e69faa 100644 --- a/tools/qwaq/main.qc +++ b/tools/qwaq/main.qc @@ -1,3 +1,53 @@ +string read_file (string filename) +{ + local QFile file; + local string data = NIL, d; + file = Qopen (filename, "rtz"); + if (!file) { + printf ("Can't open %s for reading." + " Probably a bad hardcoded filename:)\n"); + return NIL; + } + while ((d = Qgetline (file))) + data = data + d; + //FIXME can't read to a string, can't convert a pointer to a string ... + //Qread (file, data, 1023); + Qclose (file); + d = str_new (); + str_copy (d, data); + return d; +} + +void test_plist (void) +{ + local string data, l; + local plitem_t pl; + + data = read_file ("/home/bill/.quakeforge.dir"); + pl = PL_GetPropertyList ("{" + data + "}"); + l = PL_WritePropertyList (pl); + printf ("%s", data); + printf ("%s", l); + PL_Free (pl); + str_free (data); +} + +void test_script (void) +{ + local script_t script; + local string token; + local string data; + + data = read_file ("progs.src"); + script = Script_New (); + token = Script_Start (script, "progs.src", data); + while (Script_GetToken (script, 1)) { + printf ("%s\n", token); + } + Script_Delete (script); + str_free (data); +} + void () test_str = { local string a,b,c,d; @@ -47,5 +97,7 @@ integer (integer argc, string []argv) main = } else print ("did not find selector for `run:with:me:'\n"); test_str (); + test_script (); + test_plist (); return 0; };