Renamed directory src to wmud
Signed-off-by: Gergely Polonkai (W00d5t0ck) <polesz@w00d5t0ck.info>
This commit is contained in:
3
wmud/.gitignore
vendored
Normal file
3
wmud/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
.deps
|
||||
*.o
|
||||
wmud
|
5
wmud/Makefile.am
Normal file
5
wmud/Makefile.am
Normal file
@@ -0,0 +1,5 @@
|
||||
bin_PROGRAMS = wmud
|
||||
AM_CPPFLAGS = -DWMUD_STATEDIR=\""$(localstatedir)"\" -DWMUD_CONFDIR=\""$(sysconfdir)"\" $(MEMCACHED_CFLAGS) $(GLIB_CFLAGS) $(GIO_CFLAGS) $(GTHREAD_CFLAGS) $(SQLITE3_CFLAGS)
|
||||
|
||||
wmud_SOURCES = main.c game-networking.c interpreter.c db.c players.c maintenance.c game.c configuration.c world.c
|
||||
wmud_LDADD = $(MEMCACHED_LIBS) $(GLIB_LIBS) $(GIO_LIBS) $(GTHREAD_LIBS) $(SQLITE3_LIBS)
|
169
wmud/configuration.c
Normal file
169
wmud/configuration.c
Normal file
@@ -0,0 +1,169 @@
|
||||
/* wMUD - Yet another MUD codebase by W00d5t0ck
|
||||
* Copyright (C) 2012 - Gergely POLONKAI
|
||||
*
|
||||
* configuration.c: configuration file related functions
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "wmud-types.h"
|
||||
#include "configuration.h"
|
||||
|
||||
/**
|
||||
* SECTION:configuration
|
||||
* @short_description: Configuration file handling functions
|
||||
* @title: Configuration file handling functions
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* WMUD_CONFIG_ERROR:
|
||||
*
|
||||
* the GQuark for the config error GError
|
||||
*/
|
||||
GQuark WMUD_CONFIG_ERROR = 0;
|
||||
/**
|
||||
* active_config:
|
||||
*
|
||||
* the currently active configuration directives
|
||||
*/
|
||||
ConfigData *active_config = NULL;
|
||||
|
||||
/**
|
||||
* wmud_configdata_free:
|
||||
* @config_data: pointer to the ConfigData struct to free
|
||||
*
|
||||
* Correctly free a ConfigData struct with all its members
|
||||
*/
|
||||
void
|
||||
wmud_configdata_free(ConfigData **config_data)
|
||||
{
|
||||
if ((*config_data)->admin_email)
|
||||
g_free((*config_data)->admin_email);
|
||||
|
||||
if ((*config_data)->database_file)
|
||||
g_free((*config_data)->database_file);
|
||||
|
||||
g_free(*config_data);
|
||||
*config_data = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* wmud_config_init:
|
||||
* @config_data: a pointer to a ConfigData struct. This will be filled with the
|
||||
* configuration file's data
|
||||
* @err: The GError in which the config handling status should be returned
|
||||
*
|
||||
* Parses the default configuration file, and sets different variables
|
||||
* according to it.
|
||||
*
|
||||
* Return value: %TRUE if parsing was successful. %FALSE otherwise.
|
||||
*/
|
||||
gboolean
|
||||
wmud_config_init(ConfigData **config_data, GError **err)
|
||||
{
|
||||
GString *config_file = g_string_new(WMUD_CONFDIR);
|
||||
GKeyFile *config;
|
||||
GError *in_err = NULL;
|
||||
|
||||
if (!config_data)
|
||||
return FALSE;
|
||||
|
||||
if (*config_data)
|
||||
{
|
||||
g_clear_error(err);
|
||||
g_set_error(err, WMUD_CONFIG_ERROR, WMUD_CONFIG_ERROR_REUSE, "Configuration pointer reuse. Please file a bug report!");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*config_data = g_new0(ConfigData, 1);
|
||||
|
||||
g_string_append(config_file, "/wmud.conf");
|
||||
|
||||
config = g_key_file_new();
|
||||
/* TODO: Error checking */
|
||||
g_key_file_load_from_file(config, config_file->str, 0, &in_err);
|
||||
|
||||
if (!g_key_file_has_group(config, "global"))
|
||||
{
|
||||
g_set_error(err, WMUD_CONFIG_ERROR, WMUD_CONFIG_ERROR_NOGLOBAL, "Config file (%s) does not contain a [global] group", config_file->str);
|
||||
g_key_file_free(config);
|
||||
g_string_free(config_file, TRUE);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_clear_error(&in_err);
|
||||
(*config_data)->port = g_key_file_get_integer(config, "global", "port", &in_err);
|
||||
if (in_err)
|
||||
{
|
||||
if (g_error_matches(in_err, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND))
|
||||
{
|
||||
(*config_data)->port = DEFAULT_PORT;
|
||||
}
|
||||
else if (g_error_matches(in_err, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_INVALID_VALUE))
|
||||
{
|
||||
g_set_error(err, WMUD_CONFIG_ERROR, WMUD_CONFIG_ERROR_BADPORT, "Config file (%s) contains an invalid port number", config_file->str);
|
||||
g_key_file_free(config);
|
||||
g_string_free(config_file, TRUE);
|
||||
(*config_data)->port = 0;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_clear_error(&in_err);
|
||||
(*config_data)->database_file = g_key_file_get_string(config, "global", "world file", &in_err);
|
||||
if (in_err)
|
||||
{
|
||||
if (g_error_matches(in_err, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND))
|
||||
{
|
||||
g_set_error(err, WMUD_CONFIG_ERROR, WMUD_CONFIG_ERROR_NOWORLD, "Config file (%s) does not contain a world file path", config_file->str);
|
||||
g_key_file_free(config);
|
||||
g_string_free(config_file, TRUE);
|
||||
wmud_configdata_free(config_data);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
g_clear_error(&in_err);
|
||||
(*config_data)->admin_email = g_key_file_get_string(config, "global", "admin email", &in_err);
|
||||
if (in_err)
|
||||
{
|
||||
if (g_error_matches(in_err, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND))
|
||||
{
|
||||
g_set_error(err, WMUD_CONFIG_ERROR, WMUD_CONFIG_ERROR_NOEMAIL, "Config file (%s) does not contain an admin e-mail address", config_file->str);
|
||||
g_key_file_free(config);
|
||||
g_string_free(config_file, TRUE);
|
||||
wmud_configdata_free(config_data);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
g_key_file_free(config);
|
||||
g_string_free(config_file, TRUE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
48
wmud/configuration.h
Normal file
48
wmud/configuration.h
Normal file
@@ -0,0 +1,48 @@
|
||||
#ifndef __WMUD_CONFIGURATION_H__
|
||||
#define __WMUD_CONFIGURATION_H__
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
extern GQuark WMUD_CONFIG_ERROR;
|
||||
|
||||
/**
|
||||
* wmudConfigError:
|
||||
* @WMUD_CONFIG_ERROR_NOGLOBAL: Indicates that the config file read doesn't
|
||||
* contain a [global] section
|
||||
* @WMUD_CONFIG_ERROR_BADPORT: Indicates that the config file contains and
|
||||
* invalid port number
|
||||
* @WMUD_CONFIG_ERROR_NOWORLD: Indicates that the config file doesn't contain a
|
||||
* world database file
|
||||
* @WMUD_CONFIG_ERROR_NOEMAIL: Indicates that the config file doesn't contain
|
||||
* an administrator e-mail address
|
||||
* @WMUD_CONFIG_ERROR_REUSE: configuration data is reused (non-NULL)
|
||||
*
|
||||
* Error codes returned by configuration file parsing functions.
|
||||
*/
|
||||
typedef enum {
|
||||
WMUD_CONFIG_ERROR_NOGLOBAL,
|
||||
WMUD_CONFIG_ERROR_BADPORT,
|
||||
WMUD_CONFIG_ERROR_NOWORLD,
|
||||
WMUD_CONFIG_ERROR_NOEMAIL,
|
||||
WMUD_CONFIG_ERROR_REUSE
|
||||
} wmudConfigError;
|
||||
|
||||
/**
|
||||
* ConfigData:
|
||||
* @port: the port number of the game interface to listen on
|
||||
* @database_file: the database file of the world associated with this
|
||||
* configuration
|
||||
* @admin_email: the world administrator's e-mail address
|
||||
*/
|
||||
typedef struct _ConfigData {
|
||||
guint port;
|
||||
gchar *database_file;
|
||||
gchar *admin_email;
|
||||
} ConfigData;
|
||||
|
||||
extern ConfigData *active_config;
|
||||
|
||||
gboolean wmud_config_init(ConfigData **config_data, GError **err);
|
||||
|
||||
#endif /* __WMUD_CONFIGURATION_H__ */
|
||||
|
216
wmud/db.c
Normal file
216
wmud/db.c
Normal file
@@ -0,0 +1,216 @@
|
||||
/* wMUD - Yet another MUD codebase by W00d5t0ck
|
||||
* Copyright (C) 2012 - Gergely POLONKAI
|
||||
*
|
||||
* db.c: database handling routines
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <glib.h>
|
||||
#include <sqlite3.h>
|
||||
|
||||
#include "main.h"
|
||||
#include "db.h"
|
||||
#include "players.h"
|
||||
#include "configuration.h"
|
||||
|
||||
/**
|
||||
* SECTION:db
|
||||
* @short_description: Database handling
|
||||
* @title: Database handling routines
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* WMUD_DB_ERROR:
|
||||
*
|
||||
* the GQuark for the database error GError
|
||||
*/
|
||||
GQuark WMUD_DB_ERROR = 0;
|
||||
static sqlite3 *dbh = NULL;
|
||||
|
||||
/**
|
||||
* wmud_db_init:
|
||||
* @err: a GError to put error messages in it
|
||||
*
|
||||
* Initializes the wMUD database system. Checks and opens database files.
|
||||
*/
|
||||
gboolean
|
||||
wmud_db_init(GError **err)
|
||||
{
|
||||
GString *db_file = g_string_new(WMUD_STATEDIR);
|
||||
int sqlite_code;
|
||||
|
||||
g_string_append_printf(db_file, "/%s", active_config->database_file);
|
||||
|
||||
if ((sqlite_code = sqlite3_open(db_file->str, &dbh)) != SQLITE_OK)
|
||||
{
|
||||
g_set_error(err, WMUD_DB_ERROR, WMUD_DB_ERROR_CANTOPEN, "Can not open databsae file (%s): %s", db_file->str, sqlite3_errmsg(dbh));
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* wmud_db_players_load:
|
||||
* @err: a GError to put error messages in it
|
||||
*
|
||||
* Loads all player records from the database
|
||||
*/
|
||||
gboolean
|
||||
wmud_db_players_load(GError **err)
|
||||
{
|
||||
sqlite3_stmt *sth = NULL;
|
||||
int sqlite_code;
|
||||
|
||||
if (dbh == NULL)
|
||||
{
|
||||
if (err)
|
||||
g_set_error(err, WMUD_DB_ERROR, WMUD_DB_ERROR_NOINIT, "Database backend not initialized");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((sqlite_code = sqlite3_prepare_v2(dbh, "SELECT id, login, password, email FROM players", -1, &sth, NULL)) != SQLITE_OK)
|
||||
{
|
||||
g_set_error(err, WMUD_DB_ERROR, WMUD_DB_ERROR_BADQUERY, "Bad query in wmud_db_players_load(): %s", sqlite3_errmsg(dbh));
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
sqlite_code = sqlite3_step(sth);
|
||||
if (sqlite_code == SQLITE_ROW)
|
||||
{
|
||||
wmudPlayer *player = g_new0(wmudPlayer, 1);
|
||||
player->id = sqlite3_column_int(sth, 0);
|
||||
player->player_name = g_strdup((gchar *)sqlite3_column_text(sth, 1));
|
||||
player->cpassword = g_strdup((gchar *)sqlite3_column_text(sth, 2));
|
||||
player->email = g_strdup((gchar *)sqlite3_column_text(sth, 3));
|
||||
|
||||
g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Loaded player _%s_", player->player_name);
|
||||
|
||||
players = g_slist_prepend(players, player);
|
||||
}
|
||||
else if (sqlite_code == SQLITE_DONE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_set_error(err, WMUD_DB_ERROR, WMUD_DB_ERROR_BADQUERY, "Query error in wmud_db_players_load(): %s", sqlite3_errmsg(dbh));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
sqlite3_finalize(sth);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* wmud_db_save_player:
|
||||
* @player: the player record to save
|
||||
* @err: a GError to put error messages in it
|
||||
*
|
||||
* Saves a player record to the database backend.
|
||||
*
|
||||
* Return value: %TRUE on success. Upon failure, %FALSE is returned, and err is
|
||||
* set accordingly.
|
||||
*/
|
||||
gboolean
|
||||
wmud_db_save_player(wmudPlayer *player, GError **err)
|
||||
{
|
||||
sqlite3_stmt *sth = NULL;
|
||||
int sqlite_code;
|
||||
|
||||
if (dbh == NULL)
|
||||
{
|
||||
if (err)
|
||||
g_set_error(err, WMUD_DB_ERROR, WMUD_DB_ERROR_NOINIT, "Database backend not initialized");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((sqlite_code = sqlite3_prepare_v2(dbh, "INSERT INTO players (id, login, password, email) VALUES (NULL, ?, NULL, ?)", -1, &sth, NULL)) != SQLITE_OK)
|
||||
{
|
||||
g_set_error(err, WMUD_DB_ERROR, WMUD_DB_ERROR_BADQUERY, "Bad query in wmud_db_player_save(): %s", sqlite3_errmsg(dbh));
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((sqlite_code = sqlite3_bind_text(sth, 1, player->player_name, -1, SQLITE_STATIC)) != SQLITE_OK)
|
||||
{
|
||||
g_set_error(err, WMUD_DB_ERROR, WMUD_DB_ERROR_BADQUERY, "Bad parameter in wmud_db_player_save(): %s", sqlite3_errmsg(dbh));
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((sqlite_code = sqlite3_bind_text(sth, 2, player->email, -1, SQLITE_STATIC)) != SQLITE_OK)
|
||||
{
|
||||
g_set_error(err, WMUD_DB_ERROR, WMUD_DB_ERROR_BADQUERY, "Bad parameter in wmud_db_player_save(): %s", sqlite3_errmsg(dbh));
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((sqlite_code = sqlite3_step(sth)) != SQLITE_DONE)
|
||||
{
|
||||
g_set_error(err, WMUD_DB_ERROR, WMUD_DB_ERROR_BADQUERY, "Statement cannot be executed in wmud_db_player_save(): %s", sqlite3_errmsg(dbh));
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_clear_error(err);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
wmud_db_load_planes(GSList **planes, GError **err)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
wmud_db_load_planets(GSList **planets, GError **err)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
wmud_db_load_directions(GSList **directions, GError **err)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
wmud_db_load_areas(GSList **areas, GError **err)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
wmud_db_load_rooms(GSList **rooms, GError **err)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
wmud_db_load_exits(GSList **exits, GError **err)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
39
wmud/db.h
Normal file
39
wmud/db.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/* wMUD - Yet another MUD codebase by W00d5t0ck
|
||||
* Copyright (C) 2012 - Gergely POLONKAI
|
||||
*
|
||||
* db.h: database handling routine prototypes
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef __WMUD_DB_H__
|
||||
#define __WMUD_DB_H__
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "wmud-types.h"
|
||||
|
||||
extern GQuark WMUD_DB_ERROR;
|
||||
|
||||
gboolean wmud_db_init(GError **err);
|
||||
gboolean wmud_db_players_load(GError **err);
|
||||
gboolean wmud_db_save_player(wmudPlayer *player, GError **err);
|
||||
gboolean wmud_db_load_planes(GSList **planes, GError **err);
|
||||
gboolean wmud_db_load_planets(GSList **planets, GError **err);
|
||||
gboolean wmud_db_load_directions(GSList **directions, GError **err);
|
||||
gboolean wmud_db_load_areas(GSList **areas, GError **err);
|
||||
gboolean wmud_db_load_rooms(GSList **rooms, GError **err);
|
||||
gboolean wmud_db_load_exits(GSList **exits, GError **err);
|
||||
|
||||
#endif /* __WMUD__DB_H__ */
|
||||
|
518
wmud/game-networking.c
Normal file
518
wmud/game-networking.c
Normal file
@@ -0,0 +1,518 @@
|
||||
/* wMUD - Yet another MUD codebase by W00d5t0ck
|
||||
* Copyright (C) 2012 - Gergely POLONKAI
|
||||
*
|
||||
* game-networking.c: basic networking functions
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <glib.h>
|
||||
#include <gio/gio.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include "main.h"
|
||||
#include "game-networking.h"
|
||||
#include "interpreter.h"
|
||||
#include "players.h"
|
||||
#include "db.h"
|
||||
#include "configuration.h"
|
||||
|
||||
/**
|
||||
* SECTION:game-networking
|
||||
* @short_description: Game related networking code
|
||||
*
|
||||
* Functions to handle game connections
|
||||
*/
|
||||
|
||||
struct AcceptData {
|
||||
GMainContext *context;
|
||||
GSocketListener *listener;
|
||||
};
|
||||
|
||||
GSList *clients;
|
||||
|
||||
void wmud_client_interpret_newplayer_email(wmudClient *client);
|
||||
void wmud_client_interpret_newplayer_mailconfirm(wmudClient *client);
|
||||
|
||||
/**
|
||||
* wmud_client_close:
|
||||
* @client: the client whose connection should be dropped
|
||||
* @send_goodbye: if set to %TRUE, we will send a nice good-bye message to the
|
||||
* client before dropping the connection
|
||||
*
|
||||
* Closes a client connection. If send_goodbye is set to %TRUE, a good-bye
|
||||
* message will be sent to the client.
|
||||
*/
|
||||
void
|
||||
wmud_client_close(wmudClient *client, gboolean send_goodbye)
|
||||
{
|
||||
if (send_goodbye)
|
||||
wmud_client_send(client, "\r\nHave a nice real-world day!\r\n\r\n");
|
||||
|
||||
g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Connection closed.");
|
||||
g_socket_close(client->socket, NULL);
|
||||
clients = g_slist_remove(clients, client);
|
||||
wmud_player_free(&(client->player));
|
||||
if (client->buffer)
|
||||
g_string_free(client->buffer, TRUE);
|
||||
g_source_destroy(client->socket_source);
|
||||
g_free(client);
|
||||
}
|
||||
|
||||
/**
|
||||
* wmud_client_callback:
|
||||
* @client: the socket of the client on which the data arrived
|
||||
* @condition: the condition available on the client socket
|
||||
* @client: the wmudClient structure of the client
|
||||
*
|
||||
* Processes incoming client data, and client hangup
|
||||
*/
|
||||
static gboolean
|
||||
wmud_client_callback(GSocket *client_socket, GIOCondition condition, wmudClient *client)
|
||||
{
|
||||
GError *err = NULL;
|
||||
/* TODO: Error checking */
|
||||
GRegex *email_regex = g_regex_new("^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,4}$", G_REGEX_CASELESS, 0, NULL);
|
||||
|
||||
if (condition & G_IO_HUP)
|
||||
{
|
||||
wmud_client_close(client, FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
else if ((condition & G_IO_IN) || (condition & G_IO_PRI))
|
||||
{
|
||||
gssize len;
|
||||
gchar *buf2;
|
||||
gchar *buf = g_malloc0(sizeof(gchar) * (MAX_RECV_LEN + 1));
|
||||
|
||||
/* TODO: Error checking */
|
||||
if ((len = g_socket_receive(client_socket, buf, MAX_RECV_LEN, NULL, &err)) == 0)
|
||||
{
|
||||
g_free(buf);
|
||||
wmud_client_close(client, FALSE);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
buf2 = buf;
|
||||
while (TRUE)
|
||||
{
|
||||
char *r = strchr((char *)buf2, '\r'),
|
||||
*n = strchr((char *)buf2, '\n');
|
||||
|
||||
if (r || n)
|
||||
{
|
||||
gint i,
|
||||
sloc = -1;
|
||||
|
||||
if ((r < n) && r)
|
||||
{
|
||||
if (client->buffer->len > 0)
|
||||
g_string_append_len(client->buffer, buf2, (r - buf2));
|
||||
else
|
||||
g_string_overwrite_len(client->buffer, 0, buf2, (r - buf2));
|
||||
buf2 = r;
|
||||
}
|
||||
else if (n)
|
||||
{
|
||||
if (client->buffer->len > 0)
|
||||
g_string_append_len(client->buffer, buf2, (n - buf2));
|
||||
else
|
||||
g_string_overwrite_len(client->buffer, 0, buf2, (n - buf2));
|
||||
buf2 = n;
|
||||
}
|
||||
|
||||
/* Remove telnet codes from the string */
|
||||
for (i = 0; i < client->buffer->len; i++)
|
||||
{
|
||||
guchar c = (client->buffer->str)[i];
|
||||
|
||||
if ((c >= 240) || (c == 1))
|
||||
{
|
||||
if (sloc == -1)
|
||||
sloc = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sloc != -1)
|
||||
{
|
||||
g_string_erase(client->buffer, sloc, i - sloc);
|
||||
sloc = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sloc != -1)
|
||||
{
|
||||
g_string_erase(client->buffer, sloc, -1);
|
||||
}
|
||||
|
||||
switch (client->state)
|
||||
{
|
||||
case WMUD_CLIENT_STATE_FRESH:
|
||||
if (*(client->buffer->str))
|
||||
{
|
||||
wmudPlayer *player;
|
||||
|
||||
if ((player = wmud_player_exists(client->buffer->str)) != NULL)
|
||||
{
|
||||
g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Trying to login with playername '%s'\n", client->buffer->str);
|
||||
if (player->cpassword == NULL)
|
||||
{
|
||||
wmud_client_send(client, "Your registration is not finished yet.\r\n");
|
||||
wmud_client_close(client, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
client->state = WMUD_CLIENT_STATE_PASSWAIT;
|
||||
client->player = player;
|
||||
wmud_client_send(client, "Please provide us your password: %c%c%c", TELNET_IAC, TELNET_WILL, TELNET_ECHO);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
client->player = g_new0(wmudPlayer, 1);
|
||||
client->player->player_name = g_strdup(client->buffer->str);
|
||||
client->state = WMUD_CLIENT_STATE_NEWCHAR;
|
||||
wmud_client_send(client, "Is %s new to this game? [Y/N] ", client->buffer->str);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WMUD_CLIENT_STATE_PASSWAIT:
|
||||
if (*(client->buffer->str))
|
||||
{
|
||||
if (wmud_player_auth(client))
|
||||
{
|
||||
wmud_client_send(client, "%c%c%c\r\nLogin"
|
||||
" successful.\r\n", TELNET_IAC,
|
||||
TELNET_WONT, TELNET_ECHO);
|
||||
client->authenticated = TRUE;
|
||||
/* TODO: Send fail count if non-zero */
|
||||
client->state = WMUD_CLIENT_STATE_MENU;
|
||||
/* TODO: send MOTD */
|
||||
/* TODO: send menu items */
|
||||
/* TODO: send menu prologue */
|
||||
}
|
||||
else
|
||||
{
|
||||
wmud_client_send(client, "%c%c%cThis"
|
||||
" password doesn't seem to be valid."
|
||||
" Let's try it again...\r\nBy what"
|
||||
" name would you like to be called? ",
|
||||
TELNET_IAC, TELNET_WONT, TELNET_ECHO);
|
||||
client->state = WMUD_CLIENT_STATE_FRESH;
|
||||
client->login_try_count++;
|
||||
if (client->login_try_count == 3)
|
||||
{
|
||||
wmud_client_send(client, "You are"
|
||||
" trying these bad passwords for"
|
||||
" too many times. Please stop"
|
||||
" that!\r\n");
|
||||
wmud_client_close(client, TRUE);
|
||||
/* TODO: Increase IP fail count, and ban IP if it's too high */
|
||||
}
|
||||
/* TODO: Increase and save login fail count */
|
||||
client->player = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wmud_client_send(client, "\r\nEmpty passwords are"
|
||||
" not valid.\r\nTry again: ");
|
||||
}
|
||||
break;
|
||||
case WMUD_CLIENT_STATE_MENU:
|
||||
//wmud_client_interpret_menu_command(client);
|
||||
break;
|
||||
case WMUD_CLIENT_STATE_INGAME:
|
||||
wmud_interpret_game_command(client);
|
||||
break;
|
||||
case WMUD_CLIENT_STATE_QUITWAIT:
|
||||
//wmud_interpret_quit_answer(client);
|
||||
break;
|
||||
case WMUD_CLIENT_STATE_NEWCHAR:
|
||||
if (g_ascii_strcasecmp(client->buffer->str, "n") == 0)
|
||||
{
|
||||
wmud_client_send(client, "What is your player-name, then? ");
|
||||
client->state = WMUD_CLIENT_STATE_FRESH;
|
||||
}
|
||||
else if (g_ascii_strcasecmp(client->buffer->str, "y") == 0)
|
||||
{
|
||||
g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Creating new player\n");
|
||||
wmud_client_send(client, "Welcome to this MUD!\r\nPlease enter your e-mail address: ");
|
||||
client->state = WMUD_CLIENT_STATE_REGISTERING;
|
||||
}
|
||||
else
|
||||
{
|
||||
wmud_client_send(client, "Sorry, but for this question I only understand 'Y' or 'N'.\r\nIs %s a new player here? [Y/N] ", client->player->player_name);
|
||||
}
|
||||
break;
|
||||
case WMUD_CLIENT_STATE_REGISTERING:
|
||||
if (!*(client->buffer->str))
|
||||
{
|
||||
if (client->bademail)
|
||||
{
|
||||
wmud_client_close(client, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
if (g_regex_match(email_regex, client->buffer->str, 0, NULL))
|
||||
{
|
||||
client->player->email = g_strdup(client->buffer->str);
|
||||
client->state = WMUD_CLIENT_STATE_REGEMAIL_CONFIRM;
|
||||
wmud_client_send(client, "It seems to be a valid address to me, but could you write it again? ");
|
||||
}
|
||||
else
|
||||
{
|
||||
wmud_client_send(client, "\r\nSorry, but this e-mail address doesn't seem to be valid to me.\r\n\r\nIf you think this is a valid address, simply press enter to quit, and send an e-mail to %s from that address, so we can fix our e-mail validation code.\r\n\r\nIf you just mistyped your address, type it now: ", active_config->admin_email);
|
||||
if (*(client->buffer->str))
|
||||
client->bademail = TRUE;
|
||||
}
|
||||
break;
|
||||
case WMUD_CLIENT_STATE_REGEMAIL_CONFIRM:
|
||||
if (g_ascii_strcasecmp(client->player->email, client->buffer->str) == 0)
|
||||
{
|
||||
g_clear_error(&err);
|
||||
if (wmud_db_save_player(client->player, &err))
|
||||
{
|
||||
wmud_client_send(client, "Good. We will generate the password for this player name, and send it to you\r\nvia e-mail. Please come back to us, if you get that code, so you can log\r\nin.\r\n");
|
||||
players = g_slist_prepend(players, wmud_player_dup(client->player));
|
||||
}
|
||||
else
|
||||
{
|
||||
g_critical("wmud_db_save_player() error: %s", err->message);
|
||||
wmud_client_send(client, "There was an error during the database update. Please try again later!\r\n");
|
||||
}
|
||||
wmud_client_close(client, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_free(client->player->email);
|
||||
client->player->email = NULL;
|
||||
|
||||
wmud_client_send(client, "This is not the same as you entered before.\r\nLet's just try it again: ");
|
||||
client->state = WMUD_CLIENT_STATE_REGISTERING;
|
||||
}
|
||||
break;
|
||||
}
|
||||
g_string_erase(client->buffer, 0, -1);
|
||||
|
||||
for (; ((*buf2 == '\r') || (*buf2 == '\n')) && *buf2; buf2++);
|
||||
if (!*buf2)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (client->buffer->len > 0)
|
||||
g_string_append(client->buffer, buf2);
|
||||
else
|
||||
g_string_overwrite(client->buffer, 0, buf2);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_free(buf);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* game_source_callback:
|
||||
* @socket: the listener socket on which the new connection arrived
|
||||
* @condition: not used
|
||||
* @accept_data: the AcceptData structure of the game listener
|
||||
*
|
||||
* Callback function to be called when a new connection is available on the
|
||||
* game listener socket.
|
||||
*
|
||||
* Return value: this function always returns %TRUE
|
||||
*/
|
||||
gboolean
|
||||
game_source_callback(GSocket *socket, GIOCondition condition, struct AcceptData *accept_data)
|
||||
{
|
||||
GSocket *client_socket;
|
||||
GSource *client_source;
|
||||
GError *err = NULL;
|
||||
wmudClient *client;
|
||||
|
||||
/* TODO: Error checking */
|
||||
client_socket = g_socket_listener_accept_socket(accept_data->listener, NULL, NULL, &err);
|
||||
|
||||
client = g_new0(wmudClient, 1);
|
||||
client->socket = client_socket;
|
||||
client->buffer = g_string_new("");
|
||||
client->state = WMUD_CLIENT_STATE_FRESH;
|
||||
clients = g_slist_prepend(clients, client);
|
||||
|
||||
client_source = g_socket_create_source(client_socket, G_IO_IN | G_IO_OUT | G_IO_PRI | G_IO_ERR | G_IO_HUP | G_IO_NVAL, NULL);
|
||||
client->socket_source = client_source;
|
||||
g_source_set_callback(client_source, (GSourceFunc)wmud_client_callback, client, NULL);
|
||||
g_source_attach(client_source, accept_data->context);
|
||||
g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "New connection.");
|
||||
wmud_client_send(client, "By what name shall we call you? ");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* wmud_networking_init:
|
||||
* @port_number: the port number on which the game listener should listen
|
||||
* @game_context: the #GMainContext of the game thread
|
||||
* @err: the GError in which possible errors will be reported
|
||||
*
|
||||
* Initializes the game network listener
|
||||
*
|
||||
* Return value: Returns %TRUE on success. Upon failure, %FALSE is return, and
|
||||
* err is set accordingly (if not NULL)
|
||||
*/
|
||||
gboolean
|
||||
wmud_networking_init(guint port_number, GMainContext *game_context, GError **err)
|
||||
{
|
||||
struct AcceptData *accept_data;
|
||||
GSocketListener *game_listener;
|
||||
gboolean need_ipv4_socket = TRUE;
|
||||
GSocket *game_socket6,
|
||||
*game_socket4;
|
||||
GError *in_err = NULL;
|
||||
GSource *game_net_source4 = NULL,
|
||||
*game_net_source6 = NULL;
|
||||
|
||||
clients = NULL;
|
||||
game_listener = g_socket_listener_new();
|
||||
|
||||
/* The following snippet is borrowed from GLib 2.30's gsocketlistener.c
|
||||
* code, to create the necessary sockets to listen on both IPv4 and
|
||||
* IPv6 address */
|
||||
if ((game_socket6 = g_socket_new(G_SOCKET_FAMILY_IPV6, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_DEFAULT, &in_err)) != NULL)
|
||||
{
|
||||
GInetAddress *inet_address;
|
||||
GSocketAddress *address;
|
||||
gboolean result;
|
||||
|
||||
inet_address = g_inet_address_new_any(G_SOCKET_FAMILY_IPV6);
|
||||
address = g_inet_socket_address_new(inet_address, port_number);
|
||||
g_object_unref(inet_address);
|
||||
|
||||
g_socket_set_listen_backlog(game_socket6, 10);
|
||||
|
||||
result = g_socket_bind(game_socket6, address, TRUE, &in_err)
|
||||
&& g_socket_listen(game_socket6, &in_err);
|
||||
|
||||
g_object_unref(address);
|
||||
|
||||
if (!result)
|
||||
{
|
||||
g_object_unref(game_socket6);
|
||||
g_log(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, "Unable to create listener IPv6 socket");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (g_socket_speaks_ipv4(game_socket6))
|
||||
need_ipv4_socket = FALSE;
|
||||
|
||||
game_net_source6 = g_socket_create_source(game_socket6, G_IO_IN, NULL);
|
||||
/* TODO: error checking */
|
||||
g_socket_listener_add_socket(game_listener, game_socket6, NULL, &in_err);
|
||||
}
|
||||
/* TODO: else { error checking } */
|
||||
|
||||
if (need_ipv4_socket)
|
||||
{
|
||||
if ((game_socket4 = g_socket_new(G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_DEFAULT, &in_err)) != NULL)
|
||||
{
|
||||
GInetAddress *inet_address;
|
||||
GSocketAddress *address;
|
||||
gboolean result;
|
||||
|
||||
inet_address = g_inet_address_new_any(G_SOCKET_FAMILY_IPV4);
|
||||
address = g_inet_socket_address_new(inet_address, port_number);
|
||||
g_object_unref(inet_address);
|
||||
|
||||
g_socket_set_listen_backlog(game_socket4, 10);
|
||||
|
||||
result = g_socket_bind(game_socket4, address, TRUE, &in_err)
|
||||
&& g_socket_listen(game_socket4, &in_err);
|
||||
|
||||
g_object_unref(address);
|
||||
|
||||
if (!result)
|
||||
{
|
||||
g_object_unref(game_socket4);
|
||||
if (!game_socket6)
|
||||
g_object_unref(game_socket6);
|
||||
|
||||
g_log(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, "Unable to create listener IPv4 socket!\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
game_net_source4 = g_socket_create_source(game_socket4, G_IO_IN, NULL);
|
||||
/* TODO: error checking */
|
||||
g_socket_listener_add_socket(game_listener, game_socket4, NULL, &in_err);
|
||||
}
|
||||
/* TODO: else { error checking } */
|
||||
}
|
||||
else
|
||||
{
|
||||
if (game_socket6 != NULL)
|
||||
g_clear_error(&in_err);
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
accept_data = g_new(struct AcceptData, 1);
|
||||
accept_data->listener = game_listener;
|
||||
accept_data->context = game_context;
|
||||
|
||||
if (game_net_source6)
|
||||
{
|
||||
g_source_set_callback(game_net_source6, (GSourceFunc)game_source_callback, (gpointer)accept_data, NULL);
|
||||
g_source_attach(game_net_source6, game_context);
|
||||
}
|
||||
if (game_net_source4)
|
||||
{
|
||||
g_source_set_callback(game_net_source4, (GSourceFunc)game_source_callback, (gpointer)accept_data, NULL);
|
||||
g_source_attach(game_net_source4, game_context);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* wmud_client_send:
|
||||
* @client: the client to which the message will be sent
|
||||
* @fmt: the printf() style format string of the message
|
||||
* @...: optional parameters to the format string
|
||||
*
|
||||
* Sends a formatted message to a game client
|
||||
*/
|
||||
void
|
||||
wmud_client_send(wmudClient *client, const gchar *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
GString *buf = g_string_new("");
|
||||
|
||||
va_start(ap, fmt);
|
||||
g_string_vprintf(buf, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
/* TODO: error checking */
|
||||
g_socket_send(client->socket, buf->str, buf->len, NULL, NULL);
|
||||
g_string_free(buf, TRUE);
|
||||
}
|
||||
|
68
wmud/game-networking.h
Normal file
68
wmud/game-networking.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/* wMUD - Yet another MUD codebase by W00d5t0ck
|
||||
* Copyright (C) 2012 - Gergely POLONKAI
|
||||
*
|
||||
* game-networking.h: basic networking function headers, variables and defines
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef __WMUD_NETWORKING_H__
|
||||
# define __WMUD_NETWORKING_H__
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "wmud-types.h"
|
||||
|
||||
/**
|
||||
* TELNET_IAC:
|
||||
*
|
||||
* Telnet IAC code
|
||||
*/
|
||||
#define TELNET_IAC '\xff'
|
||||
/**
|
||||
* TELNET_WONT:
|
||||
*
|
||||
* Telnet WON'T code
|
||||
*/
|
||||
#define TELNET_WONT '\xfc'
|
||||
/**
|
||||
* TELNET_WILL:
|
||||
*
|
||||
* Telnet WILL code
|
||||
*/
|
||||
#define TELNET_WILL '\xfb'
|
||||
/**
|
||||
* TELNET_DO:
|
||||
*
|
||||
* Telnet DO code
|
||||
*/
|
||||
#define TELNET_DO '\xfd'
|
||||
/**
|
||||
* TELNET_DONT:
|
||||
*
|
||||
* Telnet DONT code
|
||||
*/
|
||||
#define TELNET_DONT '\xfe'
|
||||
/**
|
||||
* TELNET_ECHO:
|
||||
*
|
||||
* Telnet ECHO code
|
||||
*/
|
||||
#define TELNET_ECHO '\x01'
|
||||
|
||||
extern GSList *clients;
|
||||
|
||||
gboolean wmud_networking_init(guint port_number, GMainContext *game_context, GError **err);
|
||||
void wmud_client_send(wmudClient *client, const gchar *fmt, ...);
|
||||
|
||||
#endif
|
123
wmud/game.c
Normal file
123
wmud/game.c
Normal file
@@ -0,0 +1,123 @@
|
||||
/* wMUD - Yet another MUD codebase by W00d5t0ck
|
||||
* Copyright (C) 2012 - Gergely POLONKAI
|
||||
*
|
||||
* game.c: Game Thread related functions
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "main.h"
|
||||
#include "game.h"
|
||||
|
||||
/**
|
||||
* SECTION:game-thread
|
||||
* @short_description: Game related functions
|
||||
* @title: The Game Thread
|
||||
*
|
||||
* The game thread is supposed to serve game client connections. Also,
|
||||
* maintaining the loaded game world is the objective ot this thread.
|
||||
*
|
||||
* This thread has to serve all the game clients after a connection is
|
||||
* estabilished. Player login, menu interaction and play are both the tasks of
|
||||
* this thread.
|
||||
*
|
||||
* The other main objective is to maintain the loaded world. Moving and
|
||||
* resetting the mobs, cleaning up areas and many other things belong here.
|
||||
*/
|
||||
|
||||
/**
|
||||
* elapsed_seconds:
|
||||
*
|
||||
* the number of seconds elapsed since game boot. May be inaccurate, as it
|
||||
* simply gets updated by a timeout function which should run every second
|
||||
*/
|
||||
guint32 elapsed_seconds = 0;
|
||||
|
||||
/**
|
||||
* elapsed_cycle:
|
||||
*
|
||||
* yes, I'm optimistic. This counter is increased if, for some reason,
|
||||
* #elapsed_seconds reaches the maximum value
|
||||
*/
|
||||
guint32 elapsed_cycle = 0;
|
||||
|
||||
/**
|
||||
*
|
||||
* rl_sec_elapsed:
|
||||
* @user_data: non-used pointer to callback's user data
|
||||
*
|
||||
* Keeps track of elapsed real-world time. It is inaccurate by design, but it
|
||||
* doesn't actually matter.
|
||||
*/
|
||||
gboolean
|
||||
rl_sec_elapsed(gpointer user_data)
|
||||
{
|
||||
elapsed_seconds++;
|
||||
if (elapsed_seconds == G_MAXUINT32)
|
||||
{
|
||||
elapsed_seconds = 0;
|
||||
elapsed_cycle++;
|
||||
}
|
||||
|
||||
if (elapsed_seconds % 30 == 0)
|
||||
{
|
||||
g_log(G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, "Heartbeat");
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* game_thread_func:
|
||||
* @game_loop: the main loop to be associated with the game thread
|
||||
*
|
||||
* The game thread's main function.
|
||||
*
|
||||
* Return value: This function always returns %NULL.
|
||||
*/
|
||||
gpointer
|
||||
game_thread_func(GMainLoop *game_loop)
|
||||
{
|
||||
/* Run the game loop */
|
||||
g_main_loop_run(game_loop);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gboolean
|
||||
wmud_game_init(GThread **game_thread, GMainContext **game_context)
|
||||
{
|
||||
GMainLoop *game_loop;
|
||||
GSource *timeout_source;
|
||||
GError *err = NULL;
|
||||
|
||||
/* Create the game context and main loop */
|
||||
*game_context = g_main_context_new();
|
||||
game_loop = g_main_loop_new(*game_context, FALSE);
|
||||
|
||||
/* Create the timeout source which keeps track of elapsed real-world
|
||||
* time */
|
||||
timeout_source = g_timeout_source_new(1000);
|
||||
g_source_set_callback(timeout_source, rl_sec_elapsed, NULL, NULL);
|
||||
g_source_attach(timeout_source, *game_context);
|
||||
g_source_unref(timeout_source);
|
||||
|
||||
g_clear_error(&err);
|
||||
*game_thread = g_thread_create((GThreadFunc)game_thread_func, game_loop, TRUE, &err);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
25
wmud/game.h
Normal file
25
wmud/game.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/* wMUD - Yet another MUD codebase by W00d5t0ck
|
||||
* Copyright (C) 2012 - Gergely POLONKAI
|
||||
*
|
||||
* game.h: Game Thread related functions
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef __WMUD_GAME_H__
|
||||
#define __WMUD_GAME_H__
|
||||
|
||||
gboolean wmud_game_init(GThread **game_thread, GMainContext **game_context);
|
||||
|
||||
#endif /* __WMUD_GAME_H__ */
|
||||
|
207
wmud/interpreter.c
Normal file
207
wmud/interpreter.c
Normal file
@@ -0,0 +1,207 @@
|
||||
/* wMUD - Yet another MUD codebase by W00d5t0ck
|
||||
* Copyright (C) 2012 - Gergely POLONKAI
|
||||
*
|
||||
* interpreter.c: game command interpreter routines
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <glib.h>
|
||||
#include <gio/gio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "interpreter.h"
|
||||
#include "game-networking.h"
|
||||
#include "main.h"
|
||||
|
||||
/**
|
||||
* SECTION:interpreter
|
||||
* @short_description: Game command interpreter
|
||||
*
|
||||
* Functions to interpret and execute in-game commands
|
||||
*/
|
||||
|
||||
WMUD_COMMAND(quit);
|
||||
|
||||
static wmudCommand command_list[] = {
|
||||
{ "quit", gcmd_quit },
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
/**
|
||||
* destroy_string:
|
||||
* @string: a GString to destroy
|
||||
*
|
||||
* Callback function to destroy a list of GStrings
|
||||
*/
|
||||
static void
|
||||
destroy_string(GString *string)
|
||||
{
|
||||
g_string_free(string, TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* wmud_interpret_game_command:
|
||||
* @client: the wmudClient whose command should be processed
|
||||
*
|
||||
* Processes a wmudClient's buffer, and executes the game command if there is
|
||||
* one
|
||||
*/
|
||||
void
|
||||
wmud_interpret_game_command(wmudClient *client)
|
||||
{
|
||||
GSList *command_parts = NULL;
|
||||
gchar *a,
|
||||
*start,
|
||||
*end;
|
||||
gchar str_delim = 0;
|
||||
wmudCommand *cmd;
|
||||
int command_parts_count = 0,
|
||||
match_count = 0;
|
||||
GSList *matches = NULL;
|
||||
|
||||
if (strchr(client->buffer->str, '\r') || strchr(client->buffer->str, '\n'))
|
||||
{
|
||||
/* TODO: We should NEVER reach this point! */
|
||||
return;
|
||||
}
|
||||
|
||||
a = client->buffer->str;
|
||||
|
||||
GString *token;
|
||||
|
||||
while (*a)
|
||||
{
|
||||
for (start = a; *start; start++)
|
||||
{
|
||||
if (!str_delim)
|
||||
{
|
||||
if ((*start == '"') || (*start == '\''))
|
||||
{
|
||||
str_delim = *start;
|
||||
start++;
|
||||
break;
|
||||
}
|
||||
else if (g_ascii_isspace(*start) || (!*start))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (end = start; *end; end++)
|
||||
{
|
||||
if (!str_delim && strchr("'\" \t", *end))
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (str_delim && (*end == str_delim))
|
||||
{
|
||||
str_delim = 0;
|
||||
break;
|
||||
}
|
||||
else if (!*end)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (*start)
|
||||
{
|
||||
token = g_string_new_len(start, end - start);
|
||||
command_parts = g_slist_prepend(command_parts, token);
|
||||
command_parts_count++;
|
||||
}
|
||||
|
||||
a = end;
|
||||
if (((*a == '"') || (*a == '\'')) && str_delim)
|
||||
a++;
|
||||
}
|
||||
|
||||
if (str_delim)
|
||||
{
|
||||
wmud_client_send(client, "You should close quotes of any kind, like %c, shouldn't you?\r\n", str_delim);
|
||||
#if GLIB_CHECK_VERSION(2, 28, 0)
|
||||
g_slist_free_full(command_parts, (GDestroyNotify)destroy_string);
|
||||
#else
|
||||
g_slist_foreach(command_parts, (GFunc)destroy_string, NULL);
|
||||
g_slist_free(command_parts);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
if (command_parts_count == 0)
|
||||
{
|
||||
/* TODO: handle empty command */
|
||||
return;
|
||||
}
|
||||
|
||||
command_parts = g_slist_reverse(command_parts);
|
||||
|
||||
for (cmd = command_list; cmd->command; cmd++)
|
||||
{
|
||||
GString *input = (GString *)(command_parts->data);
|
||||
gint cmp;
|
||||
|
||||
if (((cmp = g_ascii_strncasecmp(input->str, cmd->command, input->len)) == 0) && !cmd->command[input->len])
|
||||
{
|
||||
g_slist_free(matches);
|
||||
match_count = 1;
|
||||
matches = NULL;
|
||||
matches = g_slist_prepend(matches, cmd);
|
||||
break;
|
||||
}
|
||||
else if (cmp == 0)
|
||||
{
|
||||
matches = g_slist_prepend(matches, cmd);
|
||||
match_count++;
|
||||
}
|
||||
}
|
||||
|
||||
switch (match_count)
|
||||
{
|
||||
case 0:
|
||||
switch (random_number(1, 3))
|
||||
{
|
||||
case 1:
|
||||
wmud_client_send(client, "Huh?\r\n");
|
||||
break;
|
||||
case 2:
|
||||
wmud_client_send(client, "What?\r\n");
|
||||
break;
|
||||
case 3:
|
||||
wmud_client_send(client, "I can hardly understand you...\r\n");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
((wmudCommand *)(matches->data))->commandFunc(client, ((GString *)(command_parts->data))->str, command_parts->next);
|
||||
break;
|
||||
default:
|
||||
wmud_client_send(client, "This command could mean several things, please try a more exact form!\r\n");
|
||||
}
|
||||
|
||||
g_slist_free(matches);
|
||||
}
|
||||
|
||||
/**
|
||||
* gcmd_quit:
|
||||
*
|
||||
* The QUIT game command's handler
|
||||
*/
|
||||
WMUD_COMMAND(quit)
|
||||
{
|
||||
wmud_client_send(client, "Are you sure you want to get back to that freaky other reality? [y/N] ");
|
||||
client->state = WMUD_CLIENT_STATE_QUITWAIT;
|
||||
}
|
||||
|
57
wmud/interpreter.h
Normal file
57
wmud/interpreter.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/* wMUD - Yet another MUD codebase by W00d5t0ck
|
||||
* Copyright (C) 2012 - Gergely POLONKAI
|
||||
*
|
||||
* interpreter.h: game command interpreter prototypes and variables
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef __WMUD_INTERPRETER_H__
|
||||
# define __WMUD_INTERPRETER_H__
|
||||
|
||||
#include "game-networking.h"
|
||||
|
||||
/**
|
||||
* wmudCommandFunc:
|
||||
* @client: the client from whom the command arrived
|
||||
* @command: the command itself
|
||||
* @token_list: the command arguments
|
||||
*
|
||||
* Command handler function type
|
||||
*/
|
||||
typedef void (*wmudCommandFunc)(wmudClient *client, gchar *command, GSList *token_list);
|
||||
/**
|
||||
* WMUD_COMMAND:
|
||||
* @name: the name of the command. Should be in lowercase
|
||||
*
|
||||
* Shorthand to create the function header for command handlers
|
||||
*/
|
||||
#define WMUD_COMMAND(name) void gcmd_ ## name(wmudClient *client, gchar *command, GSList *token_list)
|
||||
|
||||
/**
|
||||
* wmudCommand:
|
||||
* @command: the command itself. Should be in uppercase, but doesn't actually
|
||||
* matter
|
||||
* @commandFunc: the command handler function for this command
|
||||
*
|
||||
* This structure holds the different properties of the in-game commands.
|
||||
*/
|
||||
typedef struct _wmudCommand {
|
||||
gchar *command;
|
||||
wmudCommandFunc commandFunc;
|
||||
} wmudCommand;
|
||||
|
||||
void wmud_interpret_game_command(wmudClient *client);
|
||||
|
||||
#endif /* __WMUD_INTERPRETER_H__ */
|
||||
|
207
wmud/main.c
Normal file
207
wmud/main.c
Normal file
@@ -0,0 +1,207 @@
|
||||
/* wMUD - Yet another MUD codebase by W00d5t0ck
|
||||
* Copyright (C) 2012 - Gergely POLONKAI
|
||||
*
|
||||
* main.c: main and uncategorized functions
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <glib.h>
|
||||
#include <gio/gio.h>
|
||||
#ifdef HAVE_CRYPT_H
|
||||
#include <crypt.h>
|
||||
#endif
|
||||
|
||||
#include "wmud-types.h"
|
||||
#include "main.h"
|
||||
#include "game-networking.h"
|
||||
#include "interpreter.h"
|
||||
#include "db.h"
|
||||
#include "players.h"
|
||||
#include "maintenance.h"
|
||||
#include "game.h"
|
||||
#include "configuration.h"
|
||||
|
||||
/**
|
||||
* SECTION:utils
|
||||
* @short_description: Utilities and uncategorized functions
|
||||
* @title: Utility and uncategorized functions
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* debug_context_loc:
|
||||
*
|
||||
* This variable holds the location of the last context marker
|
||||
*/
|
||||
struct {
|
||||
char *file;
|
||||
int line;
|
||||
} debug_context_loc = {NULL, 0};
|
||||
|
||||
/**
|
||||
* wmud_random_string:
|
||||
* @len: the desired length of the generated random string
|
||||
*
|
||||
* Generates a random string of %len characters.
|
||||
*/
|
||||
gchar *
|
||||
wmud_random_string(gint len)
|
||||
{
|
||||
gchar *ret = g_malloc0(len + 1);
|
||||
gint i;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
gchar c = 0;
|
||||
/* Include only printable characters, but exclude $ because of
|
||||
* salt generation */
|
||||
while (!g_ascii_isprint(c) || (c == '$'))
|
||||
c = random_number(1, 127);
|
||||
|
||||
ret[i] = c;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
/**
|
||||
* debug_context:
|
||||
* @file: the source file name, where the context marker was found
|
||||
* @line: the line number where the context marker was found
|
||||
*
|
||||
* This function keeps track of the code flow in some way. It can help with
|
||||
* debugging, as during a SIGSEGV or such signal this will print out the last
|
||||
* place of DebugContext in the code.
|
||||
*
|
||||
* THIS FUNCTION SHOULD NEVER BE CALLED DIRECTLY!
|
||||
*/
|
||||
debug_context(char *file, int line)
|
||||
{
|
||||
if (debug_context_loc.file != NULL)
|
||||
g_free(debug_context_loc.file);
|
||||
|
||||
debug_context_loc.file = g_strdup(file);
|
||||
debug_context_loc.line = line;
|
||||
}
|
||||
/**
|
||||
* DebugContext:
|
||||
*
|
||||
* Marks the current line of the source file with a context marker. Deadly
|
||||
* signals should print the place of the last marker.
|
||||
*/
|
||||
#define DebugContext debug_context(__FILE__, __LINE__)
|
||||
#else
|
||||
#define DebugContext
|
||||
#endif
|
||||
|
||||
/**
|
||||
* wmud_type_init:
|
||||
*
|
||||
* Initializes the wMUD types.
|
||||
*/
|
||||
void
|
||||
wmud_type_init(void)
|
||||
{
|
||||
WMUD_CONFIG_ERROR = g_quark_from_string("wmud_config_error");
|
||||
WMUD_DB_ERROR = g_quark_from_string("wmud_db_error");
|
||||
}
|
||||
|
||||
/**
|
||||
* main:
|
||||
* @argc: The number of arguments on the command line
|
||||
* @argv: The command line arguments themselves
|
||||
*
|
||||
* The Main Function (TM)
|
||||
*/
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
GError *err = NULL;
|
||||
GThread *game_thread;
|
||||
GMainContext *game_context;
|
||||
|
||||
/* Initialize the thread and type system */
|
||||
g_thread_init(NULL);
|
||||
g_type_init();
|
||||
wmud_type_init();
|
||||
|
||||
/* TODO: Command line parsing */
|
||||
/* TODO: Create signal handlers! */
|
||||
|
||||
if (!wmud_config_init(&active_config, &err))
|
||||
{
|
||||
if (err)
|
||||
{
|
||||
g_critical("Config file parsing error: %s", err->message);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_critical("Config file parsing error!");
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
g_clear_error(&err);
|
||||
if (!wmud_db_init(&err))
|
||||
{
|
||||
if (err)
|
||||
{
|
||||
g_critical("Database initialization error: %s", err->message);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_critical("Database initialization error!");
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
g_clear_error(&err);
|
||||
wmud_db_players_load(&err);
|
||||
|
||||
/* Initialization ends here */
|
||||
|
||||
wmud_game_init(&game_thread, &game_context);
|
||||
|
||||
g_clear_error(&err);
|
||||
if (!wmud_networking_init(active_config->port, game_context, &err))
|
||||
{
|
||||
if (err)
|
||||
{
|
||||
g_critical("Database initialization error: %s", err->message);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_critical("Database initialization error!");
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
wmud_maintenance_init();
|
||||
|
||||
/* Initialize other threads here */
|
||||
|
||||
g_thread_join(game_thread);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
21
wmud/main.h
Normal file
21
wmud/main.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifndef __WMUD_MAIN_H__
|
||||
# define __WMUD_MAIN_H__
|
||||
|
||||
# include <glib.h>
|
||||
|
||||
extern GMainContext *game_context;
|
||||
extern guint32 elapsed_seconds;
|
||||
|
||||
/**
|
||||
* random_number:
|
||||
* @min: Minimum value for random number
|
||||
* @max: Maximum value for random number
|
||||
*
|
||||
* Generates a random number between min and max
|
||||
*/
|
||||
#define random_number(min, max) g_random_int_range((min), (max) + 1)
|
||||
|
||||
gchar *wmud_random_string(gint len);
|
||||
|
||||
#endif /* __WMUD_MAIN_H__ */
|
||||
|
132
wmud/maintenance.c
Normal file
132
wmud/maintenance.c
Normal file
@@ -0,0 +1,132 @@
|
||||
/* wMUD - Yet another MUD codebase by W00d5t0ck
|
||||
* Copyright (C) 2012 - Gergely POLONKAI
|
||||
*
|
||||
* maintenance.c: game maintenance and self-check functions
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <glib.h>
|
||||
#ifdef HAVE_CRYPT_H
|
||||
#include <crypt.h>
|
||||
#endif
|
||||
|
||||
#include "wmud-types.h"
|
||||
#include "maintenance.h"
|
||||
#include "main.h"
|
||||
#include "players.h"
|
||||
|
||||
/**
|
||||
* SECTION:maintenance-thread
|
||||
* @short_description: Runtime maintenance functions
|
||||
* @title: Runtime maintenance functions
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* wmud_maintenance_check_new_players:
|
||||
* @player: #wmudPLayer structure of the player record to check
|
||||
* @user_data: not used
|
||||
*
|
||||
* Callback called from within the maintenance loop. Checks if the player has
|
||||
* an unset password, and generate one for them, if so.
|
||||
*/
|
||||
void
|
||||
wmud_maintenance_check_new_players(wmudPlayer *player, gpointer user_data)
|
||||
{
|
||||
if (player->cpassword == NULL)
|
||||
{
|
||||
gchar *pw,
|
||||
*salt,
|
||||
*cpw;
|
||||
GString *full_salt;
|
||||
|
||||
pw = wmud_random_string(8);
|
||||
salt = wmud_random_string(8);
|
||||
full_salt = g_string_new("$1$");
|
||||
g_string_append(full_salt, salt);
|
||||
cpw = g_strdup(crypt(pw, full_salt->str));
|
||||
|
||||
g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Player %s has no"
|
||||
" password set", player->player_name);
|
||||
g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "New password will be %s", pw);
|
||||
player->cpassword = cpw;
|
||||
/* TODO: Send e-mail about the new password. Upon completion,
|
||||
* set it in the database */
|
||||
|
||||
g_free(pw);
|
||||
g_free(salt);
|
||||
g_string_free(full_salt, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* wmud_maintenance:
|
||||
* @user_data: not used
|
||||
*
|
||||
* Timeout source function for maintenance tasks
|
||||
*/
|
||||
gboolean
|
||||
wmud_maintenance(gpointer user_data)
|
||||
{
|
||||
g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Starting maintenance...");
|
||||
/* Run through the player list, and generate a random password for each
|
||||
* newly registered player */
|
||||
g_slist_foreach(players, (GFunc)wmud_maintenance_check_new_players, NULL);
|
||||
|
||||
g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Finished maintenance...");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* maint_thread_func:
|
||||
* @main_loop: the main loop to be associated with the maintenance thread
|
||||
*
|
||||
* The maintenance thread's main function.
|
||||
*
|
||||
* Return value: This function always returns %NULL.
|
||||
*/
|
||||
gpointer
|
||||
maint_thread_func(GMainLoop *maint_loop)
|
||||
{
|
||||
g_main_loop_run(maint_loop);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
wmud_maintenance_init(void)
|
||||
{
|
||||
GSource *timeout_source;
|
||||
GMainLoop *maint_loop;
|
||||
GMainContext *maint_context;
|
||||
GError *err = NULL;
|
||||
|
||||
/* Create the maintenance context and main loop */
|
||||
maint_context = g_main_context_new();
|
||||
maint_loop = g_main_loop_new(maint_context, FALSE);
|
||||
|
||||
/* Create the timeout source which will do the maintenance tasks */
|
||||
timeout_source = g_timeout_source_new_seconds(3);
|
||||
g_source_set_callback(timeout_source, wmud_maintenance, NULL, NULL);
|
||||
g_source_attach(timeout_source, maint_context);
|
||||
g_source_unref(timeout_source);
|
||||
|
||||
g_thread_create((GThreadFunc)maint_thread_func, maint_loop, FALSE, &err);
|
||||
}
|
||||
|
1
wmud/maintenance.h
Normal file
1
wmud/maintenance.h
Normal file
@@ -0,0 +1 @@
|
||||
void wmud_maintenance_init(void);
|
139
wmud/players.c
Normal file
139
wmud/players.c
Normal file
@@ -0,0 +1,139 @@
|
||||
/* wMUD - Yet another MUD codebase by W00d5t0ck
|
||||
* Copyright (C) 2012 - Gergely POLONKAI
|
||||
*
|
||||
* players.c: player structure related functions
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <glib.h>
|
||||
#ifdef HAVE_CRYPT_H
|
||||
#include <crypt.h>
|
||||
#endif
|
||||
|
||||
#include "game-networking.h"
|
||||
#include "players.h"
|
||||
|
||||
/**
|
||||
* SECTION:player
|
||||
* @short_description: Player database handling
|
||||
*
|
||||
* Functions to handle player database records
|
||||
*/
|
||||
|
||||
/**
|
||||
* players:
|
||||
*
|
||||
* GSList of all loaded players. Stores #wmudPlayer structures.
|
||||
*/
|
||||
GSList *players = NULL;
|
||||
|
||||
/**
|
||||
* wmud_player_auth:
|
||||
* @client: The client to be authenticated. The authentication password comes
|
||||
* from the client's buffer.
|
||||
*
|
||||
* Tries to authenticate a client based on the associated player structure, and
|
||||
* the password stored in the client's buffer.
|
||||
*
|
||||
* Return value: %TRUE if the password is valid, %FALSE otherwise.
|
||||
*/
|
||||
gboolean
|
||||
wmud_player_auth(wmudClient *client)
|
||||
{
|
||||
g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Player entered %s as password", client->buffer->str);
|
||||
|
||||
if (g_strcmp0(crypt(client->buffer->str, client->player->cpassword), client->player->cpassword) == 0)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gint
|
||||
find_player_by_name(wmudPlayer *player, gchar *player_name)
|
||||
{
|
||||
return g_ascii_strcasecmp(player->player_name, player_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* wmud_player_exists:
|
||||
* @player_name: The login name of the player to check
|
||||
*
|
||||
* Check if the player with the given name already exists.
|
||||
*
|
||||
* Return value: the wmudPlayer structure for the given player name, or %NULL
|
||||
* if it can not be found.
|
||||
*/
|
||||
wmudPlayer *
|
||||
wmud_player_exists(gchar *player_name)
|
||||
{
|
||||
GSList *player_elem;
|
||||
|
||||
if ((player_elem = g_slist_find_custom(players, player_name, (GCompareFunc)find_player_by_name)) == NULL)
|
||||
return NULL;
|
||||
|
||||
return player_elem->data;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* wmud_player_dup:
|
||||
* @player: the player structure to duplicate
|
||||
*
|
||||
* Duplicates a #wmudPlayer structure.
|
||||
*
|
||||
* Return value: the new, duplicated player structure. It must be freed with wmud_player_free().
|
||||
*/
|
||||
wmudPlayer *
|
||||
wmud_player_dup(wmudPlayer *player)
|
||||
{
|
||||
wmudPlayer *new_player;
|
||||
|
||||
if (!player)
|
||||
return NULL;
|
||||
|
||||
new_player = g_new0(wmudPlayer, 1);
|
||||
new_player->id = player->id;
|
||||
new_player->player_name = g_strdup(player->player_name);
|
||||
new_player->cpassword = g_strdup(player->cpassword);
|
||||
new_player->email = g_strdup(player->email);
|
||||
|
||||
return new_player;
|
||||
}
|
||||
|
||||
/**
|
||||
* wmud_player_free:
|
||||
* @player: A pointer to the player structure to be freed
|
||||
*
|
||||
* Frees a #wmudPlayer structure with all its fields, and sets the structure
|
||||
* variable to %NULL.
|
||||
*/
|
||||
void
|
||||
wmud_player_free(wmudPlayer **player)
|
||||
{
|
||||
if (!*player)
|
||||
return;
|
||||
if ((*player)->player_name)
|
||||
g_free((*player)->player_name);
|
||||
if ((*player)->cpassword)
|
||||
g_free((*player)->cpassword);
|
||||
if ((*player)->email)
|
||||
g_free((*player)->email);
|
||||
g_free(*player);
|
||||
*player = NULL;
|
||||
}
|
||||
|
33
wmud/players.h
Normal file
33
wmud/players.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/* wMUD - Yet another MUD codebase by W00d5t0ck
|
||||
* Copyright (C) 2012 - Gergely POLONKAI
|
||||
*
|
||||
* players.h: player structure related prototypes and variables
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef __WMUD_PLAYERS_H__
|
||||
#define __WMUD_PLAYERS_H__
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "wmud-types.h"
|
||||
|
||||
extern GSList *players;
|
||||
|
||||
gboolean wmud_player_auth(wmudClient *client);
|
||||
wmudPlayer *wmud_player_exists(gchar *player_name);
|
||||
void wmud_player_free(wmudPlayer **player);
|
||||
wmudPlayer *wmud_player_dup(wmudPlayer *player);
|
||||
|
||||
#endif /* __WMUD_PLAYERS_H__ */
|
127
wmud/wmud-types.h
Normal file
127
wmud/wmud-types.h
Normal file
@@ -0,0 +1,127 @@
|
||||
/* wMUD - Yet another MUD codebase by W00d5t0ck
|
||||
* Copyright (C) 2012 - Gergely POLONKAI
|
||||
*
|
||||
* wmud-types.h: Common wMUD data types
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef __WMUD_TYPES_H__
|
||||
#define __WMUD_TYPES_H__
|
||||
|
||||
#include <glib.h>
|
||||
#include <gio/gio.h>
|
||||
|
||||
/**
|
||||
* SECTION:types
|
||||
* @short_description: wMUD Data Types
|
||||
* @title: wMUD's Data Types
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* wmudClientState:
|
||||
* @WMUD_CLIENT_STATE_FRESH: Client is newly connected. Waiting for a login
|
||||
* player name
|
||||
* @WMUD_CLIENT_STATE_PASSWAIT: Login player name is entered, waiting for a
|
||||
* login password
|
||||
* @WMUD_CLIENT_STATE_MENU: Authentication was successful, player is now in the
|
||||
* main game menu
|
||||
* @WMUD_CLIENT_STATE_INGAME: Character login was successful, player is now
|
||||
* in-game
|
||||
* @WMUD_CLIENT_STATE_QUITWAIT: Player entered the in-game QUIT command, and we
|
||||
* are now waiting for an answer if they really want to quit
|
||||
* Will be removed soon, this should work totally different (TODO)
|
||||
* @WMUD_CLIENT_STATE_NEWCHAR: Player name entered on the login screen was
|
||||
* invalid. Waiting for answer if this is a new player
|
||||
* @WMUD_CLIENT_STATE_REGISTERING: Registering a new player. Waiting for the
|
||||
* e-mail address to be given
|
||||
* @WMUD_CLIENT_STATE_REGEMAIL_CONFIRM: E-mail address entered séms valid,
|
||||
* waiting for confirmation
|
||||
*
|
||||
* Game client states.
|
||||
*/
|
||||
typedef enum {
|
||||
WMUD_CLIENT_STATE_FRESH,
|
||||
WMUD_CLIENT_STATE_PASSWAIT,
|
||||
WMUD_CLIENT_STATE_MENU,
|
||||
WMUD_CLIENT_STATE_INGAME,
|
||||
WMUD_CLIENT_STATE_QUITWAIT,
|
||||
WMUD_CLIENT_STATE_NEWCHAR,
|
||||
WMUD_CLIENT_STATE_REGISTERING,
|
||||
WMUD_CLIENT_STATE_REGEMAIL_CONFIRM
|
||||
} wmudClientState;
|
||||
|
||||
/**
|
||||
* wmudPlayer:
|
||||
* @id: Player's database ID
|
||||
* @player_name: Player's login name
|
||||
* @cpassword: crypt()ed password of the player. This is NULL for newly
|
||||
* registered players, who have no password generated for them by the
|
||||
* maintenance loop
|
||||
* @email: E-mail address of the player
|
||||
*
|
||||
* The <structname>wmudPlayer</structname> structure contains all information of
|
||||
* a player.
|
||||
*/
|
||||
typedef struct _wmudPlayer {
|
||||
guint32 id;
|
||||
gchar *player_name;
|
||||
gchar *cpassword;
|
||||
gchar *email;
|
||||
} wmudPlayer;
|
||||
|
||||
/**
|
||||
* wmudClient:
|
||||
* @socket: The assigned GSocket object
|
||||
* @buffer: The client receive buffer. It may hold partial or multiple lines
|
||||
* until processed
|
||||
* @state: The state of the client
|
||||
* @authenticated: TRUE if the client is an authenticated game player
|
||||
* @player: The associatec player structure. It is also used during
|
||||
* registration, so it should be always checked if the player is a saved
|
||||
* database user
|
||||
* @bademail: indicates that the entered e-mail address is invalid
|
||||
* @socket_source: the #GSource associated with the client socket
|
||||
* @login_try_count: the failed login count of the client
|
||||
*
|
||||
* <structname>wmudClient</structname> contains all properties of a connected
|
||||
* game client.
|
||||
*/
|
||||
typedef struct _wmudClient {
|
||||
GSocket *socket;
|
||||
GSource *socket_source;
|
||||
GString *buffer;
|
||||
wmudClientState state;
|
||||
gboolean authenticated;
|
||||
wmudPlayer *player;
|
||||
gboolean bademail;
|
||||
gint login_try_count;
|
||||
} wmudClient;
|
||||
|
||||
/**
|
||||
* wmudDbError:
|
||||
* @WMUD_DB_ERROR_CANTOPEN: Database file cannot be opened
|
||||
* @WMUD_DB_ERROR_NOINIT: Database system was not initialized
|
||||
* @WMUD_DB_ERROR_BADQUERY: Invalid database query
|
||||
*
|
||||
* Error codes returned by database handling functions.
|
||||
*/
|
||||
typedef enum {
|
||||
WMUD_DB_ERROR_CANTOPEN,
|
||||
WMUD_DB_ERROR_NOINIT,
|
||||
WMUD_DB_ERROR_BADQUERY
|
||||
} wmudDbError;
|
||||
|
||||
#endif /* __WMUD_TYPES_H__ */
|
||||
|
155
wmud/world.c
Normal file
155
wmud/world.c
Normal file
@@ -0,0 +1,155 @@
|
||||
/* wMUD - Yet another MUD codebase by W00d5t0ck
|
||||
* Copyright (C) 2012 - Gergely POLONKAI
|
||||
*
|
||||
* world.c: world loading and building functions
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "world.h"
|
||||
#include "db.h"
|
||||
|
||||
/**
|
||||
* SECTION:world
|
||||
* @short_description: World loading and building functions
|
||||
* @title: Game world manipulation
|
||||
*
|
||||
*/
|
||||
|
||||
gboolean
|
||||
wmud_world_check_planes(GSList *planes, GError **err)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
wmud_world_check_planets(GSList *planets, GError **err)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
wmud_world_check_areas(GSList *areas, GError **err)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
wmud_world_check_exits(GSList *exits, GError **err)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
wmud_world_assoc_planets_planes(GSList *planets, GSList *planes, GError **err)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
wmud_world_assoc_rooms_areas(GSList *rooms, GSList *areas, GError **err)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
wmud_world_assoc_rooms_planets(GSList *rooms, GSList *planets, GError **err)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
wmud_world_assoc_exits_rooms(GSList *exits, GSList *rooms, GError **err)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* wmud_world_load:
|
||||
* @err: a #GError to put error messages into
|
||||
*
|
||||
* Load the world from the database backend without activating it.
|
||||
*/
|
||||
gboolean
|
||||
wmud_world_load(GError **err)
|
||||
{
|
||||
GSList *planes = NULL,
|
||||
*planets = NULL,
|
||||
*directions = NULL,
|
||||
*areas = NULL,
|
||||
*rooms = NULL,
|
||||
*exits = NULL;
|
||||
GError *in_err = NULL;
|
||||
|
||||
/* Load directions from the database */
|
||||
wmud_db_load_directions(&directions, &in_err);
|
||||
|
||||
/* Load planes from the database */
|
||||
wmud_db_load_planes(&planes, &in_err);
|
||||
|
||||
/* Check if the loaded planes conform to the rules */
|
||||
g_clear_error(&in_err);
|
||||
wmud_world_check_planes(planes, &in_err);
|
||||
|
||||
/* Load planets from the database */
|
||||
g_clear_error(&in_err);
|
||||
wmud_db_load_planets(&planets, &in_err);
|
||||
|
||||
/* Check if the planets conform to the rules */
|
||||
g_clear_error(&in_err);
|
||||
wmud_world_check_planets(planets, &in_err);
|
||||
|
||||
/* Put the planets on the planes */
|
||||
g_clear_error(&in_err);
|
||||
wmud_world_assoc_planets_planes(planets, planes, &in_err);
|
||||
|
||||
/* Load areas from the database */
|
||||
g_clear_error(&in_err);
|
||||
wmud_db_load_areas(&areas, &in_err);
|
||||
|
||||
/* Check if the areas conform to the rules */
|
||||
g_clear_error(&in_err);
|
||||
wmud_world_check_areas(areas, &in_err);
|
||||
|
||||
/* Load rooms from the database */
|
||||
g_clear_error(&in_err);
|
||||
wmud_db_load_rooms(&rooms, &in_err);
|
||||
|
||||
/* Associate rooms with the areas */
|
||||
g_clear_error(&in_err);
|
||||
wmud_world_assoc_rooms_areas(rooms, areas, &in_err);
|
||||
|
||||
/* Associate rooms with planets */
|
||||
g_clear_error(&in_err);
|
||||
wmud_world_assoc_rooms_planets(rooms, planets, &in_err);
|
||||
|
||||
/* Load room exits from the database */
|
||||
g_clear_error(&in_err);
|
||||
wmud_db_load_exits(&exits, &in_err);
|
||||
|
||||
/* Check if the exits conform to the rules */
|
||||
g_clear_error(&in_err);
|
||||
wmud_world_check_exits(exits, &in_err);
|
||||
|
||||
/* Associate exits with rooms */
|
||||
g_clear_error(&in_err);
|
||||
wmud_world_assoc_exits_rooms(exits, rooms, &in_err);
|
||||
|
||||
g_clear_error(&in_err);
|
||||
return TRUE;
|
||||
}
|
||||
|
33
wmud/world.h
Normal file
33
wmud/world.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/* wMUD - Yet another MUD codebase by W00d5t0ck
|
||||
* Copyright (C) 2012 - Gergely POLONKAI
|
||||
*
|
||||
* world.h: world loading and building functions
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef __WMUD_WORLD_H__
|
||||
#define __WMUD_WORLD_H__
|
||||
|
||||
gboolean wmud_world_check_planes(GSList *planes, GError **err);
|
||||
gboolean wmud_world_check_planets(GSList *planets, GError **err);
|
||||
gboolean wmud_world_check_areas(GSList *areas, GError **err);
|
||||
gboolean wmud_world_check_exits(GSList *exits, GError **err);
|
||||
|
||||
gboolean wmud_world_assoc_planets_planes(GSList *planets, GSList *planes, GError **err);
|
||||
gboolean wmud_world_assoc_rooms_areas(GSList *rooms, GSList *areas, GError **err);
|
||||
gboolean wmud_world_assoc_rooms_planets(GSList *rooms, GSList *planets, GError **err);
|
||||
gboolean wmud_world_assoc_exits_rooms(GSList *exits, GSList *rooms, GError **err);
|
||||
|
||||
#endif /* __WMUD_WORLD_H__ */
|
||||
|
Reference in New Issue
Block a user