diff --git a/src/guiInventoryMenu.cpp b/src/guiInventoryMenu.cpp index a1f7d02d0..d7af0a0b9 100644 --- a/src/guiInventoryMenu.cpp +++ b/src/guiInventoryMenu.cpp @@ -93,19 +93,35 @@ GUIInventoryMenu::GUIInventoryMenu(gui::IGUIEnvironment* env, GUIInventoryMenu::~GUIInventoryMenu() { + removeChildren(); + if(m_selected_item) delete m_selected_item; } +void GUIInventoryMenu::removeChildren() +{ + { + gui::IGUIElement *e = getElementFromId(256); + if(e != NULL) + e->remove(); + } +} + void GUIInventoryMenu::regenerateGui(v2u32 screensize) { + // Remove children + removeChildren(); + padding = v2s32(24,24); spacing = v2s32(60,56); imgsize = v2s32(48,48); + s32 helptext_h = 15; + v2s32 size( padding.X*2+spacing.X*(8-1)+imgsize.X, - padding.Y*2+spacing.Y*(7-1)+imgsize.Y + padding.Y*2+spacing.Y*(7-1)+imgsize.Y + helptext_h ); core::rect rect( @@ -127,6 +143,16 @@ void GUIInventoryMenu::regenerateGui(v2u32 screensize) basepos + v2s32(spacing.X*3, spacing.Y*0), v2s32(3, 3))); m_draw_positions.push_back(ListDrawSpec("craftresult", basepos + v2s32(spacing.X*7, spacing.Y*1), v2s32(1, 1))); + + // Add children + { + core::rect rect(0, 0, size.X-padding.X*2, helptext_h); + rect = rect + v2s32(size.X/2 - rect.getWidth()/2, + size.Y-rect.getHeight()-15); + const wchar_t *text = + L"Left click: Move all items, Right click: Move single item"; + Environment->addStaticText(text, rect, false, true, this, 256); + } } GUIInventoryMenu::ItemSpec GUIInventoryMenu::getItemAtPos(v2s32 p) const @@ -244,22 +270,25 @@ bool GUIInventoryMenu::OnEvent(const SEvent& event) m_inventory->getList(m_selected_item->listname); InventoryList *list_to = m_inventory->getList(s.listname); + // Indicates whether source slot completely empties + bool source_empties = false; if(list_from && list_to && list_from->getItem(m_selected_item->i) != NULL) { dstream<<"Queueing IACTION_MOVE"<count = right ? 1 : 0; a->from_name = m_selected_item->listname; a->from_i = m_selected_item->i; a->to_name = s.listname; a->to_i = s.i; m_actions->push_back(a); + + if(list_from->getItem(m_selected_item->i)->getCount()==1) + source_empties = true; } - bool source_empties = false; - if(list_from && list_from->getItem(m_selected_item->i)->getCount()==1) - source_empties = true; + // Remove selection if target was left-clicked or source + // slot was emptied if(right == false || source_empties) { delete m_selected_item; diff --git a/src/guiInventoryMenu.h b/src/guiInventoryMenu.h index b6766484e..82e7ee89d 100644 --- a/src/guiInventoryMenu.h +++ b/src/guiInventoryMenu.h @@ -77,6 +77,7 @@ public: int *active_menu_count); ~GUIInventoryMenu(); + void removeChildren(); /* Remove and re-add (or reposition) stuff */ diff --git a/src/guiPauseMenu.cpp b/src/guiPauseMenu.cpp index 10d272b35..9ff21a437 100644 --- a/src/guiPauseMenu.cpp +++ b/src/guiPauseMenu.cpp @@ -114,11 +114,21 @@ void GUIPauseMenu::regenerateGui(v2u32 screensize) { core::rect rect(0, 0, 180, 220); rect = rect + v2s32(size.X/2 - 90 - rect.getWidth(), size.Y/2-rect.getHeight()/2); + + v2u32 max_texture_size; + { + video::IVideoDriver* driver = Environment->getVideoDriver(); + max_texture_size = driver->getMaxTextureSize(); + } + wchar_t text[200]; swprintf(text, 200, L"Minetest-c55\n" - L"SER_FMT_VER_HIGHEST=%i", - (int)SER_FMT_VER_HIGHEST + L"SER_FMT_VER_HIGHEST=%i\n" + L"max_texture_size=\n(%i,%i)\n", + (int)SER_FMT_VER_HIGHEST, + max_texture_size.X, + max_texture_size.Y ); Environment->addStaticText(text, rect, false, true, this, 259); diff --git a/src/irrlichtwrapper.cpp b/src/irrlichtwrapper.cpp index 30de6846c..81cd7f9f0 100644 --- a/src/irrlichtwrapper.cpp +++ b/src/irrlichtwrapper.cpp @@ -1,4 +1,5 @@ #include "irrlichtwrapper.h" +#include "constants.h" IrrlichtWrapper::IrrlichtWrapper(IrrlichtDevice *device) { @@ -119,10 +120,17 @@ video::ITexture * CrackTextureMod::make(video::ITexture *original, assert(baseimage); video::ITexture *other = driver->getTexture("../data/crack.png"); + // We have to get the whole texture because getting a smaller area // messes the whole thing. It is probably a bug in Irrlicht. + // NOTE: This doesn't work probably because some systems scale + // the image to fit a texture or something... + /*video::IImage *otherimage = driver->createImage( + other, core::position2d(0,0), other->getSize());*/ + // This should work on more systems video::IImage *otherimage = driver->createImage( - other, core::position2d(0,0), other->getSize()); + other, core::position2d(0,0), + v2u32(16, CRACK_ANIMATION_LENGTH * 16)); assert(otherimage); diff --git a/src/main.cpp b/src/main.cpp index 47840eae8..0cb16c033 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -184,9 +184,8 @@ TODO: There has to be some better way to handle static objects than to Doing now: ====================================================================== -TODO: Tool capability table: Which materials, at what speed, how much - wearing -TODO: Transferring of the table from server to client +TODO: When server sees that client is removing an inexistent block or + adding a block to an existent position, resend the MapBlock. ====================================================================== @@ -1545,10 +1544,10 @@ int main(int argc, char *argv[]) &g_active_menu_count, L"Asd"); menu->drop();*/ - + // Launch pause menu - /*(new GUIPauseMenu(guienv, guiroot, -1, g_device, - &g_active_menu_count))->drop();*/ + (new GUIPauseMenu(guienv, guiroot, -1, g_device, + &g_active_menu_count))->drop(); // First line of debug text gui::IGUIStaticText *guitext = guienv->addStaticText( @@ -2349,23 +2348,36 @@ int main(int argc, char *argv[]) while(client.getChatMessage(message)) { chat_lines.push_back(ChatLine(message)); - if(chat_lines.size() > 5) + /*if(chat_lines.size() > 6) { core::list::Iterator i = chat_lines.begin(); chat_lines.erase(i); - } + }*/ } // Append them to form the whole static text and throw // it to the gui element std::wstring whole; + // This will correspond to the line number counted from + // top to bottom, from size-1 to 0 + s16 line_number = chat_lines.size(); + // Count of messages to be removed from the top u16 to_be_removed_count = 0; for(core::list::Iterator i = chat_lines.begin(); i != chat_lines.end(); i++) { + // After this, line number is valid for this loop + line_number--; + // Increment age (*i).age += dtime; - if((*i).age > 300.0) + /* + This results in a maximum age of 60*6 to the + lowermost line and a maximum of 6 lines + */ + float allowed_age = (6-line_number) * 60.0; + + if((*i).age > allowed_age) { to_be_removed_count++; continue; diff --git a/src/map.cpp b/src/map.cpp index fe94d6e97..9a23863d5 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "voxel.h" #include "porting.h" +#if 0 MapBlockPointerCache::MapBlockPointerCache(Map *map) { m_map = map; @@ -62,6 +63,7 @@ MapBlock * MapBlockPointerCache::getBlockNoCreate(v3s16 p) m_blocks[p] = b; return b; } +#endif /* Map @@ -1727,24 +1729,25 @@ MapBlock * ServerMap::emergeBlock( // Allocate the block to be a proper one. block->unDummify(); } - - // Randomize a bit. This makes dungeons. - /*bool low_block_is_empty = false; - if(rand() % 4 == 0) - low_block_is_empty = true;*/ - const s32 ued = 4; - //const s32 ued = 8; - bool underground_emptiness[ued*ued*ued]; +#if 0 + /* + Initialize dungeon making by creating a random table + */ + const s32 ued_max = 5; + const s32 ued_min = 3; + bool underground_emptiness[ued_max*ued_max*ued_max]; + s32 ued = (rand()%(ued_max-ued_min+1))+1; + //s32 ued = ued_max; for(s32 i=0; igetPosRelative(); + if(getNode(ap).d == CONTENT_AIR) + { + orp = v3f(x+1,y+1,0); + ors = 4; + } + } + } + catch(InvalidPositionException &e){} + + // Check z+ + try + { + s16 z = ued; + for(s16 y=0; ygetPosRelative(); + if(getNode(ap).d == CONTENT_AIR) + { + orp = v3f(x+1,y+1,ued-1); + ors = 4; + } + } + } + catch(InvalidPositionException &e){} + + // Check x- + try + { + s16 x = -1; + for(s16 y=0; ygetPosRelative(); + if(getNode(ap).d == CONTENT_AIR) + { + orp = v3f(0,y+1,z+1); + ors = 4; + } + } + } + catch(InvalidPositionException &e){} + + // Check x+ + try + { + s16 x = ued; + for(s16 y=0; ygetPosRelative(); + if(getNode(ap).d == CONTENT_AIR) + { + orp = v3f(ued-1,y+1,z+1); + ors = 4; + } + } + } + catch(InvalidPositionException &e){} + + /* + Generate some tunnel starting from orp and ors + */ + for(u16 i=0; i<3; i++) + { + v3f rp( + (float)(rand()%(ued-1))+0.5, + (float)(rand()%(ued-1))+0.5, + (float)(rand()%(ued-1))+0.5 + ); + s16 min_d = 0; + s16 max_d = 4; + s16 rs = (rand()%(max_d-min_d+1))+min_d; + + v3f vec = rp - orp; + + for(float f=0; f<1.0; f+=0.04) + { + v3f fp = orp + vec * f; + v3s16 cp(fp.X, fp.Y, fp.Z); + s16 d0 = -rs/2; + s16 d1 = d0 + rs - 1; + for(s16 z0=d0; z0<=d1; z0++) + { + s16 si = rs - abs(z0); + for(s16 x0=-si; x0<=si-1; x0++) + { + s16 si2 = rs - abs(x0); + for(s16 y0=-si2+1; y0<=si2-1; y0++) + { + s16 z = cp.Z + z0; + s16 y = cp.Y + y0; + s16 x = cp.X + x0; + v3s16 p(x,y,z); + if(isInArea(p, ued) == false) + continue; + underground_emptiness[ued*ued*z + ued*y + x] = 1; + } + } + } + } + + orp = rp; + ors = rs; + } + } // This is the basic material of what the visible flat ground // will consist of diff --git a/src/map.h b/src/map.h index 2a3fa5061..3c3fe9daf 100644 --- a/src/map.h +++ b/src/map.h @@ -43,6 +43,7 @@ with this program; if not, write to the Free Software Foundation, Inc., class Map; +#if 0 /* A cache for short-term fast access to map data @@ -108,6 +109,7 @@ private: u32 m_from_cache_count; u32 m_from_map_count; }; +#endif class CacheLock { @@ -303,6 +305,7 @@ public: } // virtual from NodeContainer + // throws InvalidPositionException if not found MapNode getNode(v3s16 p) { v3s16 blockpos = getNodeBlockPos(p); @@ -313,6 +316,7 @@ public: } // virtual from NodeContainer + // throws InvalidPositionException if not found void setNode(v3s16 p, MapNode & n) { v3s16 blockpos = getNodeBlockPos(p); diff --git a/src/server.cpp b/src/server.cpp index c8f9be00e..cbe2b932f 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -2215,13 +2215,13 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) } else if(command == TOSERVER_INVENTORY_ACTION) { - // Ignore inventory changes if in creative mode + /*// Ignore inventory changes if in creative mode if(g_settings.getBool("creative_mode") == true) { dstream<<"TOSERVER_INVENTORY_ACTION: ignoring in creative mode" <getName()); std::wstring line = std::wstring(L"<")+name+L"> "+message; + dstream<<"CHAT: "<inventory.getList("craft"); - InventoryList *rlist = player->inventory.getList("craftresult"); - if(rlist) + if(g_settings.getBool("creative_mode") == false) { - rlist->clearItems(); - } - if(clist && rlist) - { - InventoryItem *items[9]; - for(u16 i=0; i<9; i++) + InventoryList *clist = player->inventory.getList("craft"); + InventoryList *rlist = player->inventory.getList("craftresult"); + if(rlist) { - items[i] = clist->getItem(i); + rlist->clearItems(); } - - bool found = false; - - // Wood - if(!found) + if(clist && rlist) { - ItemSpec specs[9]; - specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_TREE); - if(checkItemCombination(items, specs)) + InventoryItem *items[9]; + for(u16 i=0; i<9; i++) { - rlist->addItem(new MaterialItem(CONTENT_WOOD, 4)); - found = true; + items[i] = clist->getItem(i); + } + + bool found = false; + + // Wood + if(!found) + { + ItemSpec specs[9]; + specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_TREE); + if(checkItemCombination(items, specs)) + { + rlist->addItem(new MaterialItem(CONTENT_WOOD, 4)); + found = true; + } + } + + // Stick + if(!found) + { + ItemSpec specs[9]; + specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD); + if(checkItemCombination(items, specs)) + { + rlist->addItem(new CraftItem("Stick", 4)); + found = true; + } + } + + // Sign + if(!found) + { + ItemSpec specs[9]; + specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD); + specs[1] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD); + specs[2] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD); + specs[3] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD); + specs[4] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD); + specs[5] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD); + specs[7] = ItemSpec(ITEM_CRAFT, "Stick"); + if(checkItemCombination(items, specs)) + { + rlist->addItem(new MapBlockObjectItem("Sign")); + found = true; + } + } + + // Torch + if(!found) + { + ItemSpec specs[9]; + specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_COALSTONE); + specs[3] = ItemSpec(ITEM_CRAFT, "Stick"); + if(checkItemCombination(items, specs)) + { + rlist->addItem(new MaterialItem(CONTENT_TORCH, 4)); + found = true; + } + } + + // Wooden pick + if(!found) + { + ItemSpec specs[9]; + specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD); + specs[1] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD); + specs[2] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD); + specs[4] = ItemSpec(ITEM_CRAFT, "Stick"); + specs[7] = ItemSpec(ITEM_CRAFT, "Stick"); + if(checkItemCombination(items, specs)) + { + rlist->addItem(new ToolItem("WPick", 0)); + found = true; + } + } + + // Stone pick + if(!found) + { + ItemSpec specs[9]; + specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_STONE); + specs[1] = ItemSpec(ITEM_MATERIAL, CONTENT_STONE); + specs[2] = ItemSpec(ITEM_MATERIAL, CONTENT_STONE); + specs[4] = ItemSpec(ITEM_CRAFT, "Stick"); + specs[7] = ItemSpec(ITEM_CRAFT, "Stick"); + if(checkItemCombination(items, specs)) + { + rlist->addItem(new ToolItem("STPick", 0)); + found = true; + } + } + + // Mese pick + if(!found) + { + ItemSpec specs[9]; + specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_MESE); + specs[1] = ItemSpec(ITEM_MATERIAL, CONTENT_MESE); + specs[2] = ItemSpec(ITEM_MATERIAL, CONTENT_MESE); + specs[4] = ItemSpec(ITEM_CRAFT, "Stick"); + specs[7] = ItemSpec(ITEM_CRAFT, "Stick"); + if(checkItemCombination(items, specs)) + { + rlist->addItem(new ToolItem("MesePick", 0)); + found = true; + } } } - - // Stick - if(!found) - { - ItemSpec specs[9]; - specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD); - if(checkItemCombination(items, specs)) - { - rlist->addItem(new CraftItem("Stick", 4)); - found = true; - } - } - - // Sign - if(!found) - { - ItemSpec specs[9]; - specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD); - specs[1] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD); - specs[2] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD); - specs[3] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD); - specs[4] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD); - specs[5] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD); - specs[7] = ItemSpec(ITEM_CRAFT, "Stick"); - if(checkItemCombination(items, specs)) - { - rlist->addItem(new MapBlockObjectItem("Sign")); - found = true; - } - } - - // Torch - if(!found) - { - ItemSpec specs[9]; - specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_COALSTONE); - specs[3] = ItemSpec(ITEM_CRAFT, "Stick"); - if(checkItemCombination(items, specs)) - { - rlist->addItem(new MaterialItem(CONTENT_TORCH, 4)); - found = true; - } - } - - // Wooden pick - if(!found) - { - ItemSpec specs[9]; - specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD); - specs[1] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD); - specs[2] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD); - specs[4] = ItemSpec(ITEM_CRAFT, "Stick"); - specs[7] = ItemSpec(ITEM_CRAFT, "Stick"); - if(checkItemCombination(items, specs)) - { - rlist->addItem(new ToolItem("WPick", 0)); - found = true; - } - } - - // Stone pick - if(!found) - { - ItemSpec specs[9]; - specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_STONE); - specs[1] = ItemSpec(ITEM_MATERIAL, CONTENT_STONE); - specs[2] = ItemSpec(ITEM_MATERIAL, CONTENT_STONE); - specs[4] = ItemSpec(ITEM_CRAFT, "Stick"); - specs[7] = ItemSpec(ITEM_CRAFT, "Stick"); - if(checkItemCombination(items, specs)) - { - rlist->addItem(new ToolItem("STPick", 0)); - found = true; - } - } - - // Mese pick - if(!found) - { - ItemSpec specs[9]; - specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_MESE); - specs[1] = ItemSpec(ITEM_MATERIAL, CONTENT_MESE); - specs[2] = ItemSpec(ITEM_MATERIAL, CONTENT_MESE); - specs[4] = ItemSpec(ITEM_CRAFT, "Stick"); - specs[7] = ItemSpec(ITEM_CRAFT, "Stick"); - if(checkItemCombination(items, specs)) - { - rlist->addItem(new ToolItem("MesePick", 0)); - found = true; - } - } - - } + } // if creative_mode == false /* Serialize it @@ -3025,18 +3027,32 @@ void Server::handlePeerChange(PeerChange &c) if(g_settings.getBool("creative_mode")) { - // Give a good pick + // Give some good picks { - InventoryItem *item = new ToolItem("STPick", 32000); + InventoryItem *item = new ToolItem("STPick", 0); void* r = player->inventory.addItem("main", item); assert(r == NULL); } - // Give all materials + { + InventoryItem *item = new ToolItem("MesePick", 0); + void* r = player->inventory.addItem("main", item); + assert(r == NULL); + } + + /* + Give materials + */ assert(USEFUL_CONTENT_COUNT <= PLAYER_INVENTORY_SIZE); + + // add torch first + InventoryItem *item = new MaterialItem(CONTENT_TORCH, 1); + player->inventory.addItem("main", item); + + // Then others for(u16 i=0; iinventory.addItem("main", item); assert(r == NULL); } - /*// Rat - { - InventoryItem *item = new MapBlockObjectItem("Rat"); - bool r = player->inventory.addItem("main", item); - assert(r == true); - }*/ } else { diff --git a/src/utility.h b/src/utility.h index bcdcd1550..3764616d0 100644 --- a/src/utility.h +++ b/src/utility.h @@ -550,6 +550,41 @@ inline bool isInArea(v2s16 p, s16 d) ); } +inline s16 rangelim(s16 i, s16 min, s16 max) +{ + if(i < min) + return min; + if(i > max) + return max; + return i; +} + +inline s16 rangelim(s16 i, s16 max) +{ + if(i < 0) + return 0; + if(i > max) + return max; + return i; +} + +inline v3s16 arealim(v3s16 p, s16 d) +{ + if(p.X < 0) + p.X = 0; + if(p.Y < 0) + p.Y = 0; + if(p.Z < 0) + p.Z = 0; + if(p.X > d-1) + p.X = d-1; + if(p.Y > d-1) + p.Y = d-1; + if(p.Z > d-1) + p.Z = d-1; + return p; +} + inline std::wstring narrow_to_wide(const std::string& mbs) { size_t wcl = mbs.size();