This repository has been archived on 2020-04-11. You can view files and clone it, but cannot push or open issues or pull requests.
gnoemoe/gnoemoe/gm-scripts.c

918 lines
21 KiB
C

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <glib.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <gtk/gtk.h>
#include <ruby.h>
#include <libgnomevfs/gnome-vfs-mime-utils.h>
#include <libgnomevfs/gnome-vfs.h>
#include <sys/stat.h>
#include <sys/types.h>
#undef PACKAGE_BUGREPORT
#undef PACKAGE_NAME
#undef PACKAGE_STRING
#undef PACKAGE_TARNAME
#undef PACKAGE_VERSION
#include "gm-support.h"
#include "gm-debug.h"
#include "gm-world.h"
#include "gm-app.h"
#include "gm-scripts.h"
#include "gm-world.h"
#include "gm-string.h"
#define GM_SCRIPTS_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), \
GM_TYPE_SCRIPTS, GmScriptsPrivate))
#define RB_CALLBACK(x) (VALUE (*)())(x)
#define GM_SCRIPTS_GLOBAL PACKAGE_DATA_DIR "/" PACKAGE "/scripts"
static VALUE rb_world_class, rb_client_class, rb_scripts_class;
VALUE script_world_name(VALUE self);
VALUE gm_scripts_rb_world_new(GmWorld *world);
VALUE gm_scripts_rb_scripts_new(GmScripts *scripts);
void gm_scripts_rb_world_class_init();
void gm_scripts_rb_client_class_init();
void gm_scripts_rb_scripts_class_init();
void gm_scripts_unload(GmScripts *scripts);
void gm_scripts_rb_init();
struct _GmScriptsPrivate {
GList *files;
GmScript *loading;
GList *monitors;
};
/* Signals */
enum {
SCRIPT_ADDED,
SCRIPT_CHANGED,
SCRIPT_REMOVED,
RELOAD,
MESSAGE,
ERROR,
RUN,
NUM_SIGNALS
};
static guint gm_scripts_signals[NUM_SIGNALS] = {0};
G_DEFINE_TYPE(GmScripts, gm_scripts, G_TYPE_OBJECT)
static void
gm_scripts_finalize(GObject *object) {
GmScripts *scripts = GM_SCRIPTS(object);
GList *monitors;
gm_scripts_unload(scripts);
for (monitors = scripts->priv->monitors; monitors;
monitors = monitors->next) {
gnome_vfs_monitor_cancel((GnomeVFSMonitorHandle *)(monitors->data));
}
g_list_free(scripts->priv->monitors);
scripts->priv->monitors = NULL;
G_OBJECT_CLASS(gm_scripts_parent_class)->finalize(object);
}
static void
gm_scripts_class_init(GmScriptsClass *klass) {
GObjectClass *object_class = G_OBJECT_CLASS(klass);
object_class->finalize = gm_scripts_finalize;
gm_scripts_signals[SCRIPT_ADDED] =
g_signal_new("script_added",
G_OBJECT_CLASS_TYPE(object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(GmScriptsClass, script_added),
NULL, NULL,
g_cclosure_marshal_VOID__POINTER,
G_TYPE_NONE,
1,
G_TYPE_POINTER);
gm_scripts_signals[SCRIPT_CHANGED] =
g_signal_new("script_changed",
G_OBJECT_CLASS_TYPE(object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(GmScriptsClass, script_changed),
NULL, NULL,
g_cclosure_marshal_VOID__POINTER,
G_TYPE_NONE,
1,
G_TYPE_POINTER);
gm_scripts_signals[SCRIPT_REMOVED] =
g_signal_new("script_removed",
G_OBJECT_CLASS_TYPE(object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(GmScriptsClass, script_removed),
NULL, NULL,
g_cclosure_marshal_VOID__POINTER,
G_TYPE_NONE,
1,
G_TYPE_POINTER);
gm_scripts_signals[RELOAD] =
g_signal_new("reload",
G_OBJECT_CLASS_TYPE(object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(GmScriptsClass, reload),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE,
0);
gm_scripts_signals[MESSAGE] =
g_signal_new("message",
G_OBJECT_CLASS_TYPE(object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(GmScriptsClass, message),
NULL, NULL,
g_cclosure_marshal_VOID__STRING,
G_TYPE_NONE,
1,
G_TYPE_STRING);
gm_scripts_signals[ERROR] =
g_signal_new("error",
G_OBJECT_CLASS_TYPE(object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(GmScriptsClass, error),
NULL, NULL,
g_cclosure_marshal_VOID__STRING,
G_TYPE_NONE,
1,
G_TYPE_STRING);
gm_scripts_signals[RUN] =
g_signal_new("run",
G_OBJECT_CLASS_TYPE(object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET(GmScriptsClass, run),
NULL, NULL,
g_cclosure_marshal_VOID__STRING,
G_TYPE_NONE,
1,
G_TYPE_STRING);
g_type_class_add_private(object_class, sizeof(GmScriptsPrivate));
gm_scripts_rb_init();
}
void
gm_scripts_rb_init(GmScriptsClass *klass) {
ruby_init();
gm_scripts_rb_world_class_init();
gm_scripts_rb_client_class_init();
gm_scripts_rb_scripts_class_init();
}
static void
gm_scripts_init(GmScripts *scripts) {
scripts->priv = GM_SCRIPTS_GET_PRIVATE(scripts);
scripts->priv->monitors = NULL;
scripts->priv->files = NULL;
}
GmScripts *
gm_scripts_new() {
GmScripts *scripts = GM_SCRIPTS(g_object_new(GM_TYPE_SCRIPTS, NULL));
return scripts;
}
void gm_scripts_monitor_cb (GnomeVFSMonitorHandle *handle,
const gchar *monitor_uri, const gchar *info_uri,
GnomeVFSMonitorEventType event_type,
GmScripts *scripts) {
gchar *filename = gnome_vfs_get_local_path_from_uri(info_uri);
switch (event_type) {
case GNOME_VFS_MONITOR_EVENT_CHANGED:
gm_scripts_reload_file(scripts, filename);
break;
case GNOME_VFS_MONITOR_EVENT_DELETED:
gm_scripts_remove_file(scripts, filename);
break;
case GNOME_VFS_MONITOR_EVENT_CREATED:
gm_scripts_add_file(scripts, filename);
break;
default:
break;
}
g_free(filename);
}
void
gm_script_function_destroy(GmScriptFunction *fi) {
g_free(fi->name);
g_free(fi->fname);
g_free(fi->description);
g_free(fi);
}
void
gm_script_destroy_functions(GmScript *script) {
GList *functions;
for (functions = script->functions; functions;
functions = functions->next) {
gm_script_function_destroy((GmScriptFunction *)(functions->data));
}
g_list_free(script->functions);
script->functions = NULL;
}
void
gm_script_destroy(GmScript *script) {
gm_script_destroy_functions(script);
g_free(script->filename);
g_free(script);
}
void
gm_scripts_unload(GmScripts *scripts) {
GList *files;
for (files = scripts->priv->files; files; files = files->next) {
gm_script_destroy((GmScript *)(files->data));
}
g_list_free(scripts->priv->files);
scripts->priv->files = NULL;
}
GmScriptFunction *
gm_scripts_find(GmScripts *scripts, gchar *name) {
GList *files;
GList *functions;
GmScriptFunction *func;
GmScript *script;
for (files = scripts->priv->files; files; files = files->next) {
script = (GmScript *)(files->data);
for (functions = script->functions; functions;
functions = functions->next) {
func = (GmScriptFunction *)(functions->data);
if (strcasecmp(func->name, name) == 0) {
return func;
}
}
}
return NULL;
}
gboolean
gm_scripts_add(GmScripts *scripts, gchar *name, gchar *fname,
gchar *description) {
GmScriptFunction *func;
if (gm_scripts_find(scripts, name) == NULL) {
func = g_new(GmScriptFunction, 1);
func->script = scripts->priv->loading;
func->name = g_strdup(name);
func->fname = g_strdup(fname);;
func->description = g_strdup(description);
scripts->priv->loading->functions =
g_list_append(scripts->priv->loading->functions, func);
return TRUE;
} else {
return FALSE;
}
}
VALUE
gm_scripts_rb_register_functions_wrap(VALUE arg) {
return rb_eval_string("register_functions");
}
void
gm_scripts_rb_script_define_world(VALUE *world) {
rb_define_variable("$world", world);
}
void
gm_scripts_rb_error(GmScripts *scripts) {
int c;
VALUE lasterr;
char *err;
gchar *msg;
VALUE ary;
if(!NIL_P(ruby_errinfo)) {
lasterr = rb_gv_get("$!");
err = RSTRING(rb_obj_as_string(lasterr))->ptr;
gm_debug_msg(DEBUG_DEFAULT, "GmScripts.Error: Error while executing Ruby code: %s",
err);
msg = g_strdup_printf(_("Error in execution: %s"), err);
g_signal_emit(scripts, gm_scripts_signals[MESSAGE], 0, msg);
g_free(msg);
ary = rb_funcall(ruby_errinfo, rb_intern("backtrace"), 0);
gm_debug_msg(DEBUG_DEFAULT, "GmScripts.Error: Ruby backtrace:");
g_signal_emit(scripts, gm_scripts_signals[ERROR], 0,
_("Ruby backtrace:"));
for (c = 0; c < RARRAY(ary)->len; c++) {
gm_debug_msg(DEBUG_DEFAULT, "GmScripts.Error: \tfrom %s",
RSTRING(RARRAY(ary)->ptr[c])->ptr);
msg = g_strdup_printf(_("\tfrom %s"),
RSTRING(RARRAY(ary)->ptr[c])->ptr);
g_signal_emit(scripts, gm_scripts_signals[ERROR], 0, msg);
g_free(msg);
}
}
}
int
gm_scripts_rb_do(GmScripts *scripts, VALUE (*body)(), VALUE arg) {
int status;
rb_protect(body, arg, &status);
if (status != 0) {
gm_scripts_rb_error(scripts);
ruby_cleanup(status);
return 0;
}
return 1;
}
VALUE
gm_scripts_run_function(GmScriptInfo *arg) {
VALUE ret;
gchar *argstr;
gchar *func_all;
if (arg->argstr) {
argstr = gm_string_escape(arg->argstr);
func_all = g_strconcat(arg->name, "(\"", argstr, "\")", NULL);
g_free(argstr);
} else {
func_all = g_strconcat(arg->name, "()", NULL);
}
ret = rb_eval_string(func_all);
g_free(func_all);
return ret;
}
gboolean
gm_scripts_run(GmScripts *scripts, GmWorld *world, gchar *name, gchar *argstr) {
VALUE rbWorld, rbClient;
gchar *msg;
GmScriptInfo *info;
GmScriptFunction *f = gm_scripts_find(scripts, name);
if (!f) {
return FALSE;
}
info = g_new0(GmScriptInfo, 1);
info->name = g_strdup(f->fname);
if (argstr) {
info->argstr = g_strdup(argstr);
msg = g_strdup_printf(_("Run script '%s' from '%s' (%s)"), f->fname,
f->script->filename, argstr);
} else {
info->argstr = NULL;
msg = g_strdup_printf(_("Run script '%s' from '%s' ()"), f->fname,
f->script->filename);
}
g_signal_emit(scripts, gm_scripts_signals[RUN], 0, msg);
g_free(msg);
gm_scripts_rb_do(scripts, RB_CALLBACK(rb_load_file),
(VALUE)(f->script->filename));
ruby_exec();
rbWorld = gm_scripts_rb_world_new(world);
rb_define_variable("$world", &rbWorld);
rbClient = rb_class_new_instance(0, NULL, rb_client_class);
rb_define_variable("$client", &rbClient);
gm_scripts_rb_do(scripts, RB_CALLBACK(gm_scripts_run_function),
(VALUE)info);
g_free(info->name);
g_free(info->argstr);
g_free(info);
return TRUE;
}
VALUE
gm_scripts_rb_register_func_old(int argc, VALUE *argv) {
gm_debug_msg(DEBUG_DEFAULT, "GmScripts.RegisterFunc: This is the deprecated way to "
"register functions is does no longer work. Use $scripts.register "
"instead.");
return Qfalse;
}
void
gm_scripts_register_functions(GmScripts *scripts) {
gchar *msg;
VALUE rbScripts;
gm_debug_msg(DEBUG_DEFAULT, "GmScripts.RegisterFunctions: registering functions in %s",
scripts->priv->loading->filename);
msg = g_strdup_printf(_("Registering functions from '%s'"),
scripts->priv->loading->filename);
g_signal_emit(scripts, gm_scripts_signals[MESSAGE], 0, msg);
g_free(msg);
// Okay, I'm desperate... define an empty register_functions method so
// that the previous when gets cleared ... :(
rb_eval_string("def register_functions() end");
if (!gm_scripts_rb_do(scripts, RB_CALLBACK(rb_load_file),
(VALUE) scripts->priv->loading->filename)) {
return;
}
ruby_exec();
rbScripts = gm_scripts_rb_scripts_new(scripts);
rb_define_variable("$scripts", &rbScripts);
rb_define_global_function("register_func", &gm_scripts_rb_register_func_old,
-1);
gm_scripts_rb_do(scripts,
RB_CALLBACK(gm_scripts_rb_register_functions_wrap), 0);
}
void
gm_scripts_remove_file(GmScripts *scripts, const gchar *uri) {
GList *f, *l;
GmScript *script;
l = g_list_copy(scripts->priv->files);
for (f = l; f; f = f->next) {
script = (GmScript *)(f->data);
if (strcmp(script->filename, uri) == 0) {
scripts->priv->files = g_list_remove(scripts->priv->files, script);
gm_debug_msg(DEBUG_DEFAULT, "GmScripts.RemoveFile: Removing scripts from `%s'",
script->filename);
g_signal_emit(scripts, gm_scripts_signals[SCRIPT_REMOVED], 0,
script);
gm_script_destroy(script);
}
}
g_list_free(l);
}
gboolean
gm_scripts_add_file(GmScripts *scripts, const gchar *uri) {
GList *f;
GmScript *script;
gchar *msg;
gchar *ext;
// Only .rb files
ext = strrchr(uri, '.');
if (ext == NULL || strncmp(ext, ".rb", 2) != 0) {
msg = g_strdup_printf(_("File `%s' is not a valid ruby file"), uri);
gm_debug_msg(DEBUG_DEFAULT, "GmScripts.AddFile: %s", msg);
g_signal_emit(scripts, gm_scripts_signals[ERROR], 0, msg);
g_free(msg);
return FALSE;
}
for (f = scripts->priv->files; f; f = f->next) {
script = (GmScript *)(f->data);
if (strcmp(script->filename, uri) == 0) {
msg = g_strdup_printf(_("File `%s' already loaded"), uri);
gm_debug_msg(DEBUG_DEFAULT, "GmScripts.AddFile: %s", msg);
g_signal_emit(scripts, gm_scripts_signals[ERROR], 0, msg);
g_free(msg);
return FALSE;
}
}
msg = g_strdup_printf(_("File `%s' added"), uri);
gm_debug_msg(DEBUG_DEFAULT, "GmScripts.AddFile: %s", msg);
g_free(msg);
script = g_new0(GmScript, 1);
script->filename = g_strdup(uri);
if (strncmp(uri, GM_SCRIPTS_GLOBAL,
strlen(GM_SCRIPTS_GLOBAL)) == 0) {
script->type = GM_SCRIPT_TYPE_SHARE;
} else {
script->type = GM_SCRIPT_TYPE_USER;
}
scripts->priv->files = g_list_append(scripts->priv->files, script);
scripts->priv->loading = script;
gm_scripts_register_functions(scripts);
g_signal_emit(scripts, gm_scripts_signals[SCRIPT_ADDED], 0, script);
return TRUE;
}
void
gm_scripts_reload_file(GmScripts *scripts, const gchar *uri) {
GList *files;
GmScript *script;
for (files = scripts->priv->files; files; files = files->next) {
script = (GmScript *)(files->data);
if (strcmp(script->filename, uri) == 0) {
// Remove all functions and reregister the file
scripts->priv->loading = script;
gm_script_destroy_functions(script);
gm_scripts_register_functions(scripts);
g_signal_emit(scripts, gm_scripts_signals[SCRIPT_CHANGED], 0,
script);
return;
}
}
// If the script does not yet exist, add it
gm_scripts_add_file(scripts, uri);
}
void
gm_scripts_load_dir(GmScripts *scripts, gchar *dirname) {
gchar *filename;
gchar *file;
GDir *d;
GnomeVFSMonitorHandle *handle;
if (g_file_test(dirname, G_FILE_TEST_EXISTS) &&
g_file_test(dirname, G_FILE_TEST_IS_DIR)) {
if ((d = g_dir_open(dirname, 0, NULL))) {
while ((file = (gchar *)g_dir_read_name(d))) {
filename = g_strconcat(dirname, "/", file, NULL);
gm_scripts_add_file(scripts, filename);
g_free(filename);
}
}
gnome_vfs_monitor_add(&handle, dirname, GNOME_VFS_MONITOR_DIRECTORY,
(GnomeVFSMonitorCallback)gm_scripts_monitor_cb, scripts);
scripts->priv->monitors = g_list_append(scripts->priv->monitors,
handle);
}
}
void
gm_scripts_load(GmScripts *scripts) {
gchar *path;
if (scripts->priv->files) {
g_signal_emit(scripts, gm_scripts_signals[RELOAD], 0);
gm_scripts_unload(scripts);
}
path = g_strconcat(gm_app_path(gm_app_instance()), "/scripts", NULL);
// Make user dir if it doesn't exist
if (!g_file_test(path, G_FILE_TEST_EXISTS)) {
mkdir(path, 0750);
}
gm_scripts_load_dir(scripts, path);
gm_scripts_load_dir(scripts, GM_SCRIPTS_GLOBAL);
g_free(path);
}
GList *
gm_scripts_scripts(GmScripts *scripts) {
return scripts->priv->files;
}
// Ruby class functions
VALUE
gm_scripts_rb_world_new(GmWorld *world) {
VALUE tdata = Data_Wrap_Struct(rb_world_class, 0, 0, world);
return tdata;
}
VALUE
gm_scripts_rb_scripts_new(GmScripts *scripts) {
VALUE tdata = Data_Wrap_Struct(rb_scripts_class, 0, 0, scripts);
return tdata;
}
// Ruby world class functions
static VALUE
gm_scripts_rb_world_name(VALUE self) {
GmWorld *world;
Data_Get_Struct(self, GmWorld, world);
return rb_str_new2(gm_options_get(gm_world_options(world), "name"));
}
static VALUE
gm_scripts_rb_world_host(VALUE self) {
GmWorld *world;
Data_Get_Struct(self, GmWorld, world);
return rb_str_new2(gm_options_get(gm_world_options(world), "host"));
}
static VALUE
gm_scripts_rb_world_port(VALUE self) {
GmWorld *world;
Data_Get_Struct(self, GmWorld, world);
return rb_str_new2(gm_options_get(gm_world_options(world), "port"));
}
static VALUE
gm_scripts_rb_world_writeln(VALUE self, VALUE str) {
GmWorld *world;
gchar *strVal;
Data_Get_Struct(self, GmWorld, world);
strVal = rb_string_value_cstr(&str);
gm_world_writeln(world, strVal);
return Qnil;
}
static VALUE
gm_scripts_rb_world_status(VALUE self, VALUE str) {
GmWorld *world;
gchar *strVal;
Data_Get_Struct(self, GmWorld, world);
strVal = rb_string_value_cstr(&str);
gm_world_status(world, strVal);
return Qnil;
}
static VALUE
gm_scripts_rb_world_sendln(VALUE self, VALUE str) {
GmWorld *world;
gchar *strVal;
Data_Get_Struct(self, GmWorld, world);
strVal = rb_string_value_cstr(&str);
gm_world_sendln(world, strVal);
return Qnil;
}
static VALUE
gm_scripts_rb_world_input(VALUE self, VALUE str) {
GmWorld *world;
gchar *strVal;
Data_Get_Struct(self, GmWorld, world);
strVal = rb_string_value_cstr(&str);
gm_world_process_input(world, strVal);
return Qnil;
}
static VALUE
gm_scripts_rb_world_loaded(VALUE self) {
GmWorld *world;
Data_Get_Struct(self, GmWorld, world);
if (gm_world_loaded(world)) {
return Qtrue;
} else {
return Qfalse;
}
}
static VALUE
gm_scripts_rb_world_connected(VALUE self) {
GmWorld *world;
Data_Get_Struct(self, GmWorld, world);
if (gm_world_state(world) == GM_NET_STATE_CONNECTED) {
return Qtrue;
} else {
return Qfalse;
}
}
static VALUE
gm_scripts_rb_world_quit(VALUE self) {
GmWorld *world;
Data_Get_Struct(self, GmWorld, world);
gm_world_unload(world);
return Qnil;
}
static VALUE
gm_scripts_rb_world_connect(int argc, VALUE *argv, VALUE self) {
GmWorld *world;
const gchar *strHost, *strPort;
Data_Get_Struct(self, GmWorld, world);
if (argc == 0) {
strHost = gm_options_get(gm_world_options(world), "host");
} else {
strHost = rb_string_value_cstr(&(argv[0]));
}
if (argc == 0 || argc == 1) {
strPort = gm_options_get(gm_world_options(world), "port");
} else {
strPort = rb_string_value_cstr(&(argv[1]));
}
gm_world_connect_to(world, (gchar *)strHost, (gchar *)strPort);
return Qnil;
}
static VALUE
gm_scripts_rb_world_disconnect(VALUE self) {
GmWorld *world;
Data_Get_Struct(self, GmWorld, world);
gm_world_disconnect(world);
return Qnil;
}
// Ruby client class functions
static VALUE
gm_scripts_rb_client_version(VALUE self) {
return rb_str_new2(VERSION);
}
static VALUE
gm_scripts_rb_client_worlds(VALUE self) {
GList *world;
VALUE rb_array = rb_ary_new();
VALUE rb_world;
for (world = gm_app_worlds(gm_app_instance()); world; world = world->next) {
rb_world = gm_scripts_rb_world_new((GmWorld *)(world->data));
rb_ary_push(rb_array, rb_world);
}
return rb_array;
}
static VALUE
gm_scripts_rb_client_open(VALUE self, VALUE str) {
GmWorld *world;
gchar *strVal;
strVal = rb_string_value_cstr(&str);
world = gm_app_world_by_name(gm_app_instance(), strVal);
if (world == NULL) {
return Qfalse;
} else {
gm_world_load(world);
return Qtrue;
}
}
// Ruby scripts class functions
VALUE
gm_scripts_rb_scripts_register(int argc, VALUE *argv, VALUE self) {
char *name, *fname = NULL, *description = NULL;
gchar *msg;
GmScripts *scripts;
Data_Get_Struct(self, GmScripts, scripts);
if (argc > 1) {
name = rb_string_value_cstr(&argv[0]);
description = rb_string_value_cstr(&argv[1]);
if (argc == 2) {
fname = name;
} else {
fname = rb_string_value_cstr(&argv[2]);
}
if (gm_scripts_add(scripts, name, fname, description)) {
msg = g_strdup_printf(_("Register function '%s' from '%s'"), name,
scripts->priv->loading->filename);
gm_debug_msg(DEBUG_DEFAULT, "GmScripts.RbScriptsRegister: Adding script function "
"%s from %s", name, scripts->priv->loading->filename);
g_signal_emit(scripts, gm_scripts_signals[MESSAGE], 0, msg);
g_free(msg);
return Qtrue;
} else {
msg = g_strdup_printf(_("Script '%s' is already defined"), name);
gm_debug_msg(DEBUG_DEFAULT, "GmScripts.RbScriptsRegister: Script function %s "
"already defined!", name);
g_signal_emit(scripts, gm_scripts_signals[ERROR], 0, msg);
g_free(msg);
return Qfalse;
}
} else {
return Qfalse;
}
}
// Ruby class initializations
void
gm_scripts_rb_world_class_init() {
rb_world_class = rb_define_class("World", rb_cObject);
rb_define_method(rb_world_class, "name", gm_scripts_rb_world_name, 0);
rb_define_method(rb_world_class, "host", gm_scripts_rb_world_host, 0);
rb_define_method(rb_world_class, "port", gm_scripts_rb_world_port, 0);
rb_define_method(rb_world_class, "writeln", gm_scripts_rb_world_writeln, 1);
rb_define_method(rb_world_class, "println", gm_scripts_rb_world_writeln, 1);
rb_define_method(rb_world_class, "status", gm_scripts_rb_world_status, 1);
rb_define_method(rb_world_class, "sendln", gm_scripts_rb_world_sendln, 1);
rb_define_method(rb_world_class, "input", gm_scripts_rb_world_input, 1);
rb_define_method(rb_world_class, "quit", gm_scripts_rb_world_quit, 0);
rb_define_method(rb_world_class, "connect",
gm_scripts_rb_world_connect, -1);
rb_define_method(rb_world_class, "disconnect",
gm_scripts_rb_world_disconnect, 0);
rb_define_method(rb_world_class, "loaded?", gm_scripts_rb_world_loaded, 0);
rb_define_method(rb_world_class, "connected?",
gm_scripts_rb_world_connected, 0);
}
void
gm_scripts_rb_client_class_init() {
rb_client_class = rb_define_class("Client", rb_cObject);
rb_define_method(rb_client_class, "version",
gm_scripts_rb_client_version, 0);
rb_define_method(rb_client_class, "worlds",
gm_scripts_rb_client_worlds, 0);
rb_define_method(rb_client_class, "open", gm_scripts_rb_client_open, 1);
}
void
gm_scripts_rb_scripts_class_init() {
rb_scripts_class = rb_define_class("Scripts", rb_cObject);
rb_define_method(rb_scripts_class, "register",
gm_scripts_rb_scripts_register, -1);
}