diff --git a/OpenRA.Launcher.Gtk/bridge.c b/OpenRA.Launcher.Gtk/bridge.c index 3456f1b95f..fc62b877e8 100644 --- a/OpenRA.Launcher.Gtk/bridge.c +++ b/OpenRA.Launcher.Gtk/bridge.c @@ -7,11 +7,14 @@ */ #include #include +#include #include #include #include +#include "main.h" + #define JS_STR(str) JSStringCreateWithUTF8CString(str) #define JS_FUNC(ctx, callback) JSObjectMakeFunctionWithCallback(ctx, NULL, \ callback) @@ -105,8 +108,10 @@ JSValueRef js_launch_mod(JSContextRef ctx, JSObjectRef func, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef * exception) { - char * mod; + char * mod_key, * mod_list; size_t mod_size; + mod_t * mod; + int offset; JSValueRef return_value = JSValueMakeNull(ctx); if (!js_check_num_args(ctx, "launchMod", argc, 1, exception)) @@ -118,12 +123,55 @@ JSValueRef js_launch_mod(JSContextRef ctx, JSObjectRef func, return return_value; } - mod = js_get_cstr_from_val(ctx, argv[0], &mod_size); + mod_key = js_get_cstr_from_val(ctx, argv[0], &mod_size); - g_message("JS LaunchMod: %s", mod); + g_message("JS LaunchMod: %s", mod_key); - free(mod); + mod = get_mod(mod_key); + offset = strlen(mod_key); + mod_list = (char *)malloc(offset + 1); + strcpy(mod_list, mod_key); + + free(mod_key); + + while (strlen(mod->requires) > 0) + { + char r[MOD_requires_MAX_LEN], * comma; + strcpy(r, mod->requires); + if (NULL != (comma = strchr(r, ','))) + { + *comma = '\0'; + } + + mod = get_mod(r); + if (mod == NULL) + { + char exception_msg[64]; + sprintf(exception_msg, "The mod %s is missing, cannot launch.", r); + *exception = JSValueMakeString(ctx, JS_STR(exception_msg)); + free(mod_list); + return return_value; + } + + mod_list = (char *)realloc(mod_list, offset + strlen(r) + 1); + sprintf(mod_list + offset, ",%s", r); + offset += strlen(r) + 1; + } + + { + char * launch_args[] = { "mono", "OpenRA.Game.exe", NULL, NULL }; + char * game_mods_arg; + + game_mods_arg = (char *)malloc(strlen(mod_list) + strlen("Game.Mods=") + 1); + sprintf(game_mods_arg, "Game.Mods=%s", mod_list); + + launch_args[2] = game_mods_arg; + + g_spawn_async(NULL, launch_args, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, NULL); + free(game_mods_arg); + } + free(mod_list); return return_value; } diff --git a/OpenRA.Launcher.Gtk/main.c b/OpenRA.Launcher.Gtk/main.c index da05c3b7e0..20b020b4d4 100644 --- a/OpenRA.Launcher.Gtk/main.c +++ b/OpenRA.Launcher.Gtk/main.c @@ -11,6 +11,7 @@ #include #include +#include "main.h" #include "server.h" #include "bridge.h" #include "utility.h" @@ -21,6 +22,7 @@ GtkWindow * window; WebKitWebView * browser; GtkTreeStore * tree_store; GtkTreeView * tree; +GdkPixbuf * generic_mod_icon; gboolean window_delete(GtkWidget * widget, GdkEvent * event, gpointer user_data) @@ -30,36 +32,6 @@ gboolean window_delete(GtkWidget * widget, GdkEvent * event, return FALSE; } -enum -{ - ICON_COLUMN, - KEY_COLUMN, - NAME_COLUMN, - N_COLUMNS -}; - -#define MOD_key_MAX_LEN 16 -#define MOD_title_MAX_LEN 32 -#define MOD_version_MAX_LEN 16 -#define MOD_author_MAX_LEN 32 -#define MOD_description_MAX_LEN 128 -#define MOD_requires_MAX_LEN 32 - -#define MAX_NUM_MODS 64 - -typedef struct mod_t -{ - char key[MOD_key_MAX_LEN]; - char title[MOD_title_MAX_LEN]; - char version[MOD_version_MAX_LEN]; - char author[MOD_author_MAX_LEN]; - char description[MOD_description_MAX_LEN]; - char requires[MOD_requires_MAX_LEN]; - int standalone; -} mod_t; - - - static mod_t mods[MAX_NUM_MODS]; static int mod_count = 0; @@ -156,6 +128,7 @@ gboolean append_to_mod(GtkTreeModel * model, GtkTreePath * path, { gtk_tree_store_append(GTK_TREE_STORE(model), &new_iter, iter); gtk_tree_store_set(GTK_TREE_STORE(model), &new_iter, + ICON_COLUMN, generic_mod_icon, KEY_COLUMN, mod->key, NAME_COLUMN, mod->title, -1); @@ -170,30 +143,31 @@ void mod_metadata_callback(GPid pid, gint status, gpointer data) { int out_len, * out_fd = (int *)data; char * msg = NULL; - mod_t mod = mods[mod_count]; + mod_t * mod = mods + mod_count; GtkTreeIter iter, mod_iter; mod_count = (mod_count + 1) % MAX_NUM_MODS; - memset(&mod, 0, sizeof(mod_t)); + memset(mod, 0, sizeof(mod_t)); msg = util_get_output(*out_fd, &out_len); - process_lines(msg, out_len, mod_metadata_line, &mod); + process_lines(msg, out_len, mod_metadata_line, mod); free(msg); gtk_tree_model_get_iter_first(GTK_TREE_MODEL(tree_store), &mod_iter); - if (mod.standalone) + if (mod->standalone) { gtk_tree_store_append(tree_store, &iter, &mod_iter); gtk_tree_store_set(tree_store, &iter, - KEY_COLUMN, mod.key, - NAME_COLUMN, mod.title, - -1); + ICON_COLUMN, generic_mod_icon, + KEY_COLUMN, mod->key, + NAME_COLUMN, mod->title, + -1); } - else if (!strlen(mod.requires)) + else if (!strlen(mod->requires)) { GtkTreeIter broken_mods_iter; if (!gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(tree_store), @@ -202,13 +176,14 @@ void mod_metadata_callback(GPid pid, gint status, gpointer data) gtk_tree_store_append(tree_store, &broken_mods_iter, NULL); } gtk_tree_store_set(tree_store, &broken_mods_iter, - KEY_COLUMN, mod.key, - NAME_COLUMN, mod.title, + ICON_COLUMN, generic_mod_icon, + KEY_COLUMN, mod->key, + NAME_COLUMN, mod->title, -1); } else { - gtk_tree_model_foreach(GTK_TREE_MODEL(tree_store), append_to_mod, &mod); + gtk_tree_model_foreach(GTK_TREE_MODEL(tree_store), append_to_mod, mod); } close(*out_fd); @@ -353,9 +328,9 @@ void make_tree_view(void) NAME_COLUMN, "MODS", -1); - tree = GTK_TREE_VIEW(gtk_tree_view_new_with_model(GTK_TREE_MODEL(tree_store))); + tree = GTK_TREE_VIEW(gtk_tree_view_new_with_model( + GTK_TREE_MODEL(tree_store))); g_object_set(tree, "headers-visible", FALSE, NULL); - g_object_set(tree, "level-indentation", 1, NULL); g_signal_connect(tree, "cursor-changed", G_CALLBACK(tree_view_selection_changed), NULL); @@ -382,8 +357,8 @@ void make_tree_view(void) int main(int argc, char ** argv) { - GtkWidget * hbox; + server_init(WEBSERVER_PORT); gtk_init(&argc, &argv); @@ -396,6 +371,8 @@ int main(int argc, char ** argv) g_signal_connect(browser, "window-object-cleared", G_CALLBACK(bind_js_bridge), 0); + generic_mod_icon = gdk_pixbuf_new_from_file_at_size("soviet-logo.png", + 16, 16, NULL); make_tree_view(); diff --git a/OpenRA.Launcher.Gtk/main.h b/OpenRA.Launcher.Gtk/main.h new file mode 100644 index 0000000000..067a8153c0 --- /dev/null +++ b/OpenRA.Launcher.Gtk/main.h @@ -0,0 +1,41 @@ +/* + * Copyright 2007-2010 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation. For more information, + * see LICENSE. + */ +#ifndef OPENRA_MAIN_H +#define OPENRA_MAIN_H + +enum +{ + ICON_COLUMN, + KEY_COLUMN, + NAME_COLUMN, + N_COLUMNS +}; + +#define MOD_key_MAX_LEN 16 +#define MOD_title_MAX_LEN 32 +#define MOD_version_MAX_LEN 16 +#define MOD_author_MAX_LEN 32 +#define MOD_description_MAX_LEN 128 +#define MOD_requires_MAX_LEN 32 + +#define MAX_NUM_MODS 64 + +typedef struct mod_t +{ + char key[MOD_key_MAX_LEN]; + char title[MOD_title_MAX_LEN]; + char version[MOD_version_MAX_LEN]; + char author[MOD_author_MAX_LEN]; + char description[MOD_description_MAX_LEN]; + char requires[MOD_requires_MAX_LEN]; + int standalone; +} mod_t; + +mod_t * get_mod(char const * key); + +#endif