Searching local game database works.

This commit is contained in:
Scott Duensing 2022-04-18 20:08:00 -05:00
parent 88369132e3
commit 377e40f28f
13 changed files with 352 additions and 112 deletions

View file

@ -72,6 +72,7 @@ HEADERS = \
$$SHARED/primes.h \ $$SHARED/primes.h \
$$SHARED/packet.h \ $$SHARED/packet.h \
$$SHARED/packets.h \ $$SHARED/packets.h \
../shared/game.h \
../shared/macros.h \ ../shared/macros.h \
src/browser.h \ src/browser.h \
src/config.h \ src/config.h \

View file

@ -27,28 +27,29 @@
#include "button.h" #include "button.h"
#include "frame.h" #include "frame.h"
#include "listbox.h" #include "listbox.h"
#include "textbox.h"
#include "timer.h"
#include "db.h"
#include "network.h" #include "network.h"
#include "util.h" #include "util.h"
static WindowT *_winBrowser = NULL; static WindowT *_winBrowser = NULL;
static ButtonT *_btnBoxTab = NULL; static TimerT *_timSearchUpdate = NULL;
static ButtonT *_btnDescriptionTab = NULL;
static ButtonT *_btnInfoTab = NULL;
static ButtonT *_btnScreensTab = NULL;
static ButtonT *_btnSearchTab = NULL; static ButtonT *_btnSearchTab = NULL;
static uint8_t _channel = 0;
static FrameT *_fraBox = NULL;
static FrameT *_fraDescription = NULL;
static FrameT *_fraInfo = NULL;
static FrameT *_fraScreens = NULL;
static FrameT *_fraSearch = NULL; static FrameT *_fraSearch = NULL;
static ListboxT *_lstDescription = NULL; static TextboxT *_txtSearch = NULL;
static ListboxT *_lstInfo = NULL; static ListboxT *_lstResults = NULL;
static ButtonT *_btnDescriptionTab = NULL;
static FrameT *_fraDescription = NULL;
static PictureT *_picBanner = NULL; static PictureT *_picBanner = NULL;
static PictureT *_picBox1 = NULL; static ListboxT *_lstDescription = NULL;
static PictureT *_picBox2 = NULL;
static ButtonT *_btnScreensTab = NULL;
static FrameT *_fraScreens = NULL;
static PictureT *_picThumb1 = NULL; static PictureT *_picThumb1 = NULL;
static PictureT *_picThumb2 = NULL; static PictureT *_picThumb2 = NULL;
static PictureT *_picThumb3 = NULL; static PictureT *_picThumb3 = NULL;
@ -56,14 +57,36 @@ static PictureT *_picThumb4 = NULL;
static PictureT *_picThumb5 = NULL; static PictureT *_picThumb5 = NULL;
static PictureT *_picThumb6 = NULL; static PictureT *_picThumb6 = NULL;
static ButtonT *_btnBoxTab = NULL;
static FrameT *_fraBox = NULL;
static PictureT *_picBox1 = NULL;
static PictureT *_picBox2 = NULL;
static ButtonT *_btnInfoTab = NULL;
static FrameT *_fraInfo = NULL;
static ListboxT *_lstInfo = NULL;
static uint8_t _channel = 0;
static char *_lastSearchText = NULL;
static void browserHide(void);
static void btnTabClick(WidgetT *widget); static void btnTabClick(WidgetT *widget);
static void packetHandler(PacketDecodeDataT *packet); static void packetHandler(PacketDecodeDataT *packet);
static void timSearchUpdate(WidgetT *widget);
static void browserHide(void) {
timerStop(_timSearchUpdate);
DEL(_lastSearchText);
netChannelRelease(_channel);
guiDelete(D(_winBrowser));
}
void browserShow(void) { void browserShow(void) {
char **lines = NULL; //char **lines = NULL;
TagItemT uiBrowser[] = { TagItemT uiBrowser[] = {
T_START, T_START,
@ -81,7 +104,18 @@ void browserShow(void) {
T_X, 5, T_Y, 32, T_X, 5, T_Y, 32,
T_WIDTH, 500, T_HEIGHT, 250, T_WIDTH, 500, T_HEIGHT, 250,
T_TITLE, P("Search"), T_TITLE, P("Search"),
T_VISIBLE, T_FALSE,
T_TEXTBOX, O(_txtSearch),
T_TITLE, P("Game, Publisher, or Developer:"),
T_X, 5, T_Y, 3,
T_WIDTH, 490,
T_LENGTH, 255,
T_TEXTBOX, T_DONE,
T_LISTBOX, O(_lstResults),
T_X, 1, T_Y, 35,
T_WIDTH, 493, T_HEIGHT, 190, // Works out to 57 characters wide, 13 high.
T_LISTBOX, T_DONE,
T_FRAME, T_DONE, T_FRAME, T_DONE,
// GAME // GAME
@ -89,6 +123,7 @@ void browserShow(void) {
T_X, 78, T_Y, 5, T_X, 78, T_Y, 5,
T_TITLE, P("Game"), T_TITLE, P("Game"),
T_CLICK, P(btnTabClick), T_CLICK, P(btnTabClick),
T_ENABLED, T_FALSE,
T_BUTTON, T_DONE, T_BUTTON, T_DONE,
T_FRAME, O(_fraDescription), T_FRAME, O(_fraDescription),
T_X, 5, T_Y, 32, T_X, 5, T_Y, 32,
@ -98,7 +133,7 @@ void browserShow(void) {
T_PICTURE, O(_picBanner), T_PICTURE, O(_picBanner),
T_X, 1, // 490PX wide T_X, 1, // 490PX wide
T_FILENAME, P("banner.png"), T_CACHENAME, P("games:d:descent:banner.png"), // ***TODO*** This needs a "browser:no-banner.png" image.
T_PICTURE, T_DONE, T_PICTURE, T_DONE,
T_LISTBOX, O(_lstDescription), T_LISTBOX, O(_lstDescription),
T_X, 1, T_Y, 105, T_X, 1, T_Y, 105,
@ -112,6 +147,7 @@ void browserShow(void) {
T_X, 135, T_Y, 5, T_X, 135, T_Y, 5,
T_TITLE, P("Screens"), T_TITLE, P("Screens"),
T_CLICK, P(btnTabClick), T_CLICK, P(btnTabClick),
T_ENABLED, T_FALSE,
T_BUTTON, T_DONE, T_BUTTON, T_DONE,
T_FRAME, O(_fraScreens), T_FRAME, O(_fraScreens),
T_X, 5, T_Y, 32, T_X, 5, T_Y, 32,
@ -121,28 +157,33 @@ void browserShow(void) {
T_PICTURE, O(_picThumb1), // Thumbs are 160x100 T_PICTURE, O(_picThumb1), // Thumbs are 160x100
T_X, 1, T_Y, 5, T_X, 1, T_Y, 5,
T_FILENAME, P("thumb1.png"), T_CACHENAME, P("browser:no-screen.png"),
T_PICTURE, T_DONE, T_PICTURE, T_DONE,
T_PICTURE, O(_picThumb2), T_PICTURE, O(_picThumb2),
T_X, 167, T_Y, 5, T_X, 167, T_Y, 5,
T_FILENAME, P("thumb2.png"), T_CACHENAME, P("browser:no-screen.png"),
T_VISIBLE, T_FALSE,
T_PICTURE, T_DONE, T_PICTURE, T_DONE,
T_PICTURE, O(_picThumb3), T_PICTURE, O(_picThumb3),
T_X, 333, T_Y, 5, T_X, 333, T_Y, 5,
T_FILENAME, P("thumb3.png"), T_CACHENAME, P("browser:no-screen.png"),
T_VISIBLE, T_FALSE,
T_PICTURE, T_DONE, T_PICTURE, T_DONE,
T_PICTURE, O(_picThumb4), T_PICTURE, O(_picThumb4),
T_X, 1, T_Y, 116, T_X, 1, T_Y, 116,
T_FILENAME, P("thumb4.png"), T_CACHENAME, P("browser:no-screen.png"),
T_VISIBLE, T_FALSE,
T_PICTURE, T_DONE, T_PICTURE, T_DONE,
T_PICTURE, O(_picThumb5), T_PICTURE, O(_picThumb5),
T_X, 167, T_Y, 116, T_X, 167, T_Y, 116,
T_FILENAME, P("thumb5.png"), T_CACHENAME, P("browser:no-screen.png"),
T_VISIBLE, T_FALSE,
T_PICTURE, T_DONE, T_PICTURE, T_DONE,
T_PICTURE, O(_picThumb6), T_PICTURE, O(_picThumb6),
T_X, 333, T_Y, 116, T_X, 333, T_Y, 116,
T_FILENAME, P("thumb6.png"), T_CACHENAME, P("browser:no-screen.png"),
T_VISIBLE, T_FALSE,
T_PICTURE, T_DONE, T_PICTURE, T_DONE,
T_FRAME, T_DONE, T_FRAME, T_DONE,
@ -152,6 +193,7 @@ void browserShow(void) {
T_X, 216, T_Y, 5, T_X, 216, T_Y, 5,
T_TITLE, P("Box"), T_TITLE, P("Box"),
T_CLICK, P(btnTabClick), T_CLICK, P(btnTabClick),
T_ENABLED, T_FALSE,
T_BUTTON, T_DONE, T_BUTTON, T_DONE,
T_FRAME, O(_fraBox), T_FRAME, O(_fraBox),
T_X, 5, T_Y, 32, T_X, 5, T_Y, 32,
@ -161,11 +203,12 @@ void browserShow(void) {
T_PICTURE, O(_picBox1), // Thumbs are 240x210 T_PICTURE, O(_picBox1), // Thumbs are 240x210
T_X, 1, T_Y, 5, T_X, 1, T_Y, 5,
T_FILENAME, P("box1.png"), T_CACHENAME, P("browser:no-box.png"),
T_PICTURE, T_DONE, T_PICTURE, T_DONE,
T_PICTURE, O(_picBox2), T_PICTURE, O(_picBox2),
T_X, 250, T_Y, 5, T_X, 250, T_Y, 5,
T_FILENAME, P("box2.png"), T_CACHENAME, P("browser:no-box.png"),
T_VISIBLE, T_FALSE,
T_PICTURE, T_DONE, T_PICTURE, T_DONE,
T_FRAME, T_DONE, T_FRAME, T_DONE,
@ -175,12 +218,13 @@ void browserShow(void) {
T_X, 265, T_Y, 5, T_X, 265, T_Y, 5,
T_TITLE, P("Info"), T_TITLE, P("Info"),
T_CLICK, P(btnTabClick), T_CLICK, P(btnTabClick),
T_ENABLED, T_FALSE,
T_BUTTON, T_DONE, T_BUTTON, T_DONE,
T_FRAME, O(_fraInfo), T_FRAME, O(_fraInfo),
T_X, 5, T_Y, 32, T_X, 5, T_Y, 32,
T_WIDTH, 500, T_HEIGHT, 250, T_WIDTH, 500, T_HEIGHT, 250,
T_TITLE, P("Information"), T_TITLE, P("Information"),
T_VISIBLE, T_TRUE, T_VISIBLE, T_FALSE,
T_LISTBOX, O(_lstInfo), T_LISTBOX, O(_lstInfo),
T_X, 1, T_Y, 5, T_X, 1, T_Y, 5,
@ -189,19 +233,24 @@ void browserShow(void) {
T_FRAME, T_DONE, T_FRAME, T_DONE,
T_TIMER, O(_timSearchUpdate),
T_EVENT, P(timSearchUpdate),
T_VALUE, 3,
T_ENABLED, 1,
T_TIMER, T_DONE,
T_WINDOW, T_DONE, T_WINDOW, T_DONE,
T_END T_END
}; };
tagListRun(uiBrowser); tagListRun(uiBrowser);
guiFocusSet(W(_txtSearch));
_channel = netChannelGet(packetHandler); _channel = netChannelGet(packetHandler);
guiDebugAreaShow(W(_btnSearchTab)); _lastSearchText = strdup("");
guiDebugAreaShow(W(_btnDescriptionTab));
guiDebugAreaShow(W(_btnScreensTab)); /*
guiDebugAreaShow(W(_btnBoxTab)); guiDebugAreaShow(W(_fraSearch));
guiDebugAreaShow(W(_btnInfoTab));
lines = utilWrapText( lines = utilWrapText(
"The Post-Terran Minerals Corporation (PTMC) digs up minerals on all nine planets of the solar system, " "The Post-Terran Minerals Corporation (PTMC) digs up minerals on all nine planets of the solar system, "
@ -216,23 +265,24 @@ void browserShow(void) {
arrdel(lines, 0); arrdel(lines, 0);
} }
listboxItemAdd(_lstInfo, "123456789012345678901234567890123456789012345678901234567"); listboxItemAdd(_lstResults, "123456789012345678901234567890123456789012345678901234567");
listboxItemAdd(_lstInfo, "2"); listboxItemAdd(_lstResults, "2");
listboxItemAdd(_lstInfo, "3"); listboxItemAdd(_lstResults, "3");
listboxItemAdd(_lstInfo, "4"); listboxItemAdd(_lstResults, "4");
listboxItemAdd(_lstInfo, "5"); listboxItemAdd(_lstResults, "5");
listboxItemAdd(_lstInfo, "6"); listboxItemAdd(_lstResults, "6");
listboxItemAdd(_lstInfo, "7"); listboxItemAdd(_lstResults, "7");
listboxItemAdd(_lstInfo, "8"); listboxItemAdd(_lstResults, "8");
listboxItemAdd(_lstInfo, "9"); listboxItemAdd(_lstResults, "9");
listboxItemAdd(_lstInfo, "10"); listboxItemAdd(_lstResults, "10");
listboxItemAdd(_lstInfo, "11"); listboxItemAdd(_lstResults, "11");
listboxItemAdd(_lstInfo, "12"); listboxItemAdd(_lstResults, "12");
listboxItemAdd(_lstInfo, "13"); listboxItemAdd(_lstResults, "13");
listboxItemAdd(_lstInfo, "14"); listboxItemAdd(_lstResults, "14");
listboxItemAdd(_lstInfo, "15"); listboxItemAdd(_lstResults, "15");
listboxItemAdd(_lstInfo, "16"); listboxItemAdd(_lstResults, "16");
listboxItemAdd(_lstInfo, "17"); listboxItemAdd(_lstResults, "17");
*/
} }
@ -255,3 +305,43 @@ static void btnTabClick(WidgetT *widget) {
static void packetHandler(PacketDecodeDataT *packet) { static void packetHandler(PacketDecodeDataT *packet) {
} }
static void timSearchUpdate(WidgetT *widget) {
char ***records = NULL;
char **fields = NULL;
uint16_t count = 0;
char query[258]; // 255 search characters, two %'s, and the terminating null.
(void)widget;
// Are there more than two characters in the search field?
if (textboxValueGet(_txtSearch) && strlen(textboxValueGet(_txtSearch)) > 2) {
// Did the search contents change?
if (strcmp(_lastSearchText, textboxValueGet(_txtSearch))) {
// Remember what was in the search box.
DEL(_lastSearchText);
_lastSearchText = strdup(textboxValueGet(_txtSearch));
// Clear current search results.
listboxItemsClear(_lstResults);
// Execute search.
snprintf(query, 258, "%%%s%%", _lastSearchText);
dbQueryMultiple(&records,
"SELECT title FROM games WHERE "
"title LIKE ? OR developer LIKE ? OR publisher LIKE ? "
"ORDER BY title",
"vvv",
query,
query,
query);
// Did we get anything?
if (records) {
for (count = 0; count < arrlen(records); count++) {
fields = records[count];
listboxItemAdd(_lstResults, fields[0]);
}
dbResultRelease(&records);
}
}
}
}

View file

@ -44,15 +44,8 @@ static void listboxSizesRecalculate(ListboxT *listbox);
static void listboxDel(WidgetT **widget) { static void listboxDel(WidgetT **widget) {
ListboxT *l = (ListboxT *)*widget; ListboxT *l = (ListboxT *)*widget;
size_t len = arrlenu(l->values);
size_t x;
if (len > 0) { listboxItemsClear(l);
for (x=0; x<len; x++) {
free(l->values[x]);
}
}
arrfree(l->values);
} }
@ -102,6 +95,7 @@ void listboxItemRemove(ListboxT *listbox, char *item) {
if (len > 0) { if (len > 0) {
for (x=0; x<len; x++) { for (x=0; x<len; x++) {
if (strcmp(item, listbox->values[x]) == 0) { if (strcmp(item, listbox->values[x]) == 0) {
DEL(listbox->values[x]);
arrdel(listbox->values, x); arrdel(listbox->values, x);
if (listbox->selected > len || listbox->selected > 0) listbox->selected--; if (listbox->selected > len || listbox->selected > 0) listbox->selected--;
GUI_SET_FLAG((WidgetT *)listbox, WIDGET_FLAG_DIRTY); GUI_SET_FLAG((WidgetT *)listbox, WIDGET_FLAG_DIRTY);
@ -112,6 +106,17 @@ void listboxItemRemove(ListboxT *listbox, char *item) {
} }
void listboxItemsClear(ListboxT *listbox) {
while (arrlen(listbox->values) > 0) {
DEL(listbox->values[0]);
arrdel(listbox->values, 0);
}
arrfree(listbox->values);
listbox->selected = 0;
}
static void listboxKeyboardEvent(WidgetT *widget, uint8_t ascii, uint8_t extended, uint8_t scancode, uint8_t shift, uint8_t control, uint8_t alt) { static void listboxKeyboardEvent(WidgetT *widget, uint8_t ascii, uint8_t extended, uint8_t scancode, uint8_t shift, uint8_t control, uint8_t alt) {
ListboxT *l = (ListboxT *)widget; ListboxT *l = (ListboxT *)widget;

View file

@ -41,6 +41,7 @@ void listboxIndexSet(ListboxT *listbox, uint16_t index);
WidgetT *listboxInit(WidgetT *widget, char *title); WidgetT *listboxInit(WidgetT *widget, char *title);
void listboxItemAdd(ListboxT *listbox, char *item); void listboxItemAdd(ListboxT *listbox, char *item);
void listboxItemRemove(ListboxT *listbox, char *item); void listboxItemRemove(ListboxT *listbox, char *item);
void listboxItemsClear(ListboxT *listbox);
ListboxT *listboxNew(uint16_t x, uint16_t y, uint16_t w, uint16_t h, char *title); ListboxT *listboxNew(uint16_t x, uint16_t y, uint16_t w, uint16_t h, char *title);
void listboxStepSet(ListboxT *listbox, int32_t step); void listboxStepSet(ListboxT *listbox, int32_t step);
void listboxTitleSet(ListboxT *listbox, char *title); void listboxTitleSet(ListboxT *listbox, char *title);

View file

@ -211,6 +211,7 @@ static uint8_t startup(int argc, char *argv[]) {
extern void browserShow(void); extern void browserShow(void);
extern void updateGameDatabase(void);
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
@ -221,8 +222,9 @@ int main(int argc, char *argv[]) {
// Perform "first run" setup tasks or start the client? // Perform "first run" setup tasks or start the client?
if (hasValidSettings()) { if (hasValidSettings()) {
// We have what we need, start the client. // We have what we need, start the client.
welcomeShow(); //welcomeShow();
//browserShow(); updateGameDatabase();
browserShow();
eventLoop(); eventLoop();
} else { } else {
// Run the setup. // Run the setup.

View file

@ -21,6 +21,7 @@
#include "network.h" #include "network.h"
#include "vesa.h" #include "vesa.h"
#include "db.h" #include "db.h"
#include "game.h"
#include "taglist.h" #include "taglist.h"
#include "msgbox.h" #include "msgbox.h"
@ -44,7 +45,7 @@ static void picForumsClick(WidgetT *widget);
static void picGamesClick(WidgetT *widget); static void picGamesClick(WidgetT *widget);
static void picLogoffClick(WidgetT *widget); static void picLogoffClick(WidgetT *widget);
static void picProfileClick(WidgetT *widget); static void picProfileClick(WidgetT *widget);
static void updateGameDatabase(void); /* static */ void updateGameDatabase(void);
static PictureT *_picChat = NULL; static PictureT *_picChat = NULL;
@ -154,6 +155,7 @@ void menuShow(void) {
"menu:48profile.png", "menu:48profile.png",
"generated:games.dat", "generated:games.dat",
// LOAD THE WORLD! This is for debugging the browser.
"games:d:descent:banner.png", "games:d:descent:banner.png",
"games:d:descent:box2.png", "games:d:descent:box2.png",
"games:d:descent:screen1.png", "games:d:descent:screen1.png",
@ -355,9 +357,51 @@ static void picProfileClick(WidgetT *widget) {
} }
static void updateGameDatabase(void) { uint8_t utilFromFileReadByte(FILE *f, uint8_t *result) {
unsigned char c;
// Get next byte.
c = fgetc(f);
// End of file?
if (feof(f)) return FAIL;
// Add to result.
*result = c;
return SUCCESS;
}
uint8_t utilFromFileReadString(FILE *f, char **result) {
unsigned char c;
char buffer[GAME_MAX_DESCRIPTION];
uint16_t x = 0;
// Something already in 'result'?
DEL(*result);
while (1) {
// Get next byte.
c = fgetc(f);
// End of file?
if (feof(f)) return FAIL;
// Add to result.
buffer[x++] = c;
buffer[x] = 0;
// End of string?
if (c == 0) {
*result = strdup(buffer);
return SUCCESS;
}
}
}
/* static */ void updateGameDatabase(void) {
FILE *f = NULL; FILE *f = NULL;
uint8_t c; uint8_t result;
GameT game;
// Clear 'game'.
memset(&game, 0, sizeof(GameT));
// Do we need to create the game database? // Do we need to create the game database?
dbExecute( dbExecute(
@ -372,7 +416,7 @@ static void updateGameDatabase(void) {
"origin VARCHAR(255), " "origin VARCHAR(255), "
"shortName VARCHAR(8) PRIMARY KEY, " "shortName VARCHAR(8) PRIMARY KEY, "
"worksWith VARCHAR(255), " "worksWith VARCHAR(255), "
"type VARCHAR(8), " "type INTEGER, "
"maxPlayers INTEGER, " "maxPlayers INTEGER, "
"joinable BOOLEAN, " "joinable BOOLEAN, "
"screens INTEGER, " "screens INTEGER, "
@ -382,22 +426,85 @@ static void updateGameDatabase(void) {
NULL); NULL);
// Mark everything untouched. // Mark everything untouched.
dbExecute("UPDATE games SET touced=0", NULL); dbExecute("UPDATE games SET touched=0", NULL);
/*
// Process latest downloaded game list. // Process latest downloaded game list.
f = cacheFOpen("generated:games.dat", "rb"); f = cacheFOpen("generated:games.dat", "rb");
if (f) { if (f) {
result = FAIL;
while (1) { while (1) {
// Get next byte. // If this first read fails, we're out of data. Any other read fails, we have problems.
c = fgetc(f); if (!utilFromFileReadString(f, &game.title)) {
// End of file? result = SUCCESS;
if (feof(f)) break; break;
}
if (!utilFromFileReadString(f, &game.publisher)) break;
if (!utilFromFileReadString(f, &game.developer)) break;
if (!utilFromFileReadString(f, &game.description)) break;
if (!utilFromFileReadString(f, &game.releaseDate)) break;
if (!utilFromFileReadString(f, &game.rating)) break;
if (!utilFromFileReadString(f, &game.series)) break;
if (!utilFromFileReadString(f, &game.origin)) break;
if (!utilFromFileReadString(f, &game.shortName)) break;
if (!utilFromFileReadString(f, &game.worksWith)) break;
if (!utilFromFileReadByte(f, (uint8_t *)&game.type)) break;
if (!utilFromFileReadByte(f, &game.maxPlayers)) break;
if (!utilFromFileReadByte(f, &game.joinable)) break;
if (!utilFromFileReadByte(f, &game.screens)) break;
if (!utilFromFileReadByte(f, &game.boxes)) break;
// Write this to the database.
dbExecute(
"REPLACE INTO games ("
"shortName, title, publisher, developer, description, releaseDate, "
"rating, series, origin, worksWith, type, maxPlayers, joinable, "
"screens, boxes, touched"
") VALUES ("
"?, ?, ?, ?, ?, ?, "
"?, ?, ?, ?, ?, ?, ?, "
"?, ?, 1 "
")",
"vvvvvv"
"vvvviii"
"iii",
game.shortName,
game.title,
game.publisher,
game.developer,
game.description,
game.releaseDate,
game.rating,
game.series,
game.origin,
game.worksWith,
game.type,
game.maxPlayers,
game.joinable,
game.screens,
game.boxes
);
} }
cacheFClose(f); cacheFClose(f);
// Delete anything untouched. // Delete anything untouched.
dbExecute("DELETE FROM games WHERE touced=0", NULL); dbExecute("DELETE FROM games WHERE touched=0", NULL);
// Free 'game'.
DEL(game.title);
DEL(game.publisher);
DEL(game.developer);
DEL(game.description);
DEL(game.releaseDate);
DEL(game.rating);
DEL(game.series);
DEL(game.origin);
DEL(game.shortName);
DEL(game.worksWith);
//***TODO*** Did we have problems updating the game database?
if (result == FAIL) {
// Do something here.
}
} }
*/
} }

View file

@ -40,10 +40,9 @@ void runtimeDataLoad(void) {
shput(__runtimeData.strings, fields[0], strdup(fields[1])); shput(__runtimeData.strings, fields[0], strdup(fields[1]));
} }
} }
dbResultRelease(&records);
} }
dbResultRelease(&records);
/* /*
logWrite("\n\n"); logWrite("\n\n");
for (int r = 0; r < shlen(__runtimeData.strings); r++) { for (int r = 0; r < shlen(__runtimeData.strings); r++) {

View file

@ -109,6 +109,8 @@ static void clientApiFileRequestCheck(ClientThreadT *client, PacketDecodeDataT *
if (!client->authenticated && mustAuth) { if (!client->authenticated && mustAuth) {
logWrite("Unauthenticated user requested file: %s\n", path); logWrite("Unauthenticated user requested file: %s\n", path);
clientApiFileFailed(client, data); clientApiFileFailed(client, data);
DEL(sha256);
DEL(path);
return; return;
} }
@ -165,13 +167,13 @@ static void clientApiFileRequestCheck(ClientThreadT *client, PacketDecodeDataT *
packetSend(client->packetThreadData, &encoded); packetSend(client->packetThreadData, &encoded);
DEL(packetData); DEL(packetData);
DEL(sha256);
DEL(path);
// Start sending actual file data. // Start sending actual file data.
clientApiFileRequestNext(client, data); clientApiFileRequestNext(client, data);
} }
DEL(sha256);
DEL(path);
END END
} }

View file

@ -286,8 +286,8 @@ static void dbFileSha256Create(char *file, char *buf) {
} }
void dbGameRelease(DbGameT **game) { void dbGameRelease(GameT **game) {
DbGameT *g = *game; GameT *g = *game;
if (g) { if (g) {
DEL(g->title); DEL(g->title);
@ -305,15 +305,15 @@ void dbGameRelease(DbGameT **game) {
} }
DbGameT **dbGamesGet(void) { GameT **dbGamesGet(void) {
char statement[STATEMENT_MAX]; char statement[STATEMENT_MAX];
char *p = statement; char *p = statement;
MYSQL_RES *result = NULL; MYSQL_RES *result = NULL;
MYSQL_ROW row = NULL; MYSQL_ROW row = NULL;
int32_t count = 0; int32_t count = 0;
int32_t i = 0; int32_t i = 0;
DbGameT **gameList = NULL; GameT **gameList = NULL;
DbGameT *game = NULL; GameT *game = NULL;
char filename[MAX_PATH]; char filename[MAX_PATH];
int32_t x = 0; int32_t x = 0;
@ -351,7 +351,7 @@ DbGameT **dbGamesGet(void) {
pthread_mutex_unlock(&_mutex); pthread_mutex_unlock(&_mutex);
return NULL; return NULL;
} }
NEW(DbGameT, game); NEW(GameT, game);
game->title = strdup(row[0]); game->title = strdup(row[0]);
game->publisher = strdup(row[1]); game->publisher = strdup(row[1]);
game->developer = strdup(row[2]); game->developer = strdup(row[2]);

View file

@ -23,20 +23,12 @@
#include "os.h" #include "os.h"
#include "game.h"
#define DB_CONFIG_ITEM_SIZE 1024 #define DB_CONFIG_ITEM_SIZE 1024
typedef enum DbGameTypeE {
GAME_TYPE_UNKNOWN = 0,
GAME_TYPE_DOOR,
GAME_TYPE_SERIAL,
GAME_TYPE_IPX,
GAME_TYPE_FICTION
} DbGameTypeT;
typedef struct DbClientConfigS { typedef struct DbClientConfigS {
char *name; char *name;
char *data; char *data;
@ -52,24 +44,6 @@ typedef struct DbFileInfoS {
uint8_t touched; uint8_t touched;
} DbFileInfoT; } DbFileInfoT;
typedef struct DbGameS {
char *title;
char *publisher;
char *developer;
char *description;
char *releaseDate;
char *rating;
char *series;
char *origin;
char *shortName;
char *worksWith;
DbGameTypeT type;
uint8_t maxPlayers;
uint8_t joinable;
uint8_t screens;
uint8_t boxes;
} DbGameT;
uint8_t dbConnect(char *host, uint16_t port, char *database, char *user, char *password); uint8_t dbConnect(char *host, uint16_t port, char *database, char *user, char *password);
void dbClientConfigRelease(DbClientConfigT **config); void dbClientConfigRelease(DbClientConfigT **config);
@ -77,8 +51,8 @@ DbClientConfigT **dbClientConfigGet(void);
uint8_t dbDisconnect(void); uint8_t dbDisconnect(void);
DbFileInfoT *dbFileInfoGet(char *vpath); DbFileInfoT *dbFileInfoGet(char *vpath);
void dbFileInfoRelease(DbFileInfoT **info); void dbFileInfoRelease(DbFileInfoT **info);
void dbGameRelease(DbGameT **game); void dbGameRelease(GameT **game);
DbGameT **dbGamesGet(void); GameT **dbGamesGet(void);
uint8_t dbSettingsStringGet(char *host, char *key, char *value, uint32_t max); uint8_t dbSettingsStringGet(char *host, char *key, char *value, uint32_t max);
uint8_t dbSettingsValueGet(char *host, char *key, int32_t *value); uint8_t dbSettingsValueGet(char *host, char *key, int32_t *value);
uint8_t dbUpdateFileData(char *file, uint64_t len, char *time); uint8_t dbUpdateFileData(char *file, uint64_t len, char *time);

View file

@ -209,8 +209,8 @@ static int32_t updateFileEntry(const char *filepath, const struct stat *info, co
static void updateGames(void) { static void updateGames(void) {
DbGameT **gameList = NULL; GameT **gameList = NULL;
DbGameT *game = NULL; GameT *game = NULL;
char file[MAX_PATH] = { 0 }; char file[MAX_PATH] = { 0 };
FILE *f = NULL; FILE *f = NULL;
uint8_t c = 0; uint8_t c = 0;

59
shared/game.h Normal file
View file

@ -0,0 +1,59 @@
/*
* Kangaroo Punch MultiPlayer Game Server Mark II
* Copyright (C) 2020-2021 Scott Duensing
*
* 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 3 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, see <https://www.gnu.org/licenses/>.
*
*/
#ifndef GAME_H
#define GAME_H
#include "os.h"
#define GAME_MAX_DESCRIPTION 4096
typedef enum GameTypeE {
GAME_TYPE_UNKNOWN = 0,
GAME_TYPE_DOOR,
GAME_TYPE_SERIAL,
GAME_TYPE_IPX,
GAME_TYPE_FICTION
} GameTypeT;
typedef struct GameS { // Data type in DAT file sent to client.
char *title; // 255
char *publisher; // 255
char *developer; // 255
char *description; // TEXT
char *releaseDate; // DATETIME
char *rating; // 255
char *series; // 255
char *origin; // 255
char *shortName; // 8
char *worksWith; // 8
GameTypeT type; // 1
uint8_t maxPlayers; // 1
uint8_t joinable; // 1
uint8_t screens; // 1
uint8_t boxes; // 1
} GameT;
#endif // GAME_H

View file

@ -38,7 +38,7 @@
// Allocation helpers. // Allocation helpers.
#define NEW(t,v) (v)=(t*)malloc(sizeof(t)) #define NEW(t,v) (v)=(t*)malloc(sizeof(t))
#define DEL(v) {free(v); v=NULL;} #define DEL(v) {if(v) {free(v); v=NULL;}}
// Some helper defines. // Some helper defines.
#define DIVISIBLE_BY_EIGHT(x) ((((x) >> 3) << 3) == (x)) #define DIVISIBLE_BY_EIGHT(x) ((((x) >> 3) << 3) == (x))