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<s32> rect(
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<s32> 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
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"<<std::endl;
- IMoveAction *a =
- new IMoveAction();
+ IMoveAction *a = new IMoveAction();
a->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;
int *active_menu_count);
~GUIInventoryMenu();
+ void removeChildren();
/*
Remove and re-add (or reposition) stuff
*/
{\r
core::rect<s32> rect(0, 0, 180, 220);\r
rect = rect + v2s32(size.X/2 - 90 - rect.getWidth(), size.Y/2-rect.getHeight()/2);\r
+ \r
+ v2u32 max_texture_size;\r
+ {\r
+ video::IVideoDriver* driver = Environment->getVideoDriver();\r
+ max_texture_size = driver->getMaxTextureSize();\r
+ }\r
+\r
wchar_t text[200];\r
swprintf(text, 200,\r
L"Minetest-c55\n"\r
- L"SER_FMT_VER_HIGHEST=%i",\r
- (int)SER_FMT_VER_HIGHEST\r
+ L"SER_FMT_VER_HIGHEST=%i\n"\r
+ L"max_texture_size=\n(%i,%i)\n",\r
+ (int)SER_FMT_VER_HIGHEST,\r
+ max_texture_size.X,\r
+ max_texture_size.Y\r
);\r
\r
Environment->addStaticText(text, rect, false, true, this, 259);\r
#include "irrlichtwrapper.h"
+#include "constants.h"
IrrlichtWrapper::IrrlichtWrapper(IrrlichtDevice *device)
{
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<s32>(0,0), other->getSize());*/
+ // This should work on more systems
video::IImage *otherimage = driver->createImage(
- other, core::position2d<s32>(0,0), other->getSize());
+ other, core::position2d<s32>(0,0),
+ v2u32(16, CRACK_ANIMATION_LENGTH * 16));
assert(otherimage);
Doing now:\r
======================================================================\r
\r
-TODO: Tool capability table: Which materials, at what speed, how much\r
- wearing\r
-TODO: Transferring of the table from server to client\r
+TODO: When server sees that client is removing an inexistent block or\r
+ adding a block to an existent position, resend the MapBlock.\r
\r
======================================================================\r
\r
&g_active_menu_count,\r
L"Asd");\r
menu->drop();*/\r
- \r
+ \r
// Launch pause menu\r
- /*(new GUIPauseMenu(guienv, guiroot, -1, g_device,\r
- &g_active_menu_count))->drop();*/\r
+ (new GUIPauseMenu(guienv, guiroot, -1, g_device,\r
+ &g_active_menu_count))->drop();\r
\r
// First line of debug text\r
gui::IGUIStaticText *guitext = guienv->addStaticText(\r
while(client.getChatMessage(message))\r
{\r
chat_lines.push_back(ChatLine(message));\r
- if(chat_lines.size() > 5)\r
+ /*if(chat_lines.size() > 6)\r
{\r
core::list<ChatLine>::Iterator\r
i = chat_lines.begin();\r
chat_lines.erase(i);\r
- }\r
+ }*/\r
}\r
// Append them to form the whole static text and throw\r
// it to the gui element\r
std::wstring whole;\r
+ // This will correspond to the line number counted from\r
+ // top to bottom, from size-1 to 0\r
+ s16 line_number = chat_lines.size();\r
+ // Count of messages to be removed from the top\r
u16 to_be_removed_count = 0;\r
for(core::list<ChatLine>::Iterator\r
i = chat_lines.begin();\r
i != chat_lines.end(); i++)\r
{\r
+ // After this, line number is valid for this loop\r
+ line_number--;\r
+ // Increment age\r
(*i).age += dtime;\r
- if((*i).age > 300.0)\r
+ /*\r
+ This results in a maximum age of 60*6 to the\r
+ lowermost line and a maximum of 6 lines\r
+ */\r
+ float allowed_age = (6-line_number) * 60.0;\r
+\r
+ if((*i).age > allowed_age)\r
{\r
to_be_removed_count++;\r
continue;\r
#include "voxel.h"
#include "porting.h"
+#if 0
MapBlockPointerCache::MapBlockPointerCache(Map *map)
{
m_map = map;
m_blocks[p] = b;
return b;
}
+#endif
/*
Map
// 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; i<ued*ued*ued; i++)
{
underground_emptiness[i] = ((rand() % 5) == 0);
}
-#if 1
/*
This is a messy hack to sort the emptiness a bit
*/
+ // Iterator through a few times
for(s32 j=0; j<2; j++)
for(s32 y0=0; y0<ued; y0++)
for(s32 z0=0; z0<ued; z0++)
/*v3s16(0,1,0), // top
v3s16(0,-1,0), // bottom*/
};
+
for(s32 i=0; i<4; i++)
{
v3s16 p1 = p0 + dirs[i];
}
}
#endif
+
+ /*
+ Create dungeon making table
+ */
+ const s32 ued = MAP_BLOCKSIZE;
+ bool underground_emptiness[ued*ued*ued];
+ for(s32 i=0; i<ued*ued*ued; i++)
+ {
+ underground_emptiness[i] = 0;
+ }
+ // Generate dungeons
+ {
+ /*
+ Initialize orp and ors. Try to find if some neighboring
+ MapBlock has a tunnel ended in its side
+ */
+
+ v3f orp;
+ s16 ors;
+
+ // Check z-
+ try
+ {
+ s16 z = -1;
+ for(s16 y=0; y<ued; y++)
+ for(s16 x=0; x<ued; x++)
+ {
+ v3s16 ap = v3s16(x,y,z) + block->getPosRelative();
+ 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; y<ued; y++)
+ for(s16 x=0; x<ued; x++)
+ {
+ v3s16 ap = v3s16(x,y,z) + block->getPosRelative();
+ 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; y<ued; y++)
+ for(s16 z=0; z<ued; z++)
+ {
+ v3s16 ap = v3s16(x,y,z) + block->getPosRelative();
+ 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; y<ued; y++)
+ for(s16 z=0; z<ued; z++)
+ {
+ v3s16 ap = v3s16(x,y,z) + block->getPosRelative();
+ 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
class Map;
+#if 0
/*
A cache for short-term fast access to map data
u32 m_from_cache_count;
u32 m_from_map_count;
};
+#endif
class CacheLock
{
}
// virtual from NodeContainer
+ // throws InvalidPositionException if not found
MapNode getNode(v3s16 p)
{
v3s16 blockpos = getNodeBlockPos(p);
}
// virtual from NodeContainer
+ // throws InvalidPositionException if not found
void setNode(v3s16 p, MapNode & n)
{
v3s16 blockpos = getNodeBlockPos(p);
}
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"
<<std::endl;
return;
- }
+ }*/
// Strip command and create a stream
std::string datastring((char*)&data[2], datasize-2);
dstream<<"TOSERVER_INVENTORY_ACTION: data="<<datastring<<std::endl;
if(a != NULL)
{
/*
- Handle craftresult specially
+ Handle craftresult specially if not in creative mode
*/
bool disable_action = false;
- if(a->getType() == IACTION_MOVE)
+ if(a->getType() == IACTION_MOVE
+ && g_settings.getBool("creative_mode") == false)
{
IMoveAction *ma = (IMoveAction*)a;
// Don't allow moving anything to craftresult
message += (wchar_t)readU16(buf);
}
- dstream<<"CHAT: "<<wide_to_narrow(message)<<std::endl;
-
// Get player name of this client
std::wstring name = narrow_to_wide(player->getName());
std::wstring line = std::wstring(L"<")+name+L"> "+message;
+ dstream<<"CHAT: "<<wide_to_narrow(line)<<std::endl;
+
/*
Send the message to all other clients
*/
/*
Calculate crafting stuff
*/
-
- InventoryList *clist = player->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;
- // Stick
- if(!found)
- {
- ItemSpec specs[9];
- specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
- if(checkItemCombination(items, specs))
+ // Wood
+ if(!found)
{
- rlist->addItem(new CraftItem("Stick", 4));
- found = true;
+ ItemSpec specs[9];
+ specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_TREE);
+ if(checkItemCombination(items, specs))
+ {
+ rlist->addItem(new MaterialItem(CONTENT_WOOD, 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))
+ // Stick
+ if(!found)
{
- rlist->addItem(new MapBlockObjectItem("Sign"));
- found = true;
+ ItemSpec specs[9];
+ specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
+ if(checkItemCombination(items, specs))
+ {
+ rlist->addItem(new CraftItem("Stick", 4));
+ 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))
+ // Sign
+ if(!found)
{
- rlist->addItem(new MaterialItem(CONTENT_TORCH, 4));
- found = true;
+ 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;
+ }
}
- }
- // 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))
+ // Torch
+ if(!found)
{
- rlist->addItem(new ToolItem("WPick", 0));
- found = true;
+ 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;
+ }
}
- }
- // 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))
+ // Wooden pick
+ if(!found)
{
- rlist->addItem(new ToolItem("STPick", 0));
- found = true;
+ 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;
+ }
}
- }
- // 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))
+ // Stone pick
+ if(!found)
{
- rlist->addItem(new ToolItem("MesePick", 0));
- found = true;
+ 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
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; i<USEFUL_CONTENT_COUNT; i++)
{
// Skip some materials
- if(i == CONTENT_OCEAN)
+ if(i == CONTENT_OCEAN || i == CONTENT_TORCH)
continue;
InventoryItem *item = new MaterialItem(i, 1);
void* r = player->inventory.addItem("main", item);
assert(r == NULL);
}
- /*// Rat
- {
- InventoryItem *item = new MapBlockObjectItem("Rat");
- bool r = player->inventory.addItem("main", item);
- assert(r == true);
- }*/
}
else
{
);
}
+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();