Reverted packaging changes from launchers.

This commit is contained in:
Matthew Bowra-Dean
2011-01-27 14:46:15 +13:00
committed by Paul Chote
parent a81c865620
commit 4eaf97f90e
32 changed files with 61 additions and 3023 deletions

View File

@@ -4,16 +4,12 @@ DEFINE = DEBUG;TRACE
COMMON_LIBS = System.dll System.Core.dll System.Drawing.dll System.Xml.dll thirdparty/ICSharpCode.SharpZipLib.dll
PHONY = core tools package all mods clean distclean
CC = gcc
CFLAGS = -O2 -Wall
CFLAGS32 = $(CFLAGS) -m32
.SUFFIXES:
core: game renderers mod_ra mod_cnc
tools: editor ralint seqed filex tsbuild utility
package: fixheader core editor utility winlaunch gtklaunch gtklaunch32
package: fixheader core editor utility
mods: mod_ra mod_cnc
all: core tools winlaunch
all: core tools
clean:
@-rm *.exe *.dll *.mdb mods/**/*.dll mods/**/*.mdb *.resources
distclean: clean
@@ -166,28 +162,6 @@ utility_LIBS = $(COMMON_LIBS) $(utility_DEPS) thirdparty/ICSharpCode.Shar
PROGRAMS += utility
utility: $(utility_TARGET)
# Windows launcher
winlaunch_SRCS = $(shell find OpenRA.Launcher/ -iname '*.cs')
winlaunch_TARGET = OpenRA.Launcher.exe
winlaunch_KIND = winexe
winlaunch_LIBS = $(COMMON_LIBS) System.Windows.Forms.dll
winlaunch_EXTRA = -resource:OpenRA.Launcher.Launcher.resources
PROGRAMS += winlaunch
OpenRA.Launcher.Launcher.resources:
resgen2 OpenRA.Launcher/Launcher.resx OpenRA.Launcher.Launcher.resources 1> /dev/null
winlaunch: OpenRA.Launcher.Launcher.resources $(winlaunch_TARGET)
gtklaunch_HEADERS = $(shell find OpenRA.Launcher.Gtk/ -iname '*.h')
gtklaunch_SRCS = $(shell find OpenRA.Launcher.Gtk/ -iname '*.c')
gtklaunch: $(gtklaunch_HEADERS) $(gtklaunch_SRCS)
@echo CC launcher
@$(CC) $(CFLAGS) $(shell pkg-config --cflags --libs gtk+-2.0 webkit-1.0) -I/usr/include/ -lgcrypt -o gtklaunch $(gtklaunch_SRCS) /usr/lib/libmicrohttpd.a
gtklaunch32: $(gtklaunch_HEADERS) $(gtklaunch_SRCS)
@echo CC launcher32
@$(CC) $(CFLAGS32) $(shell pkg-config --cflags --libs gtk+-2.0 webkit-1.0) -I/usr/include/ -lgcrypt -o gtklaunch32 $(gtklaunch_SRCS) /usr/lib/libmicrohttpd.a
.PHONY: $(PHONY) $(PROGRAMS)
#
@@ -220,9 +194,9 @@ BIN_INSTALL_DIR = $(DESTDIR)$(bindir)
INSTALL_DIR = $(DESTDIR)$(datadir)/openra
INSTALL = install
INSTALL_PROGRAM = $(INSTALL)
CORE = fileformats rcg rgl rnull game editor utility winlaunch
CORE = fileformats rcg rgl rnull game editor utility
install: all gtklaunch
install: all
@-echo "Installing OpenRA to $(INSTALL_DIR)"
@$(INSTALL_PROGRAM) -d $(INSTALL_DIR)
@$(INSTALL_PROGRAM) $(foreach prog,$(CORE),$($(prog)_TARGET)) $(INSTALL_DIR)
@@ -254,8 +228,12 @@ install: all gtklaunch
@cp --parents -r thirdparty/Tao $(INSTALL_DIR)
@$(INSTALL_PROGRAM) thirdparty/ICSharpCode.SharpZipLib.dll $(INSTALL_DIR)
@echo "#!/bin/sh" > openra
@echo "cd "$(datadir)"/openra" >> openra
@echo "mono "$(datadir)"/openra/OpenRA.Game.exe SupportDir=~/.openra \"$$""@\"" >> openra
@$(INSTALL_PROGRAM) -d $(BIN_INSTALL_DIR)
@$(INSTALL_PROGRAM) -T gtklaunch $(BIN_INSTALL_DIR)/openra
@$(INSTALL_PROGRAM) -m +rx openra $(BIN_INSTALL_DIR)
uninstall:
@-rm -r $(INSTALL_DIR)

View File

@@ -1,794 +0,0 @@
/*
* 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.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <webkit/webkit.h>
#include <JavaScriptCore/JavaScript.h>
#include <glib.h>
#include "main.h"
#include "utility.h"
#define JS_STR(str) JSStringCreateWithUTF8CString(str)
#define JS_FUNC(ctx, callback) JSObjectMakeFunctionWithCallback(ctx, NULL, \
callback)
#define JS_TRUE JSValueMakeBoolean(ctx, TRUE)
#define JS_FALSE JSValueMakeBoolean(ctx, FALSE)
#define JS_NULL JSValueMakeNull(ctx)
GString * sanitize_path(gchar const * path)
{
gchar * basename = g_path_get_basename(path);
gchar * dirname = g_path_get_dirname(path);
gchar ** frags = g_strsplit(dirname, "/", -1);
gint offset = 0;
GString * new_path = g_string_new(NULL);
while (*(frags + offset))
{
if ((strcmp(*(frags + offset), "..") == 0) || (strcmp(*(frags + offset), ".") == 0))
{
offset++;
continue;
}
g_string_append(new_path, *(frags + offset));
g_string_append_c(new_path, G_DIR_SEPARATOR);
offset++;
}
g_string_append(new_path, basename);
g_free(basename);
g_free(dirname);
g_strfreev(frags);
return new_path;
}
int js_check_num_args(JSContextRef ctx, gchar const * func_name, int argc, int num_expected, JSValueRef * exception)
{
GString * buf;
if (argc < num_expected)
{
buf = g_string_new(NULL);
g_string_printf(buf, "%s: Not enough args, expected %d got %d", func_name, num_expected, argc);
*exception = JSValueMakeString(ctx, JS_STR(buf->str));
g_string_free(buf, TRUE);
return 0;
}
return 1;
}
GString * js_get_cstr_from_val(JSContextRef ctx, JSValueRef val)
{
gchar * buf;
GString * ret;
size_t len;
JSStringRef str;
if (!JSValueIsString(ctx, val))
return NULL;
str = JSValueToStringCopy(ctx, val, NULL);
len = JSStringGetMaximumUTF8CStringSize(str);
buf = (gchar *)g_malloc(len);
ret = g_string_sized_new(JSStringGetUTF8CString(str, buf, len));
g_string_assign(ret, buf);
g_free(buf);
return ret;
}
JSValueRef js_log(JSContextRef ctx, JSObjectRef func, JSObjectRef this,
size_t argc, const JSValueRef argv[], JSValueRef * exception)
{
if (!js_check_num_args(ctx, "log", argc, 1, exception))
return JS_NULL;
GString * buffer;
buffer = js_get_cstr_from_val(ctx, argv[0]);
if (!buffer)
return JS_NULL;
g_message("JS Log: %s", buffer->str);
g_string_free(buffer, TRUE);
return JS_NULL;
}
JSValueRef js_exists_in_mod(JSContextRef ctx, JSObjectRef func,
JSObjectRef this, size_t argc,
const JSValueRef argv[], JSValueRef * exception)
{
GString * mod_buf, * file_buf, * search_path, * search_path_sanitized;
JSValueRef return_value = JS_FALSE;
FILE * f;
if (!js_check_num_args(ctx, "existsInMod", argc, 2, exception))
return JS_NULL;
file_buf = js_get_cstr_from_val(ctx, argv[0]);
if (!file_buf)
return JS_NULL;
mod_buf = js_get_cstr_from_val(ctx, argv[1]);
if (!mod_buf)
return JS_NULL;
search_path = g_string_new(NULL);
g_string_printf(search_path, "mods/%s/%s", mod_buf->str, file_buf->str);
search_path_sanitized = sanitize_path(search_path->str);
g_string_free(search_path, TRUE);
g_string_free(file_buf, TRUE);
g_string_free(mod_buf, TRUE);
g_message("JS ExistsInMod: Looking for %s", search_path_sanitized->str);
f = fopen(search_path_sanitized->str, "r");
g_string_free(search_path_sanitized, TRUE);
if (f != NULL)
{
g_message("JS ExistsInMod: Found");
fclose(f);
return_value = JS_TRUE;
}
else
g_message("JS ExistsInMod: Not found");
return return_value;
}
JSValueRef js_launch_mod(JSContextRef ctx, JSObjectRef func,
JSObjectRef this, size_t argc,
const JSValueRef argv[], JSValueRef * exception)
{
GString * mod_key, * mod_list;
mod_t * mod;
if (!js_check_num_args(ctx, "launchMod", argc, 1, exception))
return JS_NULL;
if (!JSValueIsString(ctx, argv[0]))
{
*exception = JSValueMakeString(ctx, JS_STR("One or more args are incorrect types."));
return JS_NULL;
}
mod_key = js_get_cstr_from_val(ctx, argv[0]);
g_message("JS LaunchMod: %s", mod_key->str);
mod = get_mod(mod_key->str);
mod_list = g_string_new(mod_key->str);
g_string_free(mod_key, TRUE);
while (strlen(mod->requires) > 0)
{
gchar * r = g_strdup(mod->requires), * comma;
if (NULL != (comma = g_strstr_len(r, -1, ",")))
{
*comma = '\0';
}
mod = get_mod(r);
if (mod == NULL)
{
GString * exception_msg = g_string_new(NULL);
g_string_printf(exception_msg, "The mod %s is missing, cannot launch.", r);
*exception = JSValueMakeString(ctx, JS_STR(exception_msg->str));
g_string_free(exception_msg, TRUE);
g_string_free(mod_list, TRUE);
return JS_NULL;
}
g_string_append_printf(mod_list, ",%s", r);
g_free(r);
}
{
gchar * launch_args[] = { "mono", "OpenRA.Game.exe", NULL, NULL, "SupportDir=~/.openra", NULL };
GString * game_mods_arg = g_string_new(NULL);
GString * renderer_arg = g_string_new(NULL);
g_string_printf(game_mods_arg, "Game.Mods=%s", mod_list->str);
g_string_printf(renderer_arg, "Graphics.Renderer=%s", get_renderer() == RENDERER_GL ? "Gl" : "Cg");
launch_args[2] = game_mods_arg->str;
launch_args[3] = renderer_arg->str;
g_spawn_async(NULL, launch_args, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, NULL);
g_string_free(game_mods_arg, TRUE);
g_string_free(renderer_arg, TRUE);
}
g_string_free(mod_list, TRUE);
return JS_NULL;
}
typedef struct js_callback
{
JSObjectRef func;
JSContextGroupRef ctx_group;
} js_callback;
typedef struct download_t
{
gchar * key;
gchar * url;
gchar * dest;
int current_bytes;
int total_bytes;
js_callback * download_progressed_cb;
js_callback * extraction_progressed_cb;
JSValueRef status;
JSValueRef error;
GIOChannel * output_channel;
GPid pid;
} download_t;
#define MAX_DOWNLOADS 16
static download_t downloads[MAX_DOWNLOADS];
static int num_downloads = 0;
download_t * find_download(gchar const * key)
{
int i;
for (i = 0; i < num_downloads; i++)
{
if (0 == strcmp(downloads[i].key, key))
return downloads + i;
}
return NULL;
}
void set_download_status(JSContextRef ctx, download_t * download, const char * status)
{
JSValueUnprotect(ctx, download->status);
download->status = JSValueMakeString(ctx, JS_STR(status));
JSValueProtect(ctx, download->status);
}
void set_download_error(JSContextRef ctx, download_t * download, const char * error)
{
JSValueUnprotect(ctx, download->error);
download->error = JSValueMakeString(ctx, JS_STR(error));
JSValueProtect(ctx, download->error);
}
void free_download(download_t * download)
{
g_free(download->key);
g_free(download->url);
g_free(download->dest);
g_free(download->download_progressed_cb);
g_free(download->extraction_progressed_cb);
}
JSValueRef js_register_download(JSContextRef ctx, JSObjectRef func, JSObjectRef this,
size_t argc, const JSValueRef argv[], JSValueRef * exception)
{
GString * key, * url, * filename;
download_t * download;
JSValueRef o;
FILE * f;
if (!js_check_num_args(ctx, "registerDownload", argc, 3, exception))
return JS_NULL;
key = js_get_cstr_from_val(ctx, argv[0]);
g_message("JS RegisterDownload: Registering %s", key->str);
if (NULL == (download = find_download(key->str)))
{
download = downloads + num_downloads++;
if (num_downloads >= MAX_DOWNLOADS)
{
num_downloads = MAX_DOWNLOADS - 1;
return JS_NULL;
}
}
free_download(download);
memset(download, 0, sizeof(download_t));
download->download_progressed_cb = (js_callback *)g_malloc(sizeof(js_callback));
o = JSObjectGetProperty(ctx, JSContextGetGlobalObject(ctx), JS_STR("downloadProgressed"), NULL);
download->download_progressed_cb->ctx_group = JSContextGetGroup(ctx);
download->download_progressed_cb->func = JSValueToObject(ctx, o, NULL);
download->extraction_progressed_cb = (js_callback *)g_malloc(sizeof(js_callback));
o = JSObjectGetProperty(ctx, JSContextGetGlobalObject(ctx), JS_STR("extractProgressed"), NULL);
download->extraction_progressed_cb->ctx_group = JSContextGetGroup(ctx);
download->extraction_progressed_cb->func = JSValueToObject(ctx, o, NULL);
download->key = g_strdup(key->str);
g_string_free(key, TRUE);
url = js_get_cstr_from_val(ctx, argv[1]);
download->url = g_strdup(url->str);
g_string_free(url, TRUE);
filename = js_get_cstr_from_val(ctx, argv[2]);
{
GString * path = g_string_new(NULL), * sanitized_path;
g_string_printf(path, "/tmp/%s", filename->str);
g_string_free(filename, TRUE);
sanitized_path = sanitize_path(path->str);
g_string_free(path, TRUE);
download->dest = g_strdup(sanitized_path->str);
g_string_free(sanitized_path, TRUE);
}
f = fopen(download->dest, "r");
if (NULL != f)
{
fclose(f);
set_download_status(ctx, download, "DOWNLOADED");
}
else
set_download_status(ctx, download, "AVAILABLE");
return JS_NULL;
}
gboolean update_download_stats(GIOChannel * source, GIOCondition condition, gpointer data)
{
int ret = TRUE;
download_t * download = (download_t *)data;
gchar * line;
gsize line_length;
GIOStatus io_status;
JSValueRef args[1];
JSContextRef ctx;
ctx = JSGlobalContextCreateInGroup(download->download_progressed_cb->ctx_group, NULL);
switch(condition)
{
case G_IO_IN:
io_status = g_io_channel_read_line(source, &line, &line_length, NULL, NULL);
if (G_IO_STATUS_NORMAL == io_status)
{
if (g_str_has_prefix(line, "Error:"))
{
set_download_status(ctx, download, "ERROR");
set_download_error(ctx, download, line + 7);
}
else
{
set_download_status(ctx, download, "DOWNLOADING");
GRegex * pattern = g_regex_new("(\\d{1,3})% (\\d+)/(\\d+) bytes", 0, 0, NULL);
GMatchInfo * match;
if (g_regex_match(pattern, line, 0, &match))
{
gchar * current = g_match_info_fetch(match, 2), * total = g_match_info_fetch(match, 3);
download->current_bytes = atoi(current);
download->total_bytes = atoi(total);
g_free(current);
g_free(total);
}
g_free(match);
}
}
g_free(line);
break;
case G_IO_HUP:
if (!JSStringIsEqualToUTF8CString(JSValueToStringCopy(ctx, download->status, NULL), "ERROR"))
set_download_status(ctx, download, "DOWNLOADED");
g_io_channel_shutdown(source, FALSE, NULL);
ret = FALSE;
break;
default:
break;
}
args[0] = JSValueMakeString(ctx, JS_STR(download->key));
JSObjectCallAsFunction(ctx, download->download_progressed_cb->func, NULL, 1, args, NULL);
return ret;
}
JSValueRef js_start_download(JSContextRef ctx, JSObjectRef func, JSObjectRef this,
size_t argc, const JSValueRef argv[], JSValueRef * exception)
{
GString * key;
download_t * download;
int fd;
GPid pid;
if (!js_check_num_args(ctx, "startDownload", argc, 1, exception))
return JS_NULL;
key = js_get_cstr_from_val(ctx, argv[0]);
if (NULL == (download = find_download(key->str)))
{
g_string_free(key, TRUE);
return JS_FALSE;
}
g_string_free(key, TRUE);
g_message("Starting download %s", download->key);
set_download_status(ctx, download, "DOWNLOADING");
fd = util_do_download(download->url, download->dest, &pid);
if (!fd)
return JS_FALSE;
download->pid = pid;
download->output_channel = g_io_channel_unix_new(fd);
g_io_add_watch(download->output_channel, G_IO_IN | G_IO_HUP, update_download_stats, download);
return JS_TRUE;
}
JSValueRef js_cancel_download(JSContextRef ctx, JSObjectRef func, JSObjectRef this,
size_t argc, const JSValueRef argv[], JSValueRef * exception)
{
GString * key;
download_t * download;
if (!js_check_num_args(ctx, "cancelDownload", argc, 1, exception))
return JS_NULL;
key = js_get_cstr_from_val(ctx, argv[0]);
if (NULL == (download = find_download(key->str)))
{
g_string_free(key, TRUE);
return JS_FALSE;
}
if (download->pid)
{
set_download_status(ctx, download, "ERROR");
set_download_error(ctx, download, "Download Cancelled");
kill(download->pid, SIGTERM);
remove(download->dest);
}
g_string_free(key, TRUE);
return JS_TRUE;
}
JSValueRef js_download_status(JSContextRef ctx, JSObjectRef func, JSObjectRef this,
size_t argc, const JSValueRef argv[], JSValueRef * exception)
{
GString * key;
download_t * download;
if (!js_check_num_args(ctx, "downloadStatus", argc, 1, exception))
return JS_NULL;
key = js_get_cstr_from_val(ctx, argv[0]);
if (NULL == (download = find_download(key->str)))
{
g_string_free(key, TRUE);
return JSValueMakeString(ctx, JS_STR("NOT_REGISTERED"));
}
g_string_free(key, TRUE);
return download->status;
}
JSValueRef js_download_error(JSContextRef ctx, JSObjectRef func, JSObjectRef this,
size_t argc, const JSValueRef argv[], JSValueRef * exception)
{
GString * key;
download_t * download;
if (!js_check_num_args(ctx, "downloadError", argc, 1, exception))
return JS_NULL;
key = js_get_cstr_from_val(ctx, argv[0]);
g_message("JS DownloadError: Retrieving error message for %s", key->str);
if (NULL == (download = find_download(key->str)))
{
g_string_free(key, TRUE);
return JSValueMakeString(ctx, JS_STR(""));
}
g_string_free(key, TRUE);
return download->error;
}
JSValueRef js_bytes_completed(JSContextRef ctx, JSObjectRef func, JSObjectRef this,
size_t argc, const JSValueRef argv[], JSValueRef * exception)
{
GString * key;
download_t * download;
if (!js_check_num_args(ctx, "bytesCompleted", argc, 1, exception))
return JSValueMakeNull(ctx);
key = js_get_cstr_from_val(ctx, argv[0]);
if (NULL == (download = find_download(key->str)))
{
g_string_free(key, TRUE);
return JSValueMakeNumber(ctx, -1);
}
g_string_free(key, TRUE);
return JSValueMakeNumber(ctx, download->current_bytes);
}
JSValueRef js_bytes_total(JSContextRef ctx, JSObjectRef func, JSObjectRef this,
size_t argc, const JSValueRef argv[], JSValueRef * exception)
{
GString * key;
download_t * download;
if (!js_check_num_args(ctx, "bytesTotal", argc, 1, exception))
return JS_NULL;
key = js_get_cstr_from_val(ctx, argv[0]);
if (NULL == (download = find_download(key->str)))
{
g_string_free(key, TRUE);
return JSValueMakeNumber(ctx, -1);
}
g_string_free(key, TRUE);
return JSValueMakeNumber(ctx, download->total_bytes);
}
gboolean update_extraction_progress(GIOChannel * source, GIOCondition condition, gpointer data)
{
int ret = TRUE;
download_t * download = (download_t *)data;
gchar * line;
gsize line_length;
GIOStatus io_status;
JSValueRef args[1];
JSContextRef ctx;
ctx = JSGlobalContextCreateInGroup(download->extraction_progressed_cb->ctx_group, NULL);
switch(condition)
{
case G_IO_IN:
io_status = g_io_channel_read_line(source, &line, &line_length, NULL, NULL);
if ((G_IO_STATUS_NORMAL == io_status) && (g_str_has_prefix(line, "Error:")))
{
set_download_status(ctx, download, "ERROR");
set_download_error(ctx, download, line + 7);
}
free(line);
break;
case G_IO_HUP:
if (!JSStringIsEqualToUTF8CString(JSValueToStringCopy(ctx, download->status, NULL), "ERROR"))
set_download_status(ctx, download, "EXTRACTED");
g_io_channel_shutdown(source, FALSE, NULL);
ret = FALSE;
break;
default:
break;
}
args[0] = JSValueMakeString(ctx, JS_STR(download->key));
JSObjectCallAsFunction(ctx, download->extraction_progressed_cb->func, NULL, 1, args, NULL);
return ret;
}
JSValueRef js_extract_download(JSContextRef ctx, JSObjectRef func, JSObjectRef this,
size_t argc, const JSValueRef argv[], JSValueRef * exception)
{
GString * key, * dir, * mod, * status, * dest_path, * sanitized_dest_path;
download_t * download;
int fd;
GPid pid;
if (!js_check_num_args(ctx, "extractDownload", argc, 3, exception))
return JS_NULL;
key = js_get_cstr_from_val(ctx, argv[0]);
if (NULL == (download = find_download(key->str)))
{
g_string_free(key, TRUE);
return JS_FALSE;
}
g_string_free(key, TRUE);
status = js_get_cstr_from_val(ctx, download->status);
if (0 != strcmp(status->str, "DOWNLOADED"))
{
g_string_free(status, TRUE);
return JSValueMakeBoolean(ctx, 0);
}
g_string_free(status, TRUE);
set_download_status(ctx, download, "EXTRACTING");
dir = js_get_cstr_from_val(ctx, argv[1]);
mod = js_get_cstr_from_val(ctx, argv[2]);
dest_path = g_string_new(NULL);
g_string_printf(dest_path, "%s/%s", mod->str, dir->str);
sanitized_dest_path = sanitize_path(dest_path->str);
g_string_free(dest_path, TRUE);
g_string_free(mod, TRUE);
g_string_free(dir, TRUE);
fd = util_do_extract(download->dest, sanitized_dest_path->str, &pid);
g_string_free(sanitized_dest_path, TRUE);
if (!fd)
return JS_FALSE;
download->pid = pid;
download->output_channel = g_io_channel_unix_new(fd);
g_io_add_watch(download->output_channel, G_IO_IN | G_IO_HUP, update_extraction_progress, download);
return JS_TRUE;
}
JSValueRef js_metadata(JSContextRef ctx, JSObjectRef func, JSObjectRef this,
size_t argc, const JSValueRef argv[], JSValueRef * exception)
{
GString * field, * mod;
if (!js_check_num_args(ctx, "metadata", argc, 2, exception))
return JS_NULL;
field = js_get_cstr_from_val(ctx, argv[0]);
if (!field)
return JS_NULL;
mod = js_get_cstr_from_val(ctx, argv[1]);
if (!mod)
{
g_string_free(field, TRUE);
return JS_NULL;
}
if (0 == strcmp(field->str, "VERSION"))
{
mod_t * m = get_mod(mod->str);
if (m)
{
g_string_free(mod, TRUE);
g_string_free(field, TRUE);
return JSValueMakeString(ctx, JS_STR(m->version));
}
}
g_string_free(mod, TRUE);
g_string_free(field, TRUE);
return JS_NULL;
}
void request_finished(GPid pid, gint status, gpointer data)
{
GString * msg;
JSValueRef args[1];
callback_data * d = (callback_data *)data;
js_callback * cb = (js_callback *)d->user_data;
JSContextRef ctx = JSGlobalContextCreateInGroup(cb->ctx_group, NULL);
msg = util_get_output(d->output_fd);
close(d->output_fd);
if (!msg)
{
g_free(cb);
g_free(d);
return;
}
args[0] = JSValueMakeString(ctx, JS_STR(msg->str));
g_message("Request response: %s", msg->str);
JSObjectCallAsFunction(ctx, cb->func, NULL, 1, args, NULL);
g_string_free(msg, TRUE);
g_free(cb);
g_free(d);
g_spawn_close_pid(pid);
}
JSValueRef js_http_request(JSContextRef ctx, JSObjectRef func, JSObjectRef this,
size_t argc, const JSValueRef argv[], JSValueRef * exception)
{
GString * url, * callbackname;
js_callback * cb = (js_callback *)g_malloc(sizeof(js_callback));
JSValueRef o;
if (!js_check_num_args(ctx, "httpRequest", argc, 2, exception))
return JS_NULL;
url = js_get_cstr_from_val(ctx, argv[0]);
if (!url)
return JS_NULL;
callbackname = js_get_cstr_from_val(ctx, argv[1]);
if (!callbackname)
{
g_string_free(url, TRUE);
return JS_NULL;
}
o = JSObjectGetProperty(ctx, JSContextGetGlobalObject(ctx), JS_STR(callbackname->str), NULL);
cb->func = JSValueToObject(ctx, o, NULL);
cb->ctx_group = JSContextGetGroup(ctx);
util_do_http_request(url->str, request_finished, cb);
g_string_free(url, TRUE);
g_string_free(callbackname, TRUE);
return JS_NULL;
}
void js_add_functions(JSGlobalContextRef ctx, JSObjectRef target, char ** names,
JSObjectCallAsFunctionCallback * callbacks, size_t count)
{
int i;
for (i = 0; i < count; i++)
{
JSObjectRef func = JS_FUNC(ctx, callbacks[i]);
JSObjectSetProperty(ctx, target, JS_STR(names[i]), func, kJSPropertyAttributeNone, NULL);
}
}
void bind_js_bridge(WebKitWebView * view, WebKitWebFrame * frame,
gpointer context, gpointer window_object,
gpointer user_data)
{
JSGlobalContextRef js_ctx;
JSObjectRef window_obj, external_obj;
int func_count = 13;
char * names[] = { "log", "existsInMod", "launchMod", "registerDownload",
"startDownload", "cancelDownload", "downloadStatus",
"downloadError", "bytesCompleted", "bytesTotal",
"extractDownload", "metadata", "httpRequest"};
JSObjectCallAsFunctionCallback callbacks[] = { js_log, js_exists_in_mod, js_launch_mod,
js_register_download, js_start_download,
js_cancel_download, js_download_status,
js_download_error, js_bytes_completed,
js_bytes_total, js_extract_download, js_metadata, js_http_request };
js_ctx = (JSGlobalContextRef)context;
external_obj = JSObjectMake(js_ctx, NULL, NULL);
window_obj = (JSObjectRef)window_object;
JSObjectSetProperty(js_ctx, window_obj, JS_STR("external"),
external_obj, 0, NULL);
js_add_functions(js_ctx, external_obj, names, callbacks, func_count);
}

View File

@@ -1,11 +0,0 @@
/*
* 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.
*/
void bind_js_bridge(WebKitWebView * view, WebKitWebFrame * frame,
gpointer context, gpointer window_object,
gpointer user_data);

View File

@@ -1,497 +0,0 @@
/*
* 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gtk/gtk.h>
#include <webkit/webkit.h>
#include <unistd.h>
#include "main.h"
#include "server.h"
#include "bridge.h"
#include "utility.h"
#define WEBSERVER_PORT 48764
GtkWindow * window;
WebKitWebView * browser;
GtkTreeStore * tree_store;
GtkTreeView * tree;
GdkPixbuf * generic_mod_icon;
GtkRadioButton * gl_button, * cg_button;
static mod_t mods[MAX_NUM_MODS];
static int mod_count = 0;
static int renderer = RENDERER_GL;
void free_mod(mod_t * mod)
{
g_free(mod->key);
g_free(mod->title);
g_free(mod->version);
g_free(mod->author);
g_free(mod->description);
g_free(mod->requires);
}
gboolean window_delete(GtkWidget * widget, GdkEvent * event,
gpointer user_data)
{
int i;
server_teardown();
for (i = 0; i < mod_count; i++)
free_mod(mods + i);
gtk_main_quit();
return FALSE;
}
typedef void ( * lines_callback ) (GString const * line, gpointer data);
//Splits console output into lines and passes each one to a callback
void process_lines(GString * lines, lines_callback cb, gpointer data)
{
int prev = 0, current = 0;
while (current < lines->len)
{
if (lines->str[current] == '\n')
{
GString * line = g_string_new_len(lines->str + prev, current - prev);
cb(line, data);
g_string_free(line, TRUE);
prev = current + 1;
}
current++;
}
}
#define ASSIGN_TO_MOD(FIELD) \
mod->FIELD = g_strdup(val_start)
void mod_metadata_line(GString const * line, gpointer data)
{
mod_t * mod = (mod_t *)data;
gchar * val_start = g_strstr_len(line->str, -1, ":") + 2;
if (g_str_has_prefix(line->str, "Mod:"))
{
ASSIGN_TO_MOD(key);
}
else if (g_str_has_prefix(line->str, " Title:"))
{
ASSIGN_TO_MOD(title);
}
else if (g_str_has_prefix(line->str, " Version:"))
{
ASSIGN_TO_MOD(version);
}
else if (g_str_has_prefix(line->str, " Author:"))
{
ASSIGN_TO_MOD(author);
}
else if (g_str_has_prefix(line->str, " Description:"))
{
ASSIGN_TO_MOD(description);
}
else if (g_str_has_prefix(line->str, " Requires:"))
{
ASSIGN_TO_MOD(requires);
}
else if (g_str_has_prefix(line->str, " Standalone:"))
{
if (strcmp(val_start, "True") == 0)
mod->standalone = TRUE;
else
mod->standalone = FALSE;
}
}
mod_t * get_mod(gchar const * key)
{
int i;
for (i = 0; i < mod_count; i++)
{
if (strcmp(mods[i].key, key) == 0)
return mods + i;
}
return NULL;
}
gboolean append_to_mod(GtkTreeModel * model, GtkTreePath * path,
GtkTreeIter * iter, gpointer data)
{
mod_t * mod = (mod_t *)data;
gchar * key;
GtkTreeIter new_iter;
gtk_tree_model_get(model, iter, KEY_COLUMN, &key, -1);
if (!key)
{
return FALSE;
}
if (strcmp(mod->requires, key) == 0)
{
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);
g_free(key);
return TRUE;
}
g_free(key);
return FALSE;
}
void mod_metadata_callback(GPid pid, gint status, gpointer data)
{
int * out_fd = (int *)data;
GString * msg = NULL;
mod_t * mod = mods + mod_count;
GtkTreeIter iter, mod_iter;
mod_count = (mod_count + 1) % MAX_NUM_MODS;
free_mod(mod);
memset(mod, 0, sizeof(mod_t));
msg = util_get_output(*out_fd);
close(*out_fd);
free(out_fd);
if (!msg)
return;
process_lines(msg, mod_metadata_line, mod);
g_string_free(msg, TRUE);
gtk_tree_model_get_iter_first(GTK_TREE_MODEL(tree_store), &mod_iter);
if (mod->standalone)
{
gtk_tree_store_append(tree_store, &iter, &mod_iter);
gtk_tree_store_set(tree_store, &iter,
ICON_COLUMN, generic_mod_icon,
KEY_COLUMN, mod->key,
NAME_COLUMN, mod->title,
-1);
}
else if (!strlen(mod->requires))
{
GtkTreeIter broken_mods_iter;
if (!gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(tree_store),
&broken_mods_iter, "1"))
{
gtk_tree_store_append(tree_store, &broken_mods_iter, NULL);
}
gtk_tree_store_set(tree_store, &broken_mods_iter,
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);
}
}
typedef struct tree_node
{
gchar const * key;
gchar * node_path;
} tree_node;
gboolean find_mod(GtkTreeModel * model, GtkTreePath * path,
GtkTreeIter * iter, gpointer data)
{
tree_node * n = (tree_node *)data;
gchar * key;
gtk_tree_model_get(model, iter,
KEY_COLUMN, &key,
-1);
if (!key)
return FALSE;
if (0 == strcmp(n->key, key))
{
n->node_path = gtk_tree_path_to_string(path);
g_free(key);
return TRUE;
}
g_free(key);
return FALSE;
}
void last_mod_callback(GPid pid, gint status, gpointer data)
{
int * out_fd = (int *)data;
gchar * comma_pos = 0, * newline_pos = 0;
GString * msg = NULL;
tree_node n;
memset(&n, 0, sizeof(tree_node));
msg = util_get_output(*out_fd);
close(*out_fd);
free(out_fd);
if (!msg)
return;
if (g_str_has_prefix(msg->str, "Error:"))
{
g_string_truncate(msg, 2);
g_string_overwrite(msg, 0, "ra");
}
else if (NULL != (comma_pos = g_strstr_len(msg->str, -1, ",")))
*comma_pos = '\0';
else if (NULL != (newline_pos = g_strstr_len(msg->str, -1, "\n")))
*newline_pos = '\0';
n.key = msg->str;
gtk_tree_model_foreach(GTK_TREE_MODEL(tree_store), find_mod, &n);
if (n.node_path)
{
GtkTreePath * path;
path = gtk_tree_path_new_from_string(n.node_path);
if (path == NULL)
g_warning("Invalid Path");
gtk_tree_view_expand_to_path(tree, path);
gtk_tree_view_set_cursor(tree, path, NULL, FALSE);
gtk_tree_path_free(path);
g_free(n.node_path);
}
g_string_free(msg, TRUE);
}
void mod_list_line(GString const * mod, gpointer user)
{
util_get_mod_metadata(mod->str, mod_metadata_callback);
}
void mod_list_callback(GPid pid, gint status, gpointer data)
{
callback_data * d = (callback_data *)data;
GString * msg = NULL;
msg = util_get_output(d->output_fd);
close(d->output_fd);
g_free(d);
if (!msg)
return;
mod_count = 0;
process_lines(msg, mod_list_line, NULL);
util_get_setting("Game.Mods", last_mod_callback);
g_string_free(msg, TRUE);
g_spawn_close_pid(pid);
}
void tree_view_selection_changed(GtkTreeView * tree_view, gpointer data)
{
GtkTreePath * path;
GtkTreeIter iter;
gchar * key;
GString * url;
gtk_tree_view_get_cursor(tree_view, &path, NULL);
if (path == NULL)
return;
gtk_tree_model_get_iter(GTK_TREE_MODEL(tree_store), &iter, path);
gtk_tree_model_get(GTK_TREE_MODEL(tree_store), &iter,
KEY_COLUMN, &key,
-1);
if (!key)
{
gtk_tree_path_free(path);
return;
}
url = g_string_new(NULL);
g_string_printf(url, "http://localhost:%d/mods/%s/mod.html", WEBSERVER_PORT, key);
webkit_web_view_load_uri(browser, url->str);
g_free(key);
gtk_tree_path_free(path);
g_string_free(url, TRUE);
}
void make_tree_view(void)
{
GtkTreeIter iter;
GtkCellRenderer * pixbuf_renderer, * text_renderer;
GtkTreeViewColumn * icon_column, * name_column;
tree_store = gtk_tree_store_new(N_COLUMNS, GDK_TYPE_PIXBUF,
G_TYPE_STRING, G_TYPE_STRING);
gtk_tree_store_append(tree_store, &iter, NULL);
gtk_tree_store_set(tree_store, &iter,
NAME_COLUMN, "MODS",
-1);
tree = GTK_TREE_VIEW(gtk_tree_view_new_with_model(
GTK_TREE_MODEL(tree_store)));
g_object_set(tree, "headers-visible", FALSE, NULL);
g_signal_connect(tree, "cursor-changed",
G_CALLBACK(tree_view_selection_changed), NULL);
pixbuf_renderer = gtk_cell_renderer_pixbuf_new();
text_renderer = gtk_cell_renderer_text_new();
icon_column = gtk_tree_view_column_new_with_attributes
("Icon", pixbuf_renderer,
"pixbuf", ICON_COLUMN,
NULL);
gtk_tree_view_column_set_sizing(icon_column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
name_column = gtk_tree_view_column_new_with_attributes
("Name", text_renderer,
"text", NAME_COLUMN,
NULL);
gtk_tree_view_column_set_sizing(name_column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
gtk_tree_view_append_column(tree, icon_column);
gtk_tree_view_append_column(tree, name_column);
}
void renderer_callback(GPid pid, gint status, gpointer data)
{
int * fd = (int *)data;
GString * msg;
msg = util_get_output(*fd);
close(*fd);
g_free(fd);
if (!msg)
return;
if (g_str_has_prefix(msg->str, "Error:"))
{
g_string_free(msg, TRUE);
return;
}
if (0 == strcmp(msg->str, "Gl"))
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gl_button), TRUE);
else
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cg_button), TRUE);
g_string_free(msg, TRUE);
}
void renderer_changed(GtkToggleButton * widget, gpointer user_data)
{
if (!gtk_toggle_button_get_active(widget))
return;
if (GTK_RADIO_BUTTON(widget) == gl_button)
renderer = RENDERER_GL;
else
renderer = RENDERER_CG;
}
int get_renderer(void)
{
return renderer;
}
int main(int argc, char ** argv)
{
GtkWidget * hbox1, * hbox2, * vbox;
int res = chdir("/usr/share/openra");
if (0 != res)
res = chdir("/usr/local/share/openra");
if (0 != res)
{
g_error("Couldn't change to OpenRA working directory");
return 1;
}
server_init(WEBSERVER_PORT);
gtk_init(&argc, &argv);
window = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL));
gtk_window_set_title(window, "OpenRA Launcher");
gtk_window_set_default_size(window, 800, 600);
browser = WEBKIT_WEB_VIEW(webkit_web_view_new());
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();
util_get_mod_list(mod_list_callback);
vbox = gtk_vbox_new(FALSE, 0);
hbox1 = gtk_hbox_new(FALSE, 0);
hbox2 = gtk_hbox_new(FALSE, 0);
gtk_widget_set_size_request(GTK_WIDGET(tree), 250, 0);
gtk_box_pack_end(GTK_BOX(hbox1), GTK_WIDGET(browser), TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(hbox1), GTK_WIDGET(tree), TRUE, TRUE, 0);
gl_button = GTK_RADIO_BUTTON(gtk_radio_button_new_with_label(NULL, "GL Renderer"));
g_signal_connect(gl_button, "toggled", G_CALLBACK(renderer_changed), 0);
cg_button = GTK_RADIO_BUTTON(gtk_radio_button_new_with_label_from_widget(gl_button, "CG Renderer"));
g_signal_connect(cg_button, "toggled", G_CALLBACK(renderer_changed), 0);
util_get_setting("Graphics.Renderer", renderer_callback);
gtk_box_pack_start(GTK_BOX(hbox2), GTK_WIDGET(gl_button), FALSE, FALSE, 5);
gtk_box_pack_start(GTK_BOX(hbox2), GTK_WIDGET(cg_button), FALSE, FALSE, 5);
gtk_box_pack_start(GTK_BOX(vbox), hbox1, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(vbox), hbox2, FALSE, FALSE, 10);
gtk_container_add(GTK_CONTAINER(window), vbox);
gtk_widget_show_all(GTK_WIDGET(window));
g_signal_connect(window, "delete-event", G_CALLBACK(window_delete), 0);
gtk_main();
return 0;
}

View File

@@ -1,42 +0,0 @@
/*
* 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
};
enum
{
RENDERER_GL,
RENDERER_CG
};
#define MAX_NUM_MODS 64
typedef struct mod_t
{
gchar * key;
gchar * title;
gchar * version;
gchar * author;
gchar * description;
gchar * requires;
int standalone;
} mod_t;
mod_t * get_mod(gchar const * key);
int get_renderer(void);
#endif

View File

@@ -1,97 +0,0 @@
/*
* 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.
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <stdint.h>
#include <fcntl.h>
#include <string.h>
#include <stdarg.h>
#define MHD_PLATFORM_H
#include <microhttpd.h>
#include <glib.h>
struct MHD_Daemon * server;
int try_file_response(const char * url, struct MHD_Connection * connection)
{
int fd, ret;
struct MHD_Response * response;
struct stat sbuf;
g_message("Web server: Opening %s", url + 1);
if ((-1 == (fd = open(url + 1, O_RDONLY))) ||
(0 != fstat(fd, &sbuf)))
{
return MHD_NO;
}
response = MHD_create_response_from_fd(sbuf.st_size, fd);
MHD_add_response_header(response, "Content-Type", "text/html");
ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
MHD_destroy_response(response);
return ret;
}
int access_handler_callback(void * userdata,
struct MHD_Connection * connection,
const char * url,
const char * method,
const char * version,
const char * upload_data,
size_t * upload_data_size,
void ** userpointer)
{
struct MHD_Response * response;
int ret = MHD_NO;
char * text = "1";
g_message("Web server: Got request for %s", url);
if ((ret = try_file_response(url, connection)))
return ret;
text = "<html><head><title>Not found</title></head><body>File not found</body></html>";
response = MHD_create_response_from_data(strlen(text), (void *)text,
MHD_NO, MHD_NO);
ret = MHD_queue_response(connection, MHD_HTTP_NOT_FOUND, response);
MHD_destroy_response(response);
return ret;
}
int server_init(int port)
{
server = MHD_start_daemon(MHD_USE_DEBUG | MHD_USE_SELECT_INTERNALLY,
port, NULL, NULL,
&access_handler_callback, NULL,
MHD_OPTION_END);
if (!server)
{
g_critical("Could not start web server.");
return 0;
}
g_message("Server initialised.");
return 1;
}
void * server_get_daemon(void)
{
return server;
}
void server_teardown(void)
{
MHD_stop_daemon(server);
}

View File

@@ -1,10 +0,0 @@
/*
* 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.
*/
int server_init(int);
void server_teardown(void);

View File

@@ -1,184 +0,0 @@
/*
* 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.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <glib.h>
#include <sys/wait.h>
#include "utility.h"
gboolean util_do_command_async(gchar * command, GChildWatchFunc callback, gpointer user_data)
{
GPid child_pid;
gchar * spawn_args[] = { "mono", "OpenRA.Utility.exe", command, NULL };
callback_data * d = (callback_data *)g_malloc(sizeof(callback_data));
gboolean result;
result = g_spawn_async_with_pipes(NULL, spawn_args, NULL,
G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
NULL, NULL, &child_pid, NULL, &(d->output_fd), NULL, NULL);
if (!result)
{
g_free(d);
return FALSE;
}
d->user_data = user_data;
g_child_watch_add(child_pid, callback, d);
return TRUE;
}
gboolean util_get_mod_list (GChildWatchFunc callback)
{
return util_do_command_async("-l", callback, NULL);
}
gboolean util_do_command_blocking(gchar * command, GChildWatchFunc callback)
{
GPid child_pid;
int status;
gint * out_fd = (gint *)g_malloc(sizeof(gint));
gchar * spawn_args[] = { "mono", "OpenRA.Utility.exe", command, NULL };
gboolean result;
result = g_spawn_async_with_pipes(NULL, spawn_args, NULL,
G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
NULL, NULL, &child_pid, NULL, out_fd, NULL, NULL);
if (!result)
{
return FALSE;
}
waitpid(child_pid, &status, 0);
callback(child_pid, status, out_fd);
return TRUE;
}
gboolean util_get_mod_metadata(gchar const * mod, GChildWatchFunc callback)
{
GString * util_args = g_string_new(NULL);
gboolean return_val;
g_string_printf(util_args, "-i=%s", mod);
return_val = util_do_command_blocking(util_args->str, callback);
g_string_free(util_args, TRUE);
return return_val;
}
gboolean util_get_setting(gchar const * setting, GChildWatchFunc callback)
{
GString * command = g_string_new(NULL);
gboolean return_val;
g_string_printf(command, "--settings-value=~/.openra,%s", setting);
return_val = util_do_command_blocking(command->str, callback);
g_string_free(command, TRUE);
return return_val;
}
gchar * get_graphical_sudo_client(void)
{
int num_clients = 2, i;
gchar * clients[] = { "gksudo", "kdesudo" };
for (i = 0; i < num_clients; i++)
{
FILE * f;
GString * test_path = g_string_new(NULL);
g_string_printf(test_path, "/usr/bin/%s", clients[i]);
f = fopen(test_path->str, "r");
g_string_free(test_path, TRUE);
if (f)
return g_strdup(clients[i]);
}
return NULL;
}
gint util_spawn_with_command(gchar const * command, gchar const * arg1, gchar const * arg2, gboolean root, GPid * pid)
{
GString * complete_command = g_string_new(NULL);
gint out_fd;
gboolean result;
g_string_printf(complete_command, "%s%s,%s", command, arg1, arg2);
if (root)
{
gchar * sudo = get_graphical_sudo_client();
gchar * launch_args[] = { sudo, "--", "mono", "OpenRA.Utility.exe", NULL, NULL };
launch_args[4] = complete_command->str;
result = g_spawn_async_with_pipes(NULL, launch_args, NULL, G_SPAWN_SEARCH_PATH,
NULL, NULL, pid, NULL, &out_fd, NULL, NULL);
g_free(sudo);
}
else
{
gchar * launch_args[] = { "mono", "OpenRA.Utility.exe", NULL, NULL };
launch_args[2] = complete_command->str;
result = g_spawn_async_with_pipes(NULL, launch_args, NULL, G_SPAWN_SEARCH_PATH,
NULL, NULL, pid, NULL, &out_fd, NULL, NULL);
}
g_string_free(complete_command, TRUE);
if (!result)
{
return 0;
}
return out_fd;
}
gint util_do_download(gchar const * url, gchar const * dest, GPid * pid)
{
return util_spawn_with_command("--download-url=", url, dest, FALSE, pid);
}
gint util_do_extract(gchar const * target, gchar const * dest, GPid * pid)
{
return util_spawn_with_command("--extract-zip=", target, dest, TRUE, pid);
}
gboolean util_do_http_request(gchar const * url, GChildWatchFunc callback, gpointer user_data)
{
gboolean b;
GString * command = g_string_new(NULL);
g_string_printf(command, "--download-url=%s", url);
b = util_do_command_async(command->str, callback, user_data);
g_string_free(command, TRUE);
return b;
}
GString * util_get_output(int fd)
{
char buffer[1024];
GString * msg = g_string_new(NULL);
int read_bytes = 0;
while (0 != (read_bytes = read(fd, buffer, 1024)))
{
if (-1 == read_bytes)
{
g_error("Error reading from command output");
g_string_free(msg, TRUE);
return NULL;
}
g_string_append_len(msg, buffer, read_bytes);
}
g_string_append_c(msg, '\0');
return msg;
}

View File

@@ -1,21 +0,0 @@
/*
* 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.
*/
typedef struct callback_data
{
gint output_fd;
gpointer user_data;
} callback_data;
gboolean util_get_mod_list (GChildWatchFunc);
gboolean util_get_mod_metadata(gchar const *, GChildWatchFunc);
gboolean util_get_setting(gchar const *, GChildWatchFunc);
gint util_do_download(gchar const *, gchar const *, GPid *);
gint util_do_extract(gchar const *, gchar const *, GPid *);
gboolean util_do_http_request(gchar const *, GChildWatchFunc, gpointer);
GString * util_get_output(int);

View File

@@ -1,227 +0,0 @@
#region Copyright & License Information
/*
* 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.
*/
#endregion
using System;
using System.ComponentModel;
using System.IO;
using System.IO.Pipes;
using System.Text.RegularExpressions;
using System.Windows.Forms;
namespace OpenRA.Launcher
{
public enum DownloadStatus
{
NOT_REGISTERED, AVAILABLE, DOWNLOADING, DOWNLOADED, EXTRACTING, EXTRACTED, ERROR
}
class Download : IDisposable
{
DownloadStatus status = DownloadStatus.NOT_REGISTERED;
string url = "", target = "", key = "";
BackgroundWorker downloadBGWorker, extractBGWorker;
int bytesTotal = 0, bytesDone = 0;
string errorMessage = "";
HtmlDocument document;
public string ErrorMessage
{
get { return errorMessage; }
}
public int BytesDone
{
get { return bytesDone; }
}
public int BytesTotal
{
get { return bytesTotal; }
}
public DownloadStatus Status
{
get { return status; }
}
public Download(HtmlDocument document, string key, string url, string filename)
{
this.url = url;
this.key = key;
this.document = document;
target = Path.Combine(Path.GetTempPath(), filename);
if (File.Exists(target))
status = DownloadStatus.DOWNLOADED;
else
status = DownloadStatus.AVAILABLE;
downloadBGWorker = new BackgroundWorker()
{
WorkerReportsProgress = true,
WorkerSupportsCancellation = true
};
downloadBGWorker.DoWork += RunDownload;
downloadBGWorker.ProgressChanged += UpdateProgress;
downloadBGWorker.RunWorkerCompleted += DownloadFinished;
extractBGWorker = new BackgroundWorker();
extractBGWorker.DoWork += DoExtraction;
extractBGWorker.RunWorkerCompleted += ExtractionFinished;
}
public void StartDownload()
{
if (!downloadBGWorker.IsBusy)
{
status = DownloadStatus.DOWNLOADING;
downloadBGWorker.RunWorkerAsync(new string[] { url, target });
}
}
public void CancelDownload()
{
if (downloadBGWorker.IsBusy)
downloadBGWorker.CancelAsync();
}
public void ExtractDownload(string destPath)
{
if (!extractBGWorker.IsBusy)
{
status = DownloadStatus.EXTRACTING;
extractBGWorker.RunWorkerAsync(new string[] { target, destPath });
}
}
static void RunDownload(object sender, DoWorkEventArgs e)
{
var bgWorker = sender as BackgroundWorker;
string[] args = e.Argument as string[];
string url = args[0];
string dest = args[1];
string pipename = UtilityProgram.GetPipeName();
var p = UtilityProgram.Call("--download-url", pipename, null, url, dest);
Regex r = new Regex(@"(\d{1,3})% (\d+)/(\d+) bytes");
NamedPipeClientStream pipe = new NamedPipeClientStream(".", pipename, PipeDirection.In);
pipe.Connect();
using (var response = new StreamReader(pipe))
{
while (!p.HasExited)
{
string s = response.ReadLine();
if (string.IsNullOrEmpty(s)) continue;
if (Util.IsError(ref s))
throw new Exception(s);
if (bgWorker.CancellationPending)
{
e.Cancel = true;
p.Kill();
return;
}
if (!r.IsMatch(s)) continue;
var m = r.Match(s);
bgWorker.ReportProgress(int.Parse(m.Groups[1].Value),
new string[] { m.Groups[2].Value, m.Groups[3].Value });
}
}
}
void UpdateProgress(object sender, ProgressChangedEventArgs e)
{
string[] s = e.UserState as string[];
bytesDone = int.Parse(s[0]);
bytesTotal = int.Parse(s[1]);
document.InvokeScript("downloadProgressed", new object[] { key });
}
void DownloadFinished(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
status = DownloadStatus.ERROR;
errorMessage = e.Error.Message;
//if (File.Exists(target))
// File.Delete(target);
document.InvokeScript("downloadProgressed", new object[] { key });
return;
}
if (e.Cancelled)
{
status = DownloadStatus.ERROR;
errorMessage = "Download Cancelled";
//if (File.Exists(target))
// File.Delete(target);
document.InvokeScript("downloadProgressed", new object[] { key });
return;
}
status = DownloadStatus.DOWNLOADED;
document.InvokeScript("downloadProgressed", new object[] { key });
}
void DoExtraction(object sender, DoWorkEventArgs e)
{
string[] args = e.Argument as string[];
string zipFile = args[0];
string destPath = args[1];
string pipename = UtilityProgram.GetPipeName();
var p = UtilityProgram.CallWithAdmin("--extract-zip", pipename, zipFile, destPath);
var pipe = new NamedPipeClientStream(".", pipename, PipeDirection.In);
pipe.Connect();
using (var reader = new StreamReader(pipe))
{
while (!p.HasExited)
{
string s = reader.ReadLine();
if (string.IsNullOrEmpty(s)) continue;
if (Util.IsError(ref s))
throw new Exception(s);
}
}
}
void ExtractionFinished(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
status = DownloadStatus.ERROR;
errorMessage = e.Error.Message;
document.InvokeScript("extractProgressed", new object[] { key });
}
status = DownloadStatus.EXTRACTED;
document.InvokeScript("extractProgressed", new object[] { key });
}
bool disposed = false;
~Download()
{
if (!disposed)
Dispose();
}
public void Dispose()
{
if (status == DownloadStatus.DOWNLOADING && File.Exists(target))
File.Delete(target);
disposed = true;
}
}
}

View File

@@ -1,194 +0,0 @@
#region Copyright & License Information
/*
* 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.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Pipes;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
namespace OpenRA.Launcher
{
public class JSBridge
{
Dictionary<string, Mod> allMods = new Dictionary<string,Mod>();
public Dictionary<string, Mod> AllMods
{
get { return allMods; }
set { allMods = value; }
}
Dictionary<string, Download> downloads = new Dictionary<string,Download>();
readonly Control hostControl;
HtmlDocument document = null;
public JSBridge(Control hostControl)
{
this.hostControl = hostControl;
}
public HtmlDocument Document
{
get { return document; }
set { document = value; }
}
public bool existsInMod(string file, string mod)
{
string cleanedPath = CleanPath(file);
return File.Exists(string.Format("mods{0}{1}{0}{2}", Path.DirectorySeparatorChar, mod, cleanedPath));
}
public void log(string message)
{
Console.WriteLine("js: " + message);
}
public bool launchMod(string mod)
{
string m = mod;
List<string> modList = new List<string>();
modList.Add(m);
if (!allMods.ContainsKey(m))
{
MessageBox.Show("allMods does not contain " + m);
return false;
}
while (!string.IsNullOrEmpty(allMods[m].Requires))
{
m = allMods[m].Requires;
modList.Add(m);
}
Process p = new Process();
p.StartInfo.FileName = "OpenRA.Game.exe";
p.StartInfo.Arguments = "Game.Mods=" + string.Join(",", modList.ToArray());
p.StartInfo.Arguments += " Graphics.Renderer=" + Launcher.Renderer;
p.Start();
return true;
}
Regex p = new Regex(@"\.\.[/\\]?");
string CleanPath(string path)
{
string root = Path.GetPathRoot(path);
string cleanedPath = path.Remove(0, root.Length);
return p.Replace(cleanedPath, "");
}
public void registerDownload(string key, string url, string filename)
{
string cleanedPath = CleanPath(filename);
if (!downloads.ContainsKey(key))
downloads.Add(key, new Download(document, key, url, cleanedPath));
else
downloads[key] = new Download(document, key, url, cleanedPath);
}
public bool startDownload(string key)
{
if (!downloads.ContainsKey(key))
return false;
downloads[key].StartDownload();
return true;
}
public bool cancelDownload(string key)
{
if (!downloads.ContainsKey(key))
return false;
downloads[key].CancelDownload();
return true;
}
public string downloadStatus(string key)
{
if (!downloads.ContainsKey(key))
return DownloadStatus.NOT_REGISTERED.ToString();
return downloads[key].Status.ToString();
}
public string downloadError(string key)
{
if (!downloads.ContainsKey(key))
return "";
return downloads[key].ErrorMessage;
}
public int bytesCompleted(string key)
{
if (!downloads.ContainsKey(key))
return -1;
return downloads[key].BytesDone;
}
public int bytesTotal(string key)
{
if (!downloads.ContainsKey(key))
return -1;
return downloads[key].BytesTotal;
}
public bool extractDownload(string key, string targetDir, string mod)
{
string cleanedPath = CleanPath(targetDir);
string targetPath = Path.Combine(mod, cleanedPath);
if (!downloads.ContainsKey(key))
return false;
if (downloads[key].Status != DownloadStatus.DOWNLOADED)
return false;
downloads[key].ExtractDownload(targetPath);
return true;
}
public string metadata(string field, string mod)
{
if (field == "VERSION")
return allMods[mod].Version;
return "";
}
public void httpRequest(string url, string callbackName)
{
string pipename = UtilityProgram.GetPipeName();
var pipe = new NamedPipeClientStream(".", pipename, PipeDirection.In);
var p = UtilityProgram.Call("--download-url", pipename,
(_, e) =>
{
using (var reader = new StreamReader(pipe))
{
var data = reader.ReadToEnd();
hostControl.Invoke((Delegate)(Action)(() =>
document.InvokeScript(callbackName, new object[] { data })));
}
}, url);
pipe.Connect();
}
}
}

View File

@@ -1,174 +0,0 @@
namespace OpenRA.Launcher
{
partial class Launcher
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.Windows.Forms.TreeNode treeNode1 = new System.Windows.Forms.TreeNode("Mods", -2, -2);
this.installButton = new System.Windows.Forms.Button();
this.installModDialog = new System.Windows.Forms.OpenFileDialog();
this.treeView = new System.Windows.Forms.TreeView();
this.splitContainer1 = new System.Windows.Forms.SplitContainer();
this.webBrowser = new System.Windows.Forms.WebBrowser();
this.panel1 = new System.Windows.Forms.Panel();
this.cgButton = new System.Windows.Forms.RadioButton();
this.glButton = new System.Windows.Forms.RadioButton();
this.splitContainer1.Panel1.SuspendLayout();
this.splitContainer1.Panel2.SuspendLayout();
this.splitContainer1.SuspendLayout();
this.panel1.SuspendLayout();
this.SuspendLayout();
//
// installButton
//
this.installButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.installButton.Location = new System.Drawing.Point(12, 12);
this.installButton.Name = "installButton";
this.installButton.Size = new System.Drawing.Size(116, 23);
this.installButton.TabIndex = 2;
this.installButton.Text = "Install Mod...";
this.installButton.UseVisualStyleBackColor = true;
this.installButton.Click += new System.EventHandler(this.InstallMod);
//
// installModDialog
//
this.installModDialog.Filter = "Zip files|*.zip";
this.installModDialog.RestoreDirectory = true;
//
// treeView
//
this.treeView.Dock = System.Windows.Forms.DockStyle.Fill;
this.treeView.Location = new System.Drawing.Point(0, 0);
this.treeView.Name = "treeView";
treeNode1.ImageIndex = -2;
treeNode1.Name = "ModsNode";
treeNode1.SelectedImageIndex = -2;
treeNode1.Text = "Mods";
this.treeView.Nodes.AddRange(new System.Windows.Forms.TreeNode[] {
treeNode1});
this.treeView.ShowLines = false;
this.treeView.Size = new System.Drawing.Size(160, 465);
this.treeView.TabIndex = 3;
this.treeView.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.treeView_AfterSelect);
//
// splitContainer1
//
this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
this.splitContainer1.Location = new System.Drawing.Point(0, 0);
this.splitContainer1.Name = "splitContainer1";
//
// splitContainer1.Panel1
//
this.splitContainer1.Panel1.Controls.Add(this.treeView);
//
// splitContainer1.Panel2
//
this.splitContainer1.Panel2.Controls.Add(this.webBrowser);
this.splitContainer1.Size = new System.Drawing.Size(671, 465);
this.splitContainer1.SplitterDistance = 160;
this.splitContainer1.TabIndex = 4;
//
// webBrowser
//
this.webBrowser.AllowWebBrowserDrop = false;
this.webBrowser.Dock = System.Windows.Forms.DockStyle.Fill;
this.webBrowser.Location = new System.Drawing.Point(0, 0);
this.webBrowser.MinimumSize = new System.Drawing.Size(20, 20);
this.webBrowser.Name = "webBrowser";
this.webBrowser.ScrollBarsEnabled = false;
this.webBrowser.Size = new System.Drawing.Size(507, 465);
this.webBrowser.TabIndex = 0;
//
// panel1
//
this.panel1.Controls.Add(this.cgButton);
this.panel1.Controls.Add(this.glButton);
this.panel1.Controls.Add(this.installButton);
this.panel1.Dock = System.Windows.Forms.DockStyle.Bottom;
this.panel1.Location = new System.Drawing.Point(0, 465);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(671, 47);
this.panel1.TabIndex = 5;
//
// cgButton
//
this.cgButton.AutoSize = true;
this.cgButton.Location = new System.Drawing.Point(481, 18);
this.cgButton.Name = "cgButton";
this.cgButton.Size = new System.Drawing.Size(87, 17);
this.cgButton.TabIndex = 4;
this.cgButton.TabStop = true;
this.cgButton.Text = "CG Renderer";
this.cgButton.UseVisualStyleBackColor = true;
this.cgButton.CheckedChanged += new System.EventHandler(this.rendererChanged);
//
// glButton
//
this.glButton.AutoSize = true;
this.glButton.Location = new System.Drawing.Point(574, 18);
this.glButton.Name = "glButton";
this.glButton.Size = new System.Drawing.Size(86, 17);
this.glButton.TabIndex = 3;
this.glButton.TabStop = true;
this.glButton.Text = "GL Renderer";
this.glButton.UseVisualStyleBackColor = true;
this.glButton.CheckedChanged += new System.EventHandler(this.rendererChanged);
//
// Launcher
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(671, 512);
this.Controls.Add(this.splitContainer1);
this.Controls.Add(this.panel1);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.MaximizeBox = false;
this.Name = "Launcher";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "OpenRA Launcher";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.formClosing);
this.splitContainer1.Panel1.ResumeLayout(false);
this.splitContainer1.Panel2.ResumeLayout(false);
this.splitContainer1.ResumeLayout(false);
this.panel1.ResumeLayout(false);
this.panel1.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Button installButton;
private System.Windows.Forms.OpenFileDialog installModDialog;
private System.Windows.Forms.TreeView treeView;
private System.Windows.Forms.SplitContainer splitContainer1;
private System.Windows.Forms.Panel panel1;
private System.Windows.Forms.WebBrowser webBrowser;
private System.Windows.Forms.RadioButton cgButton;
private System.Windows.Forms.RadioButton glButton;
}
}

View File

@@ -1,209 +0,0 @@
#region Copyright & License Information
/*
* 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.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using System.IO.Pipes;
using System.IO;
namespace OpenRA.Launcher
{
public partial class Launcher : Form
{
Dictionary<string, Mod> allMods;
public static string Renderer = "Gl";
static string SupportDir = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + Path.DirectorySeparatorChar + "OpenRA";
public Launcher()
{
InitializeComponent();
Util.UacShield(installButton);
webBrowser.ObjectForScripting = new JSBridge(this);
webBrowser.DocumentCompleted += (o, e) =>
{
var b = o as WebBrowser;
(b.ObjectForScripting as JSBridge).Document = b.Document;
};
RefreshMods();
string response = UtilityProgram.CallSimpleResponse("--settings-value", SupportDir, "Graphics.Renderer");
if (Util.IsError(ref response) || response.Equals("gl", StringComparison.InvariantCultureIgnoreCase))
glButton.Checked = true;
else
cgButton.Checked = true;
}
Mod GetMetadata(string mod)
{
string responseString = UtilityProgram.CallSimpleResponse("-i", mod);
if (Util.IsError(ref responseString)) return null;
string[] lines = responseString.Split(new string[] { "\n" }, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < lines.Length; i++)
lines[i] = lines[i].Trim('\r');
string title = "", version = "", author = "", description = "", requires = "";
bool standalone = false;
foreach (string line in lines)
{
string s = line.Trim(' ', '\r', '\n');
int i = s.IndexOf(':');
if (i + 2 > s.Length) continue;
string value = s.Substring(i + 2);
switch (s.Substring(0, i))
{
case "Title":
title = value;
break;
case "Version":
version = value;
break;
case "Author":
author = value;
break;
case "Description":
description = value;
break;
case "Requires":
requires = value;
break;
case "Standalone":
standalone = bool.Parse(value);
break;
default:
break;
}
}
return new Mod(title, version, author, description, requires, standalone);
}
void RefreshMods()
{
string responseString = UtilityProgram.CallSimpleResponse("--list-mods");
string[] mods;
if (!Util.IsError(ref responseString))
mods = responseString.Split(new string[] { "\n" }, StringSplitOptions.RemoveEmptyEntries);
else
throw new Exception(string.Format("Could not list mods: {0}", responseString));
for (int i = 0; i < mods.Length; i++)
mods[i] = mods[i].Trim('\r');
allMods = mods.ToDictionary(x => x, x => GetMetadata(x));
(webBrowser.ObjectForScripting as JSBridge).AllMods = allMods;
RefreshModTree(treeView, allMods.Keys.ToArray());
}
private void InstallMod(object sender, EventArgs e)
{
if (installModDialog.ShowDialog() != DialogResult.OK) return;
string pipename = UtilityProgram.GetPipeName();
var p = UtilityProgram.CallWithAdmin("--extract-zip", pipename, installModDialog.FileName, "");
var pipe = new NamedPipeClientStream(".", pipename, PipeDirection.In);
pipe.Connect();
p.WaitForExit();
using (var response = new StreamReader(pipe))
{
response.ReadToEnd();
}
RefreshMods();
}
void RefreshModTree(TreeView treeView, string[] modList)
{
treeView.Nodes["ModsNode"].Nodes.Clear();
Dictionary<string, TreeNode> nodes;
nodes = modList.Where(x => allMods[x].Standalone).ToDictionary(x => x,
x => new TreeNode(allMods[x].Title) { Name = x });
string[] rootMods = modList.Where(x => allMods[x].Standalone).ToArray();
Stack<string> remaining = new Stack<string>(modList.Except(nodes.Keys));
bool progress = true;
while (remaining.Count > 0 && progress)
{
progress = false;
string s = remaining.Pop();
var n = new TreeNode(allMods[s].Title) { Name = s };
if (allMods[s].Requires == null) { remaining.Push(s); continue; }
if (!nodes.ContainsKey(allMods[s].Requires)) { remaining.Push(s); continue; }
nodes[allMods[s].Requires].Nodes.Add(n);
nodes.Add(s, n);
progress = true;
}
foreach (string s in rootMods)
treeView.Nodes["ModsNode"].Nodes.Add(nodes[s]);
if (remaining.Count > 0)
{
var unspecified = new TreeNode("<Unspecified Dependency>") { ForeColor = SystemColors.GrayText };
var missing = new TreeNode("<Missing Dependency>") { ForeColor = SystemColors.GrayText };
foreach (var s in remaining)
{
if (allMods[s].Requires == null)
unspecified.Nodes.Add(new TreeNode(allMods[s].Title)
{ ForeColor = SystemColors.GrayText, Name = s });
else if (!nodes.ContainsKey(allMods[s].Requires))
missing.Nodes.Add(new TreeNode(allMods[s].Title)
{ ForeColor = SystemColors.GrayText, Name = s });
}
string brokenKey = "BrokenModsNode";
if (treeView.Nodes[brokenKey] != null)
treeView.Nodes.RemoveByKey(brokenKey);
treeView.Nodes.Add(brokenKey, "Broken Mods");
treeView.Nodes[brokenKey].Nodes.Add(unspecified);
treeView.Nodes[brokenKey].Nodes.Add(missing);
}
treeView.Nodes["ModsNode"].ExpandAll();
treeView.Invalidate();
string responseString = UtilityProgram.CallSimpleResponse("--settings-value", SupportDir, "Game.Mods");
if (Util.IsError(ref responseString))
treeView.SelectedNode = treeView.Nodes["ModsNode"].Nodes["ra"];
else
treeView.SelectedNode = treeView.Nodes["ModsNode"].Nodes[responseString];
}
void treeView_AfterSelect(object sender, TreeViewEventArgs e)
{
Mod selectedMod;
if (!allMods.TryGetValue(e.Node.Name, out selectedMod)) return;
string modHtmlPath = string.Format("mods{0}{1}{0}mod.html", Path.DirectorySeparatorChar, e.Node.Name);
if (!File.Exists(modHtmlPath)) return;
webBrowser.Navigate(Path.GetFullPath(modHtmlPath));
}
private void rendererChanged(object sender, EventArgs e)
{
if (sender == glButton)
Renderer = "Gl";
else
Renderer = "Cg";
}
void formClosing(object sender, FormClosingEventArgs e)
{
}
}
}

View File

@@ -1,123 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="installModDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>

View File

@@ -1,33 +0,0 @@
#region Copyright & License Information
/*
* 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.
*/
#endregion
using System;
namespace OpenRA.Launcher
{
public class Mod
{
public string Title { get; private set; }
public string Version { get; private set; }
public string Author { get; private set; }
public string Description { get; private set; }
public string Requires { get; private set; }
public bool Standalone { get; private set; }
public Mod(string title, string version, string author, string description, string requires, bool standalone)
{
Title = title;
Version = version;
Author = author;
Description = description;
Requires = requires;
Standalone = standalone;
}
}
}

View File

@@ -1,76 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{2EA6C9C7-28A8-46C6-A42C-9275692EB285}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>OpenRA.Launcher</RootNamespace>
<AssemblyName>OpenRA.Launcher</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<StartupObject>
</StartupObject>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<UseVSHostingProcess>false</UseVSHostingProcess>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
<ItemGroup>
<Compile Include="Download.cs" />
<Compile Include="JSBridge.cs" />
<Compile Include="Launcher.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Launcher.Designer.cs">
<DependentUpon>Launcher.cs</DependentUpon>
</Compile>
<Compile Include="Mod.cs" />
<Compile Include="Program.cs" />
<Compile Include="Util.cs" />
<Compile Include="UtilityProgram.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Launcher.resx">
<DependentUpon>Launcher.cs</DependentUpon>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
</Project>

View File

@@ -1,26 +0,0 @@
#region Copyright & License Information
/*
* 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.
*/
#endregion
using System;
using System.Windows.Forms;
namespace OpenRA.Launcher
{
static class Program
{
[STAThread]
static void Main(string[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Launcher());
}
}
}

View File

@@ -1,45 +0,0 @@
#region Copyright & License Information
/*
* 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.
*/
#endregion
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace OpenRA.Launcher
{
static class Util
{
[DllImport("user32")]
public static extern UInt32 SendMessage
(IntPtr hWnd, UInt32 msg, UInt32 wParam, UInt32 lParam);
internal const int BCM_FIRST = 0x1600; //Normal button
internal const int BCM_SETSHIELD = (BCM_FIRST + 0x000C); //Elevated button
static public void UacShield(Button b)
{
b.FlatStyle = FlatStyle.System;
SendMessage(b.Handle, BCM_SETSHIELD, 0, 0xFFFFFFFF);
}
static public bool IsError(ref string utilityResponseLine)
{
utilityResponseLine = utilityResponseLine.Trim('\r', '\n');
if (utilityResponseLine.StartsWith("Error:"))
{
utilityResponseLine = utilityResponseLine.Remove(0, 7);
return true;
}
return false;
}
}
}

View File

@@ -1,129 +0,0 @@
#region Copyright & License Information
/*
* 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.
*/
#endregion
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.IO.Pipes;
using System.Text;
namespace OpenRA.Launcher
{
class UtilityProgramResponse
{
public bool IsError
{
get { return response.StartsWith("Error:"); }
}
string response;
public string Response
{
get
{
if (IsError)
return response.Remove(0, 7);
else
return response;
}
}
public string[] ResponseLines
{
get
{
string s = response;
if (IsError)
s = response.Remove(0, 7);
return s.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
}
}
public UtilityProgramResponse(string response)
{
this.response = response.Trim('\r', '\n');
}
}
static class UtilityProgram
{
public static string GetPipeName()
{
return "OpenRA.Utility" + Guid.NewGuid().ToString();
}
static string BuildArgs(string command, string[] args)
{
StringBuilder arguments = new StringBuilder();
arguments.Append("\"");
arguments.Append(command + "=");
arguments.Append(string.Join(",", args));
arguments.Append("\"");
return arguments.ToString();
}
public static Process Call(string command, string pipename, EventHandler onExit, params string[] args)
{
Process p = new Process();
p.StartInfo.FileName = "OpenRA.Utility.exe";
p.StartInfo.Arguments = BuildArgs(command, args) + " --pipe=" + pipename;
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true;
if (onExit != null)
{
p.EnableRaisingEvents = true;
p.Exited += onExit;
}
p.Start();
return p;
}
public static string CallSimpleResponse(string command, params string[] args)
{
string pipename = GetPipeName();
Call(command, pipename, null, args);
string responseString;
NamedPipeClientStream pipe = new NamedPipeClientStream(".", pipename, PipeDirection.In);
pipe.Connect();
using (var response = new StreamReader(pipe))
{
responseString = response.ReadToEnd();
}
return responseString;
}
public static Process CallWithAdmin(string command, string pipename, params string[] args)
{
Process p = new Process();
p.StartInfo.FileName = "OpenRA.Utility.exe";
p.StartInfo.Arguments = BuildArgs(command, args) + " --pipe=" + pipename;
p.StartInfo.Verb = "runas";
try
{
p.Start();
}
catch (Win32Exception e)
{
if (e.NativeErrorCode == 1223) //ERROR_CANCELLED
return null;
throw e;
}
return p;
}
}
}

View File

@@ -1,10 +1,8 @@
#!/bin/bash
rm -rf packaging/linux/rootx64
rm -rf packaging/linux/rootx86
rm -rf packaging/linux/root
rm -rf packaging/built
rm packaging/linux/package32.log
rm packaging/linux/package64.log
rm packaging/linux/package.log
rm packaging/linux/deb/package.log
rm packaging/linux/rpm/package.log
rm packaging/linux/pkgbuild/package.log

View File

@@ -1,35 +1,26 @@
#!/bin/bash
# OpenRA packaging master script for linux packages
if [ $# -ne "4" ]; then
echo "Usage: `basename $0` version files-dir outputdir arch"
if [ $# -ne "3" ]; then
echo "Usage: `basename $0` version files-dir outputdir"
exit 1
fi
VERSION=$1
BUILTDIR=$2
PACKAGEDIR=$3
ROOTDIR=root$4
ROOTDIR=root
# Clean up
rm -rf $ROOTDIR
# Game files
mkdir -p $ROOTDIR/usr/bin/
if [ $4 = "x64" ]; then
cp -T $BUILTDIR/gtklaunch $ROOTDIR/usr/bin/openra
else
cp -T $BUILTDIR/gtklaunch32 $ROOTDIR/usr/bin/openra
fi
cp -T openra-bin root/usr/bin/openra
mkdir -p $ROOTDIR/usr/share/openra/
cp -R $BUILTDIR/* "$ROOTDIR/usr/share/openra/" || exit 3
# Remove unneeded files
rm $ROOTDIR/usr/share/openra/OpenRA.Launcher.exe
rm $ROOTDIR/usr/share/openra/gtklaunch
rm $ROOTDIR/usr/share/openra/gtklaunch32
# Desktop Icons
mkdir -p $ROOTDIR/usr/share/applications/
sed "s/{VERSION}/$VERSION/" openra.desktop > $ROOTDIR/usr/share/applications/openra.desktop
@@ -47,28 +38,25 @@ cp -r hicolor $ROOTDIR/usr/share/icons/
(
echo "Building Debian package."
cd deb
./buildpackage.sh "$VERSION" ../$ROOTDIR "$PACKAGEDIR" $4 &> package.log
./buildpackage.sh "$VERSION" ../$ROOTDIR "$PACKAGEDIR" &> package.log
if [ $? -ne 0 ]; then
echo "Debian package build failed, refer to $PWD/package.log."
fi
) &
if [ $4 = 'x86' ]
then
(
echo "Building Arch-Linux package."
cd pkgbuild
sh buildpackage.sh "$VERSION" ../$ROOTDIR "$PACKAGEDIR" $4 &> package.log
sh buildpackage.sh "$VERSION" ../$ROOTDIR "$PACKAGEDIR" &> package.log
if [ $? -ne 0 ]; then
echo "Arch-Linux package build failed, refer to $PWD/package.log."
fi
) &
fi
(
echo "Building RPM package."
cd rpm
sh buildpackage.sh "$VERSION" ../$ROOTDIR ~/rpmbuild "$PACKAGEDIR" $4 &> package.log
sh buildpackage.sh "$VERSION" ../$ROOTDIR ~/rpmbuild "$PACKAGEDIR" &> package.log
if [ $? -ne 0 ]; then
echo "RPM package build failed, refer to $PWD/package.log."
fi

View File

@@ -1,14 +1,14 @@
Package: openra
Version: {VERSION}
Architecture: {ARCH}
Architecture: all
Maintainer: Matthew Bowra-Dean <matthew@ijw.co.nz>
Uploaders: Maikel van den Hout <ma1kelvdh@gmail.com>, Paul Chote <sleipnir@sleipnirstuff.com>
Installed-Size: {SIZE}
Depends: libopenal1, mono-runtime, libmono-winforms2.0-cil, libfreetype6, libsdl1.2debian, libgl1-mesa-glx, libgl1-mesa-dri, libmono-i18n2.0-cil, libgtk2.0-0, libwebkit-1.0-2
Depends: libopenal1, mono-runtime, libmono-winforms2.0-cil, libfreetype6, libsdl1.2debian, libgl1-mesa-glx, libgl1-mesa-dri, libmono-i18n2.0-cil
Section: games
Priority: extra
Homepage: http://www.open-ra.org/
Description: A multiplayer reimplementation of the Command & Conquer: Red Alert game engine in .NET/Mono, OpenGL, OpenAL and SDL. Has extensive modding support and includes Command & Conquer as an official mod.
Description: A multiplayer reimplementation of the Command & Conquer: Red Alert game engine in .NET/Mono.
.
Please note: OpenRA is currently at an alpha release stage. Releases may be buggy
or unstable. If you have any problems, please report them to the IRC channel (#openra on

View File

@@ -1,40 +1,34 @@
#!/bin/bash
# OpenRA packaging script for Debian based distributions
E_BADARGS=85
if [ $# -ne "4" ]
if [ $# -ne "3" ]
then
echo "Usage: `basename $0` version root-dir outputdir arch"
echo "Usage: `basename $0` version root-dir outputdir"
exit $E_BADARGS
fi
VERSION=$1
rootdir=`readlink -f $2`
PACKAGE_SIZE=`du --apparent-size -c $rootdir/usr | grep "total" | awk '{print $1}'`
if [ $4 = "x64" ]
then
ARCH=amd64
else
ARCH=i386
fi
# Copy template files into a clean build directory (required)
mkdir root$ARCH
cp -R DEBIAN root$ARCH
cp -R $rootdir/usr root$ARCH
mkdir root
cp -R DEBIAN root
cp -R $rootdir/usr root
# Create the control and changelog files from templates
sed "s/{VERSION}/$VERSION/" DEBIAN/control | sed "s/{SIZE}/$PACKAGE_SIZE/" | sed "s/{ARCH}/$ARCH/" > root$ARCH/DEBIAN/control
sed "s/{VERSION}/$VERSION/" DEBIAN/changelog > root$ARCH/DEBIAN/changelog
sed "s/{VERSION}/$VERSION/" DEBIAN/control | sed "s/{SIZE}/$PACKAGE_SIZE/" > root/DEBIAN/control
sed "s/{VERSION}/$VERSION/" DEBIAN/changelog > root/DEBIAN/changelog
# Build it in the temp directory, but place the finished deb in our starting directory
pushd root$ARCH
pushd root
# Calculate md5sums and clean up the /usr/ part of them
md5sum `find . -type f | grep -v '^[.]/DEBIAN/'` | sed 's/\.\/usr\//usr\//g' > DEBIAN/md5sums
# Start building, the file should appear in the output directory
dpkg-deb -b . $3/openra-$VERSION-$ARCH.deb
dpkg-deb -b . $3/openra-$VERSION.deb
# Clean up
popd
rm -rf root$ARCH
rm -rf root

View File

@@ -0,0 +1,3 @@
#!/bin/sh
cd /usr/share/openra
mono /usr/share/openra/OpenRA.Game.exe SupportDir=~/.openra "$@"

View File

@@ -3,13 +3,14 @@ pkgname=openra
pkgver={VERSION}
pkgrel=1
pkgdesc="Open Source rebuild of the Red Alert game engine using Mono/OpenGL."
arch=('{ARCH}')
arch=('any')
url="http://open-ra.org"
license=('GPL3')
groups=()
depends=('mono' 'openal' 'mesa' 'freetype2' 'sdl' 'gtk2' 'libwebkit')
depends=('mono' 'openal' 'mesa' 'freetype2' 'sdl')
makedepends=('git' 'unzip' 'wget')
optdepends=()
optdepends=('gksu: Elevation for installing game packages on Gnome platforms'
'kdesudo: Elevation for installing game packages on KDE platforms')
provides=()
conflicts=()
replaces=()

View File

@@ -1,32 +1,22 @@
#!/bin/bash
E_BADARGS=85
if [ $# -ne "4" ]
if [ $# -ne "3" ]
then
echo "Usage: `basename $0` version root-dir outputdir arch"
echo "Usage: `basename $0` version root-dir outputdir"
exit $E_BADARGS
fi
if [ $4 = "x64" ]
then
ARCH=x86_64
else
ARCH=i686
fi
# Replace any dashes in the version string with periods
PKGVERSION=`echo $1 | sed "s/-/\\./g"`
cp PKGBUILD PKGBUILD$ARCH
sed -i "s/{VERSION}/$PKGVERSION/" PKGBUILD$ARCH
sed -i "s/{VERSION}/$PKGVERSION/" PKGBUILD
rootdir=`readlink -f $2`
sed -i "s|{ROOT}|$rootdir|" PKGBUILD$ARCH
sed -i "s/{ARCH}/$ARCH/" PKGBUILD$ARCH
sed -i "s|{ROOT}|$rootdir|" PKGBUILD
makepkg --holdver -p PKGBUILD$ARCH
makepkg --holdver -p PKGBUILD
if [ $? -ne 0 ]; then
exit 1
fi
mv openra-$PKGVERSION-1-$ARCH.pkg.tar.xz $3
mv openra-$PKGVERSION-1-any.pkg.tar.xz $3

View File

@@ -1,42 +1,33 @@
#!/bin/bash
E_BADARGS=85
if [ $# -ne "5" ]
if [ $# -ne "4" ]
then
echo "Usage: `basename $0` version root-dir packaging-dir outputdir arch"
echo "Usage: `basename $0` version root-dir packaging-dir outputdir"
exit $E_BADARGS
fi
if [ $5 = "x64" ]
then
ARCH=x86_64
else
ARCH=i386
fi
# Replace any dashes in the version string with periods
PKGVERSION=`echo $1 | sed "s/-/\\./g"`
cp openra.spec openra$ARCH.spec
sed -i "s/{VERSION_FIELD}/$PKGVERSION/" openra$ARCH.spec
sed -i "s/{VERSION_FIELD}/$PKGVERSION/" openra.spec
rootdir=`readlink -f $2`
sed -i "s|{ROOT_DIR}|$rootdir|" openra$ARCH.spec
sed -i "s|{ROOT_DIR}|$rootdir|" openra.spec
for x in `find $rootdir -type f`
do
y="${x#$rootdir}"
sed -i "/%files/ a $y" openra$ARCH.spec
sed -i "/%files/ a $y" openra.spec
done
cp openra$ARCH.spec "$3/SPECS/"
cp openra.spec "$3/SPECS/"
cd "$3"
rpmbuild --target $ARCH --buildroot /tmp/openra$ARCH/ -bb SPECS/openra$ARCH.spec
rpmbuild --target noarch --buildroot /tmp/openra/ -bb SPECS/openra.spec
if [ $? -ne 0 ]; then
exit 1
fi
cd RPMS/$ARCH/
mv openra-$PKGVERSION-1.$ARCH.rpm $4
cd RPMS/noarch/
mv openra-$PKGVERSION-1.noarch.rpm $4

View File

@@ -9,7 +9,7 @@ License: GPL3
URL: http://open-ra.org
Group: Amusements/Games
Packager: Matthew Bowra-Dean <matthew@ijw.co.nz>
Requires: mono-core mono-devel SDL openal mesa-dri-drivers-experimental gtk2 webkitgtk
Requires: mono-core mono-devel SDL openal mesa-dri-drivers-experimental
Prefix: /usr
Source: %{name}-%{version}.tar.gz
Buildroot: /tmp/openra

View File

@@ -17,12 +17,9 @@ fi
cp -rv ../../OpenRA.Launcher.Mac/build/Release/OpenRA.app OpenRA.app
cp -rv $2/* "OpenRA.app/Contents/Resources/" || exit 3
# Icon isn't used, and editor doesn't work, OpenRA.Launcher is Windows specific, gtklaunch is Linux specific.
# Icon isn't used, and editor doesn't work.
rm OpenRA.app/Contents/Resources/OpenRA.ico
rm OpenRA.app/Contents/Resources/OpenRA.Editor.exe
rm OpenRA.app/Contents/Resources/OpenRA.Launcher.exe
rm OpenRA.app/Contents/Resources/gtklaunch
rm OpenRA.app/Contents/Resources/gtklaunch32
# Package app bundle into a zip and clean up
zip OpenRA-$1 -r -9 OpenRA.app

View File

@@ -26,9 +26,9 @@ find . -path "*.mdb" -delete
# List of files that are packaged on all platforms
# Note that the Tao dlls are shipped on all platforms except osx and that
# they are now installed to the game directory instead of placed in the gac
FILES="OpenRA.Launcher.exe OpenRA.Game.exe OpenRA.Editor.exe OpenRA.Utility.exe OpenRA.Renderer.Cg.dll \
FILES="OpenRA.Game.exe OpenRA.Editor.exe OpenRA.Utility.exe OpenRA.Renderer.Cg.dll \
OpenRA.Renderer.Gl.dll OpenRA.Renderer.Null.dll OpenRA.FileFormats.dll FreeSans.ttf FreeSansBold.ttf titles.ttf \
cg glsl mods/ra mods/cnc COPYING HACKING INSTALL gtklaunch gtklaunch32"
cg glsl mods/ra mods/cnc COPYING HACKING INSTALL
echo "Copying files..."
for i in $FILES; do
@@ -76,15 +76,10 @@ echo "Creating packages..."
(
cd linux
sh buildpackage.sh "$VERSION" "$BUILTDIR" "$OUTPUTDIR" "x86" &> package32.log
sh buildpackage.sh "$VERSION" "$BUILTDIR" "$OUTPUTDIR" &> package.log
if [ $? -ne 0 ]; then
echo "linux package build failed, refer to linux/package.log."
fi
sh buildpackage.sh "$VERSION" "$BUILTDIR" "$OUTPUTDIR" "x64" &> package64.log
if [ $? -ne 0 ]; then
echo "linux package build failed, refer to linux/package.log."
fi
) &
wait

View File

@@ -25,11 +25,9 @@ esac
LINUXVERSION=`echo $VERSION | sed "s/-/\\./g"`
./uploader.sh linux "$VERSION" $PKGDIR/openra-$VERSION-i386.deb "deblatest32" "$FTPSERVER" "$FTPPATH" "$3" "$4"
./uploader.sh linux "$VERSION" $PKGDIR/openra-$LINUXVERSION-1.i386.rpm "rpmlatest32" "$FTPSERVER" "$FTPPATH" "$3" "$4"
./uploader.sh linux "$VERSION" $PKGDIR/openra-$LINUXVERSION-1-i686.pkg.tar.xz "archlatest32" "$FTPSERVER" "$FTPPATH" "$3" "$4"
./uploader.sh linux "$VERSION" $PKGDIR/openra-$VERSION-amd64.deb "deblatest" "$FTPSERVER" "$FTPPATH" "$3" "$4"
./uploader.sh linux "$VERSION" $PKGDIR/openra-$LINUXVERSION-1.x86_64.rpm "rpmlatest" "$FTPSERVER" "$FTPPATH" "$3" "$4"
./uploader.sh linux "$VERSION" $PKGDIR/openra-$VERSION.deb "deblatest" "$FTPSERVER" "$FTPPATH" "$3" "$4"
./uploader.sh linux "$VERSION" $PKGDIR/openra-$LINUXVERSION-1.noarch.rpm "rpmlatest" "$FTPSERVER" "$FTPPATH" "$3" "$4"
./uploader.sh linux "$VERSION" $PKGDIR/openra-$LINUXVERSION-1-any.pkg.tar.xz "archlatest" "$FTPSERVER" "$FTPPATH" "$3" "$4"
if [ "$TYPE" = "release" ]; then
wput --basename=../ -u ../VERSION ftp://$3:$4@$FTPSERVER/$FTPPATHBASE/master/

View File

@@ -75,7 +75,6 @@ SectionEnd
Section "Client" Client
SetOutPath "$INSTDIR"
File "${SRCDIR}\OpenRA.Launcher.exe"
File "${SRCDIR}\OpenRA.Game.exe"
File "${SRCDIR}\OpenRA.Utility.exe"
File "${SRCDIR}\OpenRA.FileFormats.dll"
@@ -92,8 +91,6 @@ Section "Client" Client
!insertmacro MUI_STARTMENU_WRITE_BEGIN Application
CreateDirectory "$SMPROGRAMS\$StartMenuFolder"
CreateShortCut "$SMPROGRAMS\$StartMenuFolder\OpenRA Launcher.lnk" $OUTDIR\OpenRA.Launcher.exe "" \
"$OUTDIR\OpenRA.ico" "" "" "" ""
CreateShortCut "$SMPROGRAMS\$StartMenuFolder\OpenRA - Red Alert.lnk" $OUTDIR\OpenRA.Game.exe "Game.Mods=ra" \
"$OUTDIR\OpenRA.ico" "" "" "" ""
CreateShortCut "$SMPROGRAMS\$StartMenuFolder\OpenRA - Command & Conquer.lnk" $OUTDIR\OpenRA.Game.exe "Game.Mods=cnc" \