/*\r
Minetest-c55\r
-Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>\r
+Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>\r
\r
This program is free software; you can redistribute it and/or modify\r
it under the terms of the GNU General Public License as published by\r
NOTE: If VBO (EHM_STATIC) is used, remember to explicitly free the\r
hardware buffer (it is not freed automatically)\r
\r
-Random suggeestions (AKA very old suggestions that haven't been done):\r
-----------------------------------------------------------------------\r
-\r
-SUGG: Fix address to be ipv6 compatible\r
+NOTE: A random to-do list saved here as documentation:\r
+A list of "active blocks" in which stuff happens. (+=done)\r
+ + Add a never-resetted game timer to the server\r
+ + Add a timestamp value to blocks\r
+ + The simple rule: All blocks near some player are "active"\r
+ - Do stuff in real time in active blocks\r
+ + Handle objects\r
+ - Grow grass, delete leaves without a tree\r
+ - Spawn some mobs based on some rules\r
+ - Transform cobble to mossy cobble near water\r
+ - Run a custom script\r
+ - ...And all kinds of other dynamic stuff\r
+ + Keep track of when a block becomes active and becomes inactive\r
+ + When a block goes inactive:\r
+ + Store objects statically to block\r
+ + Store timer value as the timestamp\r
+ + When a block goes active:\r
+ + Create active objects out of static objects\r
+ - Simulate the results of what would have happened if it would have\r
+ been active for all the time\r
+ - Grow a lot of grass and so on\r
+ + Initially it is fine to send information about every active object\r
+ to every player. Eventually it should be modified to only send info\r
+ about the nearest ones.\r
+ + This was left to be done by the old system and it sends only the\r
+ nearest ones.\r
+\r
+Old, wild and random suggestions that probably won't be done:\r
+-------------------------------------------------------------\r
\r
SUGG: If player is on ground, mainly fetch ground-level blocks\r
\r
SUGG: Meshes of blocks could be split into 6 meshes facing into\r
different directions and then only those drawn that need to be\r
\r
-SUGG: Calculate lighting per vertex to get a lighting effect like in\r
- bartwe's game\r
-\r
SUGG: Background music based on cellular automata?\r
http://www.earslap.com/projectslab/otomata\r
\r
+SUGG: Simple light color information to air\r
+\r
+SUGG: Server-side objects could be moved based on nodes to enable very\r
+ lightweight operation and simple AI\r
+ - Not practical; client would still need to show smooth movement.\r
+\r
+SUGG: Make a system for pregenerating quick information for mapblocks, so\r
+ that the client can show them as cubes before they are actually sent\r
+ or even generated.\r
+\r
+SUGG: Erosion simulation at map generation time\r
+ - This might be plausible if larger areas of map were pregenerated\r
+ without lighting (which is slow)\r
+ - Simulate water flows, which would carve out dirt fast and\r
+ then turn stone into gravel and sand and relocate it.\r
+ - How about relocating minerals, too? Coal and gold in\r
+ downstream sand and gravel would be kind of cool\r
+ - This would need a better way of handling minerals, mainly\r
+ to have mineral content as a separate field. the first\r
+ parameter field is free for this.\r
+ - Simulate rock falling from cliffs when water has removed\r
+ enough solid rock from the bottom\r
+\r
+SUGG: For non-mapgen FarMesh: Add a per-sector database to store surface\r
+ stuff as simple flags/values\r
+ - Light?\r
+ - A building?\r
+ And at some point make the server send this data to the client too,\r
+ instead of referring to the noise functions\r
+ - Ground height\r
+ - Surface ground type\r
+ - Trees?\r
\r
Gaming ideas:\r
-------------\r
\r
- Aim for something like controlling a single dwarf in Dwarf Fortress\r
-\r
- The player could go faster by a crafting a boat, or riding an animal\r
-\r
- Random NPC traders. what else?\r
\r
Game content:\r
-------------\r
+\r
- When furnace is destroyed, move items to player's inventory\r
- Add lots of stuff\r
- Glass blocks\r
- A bomb\r
- A spread-items-on-map routine for the bomb, and for dying players\r
\r
+- Fighting:\r
+ - Proper sword swing simulation\r
+ - Player should get damage from colliding to a wall at high speed\r
+\r
Documentation:\r
--------------\r
\r
Networking and serialization:\r
-----------------------------\r
\r
-TODO: Get rid of GotSplitPacketException\r
-\r
-GUI:\r
-----\r
+SUGG: Fix address to be ipv6 compatible\r
\r
-TODO: Configuration menu, at least for keys\r
+User Interface:\r
+---------------\r
\r
Graphics:\r
---------\r
sectors that have very large amounts of blocks (on client)\r
- Is this necessary at all?\r
\r
-TODO: Flowing water animation\r
-\r
SUGG: Draw cubes in inventory directly with 3D drawing commands, so that\r
animating them is easier.\r
\r
SUGG: Option for enabling proper alpha channel for textures\r
+\r
+TODO: Flowing water animation\r
+\r
TODO: A setting for enabling bilinear filtering for textures\r
\r
TODO: Better control of draw_control.wanted_max_blocks\r
\r
-TODO: Get player texture (and some others) from the specified texture\r
- directory\r
+TODO: Further investigate the use of GPU lighting in addition to the\r
+ current one\r
+\r
+TODO: Artificial (night) light could be more yellow colored than sunlight.\r
+ - This is technically doable.\r
+ - Also the actual colors of the textures could be made less colorful\r
+ in the dark but it's a bit more difficult.\r
+\r
+SUGG: Somehow make the night less colorful\r
+\r
+TODO: Occlusion culling\r
+ - At the same time, move some of the renderMap() block choosing code\r
+ to the same place as where the new culling happens.\r
+ - Shoot some rays per frame and when ready, make a new list of\r
+ blocks for usage of renderMap and give it a new pointer to it.\r
\r
Configuration:\r
--------------\r
\r
- Tool/weapon visualization\r
\r
+FIXME: When disconnected to the menu, memory is not freed properly\r
+\r
+TODO: Investigate how much the mesh generator thread gets used when\r
+ transferring map data\r
+\r
Server:\r
-------\r
\r
* Fix the problem with the server constantly saving one or a few\r
blocks? List the first saved block, maybe it explains.\r
- It is probably caused by oscillating water\r
+ - TODO: Investigate if this still happens (this is a very old one)\r
* Make a small history check to transformLiquids to detect and log\r
continuous oscillations, in such detail that they can be fixed.\r
\r
+FIXME: The new optimized map sending doesn't sometimes send enough blocks\r
+ from big caves and such\r
+FIXME: Block send distance configuration does not take effect for some reason\r
+\r
+Environment:\r
+------------\r
+\r
+TODO: Add proper hooks to when adding and removing active blocks\r
+\r
+TODO: Finish the ActiveBlockModifier stuff and use it for something\r
+\r
Objects:\r
--------\r
\r
-TODO: Get rid of MapBlockObjects and use ActiveObjects\r
+TODO: Get rid of MapBlockObjects and use only ActiveObjects\r
+ - Skipping the MapBlockObject data is nasty - there is no "total\r
+ length" stored; have to make a SkipMBOs function which contains\r
+ enough of the current code to skip them properly.\r
\r
SUGG: MovingObject::move and Player::move are basically the same.\r
combine them.\r
- - NOTE: Player::move is more up-to-date.\r
- - NOTE: There is a simple move implementation now in collision.{h,cpp}\r
+ - NOTE: This is a bit tricky because player has the sneaking ability\r
+ - NOTE: Player::move is more up-to-date.\r
+ - NOTE: There is a simple move implementation now in collision.{h,cpp}\r
+ - NOTE: MovingObject will be deleted (MapBlockObject)\r
+\r
+TODO: Add a long step function to objects that is called with the time\r
+ difference when block activates\r
\r
Map:\r
----\r
TODO: Mineral and ground material properties\r
- This way mineral ground toughness can be calculated with just\r
some formula, as well as tool strengths\r
+ - There are TODOs in appropriate files: material.h, content_mapnode.h\r
\r
TODO: Flowing water to actually contain flow direction information\r
- There is a space for this - it just has to be implemented.\r
\r
-SUGG: Erosion simulation at map generation time\r
- - Simulate water flows, which would carve out dirt fast and\r
- then turn stone into gravel and sand and relocate it.\r
- - How about relocating minerals, too? Coal and gold in\r
- downstream sand and gravel would be kind of cool\r
- - This would need a better way of handling minerals, mainly\r
- to have mineral content as a separate field. the first\r
- parameter field is free for this.\r
- - Simulate rock falling from cliffs when water has removed\r
- enough solid rock from the bottom\r
-\r
-SUGG: Try out the notch way of generating maps, that is, make bunches\r
- of low-res 3d noise and interpolate linearly.\r
-\r
-Mapgen v2:\r
-* Possibly add some kind of erosion and other stuff\r
-* Better water generation (spread it to underwater caverns but don't\r
- fill dungeons that don't touch big water masses)\r
-* When generating a chunk and the neighboring chunk doesn't have mud\r
- and stuff yet and the ground is fairly flat, the mud will flow to\r
- the other chunk making nasty straight walls when the other chunk\r
- is generated. Fix it. Maybe just a special case if the ground is\r
- flat?\r
+TODO: Consider smoothening cave floors after generating them\r
\r
Misc. stuff:\r
------------\r
-* Make an "environment metafile" to store at least time of day\r
-* Move digging property stuff from material.{h,cpp} to mapnode.cpp...\r
- - Or maybe move content_features to material.{h,cpp}?\r
-* Maybe:\r
- Make a system for pregenerating quick information for mapblocks, so\r
- that the client can show them as cubes before they are actually sent\r
- or even generated.\r
+TODO: Make sure server handles removing grass when a block is placed (etc)\r
+ - The client should not do it by itself\r
+ - NOTE: I think nobody does it currently...\r
+TODO: Block cube placement around player's head\r
+TODO: Protocol version field\r
+TODO: Think about using same bits for material for fences and doors, for\r
+ example\r
+TODO: Move mineral to param2, increment map serialization version, add\r
+ conversion\r
+\r
+TODO: Restart irrlicht completely when coming back to main menu from game.\r
+ - This gets rid of everything that is stored in irrlicht's caches.\r
+\r
+TODO: Merge bahamada's audio stuff (clean patch available)\r
+\r
+TODO: Merge key configuration menu (no clean patch available)\r
\r
Making it more portable:\r
------------------------\r
-* Some MSVC: std::sto* are defined without a namespace and collide\r
- with the ones in utility.h\r
+ \r
+Stuff to do before release:\r
+---------------------------\r
+\r
+Fixes to the current release:\r
+-----------------------------\r
+\r
+Stuff to do after release:\r
+---------------------------\r
+\r
+Doing currently:\r
+----------------\r
\r
======================================================================\r
\r
\r
#include <iostream>\r
#include <fstream>\r
-//#include <jmutexautolock.h>\r
#include <locale.h>\r
#include "main.h"\r
#include "common_irrlicht.h"\r
#include "debug.h"\r
-//#include "map.h"\r
-//#include "player.h"\r
#include "test.h"\r
#include "server.h"\r
-//#include "client.h"\r
#include "constants.h"\r
#include "porting.h"\r
#include "gettime.h"\r
#include "config.h"\r
#include "guiMainMenu.h"\r
#include "mineral.h"\r
-//#include "noise.h"\r
-//#include "tile.h"\r
#include "materials.h"\r
#include "game.h"\r
+#include "keycode.h"\r
+#include "tile.h"\r
+\r
+#include "gettext.h"\r
\r
// This makes textures\r
ITextureSource *g_texturesource = NULL;\r
// This is located in defaultsettings.cpp\r
extern void set_default_settings();\r
\r
+// Global profiler\r
+Profiler g_profiler;\r
+\r
/*\r
Random stuff\r
*/\r
class TimeGetter\r
{\r
public:\r
- TimeGetter(IrrlichtDevice *device):\r
+ virtual u32 getTime() = 0;\r
+};\r
+\r
+// A precise irrlicht one\r
+class IrrlichtTimeGetter: public TimeGetter\r
+{\r
+public:\r
+ IrrlichtTimeGetter(IrrlichtDevice *device):\r
m_device(device)\r
{}\r
u32 getTime()\r
private:\r
IrrlichtDevice *m_device;\r
};\r
+// Not so precise one which works without irrlicht\r
+class SimpleTimeGetter: public TimeGetter\r
+{\r
+public:\r
+ u32 getTime()\r
+ {\r
+ return porting::getTimeMs();\r
+ }\r
+};\r
\r
// A pointer to a global instance of the time getter\r
+// TODO: why?\r
TimeGetter *g_timegetter = NULL;\r
\r
u32 getTimeMs()\r
if(counter1 < 0.0)\r
{\r
counter1 = 0.1*Rand(1, 40);\r
- keydown[irr::KEY_SPACE] = !keydown[irr::KEY_SPACE];\r
+ keydown[getKeySetting("keymap_jump")] =\r
+ !keydown[getKeySetting("keymap_jump")];\r
}\r
}\r
{\r
if(counter1 < 0.0)\r
{\r
counter1 = 0.1*Rand(1, 40);\r
- keydown[irr::KEY_KEY_E] = !keydown[irr::KEY_KEY_E];\r
+ keydown[getKeySetting("keymap_special1")] =\r
+ !keydown[getKeySetting("keymap_special1")];\r
}\r
}\r
{\r
if(counter1 < 0.0)\r
{\r
counter1 = 0.1*Rand(1, 40);\r
- keydown[irr::KEY_KEY_W] = !keydown[irr::KEY_KEY_W];\r
+ keydown[getKeySetting("keymap_forward")] =\r
+ !keydown[getKeySetting("keymap_forward")];\r
}\r
}\r
{\r
if(counter1 < 0.0)\r
{\r
counter1 = 0.1*Rand(1, 40);\r
- keydown[irr::KEY_KEY_A] = !keydown[irr::KEY_KEY_A];\r
+ keydown[getKeySetting("keymap_left")] =\r
+ !keydown[getKeySetting("keymap_left")];\r
}\r
}\r
{\r
core::dimension2d<u32> screensize = driver->getScreenSize();\r
\r
video::ITexture *bgtexture =\r
- driver->getTexture(porting::getDataPath("mud.png").c_str());\r
+ driver->getTexture(getTexturePath("mud.png").c_str());\r
if(bgtexture)\r
{\r
s32 texturesize = 128;\r
}\r
\r
video::ITexture *logotexture =\r
- driver->getTexture(porting::getDataPath("menulogo.png").c_str());\r
+ driver->getTexture(getTexturePath("menulogo.png").c_str());\r
if(logotexture)\r
{\r
v2s32 logosize(logotexture->getOriginalSize().Width,\r
\r
int main(int argc, char *argv[])\r
{\r
+ /*\r
+ Initialization\r
+ */\r
+\r
+ // Set locale. This is for forcing '.' as the decimal point.\r
+ std::locale::global(std::locale("C"));\r
+ // This enables printing all characters in bitmap font\r
+ setlocale(LC_CTYPE, "en_US");\r
/*\r
Parse command line\r
*/\r
disable_stderr = true;\r
#endif\r
\r
- // Initialize debug streams\r
- debugstreams_init(disable_stderr, DEBUGFILE);\r
- // Initialize debug stacks\r
- debug_stacks_init();\r
-\r
- DSTACK(__FUNCTION_NAME);\r
-\r
porting::signal_handler_init();\r
bool &kill = *porting::signal_handler_killstatus();\r
\r
+ // Initialize porting::path_data and porting::path_userdata\r
porting::initializePaths();\r
+\r
// Create user data directory\r
fs::CreateDir(porting::path_userdata);\r
+\r
+ setlocale(LC_ALL, "");\r
+ bindtextdomain("minetest-c55", (porting::path_userdata+"/locale").c_str());\r
+ textdomain("minetest-c55");\r
\r
- // C-style stuff initialization\r
- initializeMaterialProperties();\r
+ // Initialize debug streams\r
+#ifdef RUN_IN_PLACE\r
+ std::string debugfile = DEBUGFILE;\r
+#else\r
+ std::string debugfile = porting::path_userdata+"/"+DEBUGFILE;\r
+#endif\r
+ debugstreams_init(disable_stderr, debugfile.c_str());\r
+ // Initialize debug stacks\r
+ debug_stacks_init();\r
+\r
+ DSTACK(__FUNCTION_NAME);\r
+\r
+ // Init material properties table\r
+ //initializeMaterialProperties();\r
\r
// Debug handler\r
BEGIN_DEBUG_EXCEPTION_HANDLER\r
// Initialize default settings\r
set_default_settings();\r
\r
- // Set locale. This is for forcing '.' as the decimal point.\r
- std::locale::global(std::locale("C"));\r
- // This enables printing all characters in bitmap font\r
- setlocale(LC_CTYPE, "en_US");\r
-\r
// Initialize sockets\r
sockets_init();\r
atexit(sockets_cleanup);\r
\r
- /*\r
- Initialization\r
- */\r
-\r
/*\r
Read config file\r
*/\r
port = 30000;\r
\r
// Map directory\r
- std::string map_dir = porting::path_userdata+"/map";\r
+ std::string map_dir = porting::path_userdata+"/world";\r
if(cmd_args.exists("map-dir"))\r
map_dir = cmd_args.get("map-dir");\r
else if(g_settings.exists("map-dir"))\r
{\r
DSTACK("Dedicated server branch");\r
\r
+ // Create time getter\r
+ g_timegetter = new SimpleTimeGetter();\r
+ \r
// Create server\r
Server server(map_dir.c_str());\r
server.start(port);\r
return 0;\r
}\r
\r
+\r
/*\r
More parameters\r
*/\r
\r
// Set device in game parameters\r
device = device;\r
+
+ // Set the window caption
+ device->setWindowCaption(L"Minetest [Main Menu]");
\r
// Create time getter\r
- g_timegetter = new TimeGetter(device);\r
+ g_timegetter = new IrrlichtTimeGetter(device);\r
\r
// Create game callback for menus\r
g_gamecallback = new MainGameCallback(device);\r
\r
guienv = device->getGUIEnvironment();\r
gui::IGUISkin* skin = guienv->getSkin();\r
- gui::IGUIFont* font = guienv->getFont(porting::getDataPath("fontlucida.png").c_str());\r
+ gui::IGUIFont* font = guienv->getFont(getTexturePath("fontlucida.png").c_str());\r
if(font)\r
skin->setFont(font);\r
else\r
Preload some textures and stuff\r
*/\r
\r
- init_content_inventory_texture_paths();\r
init_mapnode(); // Second call with g_texturesource set\r
init_mineral();\r
\r
*/\r
std::wstring error_message = L"";\r
\r
+ // The password entered during the menu screen,\r
+ std::string password;\r
+\r
/*\r
Menu-game loop\r
*/\r
while(device->run() && kill == false)\r
{\r
+\r
// This is used for catching disconnects\r
try\r
{\r
guienv->drawAll();\r
\r
driver->endScene();\r
+ \r
+ // On some computers framerate doesn't seem to be\r
+ // automatically limited\r
+ sleep_ms(25);\r
}\r
\r
// Break out of menu-game loop to shut down cleanly\r
}\r
\r
playername = wide_to_narrow(menudata.name);\r
+\r
+ password = translatePassword(playername, menudata.password);\r
+\r
address = wide_to_narrow(menudata.address);\r
int newport = stoi(wide_to_narrow(menudata.port));\r
if(newport != 0)\r
g_settings.set("creative_mode", itos(menudata.creative_mode));\r
g_settings.set("enable_damage", itos(menudata.enable_damage));\r
\r
- // Check for valid parameters, restart menu if invalid.\r
+ // NOTE: These are now checked server side; no need to do it\r
+ // here, so let's not do it here.\r
+ /*// Check for valid parameters, restart menu if invalid.\r
if(playername == "")\r
{\r
error_message = L"Name required.";\r
continue;\r
}\r
- \r
+ // Check that name has only valid chars\r
+ if(string_allowed(playername, PLAYERNAME_ALLOWED_CHARS)==false)\r
+ {\r
+ error_message = L"Characters allowed: "\r
+ +narrow_to_wide(PLAYERNAME_ALLOWED_CHARS);\r
+ continue;\r
+ }*/\r
+\r
// Save settings\r
g_settings.set("name", playername);\r
g_settings.set("address", address);\r
font,\r
map_dir,\r
playername,\r
+ password,\r
address,\r
port,\r
error_message\r