264 lines
6.3 KiB
C
264 lines
6.3 KiB
C
#include <stdio.h>
|
|
#include <lua5.3/lualib.h>
|
|
#include <lua5.3/lauxlib.h>
|
|
#include <signal.h>
|
|
#include "termbox_render.h"
|
|
#include "oct_termbox_sprite.h"
|
|
#include "oct_networking.h"
|
|
#include "oct_log.h"
|
|
|
|
#define TB_IMPL
|
|
#include "termbox.h"
|
|
|
|
#define OCT_MAX_FILENAME_SIZE 1024
|
|
|
|
#define OCT_VERSION "0.0"
|
|
#define OCT_URL "https://git.thejerks.club/j4nk/open-card-table"
|
|
|
|
|
|
int oct_type;
|
|
|
|
lua_State *L = NULL;
|
|
|
|
struct {
|
|
char port[6]; // max 65535 so 6 bytes needed
|
|
// Might come in handy later to keep filename
|
|
// e.g. if I ever want to allow downloading a script from peer
|
|
char lua_file[OCT_MAX_FILENAME_SIZE];
|
|
int needs_termbox;
|
|
int needs_networking;
|
|
} config;
|
|
|
|
void usage();
|
|
void version();
|
|
int process_args(int argc, char* argv[]);
|
|
int initialize_everything(char* lua_file);
|
|
int deinitialize_everything();
|
|
|
|
int finish = 0;
|
|
void handle_sigint() {finish = 1;};
|
|
|
|
int main(int argc, char* argv[]) {
|
|
if (!process_args(argc, argv)) {
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
// initialize SIGINT handler
|
|
struct sigaction sa = {0};
|
|
sa.sa_handler = handle_sigint;
|
|
sigaction(SIGINT, &sa, NULL);
|
|
|
|
struct tb_event ev;
|
|
if (config.needs_termbox) {
|
|
while (!finish) {
|
|
tb_clear();
|
|
tb_peek_event(&ev, 10);
|
|
if (ev.key == TB_KEY_ESC) {
|
|
finish = 1;
|
|
}
|
|
oct_network_recv_msgs();
|
|
lua_getglobal(L, "oct_loop");
|
|
lua_pushinteger(L, ev.key);
|
|
lua_pushinteger(L, ev.ch);
|
|
lua_call(L, 2, 0);
|
|
for (uint32_t i=0; i < oct_tb_sprite_list.new_index; i++) {
|
|
oct_render_termbox_sprite(oct_tb_sprite_list.sprite_list[i]);
|
|
}
|
|
tb_present();
|
|
oct_network_send_msgs();
|
|
}
|
|
}
|
|
else {
|
|
while (!finish) {
|
|
oct_network_recv_msgs();
|
|
lua_getglobal(L, "oct_loop");
|
|
lua_pushinteger(L, 0);
|
|
lua_pushinteger(L, 0);
|
|
if (lua_pcall(L, 2, 0, 0) != LUA_OK) {
|
|
OCT_LOG_ERROR("%s", luaL_checkstring(L, -1));
|
|
finish = 1;
|
|
}
|
|
oct_network_send_msgs();
|
|
}
|
|
}
|
|
deinitialize_everything();
|
|
return EXIT_SUCCESS;
|
|
}
|
|
|
|
int process_args(int argc, char* argv[]) {
|
|
if (argc == 1) { // Didn't specify a file
|
|
// Can't use oct_log as logging is not init
|
|
fprintf(stderr, "Error: No lua file given\n\n");
|
|
usage();
|
|
return 0;
|
|
}
|
|
|
|
// Set config.port to default
|
|
strncpy(config.port, OCT_DEFAULT_PORT, 6);
|
|
int log_level = OCT_LOG_LEVEL_ERROR;
|
|
char log_file[OCT_MAX_FILENAME_SIZE];
|
|
int log_file_spec = 0;
|
|
int valid_last_argument = 0;
|
|
|
|
for (int i = 1; i < argc; i++) {
|
|
// argv's are guaranteed to be zero-terminated, so can use
|
|
// strcmp instead of strncmp
|
|
if (strcmp(argv[i], "-p") == 0) {
|
|
if (i+1 < argc) {
|
|
strncpy(config.port, argv[i+1], 6);
|
|
i++;
|
|
}
|
|
else {
|
|
fprintf(stderr, "Error: need to specify a port after -p\n");
|
|
return 0;
|
|
}
|
|
}
|
|
else if (strcmp(argv[i], "-h") == 0) {
|
|
usage();
|
|
return 0;
|
|
}
|
|
else if (strcmp(argv[i], "-v") == 0) {
|
|
version();
|
|
return 0;
|
|
}
|
|
else if (strcmp(argv[i], "-ll") == 0) {
|
|
if (i+1 < argc) {
|
|
char* endptr = NULL;
|
|
log_level = strtoul(argv[i+1], &endptr, 10);
|
|
if (log_level == 0 && endptr == argv[i+1]) {
|
|
printf("Error: invalid log level\n");
|
|
return 0;
|
|
}
|
|
i++;
|
|
}
|
|
else {
|
|
fprintf(stderr, "Error: need to specify a log level after -ll\n");
|
|
return 0;
|
|
}
|
|
}
|
|
else if (strcmp(argv[i], "-lf") == 0) {
|
|
if (i+1 < argc) {
|
|
strncpy(log_file, argv[i+1], OCT_MAX_FILENAME_SIZE);
|
|
log_file_spec = 1;
|
|
i++;
|
|
}
|
|
else {
|
|
fprintf(stderr, "Error: need to specify a log file after -lf\n");
|
|
return 0;
|
|
}
|
|
}
|
|
else {
|
|
// This is the lua file to run
|
|
if (i == argc-1) {
|
|
valid_last_argument = 1;
|
|
break;
|
|
}
|
|
// Invalid argument
|
|
else {
|
|
fprintf(stderr, "Error: invalid argument %s\n", argv[i]);
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
if (!valid_last_argument) {
|
|
return 0;
|
|
}
|
|
|
|
oct_log_init(log_file_spec ? log_file : NULL, log_level);
|
|
|
|
strncpy(config.lua_file, argv[argc-1], OCT_MAX_FILENAME_SIZE);
|
|
OCT_LOG_INFO("Running lua file: %s", config.lua_file);
|
|
|
|
return initialize_everything(config.lua_file);
|
|
}
|
|
|
|
int initialize_everything(char* lua_file) {
|
|
// Check if file exists
|
|
if (access(lua_file, F_OK) != 0) {
|
|
// oct_log is init by this time, but don't want PITA bug in case this changes
|
|
fprintf(stderr, "Error: Could not open file: %s\n", lua_file);
|
|
deinitialize_everything();
|
|
return 0;
|
|
}
|
|
if (!oct_tb_sprite_list_initialize()) {
|
|
return 0;
|
|
}
|
|
OCT_LOG_INFO("Initialized the sprite list");
|
|
L = luaL_newstate();
|
|
if (L == NULL) {
|
|
OCT_LOG_ERROR("Can't initialize Lua\n");
|
|
return 0;
|
|
}
|
|
OCT_LOG_INFO("Initialized lua state");
|
|
luaL_openlibs(L);
|
|
oct_tb_initialize_lua(L);
|
|
oct_log_init_lua(L);
|
|
if (luaL_dofile(L, lua_file)) {
|
|
OCT_LOG_ERROR("%s", luaL_checkstring(L, -1));
|
|
deinitialize_everything();
|
|
return 0;
|
|
}
|
|
OCT_LOG_INFO("Begin running oct_init()");
|
|
lua_getglobal(L, "oct_init");
|
|
if (lua_pcall(L, 0, 2, 0) != LUA_OK) {
|
|
OCT_LOG_ERROR("%s", luaL_checkstring(L, -1));
|
|
deinitialize_everything();
|
|
return 0;
|
|
}
|
|
config.needs_networking = lua_tointeger(L, -2);
|
|
config.needs_termbox = lua_tointeger(L, -1);
|
|
OCT_LOG_INFO("Finish running oct_init()");
|
|
|
|
OCT_LOG_INFO("Lua script %s termbox", config.needs_termbox ? "requires" : "does not require");
|
|
|
|
if (!config.needs_termbox) {
|
|
oct_tb_change_oct_tb_sprite_new(L);
|
|
}
|
|
|
|
OCT_LOG_INFO("Lua script %s networking", config.needs_networking ? "requires" : "does not require");
|
|
|
|
if (config.needs_networking) {
|
|
if (!oct_network_node_init(config.port, L)) {
|
|
OCT_LOG_ERROR("Could not establish a socket on port %s\n", config.port);
|
|
deinitialize_everything();
|
|
return 0;
|
|
}
|
|
// initialize the address book
|
|
oct_network_ab_init();
|
|
}
|
|
|
|
if (config.needs_termbox) {
|
|
tb_init();
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int deinitialize_everything() {
|
|
OCT_LOG_INFO("Deinitializing everything");
|
|
tb_shutdown();
|
|
if (L) lua_close(L);
|
|
oct_tb_sprite_list_deinitialize();
|
|
oct_network_ab_deinit();
|
|
//oct_network_node_deinit();
|
|
oct_log_deinit();
|
|
return 1;
|
|
}
|
|
|
|
void usage() {
|
|
fprintf(stderr, "Open Card Table, version %s\n", OCT_VERSION);
|
|
fprintf(stderr, "%s\n", OCT_URL);
|
|
fprintf(stderr, "\n");
|
|
fprintf(stderr, "Usage: ./open_card_table [OPTIONS] FILE\n");
|
|
fprintf(stderr, "\n");
|
|
fprintf(stderr, " -p\t\tPort on which to listen\n");
|
|
fprintf(stderr, " -v\t\tPrint version and exit\n");
|
|
fprintf(stderr, " -h\t\tPrint this message and exit\n");
|
|
fprintf(stderr, " -ll\t\t Set log level: 0=err, 1=warn, 2=info, 3=debug\n");
|
|
fprintf(stderr, " -lf\t\t Specify log output file\n");
|
|
fprintf(stderr, "\n");
|
|
}
|
|
|
|
void version() {
|
|
fprintf(stderr, "%s\n", OCT_VERSION);
|
|
}
|