From b8a20629dc45102454d1f57a2407970ba1767bf3 Mon Sep 17 00:00:00 2001 From: Alvarito050506 Date: Sun, 4 Jul 2021 16:16:01 -0300 Subject: [PATCH] Work-In-Progress... very WIP, so memory leak, much broken --- Makefile | 14 +- src/callbacks.c | 217 ------------------------- src/config.c | 125 ++++++--------- src/features.c | 252 +++++++++++++++++++++++++++++ src/helpers.c | 151 ------------------ src/include/config.h | 87 +++++------ src/include/libreborn.h | 47 ------ src/include/mcpil.h | 85 ++++------ src/include/servers.h | 44 ------ src/include/splashes.h | 2 +- src/mcpil.c | 82 ++++++++-- src/mods/multiplayer.c | 142 ----------------- src/play.c | 290 ++++++++++++++++++++++++++++++++++ src/servers.c | 116 ++++++++++++++ src/tabs.c | 339 ---------------------------------------- 15 files changed, 845 insertions(+), 1148 deletions(-) delete mode 100644 src/callbacks.c create mode 100644 src/features.c delete mode 100644 src/helpers.c delete mode 100644 src/include/libreborn.h delete mode 100644 src/include/servers.h delete mode 100644 src/mods/multiplayer.c create mode 100644 src/play.c create mode 100644 src/servers.c delete mode 100644 src/tabs.c diff --git a/Makefile b/Makefile index bf2dc73..8a9630e 100644 --- a/Makefile +++ b/Makefile @@ -36,13 +36,13 @@ ARM_STRIP:=arm-linux-gnueabihf-strip ARCH:=$(shell $(CC) -print-multiarch | grep -Eo "arm|aarch|86|x86_64") endif -VERSION:=0.11.2 +VERSION:=0.12.0 -OBJS:=$(patsubst %,build/%.o,mcpil config helpers callbacks tabs) +OBJS:=$(patsubst %,build/%.o,mcpil config features play servers) CFLAGS:=-DGMCPIL_VERSION=\"v$(VERSION)\" -I./src/include -Wall -Wno-address-of-packed-member -Wno-pointer-to-int-cast -Wno-unused-result -CFLAGS+=`pkg-config --cflags gtk+-3.0 json-glib-1.0` -LDFLAGS+=-Wl,--no-undefined `pkg-config --libs gtk+-3.0 json-glib-1.0` +CFLAGS+=$(shell pkg-config --cflags gtk+-3.0 json-glib-1.0) +LDFLAGS+=-Wl,--no-undefined $(shell pkg-config --libs gtk+-3.0 json-glib-1.0) ifdef DEBUG CFLAGS+=-g -Wextra -Werror @@ -63,7 +63,7 @@ ifndef DEBUG endif ./build/%.o: ./src/%.c ./src/include/*.h - $(CC) -fPIC -c $< -o $@ $(CFLAGS) + $(CC) -fPIC -fpie -c $< -o $@ $(CFLAGS) mkdir: mkdir -p ./build/ @@ -88,7 +88,7 @@ else @echo "Architecture: armhf" >> ./deb/DEBIAN/control endif @echo "Section: contrib/misc" >> ./deb/DEBIAN/control - @echo "Depends: libc6 (>= 2.28), minecraft-pi-reborn-client (>= 2.0), libgtk-3-0, libjson-glib-1.0-0" >> ./deb/DEBIAN/control + @echo "Depends: libc6 (>= 2.28), minecraft-pi-reborn-client (>= 2.1.0), libgtk-3-0, libjson-glib-1.0-0" >> ./deb/DEBIAN/control @echo "Maintainer: Alvarito050506 " >> ./deb/DEBIAN/control @echo "Homepage: https://mcpirevival.tk" >> ./deb/DEBIAN/control @echo "Vcs-Browser: https://github.com/MCPI-Revival/gMCPIL" >> ./deb/DEBIAN/control @@ -101,4 +101,4 @@ endif clean: rm -rf ./deb/ rm -rf ./build/ - rm -f ./gmcpil_*-*.deb + rm -f ./gmcpil_*.deb diff --git a/src/callbacks.c b/src/callbacks.c deleted file mode 100644 index efcdc5c..0000000 --- a/src/callbacks.c +++ /dev/null @@ -1,217 +0,0 @@ -/* - * callbacks.c - MCPIL GTK+ callbacks - * - * Copyright 2021 Alvarito050506 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - * - */ - -#define _GNU_SOURCE /* Required for asprintf */ - -#include -#include -#include -#include -#include - -#include -#include -#include - -/* Callbacks */ -void features_cb(__attribute__((unused)) GtkWidget* button, void* udata) -{ - int i = 0; - int sz = 1; - int len = 0; - int tmp = 0; - - if (features_envs[4] != NULL) - { - free(features_envs[4]); - } - features_envs[4] = (char*)malloc(1); - - while (i < featc) - { - if (FEAT_INT(i) == TRUE) - { - len = strlen(FEAT_STR(i)); - tmp = sz + len + 1; - features_envs[4] = (char*)realloc((void*)features_envs[4], tmp); - if (sz == 1) - { - strcpy(features_envs[4], FEAT_STR(i)); - } else - { - strcat(features_envs[4], FEAT_STR(i)); - } - features_envs[4][tmp - 2] = '|'; - features_envs[4][tmp - 1] = 0x00; - sz = tmp; - } - i++; - } - - if ((int)udata == TRUE) - { - mcpil_config_set_features(config, features_envs[4]); - mcpil_config_save(config); - } - return; -} - -void toggle_cb(__attribute__((unused)) GtkWidget* check, void* udata) -{ - int i = (int)udata; - - FEAT_BOOL(i) = (void*)(intptr_t)(!FEAT_INT(i)); - return; -} - -void multiplayer_cb(__attribute__((unused)) GtkWidget* button, __attribute__((unused)) void* udata) -{ - const char* ip; - const char* port; - GtkEntryBuffer* ip_buff; - GtkEntryBuffer* port_buff; - - ip_buff = gtk_entry_get_buffer(GTK_ENTRY(settings_box.ip_entry)); - port_buff = gtk_entry_get_buffer(GTK_ENTRY(settings_box.port_entry)); - ip = gtk_entry_buffer_get_text(ip_buff); - port = gtk_entry_buffer_get_text(port_buff); - - if (strlen(port) < 2 || strlen(ip) < 3) - { - return; - } - - mcpil_config_set_ip(config, ip); - mcpil_config_set_port(config, port); - mcpil_config_save(config); - setenv("GMCPIL_SERVER_IP", ip, 1); - setenv("GMCPIL_SERVER_PORT", port, 1); - return; -} - -void watch_cb(GPid pid, __attribute__((unused)) int status, __attribute__((unused)) void* udata) -{ - gtk_widget_show_all(window); - g_spawn_close_pid(pid); - return; -} - -void launch_cb(__attribute__((unused)) GtkWidget* button, __attribute__((unused)) void* udata) -{ - char* argv[] = {"minecraft-pi-reborn-client", NULL}; - GPid pid; - GError* err = NULL; - - g_spawn_async(NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH, NULL, NULL, &pid, &err); - - if (err != NULL) - { - g_error("Spawning child failed: %s", err->message); - return; - } - if (mcpil_config_get_hide(config)[0] == 'T') - { - gtk_widget_hide(window); - } - g_child_watch_add(pid, watch_cb, NULL); - return; -} - -void select_cb(__attribute__((unused)) GtkWidget* list, GtkListBoxRow* row, void* udata) -{ - int i = 0; - char tmp[2] = {0x00, 0x00}; - - i = gtk_list_box_row_get_index(row); - gtk_label_set_text(GTK_LABEL(udata), profile_descriptions[i]); - - setenv("MCPI_FEATURE_FLAGS", features_envs[i], 1); - tmp[0] = i + 0x30; - mcpil_config_set_last_profile(config, tmp); - return; -} - -void settings_cb(__attribute__((unused)) GtkWidget* button, __attribute__((unused)) void* udata) -{ - const char* username; - const char* distance; - const char* hud; - gboolean hide; - GtkEntryBuffer* username_buff; - GtkEntryBuffer* hud_buff; - - username_buff = gtk_entry_get_buffer(GTK_ENTRY(settings_box.username_entry)); - hud_buff = gtk_entry_get_buffer(GTK_ENTRY(settings_box.hud_entry)); - - username = gtk_entry_buffer_get_text(username_buff); - distance = gtk_combo_box_text_get_active_text(settings_box.distance_combo); - hud = gtk_entry_buffer_get_text(hud_buff); - hide = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(settings_box.hide_check)); - - setenv("MCPI_USERNAME", username, 1); - setenv("MCPI_RENDER_DISTANCE", distance, 1); - setenv("GALLIUM_HUD", hud, 1); - - mcpil_config_set_username(config, username); - mcpil_config_set_distance(config, distance); - mcpil_config_set_hud(config, hud); - if (hide) - { - mcpil_config_set_hide(config, "TRUE"); - } else - { - mcpil_config_set_hide(config, "FALSE"); - } - mcpil_config_save(config); - return; -} - -void about_cb(__attribute__((unused)) GtkWidget* button, __attribute__((unused)) void* udata) -{ - GError* err; - gtk_show_uri_on_window(GTK_WINDOW(window), "https://discord.gg/jEXwEdx", GDK_CURRENT_TIME, &err); - return; -} - -void activate_cb(GtkApplication* app, __attribute__((unused)) void* udata) -{ - GdkPixbuf* icon; - GtkWidget* notebook; - - window = gtk_application_window_new(app); - gtk_window_set_title(GTK_WINDOW(window), "gMCPIL - MCPIL GTK+ Edition"); - gtk_window_set_default_size(GTK_WINDOW(window), 458, 375); // I don't even know - - icon = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(), "gmcpil", 32, GTK_ICON_LOOKUP_NO_SVG, NULL); - gtk_window_set_icon(GTK_WINDOW(window), icon); - - notebook = gtk_notebook_new(); - - Play_tab(notebook); - Features_tab(notebook); - Settings_tab(notebook); - About_tab(notebook); - - gtk_container_add(GTK_CONTAINER(window), notebook); - gtk_widget_show_all(window); - return; -} diff --git a/src/config.c b/src/config.c index d7e3fce..49c12ac 100644 --- a/src/config.c +++ b/src/config.c @@ -1,5 +1,5 @@ /* - * config.c + * config.c - GMCPILConfig class * * Copyright 2021 Alvarito050506 * @@ -27,10 +27,8 @@ #include #include -struct __attribute__((packed)) MCPILConfigPrivate +struct __attribute__((packed)) GMCPILConfigPrivate { - gchar* ip; - gchar* port; gchar* username; gchar* features; gchar* distance; @@ -43,8 +41,6 @@ struct __attribute__((packed)) MCPILConfigPrivate enum { PROP_NULL, - PROP_IP, - PROP_PORT, PROP_USERNAME, PROP_FEATURES, PROP_DISTANCE, @@ -54,37 +50,35 @@ enum PROP_LAST }; -G_DEFINE_TYPE_WITH_CODE(MCPILConfig, mcpil_config, G_TYPE_OBJECT, G_ADD_PRIVATE(MCPILConfig)) +G_DEFINE_TYPE_WITH_CODE(GMCPILConfig, gmcpil_config, G_TYPE_OBJECT, G_ADD_PRIVATE(GMCPILConfig)) -static void mcpil_config_finalize(GObject* obj); -static void mcpil_config_set_property(GObject* obj, guint prop_id, const GValue* value, GParamSpec* pspec); -static void mcpil_config_get_property(GObject* obj, guint prop_id, GValue* value, GParamSpec* pspec); +static void gmcpil_config_finalize(GObject* obj); +static void gmcpil_config_set_property(GObject* obj, guint prop_id, const GValue* value, GParamSpec* pspec); +static void gmcpil_config_get_property(GObject* obj, guint prop_id, GValue* value, GParamSpec* pspec); -static void mcpil_config_class_init(MCPILConfigClass* klass) +static void gmcpil_config_class_init(GMCPILConfigClass* klass) { GObjectClass* gobject_class = G_OBJECT_CLASS(klass); GParamSpec* pspec; - gobject_class->finalize = mcpil_config_finalize; + gobject_class->finalize = gmcpil_config_finalize; - gobject_class->get_property = mcpil_config_get_property; - gobject_class->set_property = mcpil_config_set_property; + gobject_class->get_property = gmcpil_config_get_property; + gobject_class->set_property = gmcpil_config_set_property; - MCPIL_GLIB_PROPERTY("ip", "IP", "Server IP", PROP_IP); - MCPIL_GLIB_PROPERTY("port", "Port", "Server Port", PROP_PORT); - MCPIL_GLIB_PROPERTY("username", "Username", "Player name", PROP_USERNAME); - MCPIL_GLIB_PROPERTY("features", "Features", "MCPI-Reborn features", PROP_FEATURES); - MCPIL_GLIB_PROPERTY("distance", "Distance", "Render distance", PROP_DISTANCE); - MCPIL_GLIB_PROPERTY("last_profile", "Last profile", "Last selected profile", PROP_LAST_PROFILE); - MCPIL_GLIB_PROPERTY("hud", "Gallium HUD", "Gallium HUD options", PROP_HUD); - MCPIL_GLIB_PROPERTY("hide", "Hide launcher", "Hide launcher on launch", PROP_HIDE); + GMCPIL_GLIB_PROPERTY("username", "Username", "Player name", PROP_USERNAME); + GMCPIL_GLIB_PROPERTY("features", "Features", "MCPI-Reborn features", PROP_FEATURES); + GMCPIL_GLIB_PROPERTY("distance", "Distance", "Render distance", PROP_DISTANCE); + GMCPIL_GLIB_PROPERTY("last_profile", "Last profile", "Last selected profile", PROP_LAST_PROFILE); + GMCPIL_GLIB_PROPERTY("hud", "Gallium HUD", "Gallium HUD options", PROP_HUD); + GMCPIL_GLIB_PROPERTY("hide", "Hide launcher", "Hide launcher on launch", PROP_HIDE); return; } -static void mcpil_config_init(MCPILConfig* self) +static void gmcpil_config_init(GMCPILConfig* self) { int i = 0; - MCPILConfigPrivate* private = MCPIL_CONFIG_PRIVATE(self); + GMCPILConfigPrivate* private = GMCPIL_CONFIG_PRIVATE(self); gchar** private_gchar = (gchar**)(private); while (i < PROP_LAST - 1) @@ -95,12 +89,12 @@ static void mcpil_config_init(MCPILConfig* self) return; } -static void mcpil_config_finalize(GObject* obj) +static void gmcpil_config_finalize(GObject* obj) { int i = 0; - MCPILConfig* self = MCPIL_CONFIG(obj); - MCPILConfigPrivate* private = MCPIL_CONFIG_PRIVATE(self); - GObjectClass* parent_class = G_OBJECT_CLASS(mcpil_config_parent_class); + GMCPILConfig* self = GMCPIL_CONFIG(obj); + GMCPILConfigPrivate* private = GMCPIL_CONFIG_PRIVATE(self); + GObjectClass* parent_class = G_OBJECT_CLASS(gmcpil_config_parent_class); gchar** private_gchar = (gchar**)(private); while (i < PROP_LAST - 1) @@ -115,19 +109,17 @@ static void mcpil_config_finalize(GObject* obj) return; } -GETTER_SETTER(ip); -GETTER_SETTER(port); -GETTER_SETTER(username); -GETTER_SETTER(features); -GETTER_SETTER(distance); -GETTER_SETTER(last_profile); -GETTER_SETTER(hud); -GETTER_SETTER(hide); +GMCPIL_GETTER_SETTER(username); +GMCPIL_GETTER_SETTER(features); +GMCPIL_GETTER_SETTER(distance); +GMCPIL_GETTER_SETTER(last_profile); +GMCPIL_GETTER_SETTER(hud); +GMCPIL_GETTER_SETTER(hide); -static void mcpil_config_set_property(GObject* obj, guint prop_id, const GValue* value, GParamSpec* pspec) +static void gmcpil_config_set_property(GObject* obj, guint prop_id, const GValue* value, GParamSpec* pspec) { - MCPILConfig* self = MCPIL_CONFIG(obj); - MCPILConfigPrivate* private = MCPIL_CONFIG_PRIVATE(self); + GMCPILConfig* self = GMCPIL_CONFIG(obj); + GMCPILConfigPrivate* private = GMCPIL_CONFIG_PRIVATE(self); gchar** private_gchar = (gchar**)(private); if (prop_id <= PROP_LAST) @@ -140,11 +132,10 @@ static void mcpil_config_set_property(GObject* obj, guint prop_id, const GValue* return; } -static void mcpil_config_get_property(GObject* obj, guint prop_id, GValue* value, GParamSpec* pspec) +static void gmcpil_config_get_property(GObject* obj, guint prop_id, GValue* value, GParamSpec* pspec) { - MCPILConfig* self = MCPIL_CONFIG(obj); - - MCPILConfigPrivate* private = MCPIL_CONFIG_PRIVATE(self); + GMCPILConfig* self = GMCPIL_CONFIG(obj); + GMCPILConfigPrivate* private = GMCPIL_CONFIG_PRIVATE(self); gchar** private_gchar = (gchar**)(private); if (prop_id <= PROP_LAST) @@ -157,39 +148,13 @@ static void mcpil_config_get_property(GObject* obj, guint prop_id, GValue* value return; } -MCPILConfig* mcpil_config_new_from_file(gchar* filename, GError** err) -{ - int sz; - char* buff; - FILE* fd; - MCPILConfig* self; - - fd = fopen(filename, "a+"); - if (fd == NULL) - { - return NULL; - } - - fseek(fd, 0, SEEK_END); - sz = ftell(fd); - fseek(fd, 0, SEEK_SET); - - buff = (char*)malloc(sz); - fread(buff, 1, sz, fd); - - self = MCPIL_CONFIG(json_gobject_from_data(MCPIL_TYPE_CONFIG, buff, sz, err)); - free(buff); - fclose(fd); - return self; -} - -MCPILConfig* mcpil_config_new(gchar* filename) +GMCPILConfig* gmcpil_config_new(gchar* filename) { int sz; char* buff; FILE* fd; - MCPILConfig* self; - MCPILConfigPrivate* private; + GMCPILConfig* self; + GMCPILConfigPrivate* private; GObject* obj; GError* err = NULL; @@ -203,7 +168,7 @@ MCPILConfig* mcpil_config_new(gchar* filename) sz = ftell(fd); fseek(fd, 0, SEEK_SET); - if (sz <= 2) + if (sz <= 13) /* {"ip":"a.co"} */ { buff = (char*)malloc(2); buff[0] = '{'; @@ -211,18 +176,18 @@ MCPILConfig* mcpil_config_new(gchar* filename) sz = 2; } else { - buff = (char*)malloc(sz); + buff = (char*)malloc(sz + 1); fread(buff, 1, sz, fd); } - obj = json_gobject_from_data(MCPIL_TYPE_CONFIG, buff, sz, &err); + obj = json_gobject_from_data(GMCPIL_TYPE_CONFIG, buff, sz, &err); if (err != NULL) { err = NULL; - obj = g_object_new(MCPIL_TYPE_CONFIG, 0); + obj = g_object_new(GMCPIL_TYPE_CONFIG, 0); } - self = MCPIL_CONFIG(obj); - private = MCPIL_CONFIG_PRIVATE(self); + self = GMCPIL_CONFIG(obj); + private = GMCPIL_CONFIG_PRIVATE(self); private->filename = g_strdup(filename); free(buff); @@ -230,11 +195,11 @@ MCPILConfig* mcpil_config_new(gchar* filename) return self; } -int mcpil_config_save(MCPILConfig* self) +int gmcpil_config_save(GMCPILConfig* self) { char* buff; FILE* fd; - MCPILConfigPrivate* private = MCPIL_CONFIG_PRIVATE(self); + GMCPILConfigPrivate* private = GMCPIL_CONFIG_PRIVATE(self); fd = fopen(private->filename, "w"); if (fd == NULL) diff --git a/src/features.c b/src/features.c new file mode 100644 index 0000000..96beaa2 --- /dev/null +++ b/src/features.c @@ -0,0 +1,252 @@ +/* + * features.c - gMCPIL features tab + * + * Copyright 2021 Alvarito050506 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + */ + +#include +#include +#include +#include +#include + +#include +#include + +int featc; +char* features_envs[5] = {""}; +feature_t features[32]; + +static int get_features() +{ + int i = 0; + int sz = 0; + int offset = 0; + size_t buff_sz; + char* buff; + FILE* file; + + file = fopen("/opt/minecraft-pi-reborn-client/available-feature-flags", "r"); + if (file == NULL) + { + return -1; + } + + buff_sz = 48; + buff = (char*)malloc((int)buff_sz + 1); + buff[0] = 0x00; + while ((sz = getline(&buff, &buff_sz, file)) > 0) + { + FEAT_BOOL(i) = (void*)(intptr_t)(buff[0] == 'T'); + buff[sz - 1] = 0x00; + offset = FEAT_BOOL(i) == FALSE ? 6 : 5; + FEAT_PTR(i) = strdup(buff + offset); + i++; + } + free(buff); + fclose(file); + return i; +} + +static int set_feature_envs(int feat) +{ + int i = 0; + static int sz[3] = {1, 1, 1}; + static int len[3] = {0, 0, 0}; + static int tmp[3] = {0, 0, 0}; + + while (i < 3) + { + if (i == 0 && FEAT_CMP(feat, "Touch GUI")) + { + i++; + continue; + } + if (i == 2) + { + if (FEAT_CMP(feat, "Fancy Graphics") + || FEAT_CMP(feat, "Smooth Lighting") + || FEAT_CMP(feat, "Animated Water") + || FEAT_CMP(feat, "Disable gui_blocks Atlas")) + { + i++; + continue; + } + } + if (FEAT_INT(feat) == TRUE || (i >= 2 && i <= 3 && FEAT_CMP(feat, "Force Mob Spawning"))) + { + len[i] = strlen(FEAT_STR(feat)); + tmp[i] = sz[i] + len[i] + 1; + features_envs[i + 1] = (char*)realloc((void*)features_envs[i + 1], tmp[i]); + if (sz[i] == 1) + { + strcpy(features_envs[i + 1], FEAT_STR(feat)); + } else + { + strcat(features_envs[i + 1], FEAT_STR(feat)); + } + features_envs[i + 1][tmp[i] - 2] = '|'; + features_envs[i + 1][tmp[i] - 1] = 0x00; + sz[i] = tmp[i]; + } + i++; + } + return 0; +} + +static feature_t* get_feature(char* str) +{ + int i = 0; + + while (i < featc) + { + if (FEAT_CMP(i, str)) + { + return &(features[i]); + } + i++; + } + return NULL; +} + +static void features_cb(__attribute__((unused)) GtkWidget* button, void* udata) +{ + int i = 0; + int sz = 1; + int len = 0; + int tmp = 0; + + if (features_envs[4] != NULL) + { + free(features_envs[4]); + } + features_envs[4] = (char*)malloc(1); + + while (i < featc) + { + if (FEAT_INT(i) == TRUE) + { + len = strlen(FEAT_STR(i)); + tmp = sz + len + 1; + features_envs[4] = (char*)realloc((void*)features_envs[4], tmp); + if (sz == 1) + { + strcpy(features_envs[4], FEAT_STR(i)); + } else + { + strcat(features_envs[4], FEAT_STR(i)); + } + features_envs[4][tmp - 2] = '|'; + features_envs[4][tmp - 1] = 0x00; + sz = tmp; + } + i++; + } + + if (udata == NULL) + { + gmcpil_config_set_features(config, features_envs[4]); + gmcpil_config_save(config); + } + return; +} + +static void toggle_cb(__attribute__((unused)) GtkWidget* check, void* udata) +{ + int i = (int)udata; + + FEAT_BOOL(i) = (void*)(intptr_t)(!FEAT_INT(i)); + return; +} + +TAB(Features, features_cb, { + int i = 0; + int last_profile; + char* tmp; + char* features_buff; + GtkWidget* feature_check; + GtkWidget* scroll; + GtkWidget* vbox; + feature_t* feature; + + featc = 0; + featc = get_features(); + + features_envs[1] = (char*)malloc(1); + features_envs[2] = (char*)malloc(1); + features_envs[3] = (char*)malloc(1); + features_envs[4] = NULL; + while (i < featc) + { + set_feature_envs(i); + i++; + } + + features_buff = gmcpil_config_get_features(config); + if (features_buff != NULL) + { + i = 0; + while (i < featc) + { + FEAT_BOOL(i) = FALSE; + i++; + } + + i = 0; + tmp = strtok(features_buff, "|"); + while (tmp != NULL && i < featc) + { + feature = get_feature(tmp); + if (feature != NULL) + { + *feature[0] = (void*)TRUE; + } + tmp = strtok(NULL, "|"); + i++; + } + } else + { + printf("Yeah, no.\n"); + } + + scroll = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll), GTK_SHADOW_NONE); + gtk_container_set_border_width(GTK_CONTAINER(scroll), 0); + + vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + gtk_widget_set_margin_top(vbox, 6); + + i = 0; + while (i < featc) + { + feature_check = gtk_check_button_new_with_label(FEAT_STR(i)); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(feature_check), FEAT_INT(i)); + g_signal_connect(feature_check, "toggled", G_CALLBACK(toggle_cb), (void*)(intptr_t)i); + gtk_box_pack_start(GTK_BOX(vbox), feature_check, FALSE, FALSE, 0); + i++; + } + + features_cb(NULL, (void*)TRUE); + gmcpil_config_set_features(config, features_envs[4]); + last_profile = SAFE_ATOI(gmcpil_config_get_last_profile(config)); + setenv("MCPI_FEATURE_FLAGS", features_envs[last_profile], 1); + gtk_container_add(GTK_CONTAINER(scroll), vbox); + gtk_box_pack_start(GTK_BOX(tab), scroll, TRUE, TRUE, 0); +}); diff --git a/src/helpers.c b/src/helpers.c deleted file mode 100644 index 2652c32..0000000 --- a/src/helpers.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - * helpers.c - MCPIL GTK+ helper functions - * - * Copyright 2021 Alvarito050506 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - * - */ - -#define _GNU_SOURCE /* Required for asprintf */ - -#include -#include -#include -#include -#include - -#include -#include -#include - -/* Helper functions */ -char* get_splash_text() -{ - return splashes[rand() % sizeof(splashes) / sizeof(char*)]; -} - -int get_features() -{ - int i = 0; - int sz = 0; - int offset = 0; - size_t buff_sz; - char* buff; - FILE* file; - - file = fopen("/opt/minecraft-pi-reborn-client/available-feature-flags", "r"); - if (file == NULL) - { - return -1; - } - - buff_sz = 48; - buff = (char*)malloc((int)buff_sz + 1); - buff[0] = 0x00; - while ((sz = getline(&buff, &buff_sz, file)) > 0) - { - FEAT_BOOL(i) = (void*)(intptr_t)(buff[0] == 'T'); - buff[sz - 1] = 0x00; - offset = FEAT_BOOL(i) == FALSE ? 6 : 5; - FEAT_PTR(i) = strdup(buff + offset); - i++; - } - free(buff); - fclose(file); - return i; -} - -int set_feature_envs(int feat) -{ - int i = 0; - static int sz[3] = {1, 1, 1}; - static int len[3] = {0, 0, 0}; - static int tmp[3] = {0, 0, 0}; - - while (i < 3) - { - if (i == 0 && FEAT_CMP(feat, "Touch GUI")) - { - i++; - continue; - } - if (i == 2) - { - if (FEAT_CMP(feat, "Fancy Graphics") || - FEAT_CMP(feat, "Smooth Lighting") || - FEAT_CMP(feat, "Animated Water") || - FEAT_CMP(feat, "Disable gui_blocks Atlas")) - { - i++; - continue; - } - } - if (FEAT_INT(feat) == TRUE) - { - len[i] = strlen(FEAT_STR(feat)); - tmp[i] = sz[i] + len[i] + 1; - features_envs[i + 1] = (char*)realloc((void*)features_envs[i + 1], tmp[i]); - if (sz[i] == 1) - { - strcpy(features_envs[i + 1], FEAT_STR(feat)); - } else - { - strcat(features_envs[i + 1], FEAT_STR(feat)); - } - features_envs[i + 1][tmp[i] - 2] = '|'; - features_envs[i + 1][tmp[i] - 1] = 0x00; - sz[i] = tmp[i]; - } - i++; - } - return 0; -} - -feature_t* get_feature(char* str) -{ - int i = 0; - - while (i < featc) - { - if (FEAT_CMP(i, str)) - { - return &(features[i]); - } - i++; - } - return NULL; -} - -int get_distance(char* str) -{ - switch (str[0]) - { - case 'F': - return 0; - break; - case 'N': - return 1; - break; - case 'S': - return 2; - break; - case 'T': - return 3; - break; - } - return -1; -} diff --git a/src/include/config.h b/src/include/config.h index 408ad44..3ba24ef 100644 --- a/src/include/config.h +++ b/src/include/config.h @@ -28,81 +28,74 @@ G_BEGIN_DECLS -#define MCPIL_TYPE_CONFIG mcpil_config_get_type() -#define MCPIL_CONFIG(obj) G_TYPE_CHECK_INSTANCE_CAST(obj, MCPIL_TYPE_CONFIG, MCPILConfig) -#define MCPIL_IS_CONFIG(obj) G_TYPE_CHECK_INSTANCE_TYPE(obj, MCPIL_TYPE_CONFIG) -#define MCPIL_CONFIG_PRIVATE(obj) mcpil_config_get_instance_private(obj) +#define GMCPIL_TYPE_CONFIG gmcpil_config_get_type() +#define GMCPIL_CONFIG(obj) G_TYPE_CHECK_INSTANCE_CAST(obj, GMCPIL_TYPE_CONFIG, GMCPILConfig) +#define GMCPIL_IS_CONFIG(obj) G_TYPE_CHECK_INSTANCE_TYPE(obj, GMCPIL_TYPE_CONFIG) +#define GMCPIL_CONFIG_PRIVATE(obj) gmcpil_config_get_instance_private(obj) #define VALID_JSON_ARGS(dst, name, parent) \ (parent.node != NULL || dst != NULL || name != NULL || JSON_NODE_HOLDS_OBJECT(parent.node) || parent.obj == NULL) -#define GETTER(name) gchar* mcpil_config_get_ ## name (MCPILConfig* self) \ +#define GMCPIL_GETTER(name) gchar* gmcpil_config_get_ ## name (GMCPILConfig* self) \ { \ - MCPILConfigPrivate* private; \ - private = MCPIL_CONFIG_PRIVATE(self); \ + GMCPILConfigPrivate* private; \ + private = GMCPIL_CONFIG_PRIVATE(self); \ return private->name; \ } -#define SETTER(name) void mcpil_config_set_ ## name (MCPILConfig* self, const gchar* name) \ +#define GMCPIL_SETTER(name) void gmcpil_config_set_ ## name (GMCPILConfig* self, const gchar* name) \ { \ - MCPILConfigPrivate* private; \ - private = MCPIL_CONFIG_PRIVATE(self); \ + GMCPILConfigPrivate* private; \ + private = GMCPIL_CONFIG_PRIVATE(self); \ private->name = g_strdup((gchar*)name); \ return; \ } -#define GETTER_SETTER(name) GETTER(name); SETTER(name); -#define GETTER_SETTER_PROTO(name) \ -gchar* mcpil_config_get_ ## name (MCPILConfig* self) \ -void mcpil_config_set_ ## name (MCPILConfig* self, const gchar* name); +#define GMCPIL_GETTER_SETTER(name) GMCPIL_GETTER(name); GMCPIL_SETTER(name); -#define MCPIL_GLIB_PROPERTY(id, name, description, prop) \ +#define GMCPIL_GLIB_PROPERTY(id, name, description, prop) \ pspec = g_param_spec_string(id, name, description, NULL, G_PARAM_READWRITE); \ g_object_class_install_property(gobject_class, prop, pspec); -#define MCPIL_SET_DEFAULT(name, value) \ - default_##name = mcpil_config_get_##name(config); \ +#define GMCPIL_SET_DEFAULT(name, value) \ + default_##name = gmcpil_config_get_##name(config); \ if (default_##name == NULL) \ { \ default_##name = value; \ - mcpil_config_set_##name(config, default_##name); \ + gmcpil_config_set_##name(config, default_##name); \ } -typedef struct MCPILConfigPrivate MCPILConfigPrivate; +typedef struct GMCPILConfigPrivate GMCPILConfigPrivate; -typedef struct MCPILConfig +typedef struct GMCPILConfig { GObject parent; -} MCPILConfig; +} GMCPILConfig; -typedef struct MCPILConfigClass +typedef struct GMCPILConfigClass { GObjectClass parent_class; -} MCPILConfigClass; - -GType mcpil_config_get_type() G_GNUC_CONST; - -MCPILConfig* mcpil_config_new(gchar* filename); - -void mcpil_config_set_ip(MCPILConfig* self, const gchar* ip); -void mcpil_config_set_port(MCPILConfig* self, const gchar* port); -void mcpil_config_set_username(MCPILConfig* self, const gchar* username); -void mcpil_config_set_features(MCPILConfig* self, const gchar* features); -void mcpil_config_set_distance(MCPILConfig* self, const gchar* distance); -void mcpil_config_set_last_profile(MCPILConfig* self, const gchar* last_profile); -void mcpil_config_set_hud(MCPILConfig* self, const gchar* hud); -void mcpil_config_set_hide(MCPILConfig* self, const gchar* hide); - -gchar* mcpil_config_get_ip(MCPILConfig* self); -gchar* mcpil_config_get_port(MCPILConfig* self); -gchar* mcpil_config_get_username(MCPILConfig* self); -gchar* mcpil_config_get_features(MCPILConfig* self); -gchar* mcpil_config_get_distance(MCPILConfig* self); -gchar* mcpil_config_get_last_profile(MCPILConfig* self); -gchar* mcpil_config_get_hud(MCPILConfig* self); -gchar* mcpil_config_get_hide(MCPILConfig* self); - -int mcpil_config_save(MCPILConfig* self); +} GMCPILConfigClass; + +GType gmcpil_config_get_type() G_GNUC_CONST; + +GMCPILConfig* gmcpil_config_new(gchar* filename); + +void gmcpil_config_set_username(GMCPILConfig* self, const gchar* username); +void gmcpil_config_set_features(GMCPILConfig* self, const gchar* features); +void gmcpil_config_set_distance(GMCPILConfig* self, const gchar* distance); +void gmcpil_config_set_last_profile(GMCPILConfig* self, const gchar* last_profile); +void gmcpil_config_set_hud(GMCPILConfig* self, const gchar* hud); +void gmcpil_config_set_hide(GMCPILConfig* self, const gchar* hide); + +gchar* gmcpil_config_get_username(GMCPILConfig* self); +gchar* gmcpil_config_get_features(GMCPILConfig* self); +gchar* gmcpil_config_get_distance(GMCPILConfig* self); +gchar* gmcpil_config_get_last_profile(GMCPILConfig* self); +gchar* gmcpil_config_get_hud(GMCPILConfig* self); +gchar* gmcpil_config_get_hide(GMCPILConfig* self); + +int gmcpil_config_save(GMCPILConfig* self); G_END_DECLS diff --git a/src/include/libreborn.h b/src/include/libreborn.h deleted file mode 100644 index b5a26fa..0000000 --- a/src/include/libreborn.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * libreborn.h - Helpers and utilities extracted from the old libreborn - * - * Copyright (c) 2021 TheBrokenRail - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ - -#ifndef LIBREBORN_H -#define LIBREBORN_H - -/* Hook Library Function */ -#define HOOK(name, return_type, args) \ - typedef return_type (*name##_t)args; \ - static name##_t real_##name = NULL; \ - static void ensure_##name() \ - { \ - if (!real_##name) \ - { \ - dlerror(); \ - real_##name = (name##_t)dlsym(RTLD_NEXT, #name); \ - if (!real_##name) \ - { \ - fprintf(stderr, "ERROR: Resolving Symbol: "#name", %s\n", dlerror()); \ - } \ - } \ - }; \ - return_type name args - -#endif /* LIBREBORN_H */ diff --git a/src/include/mcpil.h b/src/include/mcpil.h index ecf2eec..7ba62ec 100644 --- a/src/include/mcpil.h +++ b/src/include/mcpil.h @@ -1,5 +1,5 @@ /* - * mcpil.h - MCPIL GTK+ PoC/Edition + * mcpil.h - gMCPIL main header * * Copyright 2021 Alvarito050506 * @@ -20,8 +20,8 @@ * */ -#ifndef MCPIL_H -#define MCPIL_H +#ifndef GMCPIL_H +#define GMCPIL_H #include #include @@ -35,86 +35,55 @@ #define FEAT_STR(i) ((char*)features[i][1]) #define FEAT_CMP(i, str) (strcmp(FEAT_STR(i), str) == 0) -#define TAB(name_str, title_str, button_str, button_cb, code) GtkWidget* name_str ## _tab(GtkWidget* notebook) \ +#define TAB(name, button_cb, code) GtkWidget* name ## _tab(GtkWidget* stack) \ { \ void* cb_udata = NULL; \ GtkWidget* tab = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); \ - GtkWidget* title = gtk_label_new(NULL); \ - GtkWidget* button = gtk_button_new_with_label(button_str); \ - GtkWidget* title_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); \ - GtkWidget* button_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); \ - gtk_label_set_markup(GTK_LABEL(title), "" title_str ""); \ - gtk_box_pack_start(GTK_BOX(title_hbox), title, TRUE, FALSE, 0); \ + GtkWidget* button = gtk_button_new_with_label("Save"); \ + GtkWidget* button_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 2); \ + code; \ gtk_box_pack_end(GTK_BOX(button_hbox), button, FALSE, FALSE, 0); \ - gtk_box_pack_start(GTK_BOX(tab), title_hbox, FALSE, FALSE, 8); \ gtk_box_pack_end(GTK_BOX(tab), button_hbox, FALSE, FALSE, 0); \ - gtk_notebook_append_page(GTK_NOTEBOOK(notebook), tab, gtk_label_new(STR(name_str))); \ - code; \ + gtk_stack_add_titled(GTK_STACK(stack), tab, STR(name), STR(name)); \ g_signal_connect(button, "clicked", G_CALLBACK(button_cb), cb_udata); \ return tab; \ } +//gtk_notebook_append_page(GTK_NOTEBOOK(notebook), tab, gtk_label_new(STR(name_str))); -#define MCPIL_REPO_URL "https://github.com/MCPI-Revival/gMCPIL" -#define MCPIL_FEATURED_NOTICE "Note: TBR's and PBPT servers are now featured servers,\n" \ - "this means you don't need to add them here to be able to join." +#define GMCPIL_REPO_URL "https://github.com/MCPI-Revival/gMCPIL" +#define GMCPIL_COPYRIGHT "Copyright 2021 MCPI-Revival contributors" +#define GMCPIL_DESCRIPTION "Simple launcher for MCPI-Reborn - GTK+ Edition." +#define DEFAULT_SERVERS "thebrokenrail.com\npbptanarchy.tk\n" +#define SERVERS_LABEL "External multiplayer is now built-in into MCPI-Reborn,\n" \ + "this is a just simple editor for the servers.txt file.\n" \ + "Each line is an ip:port tuple. If the port is omitted,\n" \ + "the default (19132) is used.\n" typedef void* feature_t[2]; typedef struct settings_box_t { - GtkEntry* ip_entry; - GtkEntry* port_entry; GtkEntry* username_entry; GtkEntry* hud_entry; GtkComboBoxText* distance_combo; + GtkComboBoxText* profile_combo; GtkCheckButton* hide_check; char* buff; } settings_box_t; -feature_t features[24]; -settings_box_t settings_box; -MCPILConfig* config; - -int featc; - -/* Play */ -char* get_splash_text(); -void launch_cb(GtkWidget* button, void* udata); -void select_cb(GtkWidget* list, GtkListBoxRow* row, void* udata); - -/* Features */ -int get_features(); -feature_t* get_feature(char* str); -int set_feature_envs(int feat); -void features_cb(GtkWidget* button, void* udata); -void toggle_cb(GtkWidget* check, void* udata); - -/* Multiplayer */ -int get_servers(char** ip, char** port); -void multiplayer_cb(GtkWidget* button, void* udata); - -/* Settings */ -int get_distance(char* str); -void settings_cb(GtkWidget* button, void* udata); - -/* About */ -void about_cb(GtkWidget* button, void* udata); - -/* Misc/App */ -void activate_cb(GtkApplication* app, void* udata); +/* Global variables */ +extern int featc; +extern char* servers_path; +extern char* features_envs[5]; +extern settings_box_t settings_box; +extern feature_t features[32]; +extern GMCPILConfig* config; +extern GtkWidget* window; /* Tabs */ GtkWidget* Play_tab(GtkWidget* notebook); GtkWidget* Features_tab(GtkWidget* notebook); -GtkWidget* Multiplayer_tab(GtkWidget* notebook); +GtkWidget* Servers_tab(GtkWidget* notebook); GtkWidget* Settings_tab(GtkWidget* notebook); -GtkWidget* About_tab(GtkWidget* notebook); - -/* Variable declarations */ -GtkWidget* window; -char* profile_names[5]; -char* profile_descriptions[5]; -char* features_envs[5]; -char* distances[4]; #endif /* MCPIL_H */ diff --git a/src/include/servers.h b/src/include/servers.h deleted file mode 100644 index a69c76c..0000000 --- a/src/include/servers.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * servers.h - MCPI featured servers - * - * Copyright 2021 Alvarito050506 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - * - */ - -#ifndef SERVERS_H -#define SERVERS_H - -#include -#include - -typedef struct server_t -{ - char* ip; - unsigned short port; - struct sockaddr addr; -} server_t; - -server_t servers[] = { - /* gMCPIL "custom" server */ - {NULL, 0, {}}, - /* Featured servers */ - {"pbptanarchy.tk", 19132, {}}, - {"thebrokenrail.com", 19132, {}} -}; - -#endif /* SERVERS_H */ diff --git a/src/include/splashes.h b/src/include/splashes.h index 16f8acd..3d78702 100644 --- a/src/include/splashes.h +++ b/src/include/splashes.h @@ -26,7 +26,7 @@ #include -char* splashes[41]; +extern char* splashes[41]; #ifdef DEFINE_SPLASHES char* splashes[41] = { diff --git a/src/mcpil.c b/src/mcpil.c index 1fe3f9b..0801394 100644 --- a/src/mcpil.c +++ b/src/mcpil.c @@ -36,22 +36,73 @@ #include #include -/* Widget variables */ +/* Global variables */ +settings_box_t settings_box; +GMCPILConfig* config; GtkWidget* window; -/* Profiles */ -char* profile_names[5] = {"Classic MCPI", "Modded MCPI", "Modded MCPE", "Optimized MCPE", "Custom Profile"}; -char* profile_descriptions[5] = { - "Classic Minecraft Pi Edition.\n(Not Recommended)\nAll optional features disabled.", - "Modded Minecraft Pi Edition.\nDefault MCPI-Reborn optional features without Touch GUI.", - "Minecraft Pocket Edition.\n(Recommended)\nDefault MCPI-Reborn optional features.", - "Optimized Minecraft Pocket Edition.\nDefault MCPI-Reborn optional features with lower quality graphics.", - "Custom Profile.\nModify its settings in the Features tab." -}; -char* features_envs[5] = {""}; +void about_cb(__attribute__((unused)) GtkWidget* button, __attribute__((unused)) void* udata) +{ + GdkPixbuf* logo; + GtkWidget* about_dialog; + + logo = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(), "gmcpil", 64, GTK_ICON_LOOKUP_NO_SVG, NULL); + about_dialog = gtk_about_dialog_new(); + gtk_about_dialog_set_program_name(GTK_ABOUT_DIALOG(about_dialog), "gMCPIL"); + gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(about_dialog), GMCPIL_VERSION); + gtk_about_dialog_set_logo(GTK_ABOUT_DIALOG(about_dialog), logo); + gtk_about_dialog_set_copyright(GTK_ABOUT_DIALOG(about_dialog), GMCPIL_COPYRIGHT); + gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(about_dialog), GMCPIL_REPO_URL); + gtk_about_dialog_set_comments(GTK_ABOUT_DIALOG(about_dialog), GMCPIL_DESCRIPTION); + gtk_dialog_run(GTK_DIALOG(about_dialog)); + gtk_widget_destroy(about_dialog); + return; +} + +void activate_cb(GtkApplication* app, __attribute__((unused)) void* udata) +{ + GdkPixbuf* icon; + GtkWidget* stack; + GtkWidget* switcher; + GtkWidget* header; + GtkWidget* switcher_box; + GtkWidget* about_button; + + window = gtk_application_window_new(app); + gtk_window_set_title(GTK_WINDOW(window), "gMCPIL"); + gtk_window_set_default_size(GTK_WINDOW(window), -1, 375); + + icon = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(), "gmcpil", 32, GTK_ICON_LOOKUP_NO_SVG, NULL); + gtk_window_set_icon(GTK_WINDOW(window), icon); + + stack = gtk_stack_new(); -/* Rendering distances */ -char* distances[4] = {"Far", "Normal", "Short", "Tiny"}; + switcher_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + + switcher = gtk_stack_switcher_new(); + gtk_stack_switcher_set_stack(GTK_STACK_SWITCHER(switcher), GTK_STACK(stack)); + + about_button = gtk_button_new_from_icon_name("help-about-symbolic", GTK_ICON_SIZE_LARGE_TOOLBAR); + + header = gtk_header_bar_new(); + gtk_header_bar_set_show_close_button(GTK_HEADER_BAR(header), TRUE); + gtk_header_bar_set_custom_title(GTK_HEADER_BAR(header), switcher_box); + + Play_tab(stack); + Features_tab(stack); + Servers_tab(stack); + //Settings_tab(stack); + + gtk_box_pack_start(GTK_BOX(switcher_box), switcher, TRUE, FALSE, 0); + gtk_box_pack_end(GTK_BOX(switcher_box), about_button, TRUE, FALSE, 2); + + g_signal_connect(about_button, "clicked", G_CALLBACK(about_cb), NULL); + + gtk_window_set_titlebar(GTK_WINDOW(window), header); + gtk_container_add(GTK_CONTAINER(window), stack); + gtk_widget_show_all(window); + return; +} int main(int argc, char* argv[]) { @@ -66,7 +117,7 @@ int main(int argc, char* argv[]) setenv("GTK_THEME", "Adwaita:dark", 1); asprintf(&config_path, "%s/.minecraft-pi/gmcpil.json", getenv("HOME")); - config = mcpil_config_new(config_path); + config = gmcpil_config_new(config_path); free(config_path); gtk_init(&argc, &argv); @@ -93,8 +144,9 @@ int main(int argc, char* argv[]) { free(settings_box.buff); } + free(servers_path); - mcpil_config_save(config); + gmcpil_config_save(config); g_object_unref(config); return rt; } diff --git a/src/mods/multiplayer.c b/src/mods/multiplayer.c deleted file mode 100644 index 37d475d..0000000 --- a/src/mods/multiplayer.c +++ /dev/null @@ -1,142 +0,0 @@ -/* - * multiplayer.c - Proxy-free MCPI multiplayer - * - * Copyright 2021 Alvarito050506 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - * - */ - -#define _GNU_SOURCE /* Required for RTLD_NEXT */ - -/* Lots of standard includes and libraries, for types and function prototypes. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -/* I hope this optimizes at least a little bit, or else... */ -#if __GNUC__ -# define unlikely(x) __builtin_expect(!!(x), 0) -#elif defined(__has_builtin) -# if __has_builtin(__builtin_expect) -# define unlikely(x) __builtin_expect(!!(x), 0) -# endif -#endif - -#ifndef unlikely -# define unlikely(x) (x) -#endif - -int build_sockaddr(server_t* server) -{ - struct hostent* host; - struct sockaddr_in* addr_in; - - addr_in = (struct sockaddr_in*)&server->addr; - if (server == NULL || server->ip == NULL || server->port == 0) - { - return -1; - } - - host = gethostbyname(server->ip); - if (host == NULL) - { - return -2; - } - - memcpy(&addr_in->sin_addr, host->h_addr_list[0], host->h_length); - addr_in->sin_family = AF_INET; - addr_in->sin_port = htons(server->port); - return 0; -} - -/* Extends port search (19132-19139) and address search (servers->ip:servers->port). */ -HOOK(sendto, ssize_t, (int sockfd, const void* buf, size_t len, int flags, const struct sockaddr* dest_addr, socklen_t addrlen)) -{ - unsigned int i = 19136; - struct sockaddr_in* addr = (struct sockaddr_in*)dest_addr; - - ensure_sendto(); - /* This IS intentional, -1 is the equivalent to the broadcast address. */ - if (unlikely(addr->sin_addr.s_addr == (unsigned int)-1 && ntohs(addr->sin_port) == 19135)) - { - while (i < 19139) - { - addr->sin_port = htons(i); - if ((*real_sendto)(sockfd, buf, len, flags, dest_addr, addrlen) < 0) - { - fprintf(stderr, "sendto failed with exit errno %i\n", errno); - } - i++; - } - i = 0; - while (i < (sizeof(servers) / sizeof(server_t))) - { - if ((*real_sendto)(sockfd, buf, len, flags, &servers[i].addr, (socklen_t)(sizeof(servers[i].addr))) < 0) - { - fprintf(stderr, "sendto failed with exit errno %i\n", errno); - } - i++; - } - addr->sin_port = htons(19135); - } - return (*real_sendto)(sockfd, buf, len, flags, dest_addr, addrlen); -} - -void __attribute__((constructor)) init() -{ - unsigned int i = 1; - char* tmp_ip = NULL; - char* tmp_port = NULL; - - while (i < (sizeof(servers) / sizeof(server_t))) - { - build_sockaddr(&servers[i]); - i++; - } - - tmp_ip = getenv("GMCPIL_SERVER_IP"); - tmp_port = getenv("GMCPIL_SERVER_PORT"); - if (tmp_ip == NULL || tmp_port == NULL) - { - goto err; - } - servers[0].port = (short)strtol(tmp_port, NULL, 10); - servers[0].ip = tmp_ip; - - goto end; - -err: - servers[0].port = 0; - servers[0].ip = NULL; - -end: - build_sockaddr(&servers[0]); - return; -} diff --git a/src/play.c b/src/play.c new file mode 100644 index 0000000..07b11cc --- /dev/null +++ b/src/play.c @@ -0,0 +1,290 @@ +/* + * settings.c - gMCPIL settings tab + * + * Copyright 2021 Alvarito050506 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + */ + +#define _GNU_SOURCE /* Required for asprintf */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +char* distances[4] = {"Far", "Normal", "Short", "Tiny"}; +char* profile_names[5] = {"Classic MCPI", "Modded MCPI", "Modded MCPE", "Optimized MCPE", "Custom Profile"}; +char* profile_descriptions[5] = { + "Classic Minecraft Pi Edition (Not Recommended):\nAll optional features disabled.", + "Modded Minecraft Pi Edition:\nDefault MCPI-Reborn optional features without Touch GUI.", + "Modded Minecraft Pocket Edition (Recommended):\nDefault MCPI-Reborn optional features.", + "Optimized Minecraft Pocket Edition:\nDefault MCPI-Reborn features with lower quality graphics.", + "Custom Profile: Modify its settings in the Features tab." +}; + +static char* get_splash_text() +{ + return splashes[rand() % sizeof(splashes) / sizeof(char*)]; +} + +static int get_distance(char* str) +{ + switch (str[0]) + { + case 'F': + return 0; + break; + case 'N': + return 1; + break; + case 'S': + return 2; + break; + case 'T': + return 3; + break; + } + return -1; +} + +static void settings_cb(__attribute__((unused)) GtkWidget* button, void* udata) +{ + int profile; + char tmp[2] = {0x00, 0x00}; + const char* username; + const char* distance; + const char* hud; + gboolean hide; + GtkEntryBuffer* username_buff; + GtkEntryBuffer* hud_buff; + + if ((int)udata == TRUE) + { + goto profile; + } + + username_buff = gtk_entry_get_buffer(GTK_ENTRY(settings_box.username_entry)); + hud_buff = gtk_entry_get_buffer(GTK_ENTRY(settings_box.hud_entry)); + + username = gtk_entry_buffer_get_text(username_buff); + hud = gtk_entry_buffer_get_text(hud_buff); + distance = gtk_combo_box_text_get_active_text(settings_box.distance_combo); + hide = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(settings_box.hide_check)); + + setenv("MCPI_USERNAME", username, 1); + setenv("MCPI_RENDER_DISTANCE", distance, 1); + setenv("GALLIUM_HUD", hud, 1); + + gmcpil_config_set_username(config, username); + gmcpil_config_set_hud(config, hud); + gmcpil_config_set_distance(config, distance); + if (hide) + { + gmcpil_config_set_hide(config, "TRUE"); + } else + { + gmcpil_config_set_hide(config, "FALSE"); + } + +profile: + profile = gtk_combo_box_get_active(GTK_COMBO_BOX(settings_box.profile_combo)); + setenv("MCPI_FEATURE_FLAGS", features_envs[profile], 1); + tmp[0] = profile + 0x30; + + gmcpil_config_set_last_profile(config, tmp); + gmcpil_config_save(config); + return; +} + +static void watch_cb(GPid pid, __attribute__((unused)) int status, __attribute__((unused)) void* udata) +{ + gtk_widget_show_all(window); + g_spawn_close_pid(pid); + return; +} + +static void launch_cb(__attribute__((unused)) GtkWidget* button, __attribute__((unused)) void* udata) +{ + char* argv[] = {"minecraft-pi-reborn-client", NULL}; + GPid pid; + GError* err = NULL; + + settings_cb(NULL, (void*)(intptr_t)TRUE); + g_spawn_async(NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH, NULL, NULL, &pid, &err); + + if (err != NULL) + { + g_error("Spawning child failed: %s", err->message); + return; + } + if (gmcpil_config_get_hide(config)[0] == 'T') + { + gtk_widget_hide(window); + } + g_child_watch_add(pid, watch_cb, NULL); + return; +} + +static void select_cb(GtkComboBox* combo, void* udata) +{ + int profile; + GtkLabel* description; + + description = GTK_LABEL(udata); + profile = gtk_combo_box_get_active(combo); + gtk_label_set_text(description, profile_descriptions[profile]); + return; +} + +TAB(Play, settings_cb, { + int i = 0; + int distance_int; + int last_profile; + char* default_username; + char* default_distance; + char* default_hud; + char* default_hide; + char* splash_text; + GtkWidget* username_hbox; + GtkWidget* username_label; + GtkWidget* username_entry; + GtkWidget* distance_hbox; + GtkWidget* distance_label; + GtkWidget* distance_combo; + GtkWidget* profile_hbox; + GtkWidget* profile_label; + GtkWidget* profile_combo; + GtkWidget* hud_hbox; + GtkWidget* hud_label; + GtkWidget* hud_entry; + GtkWidget* hide_hbox; + GtkWidget* hide_check; + GtkWidget* launch_button; + GtkWidget* splash; + GtkWidget* title; + GtkWidget* title_hbox; + GtkWidget* description; + + title_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + + title = gtk_label_new(NULL); + gtk_label_set_markup(GTK_LABEL(title), "Minecraft Pi Launcher"); + + splash = gtk_label_new(NULL); + asprintf(&splash_text, "%s\n", get_splash_text()); + gtk_label_set_markup(GTK_LABEL(splash), splash_text); + + GMCPIL_SET_DEFAULT(distance, "Short"); + GMCPIL_SET_DEFAULT(username, "StevePi"); + GMCPIL_SET_DEFAULT(hud, "simple,fps"); + GMCPIL_SET_DEFAULT(hide, "TRUE"); + + distance_int = get_distance(default_distance); + + username_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + username_label = gtk_label_new("Username"); + username_entry = gtk_entry_new_with_buffer(gtk_entry_buffer_new(default_username, strlen(default_username))); + gtk_widget_set_size_request(username_entry, 25 * 10, -1); + + hud_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + hud_label = gtk_label_new("Gallium HUD options"); + hud_entry = gtk_entry_new_with_buffer(gtk_entry_buffer_new(default_hud, strlen(default_hud))); + gtk_widget_set_size_request(hud_entry, 25 * 10, -1); + + distance_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + distance_label = gtk_label_new("Rendering distance"); + distance_combo = gtk_combo_box_text_new(); + while (i < 4) + { + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(distance_combo), distances[i]); + i++; + } + gtk_combo_box_set_active(GTK_COMBO_BOX(distance_combo), distance_int); + gtk_widget_set_size_request(distance_combo, 25 * 10, -1); + + i = 0; + profile_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + profile_label = gtk_label_new("Profile"); + profile_combo = gtk_combo_box_text_new(); + last_profile = SAFE_ATOI(gmcpil_config_get_last_profile(config)); + while (i < 5) + { + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(profile_combo), profile_names[i]); + i++; + } + gtk_combo_box_set_active(GTK_COMBO_BOX(profile_combo), last_profile); + gtk_widget_set_size_request(profile_combo, 25 * 10, -1); + + hide_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + hide_check = gtk_check_button_new_with_label("Hide launcher"); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(hide_check), default_hide[0] == 'T'); + gtk_widget_set_size_request(hide_check, -1, 32); // To match rest of input widgets + + description = gtk_label_new(profile_descriptions[last_profile]); + gtk_label_set_justify(GTK_LABEL(description), GTK_JUSTIFY_CENTER); + gtk_label_set_line_wrap(GTK_LABEL(description), TRUE); + + launch_button = gtk_button_new_with_label("Launch"); + + gtk_box_pack_start(GTK_BOX(title_hbox), title, TRUE, FALSE, 0); + + gtk_box_pack_start(GTK_BOX(tab), title_hbox, FALSE, FALSE, 4); + gtk_box_pack_start(GTK_BOX(tab), splash, FALSE, FALSE, 0); + + gtk_box_pack_start(GTK_BOX(username_hbox), username_label, FALSE, FALSE, 10); + gtk_box_pack_end(GTK_BOX(username_hbox), username_entry, FALSE, FALSE, 10); + + gtk_box_pack_start(GTK_BOX(hud_hbox), hud_label, FALSE, FALSE, 10); + gtk_box_pack_end(GTK_BOX(hud_hbox), hud_entry, FALSE, FALSE, 10); + + gtk_box_pack_start(GTK_BOX(distance_hbox), distance_label, FALSE, FALSE, 10); + gtk_box_pack_end(GTK_BOX(distance_hbox), distance_combo, FALSE, FALSE, 10); + + gtk_box_pack_start(GTK_BOX(profile_hbox), profile_label, FALSE, FALSE, 10); + gtk_box_pack_end(GTK_BOX(profile_hbox), profile_combo, FALSE, FALSE, 10); + + gtk_box_pack_end(GTK_BOX(hide_hbox), hide_check, FALSE, FALSE, 10); + + gtk_box_pack_start(GTK_BOX(tab), username_hbox, FALSE, FALSE, 2); + gtk_box_pack_start(GTK_BOX(tab), hud_hbox, FALSE, FALSE, 2); + gtk_box_pack_start(GTK_BOX(tab), distance_hbox, FALSE, FALSE, 2); + gtk_box_pack_start(GTK_BOX(tab), profile_hbox, FALSE, FALSE, 2); + gtk_box_pack_start(GTK_BOX(tab), hide_hbox, FALSE, FALSE, 2); + gtk_box_pack_start(GTK_BOX(tab), description, FALSE, FALSE, 2); + + gtk_box_pack_end(GTK_BOX(button_hbox), launch_button, FALSE, FALSE, 0); + + settings_box.username_entry = GTK_ENTRY(username_entry); + settings_box.hud_entry = GTK_ENTRY(hud_entry); + settings_box.distance_combo = GTK_COMBO_BOX_TEXT(distance_combo); + settings_box.profile_combo = GTK_COMBO_BOX_TEXT(profile_combo); + settings_box.hide_check = GTK_CHECK_BUTTON(hide_check); + + g_signal_connect(launch_button, "clicked", G_CALLBACK(launch_cb), NULL); + g_signal_connect(profile_combo, "changed", G_CALLBACK(select_cb), (void*)description); + + setenv("MCPI_USERNAME", default_username, 1); + setenv("MCPI_RENDER_DISTANCE", distances[distance_int], 1); + setenv("GALLIUM_HUD", default_hud, 1); + free(splash_text); +}); diff --git a/src/servers.c b/src/servers.c new file mode 100644 index 0000000..958d6ec --- /dev/null +++ b/src/servers.c @@ -0,0 +1,116 @@ +/* + * servers.c - gMCPIL servers tab + * + * Copyright 2021 Alvarito050506 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + */ + +#define _GNU_SOURCE /* Required for asprintf */ + +#include +#include +#include +#include +#include + +#include +#include + +char* servers_path; + +static void servers_cb(__attribute__((unused)) GtkWidget* button, void* udata) +{ + char* buff; + FILE* fd; + GtkTextView* view; + GtkTextBuffer* gtk_buff; + GtkTextIter start; + GtkTextIter end; + + fd = fopen(servers_path, "w+"); + if (fd == NULL) + { + fprintf(stderr, "Could not save servers file: %s.", strerror(errno)); + return; + } + view = (GtkTextView*)udata; + + gtk_buff = gtk_text_view_get_buffer(view); + gtk_text_buffer_get_start_iter(gtk_buff, &start); + gtk_text_buffer_get_end_iter(gtk_buff, &end); + buff = gtk_text_buffer_get_text(gtk_buff, &start, &end, FALSE); + + fwrite(buff, 1, strlen(buff), fd); + fclose(fd); + return; +} + +TAB(Servers, servers_cb, { + int sz = 0; + char* buff; + FILE* fd; + GtkWidget* label; + GtkWidget* scroll; + GtkWidget* view; + GtkTextBuffer* gtk_buff; + + buff = NULL; + asprintf(&servers_path, "%s/.minecraft-pi/servers.txt", getenv("HOME")); + + fd = fopen(servers_path, "r+"); + if (fd != NULL) + { + fseek(fd, 0, SEEK_END); + sz = ftell(fd); + fseek(fd, 0, SEEK_SET); + buff = (char*)malloc(sz + 1); + fread((void*)buff, 1, sz, fd); + buff[sz] = 0x00; + fclose(fd); + } + + label = gtk_label_new(SERVERS_LABEL); + gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); + gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER); + gtk_widget_set_margin_top(label, 6); + + scroll = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll), GTK_SHADOW_ETCHED_IN); + gtk_container_set_border_width(GTK_CONTAINER(scroll), 5); + + gtk_buff = gtk_text_buffer_new(NULL); + + if (buff != NULL) + { + gtk_text_buffer_set_text(gtk_buff, buff, -1); + } else + { + gtk_text_buffer_set_text(gtk_buff, DEFAULT_SERVERS, -1); + } + + view = gtk_text_view_new_with_buffer(gtk_buff); + gtk_text_view_set_editable(GTK_TEXT_VIEW(view), TRUE); + gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(view), TRUE); + gtk_container_add(GTK_CONTAINER(scroll), view); + + gtk_box_pack_start(GTK_BOX(tab), label, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(tab), scroll, TRUE, TRUE, 0); + cb_udata = (void*)view; + free(buff); +}); diff --git a/src/tabs.c b/src/tabs.c deleted file mode 100644 index 1820af4..0000000 --- a/src/tabs.c +++ /dev/null @@ -1,339 +0,0 @@ -/* - * tabs.c - MCPIL GTK+ tabs - * - * Copyright 2021 Alvarito050506 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. - * - */ - -#define _GNU_SOURCE /* Required for asprintf */ - -#include -#include -#include -#include -#include - -#include -#include -#include - -/* Tabs */ -TAB(Play, "Minecraft Pi Launcher", "Launch", launch_cb, { - int i = 0; - int last_profile; - char* splash_text; - GtkWidget* list; - GtkWidget* rows[5]; - GtkWidget* hbox; - GtkWidget* tmp_hbox; - GtkWidget* splash; - GtkWidget* description; - - asprintf(&splash_text, "%s\n", get_splash_text()); - - splash = gtk_label_new(NULL); - gtk_label_set_markup(GTK_LABEL(splash), splash_text); - gtk_box_pack_start(GTK_BOX(tab), splash, FALSE, FALSE, 0); - - gtk_box_pack_start(GTK_BOX(tab), gtk_label_new("Select a Minecraft profile to launch"), FALSE, FALSE, 0); - hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); - - list = gtk_list_box_new(); - gtk_list_box_set_selection_mode(GTK_LIST_BOX(list), GTK_SELECTION_SINGLE); - - description = gtk_label_new("The description of the selected profile\nshould appear here."); - gtk_label_set_justify(GTK_LABEL(description), GTK_JUSTIFY_CENTER); - gtk_label_set_line_wrap(GTK_LABEL(description), TRUE); - - last_profile = SAFE_ATOI(mcpil_config_get_last_profile(config)); - while (i < 5) - { - rows[i] = gtk_list_box_row_new(); - tmp_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); - gtk_box_pack_start(GTK_BOX(tmp_hbox), gtk_label_new(profile_names[i]), FALSE, FALSE, 8); - gtk_container_add(GTK_CONTAINER(rows[i]), tmp_hbox); - gtk_container_add(GTK_CONTAINER(list), rows[i]); - i++; - } - gtk_list_box_select_row(GTK_LIST_BOX(list), GTK_LIST_BOX_ROW(rows[last_profile])); - gtk_label_set_text(GTK_LABEL(description), profile_descriptions[last_profile]); - - g_signal_connect(list, "row-selected", G_CALLBACK(select_cb), (void*)description); - - gtk_box_pack_start(GTK_BOX(hbox), list, FALSE, FALSE, 6); - gtk_box_pack_start(GTK_BOX(hbox), description, TRUE, TRUE, 0); - gtk_box_pack_start(GTK_BOX(tab), hbox, TRUE, FALSE, 0); - - gtk_widget_show_all(list); - free(splash_text); -}); - -TAB(Features, "Features", "Save", features_cb, { - int i = 0; - int last_profile; - char* tmp; - char* features_buff; - GtkWidget* feature_check; - GtkWidget* scroll; - GtkWidget* vbox; - feature_t* feature; - - featc = 0; - featc = get_features(); - - features_envs[1] = (char*)malloc(1); - features_envs[2] = (char*)malloc(1); - features_envs[3] = (char*)malloc(1); - features_envs[4] = NULL; - while (i < featc) - { - set_feature_envs(i); - i++; - } - - features_buff = mcpil_config_get_features(config); - if (features_buff != NULL) - { - i = 0; - while (i < featc) - { - FEAT_BOOL(i) = FALSE; - i++; - } - - i = 0; - tmp = strtok(features_buff, "|"); - while (tmp != NULL && i < featc) - { - feature = get_feature(tmp); - if (feature != NULL) - { - *feature[0] = (void*)TRUE; - } - tmp = strtok(NULL, "|"); - i++; - } - } else - { - printf("Yeah, no.\n"); - } - - scroll = gtk_scrolled_window_new(NULL, NULL); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll), GTK_SHADOW_NONE); - gtk_container_set_border_width(GTK_CONTAINER(scroll), 0); - - vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); - - i = 0; - while (i < featc) - { - feature_check = gtk_check_button_new_with_label(FEAT_STR(i)); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(feature_check), FEAT_INT(i)); - g_signal_connect(feature_check, "toggled", G_CALLBACK(toggle_cb), (void*)(intptr_t)i); - gtk_box_pack_start(GTK_BOX(vbox), feature_check, FALSE, FALSE, 0); - i++; - } - - features_cb(NULL, (void*)FALSE); - cb_udata = (void*)TRUE; - mcpil_config_set_features(config, features_envs[4]); - last_profile = SAFE_ATOI(mcpil_config_get_last_profile(config)); - setenv("MCPI_FEATURE_FLAGS", features_envs[last_profile], 1); - - gtk_container_add(GTK_CONTAINER(scroll), vbox); - gtk_box_pack_start(GTK_BOX(tab), scroll, TRUE, TRUE, 0); -}); - -TAB(Multiplayer, "Multiplayer", "Save", multiplayer_cb, { - char* default_port; - char* default_ip; - GtkWidget* ip_hbox; - GtkWidget* ip_label; - GtkWidget* ip_entry; - GtkWidget* port_hbox; - GtkWidget* port_label; - GtkWidget* port_entry; - GtkWidget* notice_label; - - MCPIL_SET_DEFAULT(ip, "thebrokenrail.com"); - MCPIL_SET_DEFAULT(port, "19132"); - - ip_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); - ip_label = gtk_label_new("IP Address"); - ip_entry = gtk_entry_new_with_buffer(gtk_entry_buffer_new(default_ip, strlen(default_ip))); - gtk_entry_set_width_chars(GTK_ENTRY(ip_entry), 25); - - port_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); - port_label = gtk_label_new("Port"); - port_entry = gtk_entry_new_with_buffer(gtk_entry_buffer_new(default_port, strlen(default_port))); - gtk_entry_set_width_chars(GTK_ENTRY(port_entry), 25); - gtk_entry_set_input_purpose(GTK_ENTRY(port_entry), GTK_INPUT_PURPOSE_DIGITS); - - gtk_box_pack_start(GTK_BOX(ip_hbox), ip_label, FALSE, FALSE, 10); - gtk_box_pack_end(GTK_BOX(ip_hbox), ip_entry, FALSE, FALSE, 10); - - gtk_box_pack_start(GTK_BOX(port_hbox), port_label, FALSE, FALSE, 10); - gtk_box_pack_end(GTK_BOX(port_hbox), port_entry, FALSE, FALSE, 10); - - notice_label = gtk_label_new(NULL); - gtk_label_set_markup(GTK_LABEL(notice_label), MCPIL_FEATURED_NOTICE); - gtk_label_set_justify(GTK_LABEL(notice_label), GTK_JUSTIFY_CENTER); - gtk_label_set_line_wrap(GTK_LABEL(notice_label), TRUE); - - gtk_box_pack_start(GTK_BOX(tab), ip_hbox, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(tab), port_hbox, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(tab), notice_label, FALSE, FALSE, 10); - - settings_box.ip_entry = GTK_ENTRY(ip_entry); - settings_box.port_entry = GTK_ENTRY(port_entry); - setenv("GMCPIL_SERVER_IP", default_ip, 1); - setenv("GMCPIL_SERVER_PORT", default_port, 1); -}); - -TAB(Settings, "Settings", "Save", settings_cb, { - int i = 0; - int distance_int; - char* default_username; - char* default_distance; - char* default_hud; - char* default_hide; - GtkWidget* username_hbox; - GtkWidget* username_label; - GtkWidget* username_entry; - GtkWidget* distance_hbox; - GtkWidget* distance_label; - GtkWidget* distance_combo; - GtkWidget* hud_hbox; - GtkWidget* hud_label; - GtkWidget* hud_entry; - GtkWidget* hide_hbox; - GtkWidget* hide_check; - - MCPIL_SET_DEFAULT(distance, "Short"); - MCPIL_SET_DEFAULT(username, "StevePi"); - MCPIL_SET_DEFAULT(hud, "simple,fps"); - MCPIL_SET_DEFAULT(hide, "TRUE"); - - distance_int = get_distance(default_distance); - - username_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); - username_label = gtk_label_new("Username"); - username_entry = gtk_entry_new_with_buffer(gtk_entry_buffer_new(default_username, strlen(default_username))); - gtk_entry_set_width_chars(GTK_ENTRY(username_entry), 25); - - distance_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); - distance_label = gtk_label_new("Rendering distance"); - distance_combo = gtk_combo_box_text_new(); - while (i < 4) - { - gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(distance_combo), distances[i]); - i++; - } - gtk_combo_box_set_active(GTK_COMBO_BOX(distance_combo), distance_int); - - hud_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); - hud_label = gtk_label_new("Gallium HUD options"); - hud_entry = gtk_entry_new_with_buffer(gtk_entry_buffer_new(default_hud, strlen(default_hud))); - gtk_entry_set_width_chars(GTK_ENTRY(hud_entry), 25); - - hide_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); - hide_check = gtk_check_button_new_with_label("Hide launcher"); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(hide_check), default_hide[0] == 'T'); - gtk_widget_set_size_request(hide_check, -1, 32); // To match rest of input widgets - - gtk_box_pack_start(GTK_BOX(username_hbox), username_label, FALSE, FALSE, 10); - gtk_box_pack_end(GTK_BOX(username_hbox), username_entry, FALSE, FALSE, 10); - - gtk_box_pack_start(GTK_BOX(distance_hbox), distance_label, FALSE, FALSE, 10); - gtk_box_pack_end(GTK_BOX(distance_hbox), distance_combo, FALSE, FALSE, 10); - - gtk_box_pack_start(GTK_BOX(hud_hbox), hud_label, FALSE, FALSE, 10); - gtk_box_pack_end(GTK_BOX(hud_hbox), hud_entry, FALSE, FALSE, 10); - - gtk_box_pack_end(GTK_BOX(hide_hbox), hide_check, FALSE, FALSE, 10); - - gtk_box_pack_start(GTK_BOX(tab), username_hbox, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(tab), distance_hbox, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(tab), hud_hbox, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(tab), hide_hbox, FALSE, FALSE, 0); - - settings_box.username_entry = GTK_ENTRY(username_entry); - settings_box.distance_combo = GTK_COMBO_BOX_TEXT(distance_combo); - settings_box.hud_entry = GTK_ENTRY(hud_entry); - settings_box.hide_check = GTK_CHECK_BUTTON(hide_check); - - setenv("MCPI_USERNAME", default_username, 1); - setenv("MCPI_RENDER_DISTANCE", distances[distance_int], 1); - setenv("GALLIUM_HUD", default_hud, 1); -}); - -TAB(About, "Minecraft Pi Launcher", "Help", about_cb, { - int sz = 0; - char* buff; - FILE* changelog_file; - GtkWidget* scroll; - GtkWidget* info_label; - GtkWidget* changelog_view; - GtkWidget* link; - GtkTextBuffer* changelog_buffer; - - buff = NULL; - changelog_file = fopen("/usr/share/doc/gmcpil/CHANGELOG.txt", "r"); - if (changelog_file != NULL) - { - fseek(changelog_file, 0, SEEK_END); - sz = ftell(changelog_file); - fseek(changelog_file, 0, SEEK_SET); - buff = (char*)malloc(sz + 1); - fread((void*)buff, 1, sz, changelog_file); - buff[sz] = 0x00; - fclose(changelog_file); - } - - info_label = gtk_label_new(NULL); - gtk_label_set_markup(GTK_LABEL(info_label), "" GMCPIL_VERSION "\nby all its contributors"); - gtk_label_set_justify(GTK_LABEL(info_label), GTK_JUSTIFY_CENTER); - - link = gtk_link_button_new_with_label(MCPIL_REPO_URL, MCPIL_REPO_URL); - - scroll = gtk_scrolled_window_new(NULL, NULL); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll), GTK_SHADOW_ETCHED_IN); - gtk_container_set_border_width(GTK_CONTAINER(scroll), 5); - - changelog_buffer = gtk_text_buffer_new(NULL); - - if (buff != NULL) - { - gtk_text_buffer_set_text(changelog_buffer, buff, -1); - } else - { - gtk_text_buffer_set_text(changelog_buffer, "ERROR: Could not load changelog.", -1); - } - - changelog_view = gtk_text_view_new_with_buffer(changelog_buffer); - gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(changelog_view), GTK_WRAP_WORD); - gtk_text_view_set_editable(GTK_TEXT_VIEW(changelog_view), FALSE); - gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(changelog_view), FALSE); - - gtk_container_add(GTK_CONTAINER(scroll), changelog_view); - gtk_box_pack_start(GTK_BOX(tab), info_label, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(tab), link, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(tab), scroll, TRUE, TRUE, 0); -});