mirror of
https://github.com/ondra-novak/gates_of_skeldal.git
synced 2025-07-20 13:15:16 -04:00
Merge remote-tracking branch 'origin/sse' into mapedit_support
This commit is contained in:
commit
9a41bc0f67
8 changed files with 294 additions and 38 deletions
|
@ -44,7 +44,7 @@
|
||||||
#define E_MENU_SELECT 36
|
#define E_MENU_SELECT 36
|
||||||
#define E_CLOSE_MAP 37
|
#define E_CLOSE_MAP 37
|
||||||
#define E_CLOSE_GEN 38
|
#define E_CLOSE_GEN 38
|
||||||
#define E_HACKER 39
|
#define E_EXTERNAL_MSG 40 //external message arrived from sse_listener
|
||||||
|
|
||||||
//side flags
|
//side flags
|
||||||
|
|
||||||
|
|
|
@ -281,6 +281,10 @@ INIS sinit[]=
|
||||||
int last_ms_cursor=-1;
|
int last_ms_cursor=-1;
|
||||||
int vmode=2;
|
int vmode=2;
|
||||||
|
|
||||||
|
#include <platform/sse_receiver.h>
|
||||||
|
|
||||||
|
static SSE_RECEIVER *sse_receiver = NULL;
|
||||||
|
|
||||||
|
|
||||||
void purge_temps(char _) {
|
void purge_temps(char _) {
|
||||||
temp_storage_clear();
|
temp_storage_clear();
|
||||||
|
@ -740,7 +744,7 @@ void done_skeldal(void)
|
||||||
cur_config = NULL;
|
cur_config = NULL;
|
||||||
}
|
}
|
||||||
kill_timer();
|
kill_timer();
|
||||||
|
if (sse_receiver) sse_receiver_destroy(sse_receiver);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -960,6 +964,34 @@ char end_of_song_callback(void *, TMUSIC_SOURCE *s, TMUSIC_SOURCE_TYPE *t) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void sse_listener_watch(EVENT_MSG *msg, void **userdata) {
|
||||||
|
if (msg->msg == E_WATCH) {
|
||||||
|
const char *s = sse_receiver_receive(sse_receiver);
|
||||||
|
if (s) {
|
||||||
|
send_message(E_EXTERNAL_MSG, s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void sse_listener_init(const char *hostport) {
|
||||||
|
|
||||||
|
char *host = local_strdup(hostport);
|
||||||
|
char *port = strrchr(host,':');
|
||||||
|
if (port == NULL) {
|
||||||
|
port = local_strdup("80");
|
||||||
|
} else {
|
||||||
|
*port = 0;
|
||||||
|
++port;
|
||||||
|
}
|
||||||
|
|
||||||
|
SSE_RECEIVER *rcv = sse_receiver_create(host, port);
|
||||||
|
|
||||||
|
if (rcv == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sse_receiver = rcv;
|
||||||
|
send_message(E_ADD, E_WATCH, sse_listener_watch);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void init_skeldal(const INI_CONFIG *cfg)
|
void init_skeldal(const INI_CONFIG *cfg)
|
||||||
{
|
{
|
||||||
|
@ -973,6 +1005,7 @@ void init_skeldal(const INI_CONFIG *cfg)
|
||||||
|
|
||||||
steam_init();
|
steam_init();
|
||||||
|
|
||||||
|
|
||||||
char verr = game_display_init(ini_section_open(cfg, "video"), "Skeldal");
|
char verr = game_display_init(ini_section_open(cfg, "video"), "Skeldal");
|
||||||
if (!verr)
|
if (!verr)
|
||||||
{
|
{
|
||||||
|
@ -980,7 +1013,7 @@ void init_skeldal(const INI_CONFIG *cfg)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
showview = game_display_update_rect;
|
showview = game_display_update_rect;
|
||||||
game_display_set_icon(getWindowIcon(), getWindowIconSize());
|
// game_display_set_icon(getWindowIcon(), getWindowIconSize());
|
||||||
init_joystick(ini_section_open(cfg, "controller"));
|
init_joystick(ini_section_open(cfg, "controller"));
|
||||||
|
|
||||||
general_engine_init();
|
general_engine_init();
|
||||||
|
@ -1090,29 +1123,39 @@ char doNotLoadMapState=0;
|
||||||
static int reload_map_handler(EVENT_MSG *msg,void **usr)
|
static int reload_map_handler(EVENT_MSG *msg,void **usr)
|
||||||
{
|
{
|
||||||
extern char running_battle;
|
extern char running_battle;
|
||||||
if (msg->msg==E_RELOADMAP)
|
if (msg->msg==E_EXTERNAL_MSG)
|
||||||
{
|
{
|
||||||
int i;
|
const char *m = va_arg(msg->data, const char *);
|
||||||
ReloadMapInfo *minfo=va_arg(msg->data, ReloadMapInfo *);
|
char fname[13];
|
||||||
const char *fname=minfo->fname;
|
int sector;
|
||||||
int sektor=minfo->sektor;
|
int i;
|
||||||
strcopy_n(loadlevel.name,fname,sizeof(loadlevel.name));
|
|
||||||
loadlevel.start_pos=sektor;
|
if (sscanf(m, "RELOAD %12s %d", fname, §or) == 2) {
|
||||||
for(i=0;i<POCET_POSTAV;i++)postavy[i].sektor=loadlevel.start_pos;
|
|
||||||
SEND_LOG("(WIZARD) Load map '%s' %d",loadlevel.name,loadlevel.start_pos);
|
strcopy_n(loadlevel.name,fname,sizeof(loadlevel.name));
|
||||||
unwire_proc();
|
loadlevel.start_pos=sector;
|
||||||
if (battle) konec_kola();
|
for(i=0;i<POCET_POSTAV;i++) if (postavy[i].used) {
|
||||||
battle=0;
|
postavy[i].sektor=loadlevel.start_pos;
|
||||||
running_battle=0;
|
postavy[i].groupnum = 1;
|
||||||
doNotLoadMapState=1;
|
}
|
||||||
hl_ptr=ikon_libs;
|
SEND_LOG("(WIZARD) Load map '%s' %d",loadlevel.name,loadlevel.start_pos);
|
||||||
destroy_fly_map();
|
unwire_proc();
|
||||||
load_items();
|
if (battle) konec_kola();
|
||||||
zneplatnit_block(H_ENEMY);
|
battle=0;
|
||||||
zneplatnit_block(H_SHOP_PIC);
|
running_battle=0;
|
||||||
zneplatnit_block(H_DIALOGY_DAT);
|
doNotLoadMapState=1;
|
||||||
load_shops();
|
hl_ptr=ikon_libs;
|
||||||
send_message(E_CLOSE_MAP);
|
destroy_fly_map();
|
||||||
|
load_items();
|
||||||
|
zneplatnit_block(H_ENEMY);
|
||||||
|
zneplatnit_block(H_SHOP_PIC);
|
||||||
|
zneplatnit_block(H_DIALOGY_DAT);
|
||||||
|
load_shops();
|
||||||
|
send_message(E_CLOSE_MAP);
|
||||||
|
} else if (strncmp(m, "MESSAGE ", 8) == 0) {
|
||||||
|
bott_disp_text(m+8);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1612,6 +1655,10 @@ int skeldal_entry_point(const SKELDAL_CONFIG *start_cfg)
|
||||||
enable_achievements(1);
|
enable_achievements(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (start_cfg->sse_hostport) {
|
||||||
|
sse_listener_init(start_cfg->sse_hostport);
|
||||||
|
}
|
||||||
|
|
||||||
start_check();
|
start_check();
|
||||||
purge_temps(1);
|
purge_temps(1);
|
||||||
clrscr();
|
clrscr();
|
||||||
|
|
|
@ -14,6 +14,7 @@ typedef struct {
|
||||||
const char *lang_path;
|
const char *lang_path;
|
||||||
const char *patch_file;
|
const char *patch_file;
|
||||||
|
|
||||||
|
const char *sse_hostport;
|
||||||
|
|
||||||
} SKELDAL_CONFIG;
|
} SKELDAL_CONFIG;
|
||||||
|
|
||||||
|
|
|
@ -12,17 +12,18 @@ target_sources(skeldal_platform PRIVATE
|
||||||
timer.cpp
|
timer.cpp
|
||||||
getopt.c
|
getopt.c
|
||||||
achievements.cpp
|
achievements.cpp
|
||||||
|
sse_receiver.c
|
||||||
)
|
)
|
||||||
|
|
||||||
set(all_libs
|
set(all_libs
|
||||||
skeldal_main
|
skeldal_main
|
||||||
skeldal_libs
|
skeldal_libs
|
||||||
skeldal_platform
|
skeldal_platform
|
||||||
skeldal_sdl
|
skeldal_sdl
|
||||||
skeldal_libs
|
skeldal_libs
|
||||||
${SDL2_LIBRARIES}
|
${SDL2_LIBRARIES}
|
||||||
${STANDARD_LIBRARIES})
|
${STANDARD_LIBRARIES})
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
target_sources(skeldal_platform PRIVATE
|
target_sources(skeldal_platform PRIVATE
|
||||||
windows/save_folder.cpp
|
windows/save_folder.cpp
|
||||||
|
@ -35,7 +36,7 @@ if(WIN32)
|
||||||
windows/skeldal.rc
|
windows/skeldal.rc
|
||||||
)
|
)
|
||||||
target_compile_definitions(skeldal_platform PRIVATE PLATFORM_WINDOWS)
|
target_compile_definitions(skeldal_platform PRIVATE PLATFORM_WINDOWS)
|
||||||
if(STEAM_ENABLED)
|
if(STEAM_ENABLED)
|
||||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||||
# 64-bit
|
# 64-bit
|
||||||
set(STEAMLIB ${STEAMWORKS_SDK_DIR}/redistributable_bin/win64/steam_api64.lib)
|
set(STEAMLIB ${STEAMWORKS_SDK_DIR}/redistributable_bin/win64/steam_api64.lib)
|
||||||
|
@ -49,7 +50,7 @@ if(WIN32)
|
||||||
set(STEAMLIB "")
|
set(STEAMLIB "")
|
||||||
set(STEAMDLL "")
|
set(STEAMDLL "")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_link_libraries(skeldal ${all_libs} ${STEAMLIB})
|
target_link_libraries(skeldal ${all_libs} ${STEAMLIB})
|
||||||
|
|
||||||
if(STEAMDLL)
|
if(STEAMDLL)
|
||||||
|
@ -69,7 +70,7 @@ elseif(UNIX AND NOT APPLE)
|
||||||
linux/app_start.cpp
|
linux/app_start.cpp
|
||||||
)
|
)
|
||||||
target_compile_definitions(skeldal_bin PRIVATE PLATFORM_LINUX)
|
target_compile_definitions(skeldal_bin PRIVATE PLATFORM_LINUX)
|
||||||
if(STEAM_ENABLED)
|
if(STEAM_ENABLED)
|
||||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||||
# 64-bit
|
# 64-bit
|
||||||
set(STEAMLIB ${STEAMWORKS_SDK_DIR}/redistributable_bin/linux64/libsteam_api.so)
|
set(STEAMLIB ${STEAMWORKS_SDK_DIR}/redistributable_bin/linux64/libsteam_api.so)
|
||||||
|
@ -83,10 +84,10 @@ elseif(UNIX AND NOT APPLE)
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy
|
COMMAND ${CMAKE_COMMAND} -E copy
|
||||||
${CMAKE_CURRENT_LIST_DIR}/linux/skeldal.sh
|
${CMAKE_CURRENT_LIST_DIR}/linux/skeldal.sh
|
||||||
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/skeldal.sh)
|
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/skeldal.sh)
|
||||||
target_link_libraries(skeldal_bin ${all_libs} ${STEAMLIB})
|
target_link_libraries(skeldal_bin ${all_libs} ${STEAMLIB})
|
||||||
message(STATUS "Building for Linux")
|
message(STATUS "Building for Linux")
|
||||||
|
|
||||||
elseif(APPLE)
|
elseif(APPLE)
|
||||||
target_sources(skeldal_platform PRIVATE
|
target_sources(skeldal_platform PRIVATE
|
||||||
mac_os/save_folder.cpp
|
mac_os/save_folder.cpp
|
||||||
)
|
)
|
||||||
|
@ -100,7 +101,7 @@ elseif(APPLE)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated-declarations")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated-declarations")
|
||||||
message(STATUS "Building for macOS")
|
message(STATUS "Building for macOS")
|
||||||
target_link_libraries(skeldal ${all_libs} ${STEAMLIB})
|
target_link_libraries(skeldal ${all_libs} ${STEAMLIB})
|
||||||
else()
|
else()
|
||||||
error("Platform not detected, please add new platform here")
|
error("Platform not detected, please add new platform here")
|
||||||
endif()
|
endif()
|
||||||
set_property(TARGET skeldal_platform PROPERTY CXX_STANDARD 20)
|
set_property(TARGET skeldal_platform PROPERTY CXX_STANDARD 20)
|
||||||
|
|
|
@ -21,6 +21,7 @@ void show_help(const char *arg0) {
|
||||||
"-p <file> patch data with custom DDL\n"
|
"-p <file> patch data with custom DDL\n"
|
||||||
"-l <lang> set language (cz|en)\n"
|
"-l <lang> set language (cz|en)\n"
|
||||||
"-s <directory> generate string-tables (for localization) and exit\n"
|
"-s <directory> generate string-tables (for localization) and exit\n"
|
||||||
|
"-c <host:port> connect to host:port for remote control (mapedit)\n"
|
||||||
"-h this help\n");
|
"-h this help\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
@ -36,7 +37,8 @@ int main(int argc, char **argv) {
|
||||||
std::string gen_stringtable_path;
|
std::string gen_stringtable_path;
|
||||||
std::string patch;
|
std::string patch;
|
||||||
std::string lang;
|
std::string lang;
|
||||||
for (int optchr = -1; (optchr = getopt(argc, argv, "hf:a:s:l:p:")) != -1; ) {
|
std::string sse_hostport;
|
||||||
|
for (int optchr = -1; (optchr = getopt(argc, argv, "hf:a:s:l:p:c:")) != -1; ) {
|
||||||
switch (optchr) {
|
switch (optchr) {
|
||||||
case 'f': config_name = optarg;break;
|
case 'f': config_name = optarg;break;
|
||||||
case 'a': adv_config_file = optarg;break;
|
case 'a': adv_config_file = optarg;break;
|
||||||
|
@ -44,6 +46,7 @@ int main(int argc, char **argv) {
|
||||||
case 'p': patch = optarg; break;
|
case 'p': patch = optarg; break;
|
||||||
case 'l': lang = optarg;break;
|
case 'l': lang = optarg;break;
|
||||||
case 's': gen_stringtable_path = optarg;break;
|
case 's': gen_stringtable_path = optarg;break;
|
||||||
|
case 'c': sse_hostport = optarg;break;
|
||||||
default: show_help_short();
|
default: show_help_short();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -58,6 +61,7 @@ int main(int argc, char **argv) {
|
||||||
cfg.config_path = config_name.c_str();
|
cfg.config_path = config_name.c_str();
|
||||||
cfg.lang_path = lang.empty()?NULL:lang.c_str();
|
cfg.lang_path = lang.empty()?NULL:lang.c_str();
|
||||||
cfg.patch_file = patch.empty()?NULL:patch.c_str();
|
cfg.patch_file = patch.empty()?NULL:patch.c_str();
|
||||||
|
cfg.sse_hostport = sse_hostport.c_str();
|
||||||
try {
|
try {
|
||||||
|
|
||||||
if (!gen_stringtable_path.empty()) {
|
if (!gen_stringtable_path.empty()) {
|
||||||
|
|
183
platform/sse_receiver.c
Normal file
183
platform/sse_receiver.c
Normal file
|
@ -0,0 +1,183 @@
|
||||||
|
// sse_receiver.c
|
||||||
|
#include "sse_receiver.h"
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <winsock2.h>
|
||||||
|
#include <ws2tcpip.h>
|
||||||
|
#pragma comment(lib, "ws2_32.lib")
|
||||||
|
typedef SOCKET sock_t;
|
||||||
|
#define CLOSESOCK closesocket
|
||||||
|
#define sock_init() { WSADATA wsa; WSAStartup(MAKEWORD(2,2), &wsa); }
|
||||||
|
#define sock_cleanup() WSACleanup()
|
||||||
|
#else
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
typedef int sock_t;
|
||||||
|
#define INVALID_SOCKET -1
|
||||||
|
#define CLOSESOCK close
|
||||||
|
#define sock_init()
|
||||||
|
#define sock_cleanup()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define BUFFER_SIZE 4096
|
||||||
|
|
||||||
|
struct tag_sse_receiver {
|
||||||
|
char host[256];
|
||||||
|
char port[16];
|
||||||
|
sock_t sock;
|
||||||
|
int connected;
|
||||||
|
char buffer[BUFFER_SIZE+1];
|
||||||
|
size_t buf_len;
|
||||||
|
size_t line_len;
|
||||||
|
time_t next_attempt;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void set_nonblocking(sock_t sock) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
u_long mode = 1;
|
||||||
|
ioctlsocket(sock, FIONBIO, &mode);
|
||||||
|
#else
|
||||||
|
fcntl(sock, F_SETFL, fcntl(sock, F_GETFL, 0) | O_NONBLOCK);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static int connect_and_handshake(SSE_RECEIVER *sse) {
|
||||||
|
struct addrinfo hints = {0}, *res = NULL;
|
||||||
|
|
||||||
|
hints.ai_family = AF_INET;
|
||||||
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
|
||||||
|
if (getaddrinfo(sse->host, sse->port, &hints, &res) != 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sock_t sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
|
||||||
|
if (sock == INVALID_SOCKET) {
|
||||||
|
freeaddrinfo(res);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (connect(sock, res->ai_addr, (int)res->ai_addrlen) != 0) {
|
||||||
|
CLOSESOCK(sock);
|
||||||
|
freeaddrinfo(res);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
freeaddrinfo(res);
|
||||||
|
|
||||||
|
const char *req_fmt =
|
||||||
|
"GET /command HTTP/1.1\r\n"
|
||||||
|
"Host: %s\r\n"
|
||||||
|
"Accept: text/event-stream\r\n"
|
||||||
|
"Connection: keep-alive\r\n\r\n";
|
||||||
|
|
||||||
|
char req[512];
|
||||||
|
snprintf(req, sizeof(req), req_fmt, sse->host);
|
||||||
|
send(sock, req, (int)strlen(req), 0);
|
||||||
|
|
||||||
|
set_nonblocking(sock);
|
||||||
|
sse->sock = sock;
|
||||||
|
sse->buf_len = 0;
|
||||||
|
sse->line_len = 0;
|
||||||
|
sse->connected = 1;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
SSE_RECEIVER *sse_receiver_create(const char *host, const char *port) {
|
||||||
|
sock_init();
|
||||||
|
SSE_RECEIVER *sse = calloc(1, sizeof(SSE_RECEIVER));
|
||||||
|
strncpy(sse->host, host, sizeof(sse->host) - 1);
|
||||||
|
strncpy(sse->port, port, sizeof(sse->port) - 1);
|
||||||
|
sse->sock = INVALID_SOCKET;
|
||||||
|
sse->connected = 0;
|
||||||
|
sse->buf_len = 0;
|
||||||
|
sse->line_len = 0;
|
||||||
|
sse->next_attempt = 0;
|
||||||
|
return sse;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t find_sep(const char *buffer, size_t size, char sep) {
|
||||||
|
for (size_t i = 0; i < size; ++i) {
|
||||||
|
if (buffer[i] == sep) return i;
|
||||||
|
}
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *sse_receiver_receive(SSE_RECEIVER *sse) {
|
||||||
|
while(1) {
|
||||||
|
size_t rm = sse->buf_len-sse->line_len;
|
||||||
|
if (rm) {
|
||||||
|
const char *r = sse->buffer+sse->line_len;
|
||||||
|
size_t sep = find_sep(r, rm, '\n');
|
||||||
|
if (sep < rm) {
|
||||||
|
sep += sse->line_len;
|
||||||
|
sse->buffer[sep] = 0;
|
||||||
|
sse->line_len = sep+1;
|
||||||
|
|
||||||
|
if (strncmp(r,"data:",5) == 0) {
|
||||||
|
r+=5;
|
||||||
|
while (*r && isspace(*r)) ++r;
|
||||||
|
if (*r) {
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (r != sse->buffer) memmove(sse->buffer, r, rm);
|
||||||
|
}
|
||||||
|
sse->line_len = 0;
|
||||||
|
sse->buf_len = rm;
|
||||||
|
|
||||||
|
if (!sse->connected) {
|
||||||
|
time_t t = time(NULL);
|
||||||
|
if (t < sse->next_attempt) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!connect_and_handshake(sse)) {
|
||||||
|
snprintf(sse->buffer, sizeof(sse->buffer) - 1,
|
||||||
|
"MESSAGE Failed to connect the command server %s:%s ",
|
||||||
|
sse->host, sse->port);
|
||||||
|
sse->next_attempt = t+5;
|
||||||
|
return sse->buffer;
|
||||||
|
} else {
|
||||||
|
return "MESSAGE Connected to command server";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int n = recv(sse->sock, sse->buffer + sse->buf_len, (int)(BUFFER_SIZE - sse->buf_len), 0);
|
||||||
|
if (n <= 0) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
int err = WSAGetLastError();
|
||||||
|
if (err != WSAEWOULDBLOCK && err != WSAEINPROGRESS)
|
||||||
|
#else
|
||||||
|
if (errno != EWOULDBLOCK && errno != EAGAIN)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
CLOSESOCK(sse->sock);
|
||||||
|
sse->connected = 0;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sse->buf_len += n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sse_receiver_destroy(SSE_RECEIVER *sse) {
|
||||||
|
if (sse->connected) {
|
||||||
|
CLOSESOCK(sse->sock);
|
||||||
|
}
|
||||||
|
free(sse);
|
||||||
|
sock_cleanup();
|
||||||
|
}
|
16
platform/sse_receiver.h
Normal file
16
platform/sse_receiver.h
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct tag_sse_receiver SSE_RECEIVER;
|
||||||
|
SSE_RECEIVER *sse_receiver_create(const char *host, const char *port);
|
||||||
|
const char *sse_receiver_receive(SSE_RECEIVER *sse);
|
||||||
|
void sse_receiver_destroy(SSE_RECEIVER *inst);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -24,6 +24,7 @@ void show_help(std::ostream &out, const char *arg0) {
|
||||||
"-p <file> patch data with custom DDL\n"
|
"-p <file> patch data with custom DDL\n"
|
||||||
"-l <lang> set language (cz|en)\n"
|
"-l <lang> set language (cz|en)\n"
|
||||||
"-s <directory> generate string-tables (for localization) and exit\n"
|
"-s <directory> generate string-tables (for localization) and exit\n"
|
||||||
|
"-c <host:port> connect to host:port for remote control (mapedit)\n"
|
||||||
"-h this help\n";
|
"-h this help\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,8 +39,9 @@ int main(int argc, char **argv) {
|
||||||
std::string gen_stringtable_path;
|
std::string gen_stringtable_path;
|
||||||
std::string lang;
|
std::string lang;
|
||||||
std::string patch;
|
std::string patch;
|
||||||
|
std::string sse_hostport;
|
||||||
std::ostringstream console;
|
std::ostringstream console;
|
||||||
for (int optchr = -1; (optchr = getopt(argc, argv, "hf:a:s:l:p:")) != -1; ) {
|
for (int optchr = -1; (optchr = getopt(argc, argv, "hf:a:s:l:c:p:")) != -1; ) {
|
||||||
switch (optchr) {
|
switch (optchr) {
|
||||||
case 'f': config_name = optarg;break;
|
case 'f': config_name = optarg;break;
|
||||||
case 'a': adv_config_file = optarg;break;
|
case 'a': adv_config_file = optarg;break;
|
||||||
|
@ -47,6 +49,7 @@ int main(int argc, char **argv) {
|
||||||
case 'p': patch = optarg; break;
|
case 'p': patch = optarg; break;
|
||||||
case 'l': lang = optarg;break;
|
case 'l': lang = optarg;break;
|
||||||
case 's': gen_stringtable_path = optarg;break;
|
case 's': gen_stringtable_path = optarg;break;
|
||||||
|
case 'c': sse_hostport = optarg;break;
|
||||||
default: show_help_short(console);break;
|
default: show_help_short(console);break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,7 +59,7 @@ int main(int argc, char **argv) {
|
||||||
show_help(console, argv[0]);
|
show_help(console, argv[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
SKELDAL_CONFIG cfg;
|
SKELDAL_CONFIG cfg = {};
|
||||||
cfg.short_help = []{};
|
cfg.short_help = []{};
|
||||||
cfg.show_error = [](const char *txt) {
|
cfg.show_error = [](const char *txt) {
|
||||||
char buff[MAX_PATH];
|
char buff[MAX_PATH];
|
||||||
|
@ -68,6 +71,7 @@ int main(int argc, char **argv) {
|
||||||
cfg.config_path = config_name.c_str();
|
cfg.config_path = config_name.c_str();
|
||||||
cfg.lang_path = lang.empty()?NULL:lang.c_str();
|
cfg.lang_path = lang.empty()?NULL:lang.c_str();
|
||||||
cfg.patch_file = patch.empty()?NULL:patch.c_str();
|
cfg.patch_file = patch.empty()?NULL:patch.c_str();
|
||||||
|
cfg.sse_hostport = sse_hostport.c_str();
|
||||||
|
|
||||||
{
|
{
|
||||||
std::string msg = console.str();
|
std::string msg = console.str();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue