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
+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: Background music based on cellular automata?\r
http://www.earslap.com/projectslab/otomata\r
\r
-Storyline:\r
-----------\r
-NOTE: If you read the text below, PLEASE DON'T TELL ANYTHING ABOUT IT TO\r
-ANYONE, EVEN OF THE EXISTENCE OF IT. I WILL BE VERY DISAPPOINTED IF I SEE\r
-PEOPLE ON THE INTERNET TALKING ABOUT THIS AND IT WILL TAKE AT LEAST HALF\r
-OF MY MOTIVATION AWAY.\r
-\r
-At the beginning, there is a sky city (like in CT), in wich is a library\r
-(The Important Library), a part of which explodes. Unfortunately the\r
-magical Important Book in the library gets thrown out in the wind and flies\r
-far away to the dangerous Low Lands. The book is shown to glow in blue when\r
-flying in the wind in some animation, when the wind flies it to the\r
-horizon. It is early morning and quicky sunrise takes the place of the blue\r
-glow. This marks the direction where the book is.\r
-\r
-The rulers of the sky city choose to let some brave young men go and start\r
-a mission to get the book back. The rulers still have some magic so they\r
-can let them fall onto the ground without damage, but not further. When a\r
-new player spawns, he will just be an another missioner.\r
-\r
-The Low Lands are a very dangerous and a tough place to be in, but\r
-immediately underneath the sky city there is fairly peaceful, but sometimes\r
-dangerous creatures come there too, especially at night.\r
-\r
-The far ancestors of the highlanders lived in the lowlands, but then they\r
-learned magic and went to live in the sky. They have really no idea and no\r
-tools to survive in the lowlands. One guy is known to have dropped down to\r
-the lowlands a long time ago, but it is not known if he survived.\r
-\r
-The missioners will have to find out how to survive in the lowlands by\r
-finding materials and crafting tools and weapons and armor and interesting\r
-items. As they build up their capabilities, they can go and explore the\r
-lowlands further.\r
-\r
-The main flying direction of the book is known from the beginning. The book\r
-will have ended up in anywhere, but quite far in any case. A few or ten\r
-kilometers probably.\r
-\r
-The book might just lie on the ground but usually some evil castle lord\r
-will have hidden it in his castle. There are fairly many peaceful people\r
-in the lowlands, and the missioners can talk to them. They will sometimes\r
-tell some rumours of the book. "The Important Book? One guy going by told\r
-me it was seen falling from the highlands, probably towards the town of\r
-Clystaleon." (eh, just a random name I just made up)\r
-\r
-The map would of course be generated randomly, with some small towns and\r
-roads. Roads will occasionally have some road signs.\r
-\r
-But of course there will be monsters, especially at night. At the location\r
-of the book, there will usually be very little chance to survive without\r
-diamond armor and weapons, at least when the book has been stored by the\r
-evil castle lord. Useful rare minerals and items will be found only in\r
-areas of dangerous monsters.\r
-\r
-There is a blue glow coming from the book, which is a blue circle with a\r
-radius of 30m, and which is seen at a distance of 50 to 100m.\r
-\r
-When found, the book has to be transported back to beneath the sky city.\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
+ - 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
Gaming ideas:\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
\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
-\r
-SUGG: Simple light color information to air\r
-\r
-TODO: Block mesh generator to tile properly on smooth lighting\r
+TODO: Further investigate the use of GPU lighting in addition to the\r
+ current one\r
\r
Configuration:\r
--------------\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
\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
+TODO: Map saving should be done by EmergeThread\r
+\r
+SUGG: Map unloading based on sector reference is not very good, it keeps\r
+ unnecessary stuff in memory. I guess. Investigate this.\r
+\r
+TODO: When block is placed and it has param_type==CPT_FACEDIR_SIMPLE, set\r
+ the direction accordingly.\r
+\r
+Environment:\r
+------------\r
+\r
+TODO: 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
+ TODO: Make proper hooks in here\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
+ TODO: Make proper hooks in here\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
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: 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
-SUGG: Server-side objects could be moved based on nodes to enable very\r
- lightweight operation and simple AI\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
+Mapgen v2 (the current one):\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
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
+* Consider not updating this one and make a good mainly block-based\r
+ generator\r
+\r
+SUGG: Make two "modified states", one that forces the block to be saved at\r
+ the next save event, and one that makes the block to be saved at exit\r
+ time.\r
+\r
+TODO: Add a not_fully_generated flag to MapBlock, which would be set for\r
+ blocks that contain eg. trees from neighboring generations but haven't\r
+ been generated itself. This is required for the future generator.\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
+- Make sure server handles removing grass when a block is placed (etc)\r
+ - The client should not do it by itself\r
+- Block cube placement around player's head\r
+- Protocol version field\r
+- Consider getting some textures from cisoun's texture pack\r
+ - Ask from Cisoun\r
+- Make sure the fence implementation and data format is good\r
+ - Think about using same bits for material for fences and doors, for\r
+ example\r
+- Finish the ActiveBlockModifier stuff and use it for something\r
+- Move mineral to param2, increment map serialization version, add conversion\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
======================================================================\r
\r
//#include "tile.h"\r
#include "materials.h"\r
#include "game.h"\r
+#include "keycode.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
/*\r
Parse command line\r
*/\r
disable_stderr = true;\r
#endif\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
// Initialize debug streams\r
- debugstreams_init(disable_stderr, DEBUGFILE);\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
- porting::signal_handler_init();\r
- bool &kill = *porting::signal_handler_killstatus();\r
- \r
- porting::initializePaths();\r
// Create user data directory\r
fs::CreateDir(porting::path_userdata);\r
\r
- // C-style stuff initialization\r
- initializeMaterialProperties();\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
device = device;\r
\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