Split HUD code off to hud.cpp, make into a class, extensive Lua HUD modification
authorkwolekr <kwolekr@minetest.net>
Sat, 13 Apr 2013 22:20:22 +0000 (18:20 -0400)
committerkwolekr <kwolekr@minetest.net>
Thu, 18 Apr 2013 06:19:31 +0000 (02:19 -0400)
12 files changed:
doc/lua_api.txt
src/CMakeLists.txt
src/client.cpp
src/client.h
src/game.cpp
src/hud.cpp [new file with mode: 0644]
src/hud.h [new file with mode: 0644]
src/player.h
src/scriptapi_object.cpp
src/scriptapi_object.h
src/server.cpp
src/server.h

index d4d078e27d11f2089a9ba8d724d47704c39b0532..44b2a0b632adf7bfdd8368a3848247aebe1854ae 100644 (file)
@@ -401,6 +401,43 @@ Currently supported flags:  absheight
     Also produce this same ore between the height range of -height_max and -height_min.
     Useful for having ore in sky realms without having to duplicate ore entries.
 
+HUD element types
+-------------------
+The position field is used for all element types.
+To account for differing resolutions, the position coordinates are the percentage of the screen,
+ranging in value from 0 to 1.
+The name field is not yet used, but should contain a description of what the HUD element represents.
+Below are the specific uses for fields in each type; fields not listed for that type are ignored.
+
+Note: Future revisions to the HUD API may be incompatible; the HUD API is still in the experimental stages.
+
+- image
+    Displays an image on the HUD.
+       - scale: The scale of the image, with 1 being the original texture size.
+             Only the X coordinate scale is used.
+    - text: The name of the texture that is displayed.
+- text
+    Displays text on the HUD.
+    - scale: Defines the bounding rectangle of the text.
+             A value such as {x=100, y=100} should work.
+    - text: The text to be displayed in the HUD element.
+    - number: An integer containing the RGB value of the color used to draw the text.
+              Specify 0xFFFFFF for white text, 0xFF0000 for red, and so on.
+- statbar
+    Displays a horizontal bar made up of half-images.
+    - text: The name of the texture that is used.
+    - number: The number of half-textures that are displayed.
+              If odd, will end with a vertically center-split texture.
+- inventory
+    - text: The name of the inventory list to be displayed.
+    - number: Number of items in the inventory to be displayed.
+    - item: Position of item that is selected.
+    - direction: Direction in which the inventory list is drawn.
+                 0 draws from left to right,
+                 1 draws from right to left,
+                 2 draws from top to bottom, and
+                 3 draws from bottom to top.
+
 Representations of simple things
 --------------------------------
 Position/vector:
@@ -1379,19 +1416,11 @@ Player-only: (no-op for other objects)
     modifies per-player walking speed, jump height, and gravity.
     Values default to 1 and act as offsets to the physics settings 
     in minetest.conf. nil will keep the current setting.
-- hud_add(id, hud definition)
-  ^ id is used for later reference
-  ^ If this id has already been used, it will reset its drawform
-- hud_rm(id): remove an id from the lua hud
-- hud_change(id, stat, value): change a value of a previously added element
-  ^ stat/table key: 0/position, 1/name, 2/scale, 3/text, 4/number,
-  ^ 5/item, 6/dir
-- hud_get_next_id(): get the next available id for a hud element
-- hud_lock_next_bar(right): add a non-conflicting statbar
-  ^ if right, will claim spot on right side, rather then left
-  ^ returns element id on success, false otherwise
-- hud_unlock_bar(id): remove a non-conflicting statbar
-  ^ id is the value returned by calling hud_lock_next_bar()
+- hud_add(hud definition): add a HUD element described by HUD def, returns ID number on success
+- hud_remove(id): remove the HUD element of the specified id
+- hud_change(id, stat, value): change a value of a previously added HUD element
+  ^ element stat values: position, name, scale, text, number, item, dir
+- hud_get(id): gets the HUD element definition structure of the specified ID
 
 InvRef: Reference to an inventory
 methods:
@@ -1815,20 +1844,18 @@ Detached inventory callbacks
     ^ No return value
 }
 
-HUD Definition (hud_add)
+HUD Definition (hud_add, hud_get)
 {
-    type = "I",           -- One of "I"(image), "S"(statbar),
-    ^ "T"(text), "i"(inv)
-    position = {x=0.5, y=0.5},   -- Left corner position
+    type = "image",
+    ^ type of HUD element, can be either of "image", "text", "statbar", or "inventory"
+    position = {x=0.5, y=0.5},
+    ^ Left corner position of element
     name = "<name>",
     scale = {x=2, y=2},
     text = "<text>",
-    ^ Used as texture name for statbars and images, and as list name
-    ^ for inv
     number = 2,
-    ^ Used as stat for statbar, and as # of items for inv
-    item = 3,      -- Selected item in inv. 0 -> no item selected
+    item = 3,
+    ^ Selected item in inventory.  0 for no item selected.
     dir = 0,
-    ^ dir/inv direction: 0/left-right, 1/right-left,
-    ^ 2/top-bottom, 3/bottom-top
+    ^ Direction: 0: left-right, 1: right-left, 2: top-bottom, 3: bottom-top
 }
index 62bb42b9e0448f2ad14f311e6fb992fac79f8dc1..7ddeeb02e425c85ef307e66326bf18db9e27505b 100644 (file)
@@ -327,6 +327,7 @@ set(minetest_SRCS
        particles.cpp
        clientobject.cpp
        chat.cpp
+       hud.cpp
        guiMainMenu.cpp
        guiKeyChangeMenu.cpp
        guiMessageMenu.cpp
index 1f8b9cacafb266aaafd1a9947c968a1709d1ed8b..03a710599a4af4b3c035910013e21a96bbbf407c 100644 (file)
@@ -2042,35 +2042,35 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
        }
        else if(command == TOCLIENT_HUDADD)
        {
-               std::string datastring((char*)&data[2], datasize-2);
+               std::string datastring((char *)&data[2], datasize - 2);
                std::istringstream is(datastring, std::ios_base::binary);
 
-               u32 id                = readU32(is);
-               u8 type               = readU8(is);
-               core::vector2df pos   = readV2F1000(is);
-               std::string name      = deSerializeString(is);
-               core::vector2df scale = readV2F1000(is);
-               std::string text      = deSerializeString(is);
-               u32 number            = readU32(is);
-               u32 item              = readU32(is);
-               u32 dir               = readU32(is);
+               u32 id           = readU32(is);
+               u8 type          = readU8(is);
+               v2f pos          = readV2F1000(is);
+               std::string name = deSerializeString(is);
+               v2f scale        = readV2F1000(is);
+               std::string text = deSerializeString(is);
+               u32 number       = readU32(is);
+               u32 item         = readU32(is);
+               u32 dir          = readU32(is);
 
                ClientEvent event;
                event.type = CE_HUDADD;
-               event.hudadd.id = id;
-               event.hudadd.type = type;
-               event.hudadd.pos = new v2f(pos);
-               event.hudadd.name = new std::string(name);
-               event.hudadd.scale = new v2f(scale);
-               event.hudadd.text = new std::string(text);
+               event.hudadd.id     = id;
+               event.hudadd.type   = type;
+               event.hudadd.pos    = new v2f(pos);
+               event.hudadd.name   = new std::string(name);
+               event.hudadd.scale  = new v2f(scale);
+               event.hudadd.text   = new std::string(text);
                event.hudadd.number = number;
-               event.hudadd.item = item;
-               event.hudadd.dir = dir;
+               event.hudadd.item   = item;
+               event.hudadd.dir    = dir;
                m_client_event_queue.push_back(event);
        }
        else if(command == TOCLIENT_HUDRM)
        {
-               std::string datastring((char*)&data[2], datasize-2);
+               std::string datastring((char *)&data[2], datasize - 2);
                std::istringstream is(datastring, std::ios_base::binary);
 
                u32 id = readU32(is);
@@ -2081,30 +2081,31 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
                m_client_event_queue.push_back(event);
        }
        else if(command == TOCLIENT_HUDCHANGE)
-       {
-               std::string datastring((char*)&data[2], datasize-2);
+       {       
+               std::string sdata;
+               v2f v2fdata;
+               u32 intdata = 0;
+               
+               std::string datastring((char *)&data[2], datasize - 2);
                std::istringstream is(datastring, std::ios_base::binary);
 
-               u32 id = readU32(is);
-               u8 stat = readU8(is);
-               core::vector2df v2fdata;
-               std::string sdata;
-               u32 data = 0;
-               if(stat == 0 || stat == 2) {
+               u32 id  = readU32(is);
+               u8 stat = (HudElementStat)readU8(is);
+               
+               if (stat == HUD_STAT_POS || stat == HUD_STAT_SCALE)
                        v2fdata = readV2F1000(is);
-               } else if(stat == 1 || stat == 3) {
+               else if (stat == HUD_STAT_NAME || stat == HUD_STAT_TEXT)
                        sdata = deSerializeString(is);
-               } else {
-                       data = readU32(is);
-               }
-
+               else
+                       intdata = readU32(is);
+               
                ClientEvent event;
                event.type = CE_HUDCHANGE;
-               event.hudchange.id = id;
-               event.hudchange.stat stat;
+               event.hudchange.id      = id;
+               event.hudchange.stat    = (HudElementStat)stat;
                event.hudchange.v2fdata = new v2f(v2fdata);
-               event.hudchange.sdata = new std::string(sdata);
-               event.hudchange.data data;
+               event.hudchange.sdata   = new std::string(sdata);
+               event.hudchange.data    = intdata;
                m_client_event_queue.push_back(event);
        }
        else
index 696385a9ab6b9f1f9f4e1477e3be62360ab75894..f59588680729f523b519aff24409e7ae1f530738 100644 (file)
@@ -186,8 +186,8 @@ struct ClientEvent
                        f32 camera_point_target_z;
                } deathscreen;
                struct{
-                       std::stringformspec;
-                       std::stringformname;
+                       std::string *formspec;
+                       std::string *formname;
                } show_formspec;
                struct{
                } textures_updated;
@@ -221,24 +221,24 @@ struct ClientEvent
                        u32 id;
                } delete_particlespawner;
                struct{
-                       u32          id;
-                       u8           type;
-                       v2f*         pos;
-                       std::stringname;
-                       v2f*         scale;
-                       std::stringtext;
-                       u32          number;
-                       u32          item;
-                       u32          dir;
+                       u32 id;
+                       u8 type;
+                       v2f *pos;
+                       std::string *name;
+                       v2f *scale;
+                       std::string *text;
+                       u32 number;
+                       u32 item;
+                       u32 dir;
                } hudadd;
                struct{
                        u32 id;
                } hudrm;
                struct{
                        u32 id;
-                       u8 stat;
-                       v2fv2fdata;
-                       std::stringsdata;
+                       HudElementStat stat;
+                       v2f *v2fdata;
+                       std::string *sdata;
                        u32 data;
                } hudchange;
        };
index 046b7bdbf9fc6557b56bd8fb41f8205587f97c0f..a2d94ac0a0f07e57750d17bea756a236d751a736 100644 (file)
@@ -59,6 +59,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "subgame.h"
 #include "quicktune_shortcutter.h"
 #include "clientmap.h"
+#include "hud.h"
 #include "sky.h"
 #include "sound.h"
 #if USE_SOUND
@@ -229,296 +230,6 @@ public:
        FormspecFormSource** m_game_formspec;
 };
 
-/*
-       Item draw routine
-*/
-void draw_item(video::IVideoDriver *driver, gui::IGUIFont *font, IGameDef *gamedef,
-               v2s32 upperleftpos, s32 imgsize, s32 itemcount,
-               InventoryList *mainlist, u16 selectitem, unsigned short int direction)
-               //NOTE: selectitem = 0 -> no selected; selectitem 1-based
-               //NOTE: direction: 0-> left-right, 1-> right-left, 2->top-bottom, 3->bottom-top
-{
-       s32 padding = imgsize/12;
-       s32 height = imgsize + padding*2;
-       s32 width = itemcount*(imgsize+padding*2);
-       if(direction == 2 or direction == 3){
-               width = imgsize + padding*2;
-               height = itemcount*(imgsize+padding*2);
-       }
-       s32 fullimglen = imgsize + padding*2;
-
-       // Position of upper left corner of bar
-       v2s32 pos = upperleftpos;
-
-       // Draw background color
-       /*core::rect<s32> barrect(0,0,width,height);
-       barrect += pos;
-       video::SColor bgcolor(255,128,128,128);
-       driver->draw2DRectangle(bgcolor, barrect, NULL);*/
-
-       core::rect<s32> imgrect(0,0,imgsize,imgsize);
-
-       for(s32 i=0; i<itemcount; i++)
-       {
-               const ItemStack &item = mainlist->getItem(i);
-
-               v2s32 steppos;
-               if(direction == 1){
-                       steppos = v2s32(-(padding+i*fullimglen), padding);
-               } else if(direction == 2) {
-                       steppos = v2s32(padding, padding+i*fullimglen);
-               } else if(direction == 3) {
-                       steppos = v2s32(padding, -(padding+i*fullimglen));
-               } else {
-                       steppos = v2s32(padding+i*fullimglen, padding);
-               }
-               core::rect<s32> rect = imgrect + pos
-                               + steppos;
-
-               if(selectitem == (i+1))
-               {
-                       video::SColor c_outside(255,255,0,0);
-                       //video::SColor c_outside(255,0,0,0);
-                       //video::SColor c_inside(255,192,192,192);
-                       s32 x1 = rect.UpperLeftCorner.X;
-                       s32 y1 = rect.UpperLeftCorner.Y;
-                       s32 x2 = rect.LowerRightCorner.X;
-                       s32 y2 = rect.LowerRightCorner.Y;
-                       // Black base borders
-                       driver->draw2DRectangle(c_outside,
-                                       core::rect<s32>(
-                                               v2s32(x1 - padding, y1 - padding),
-                                               v2s32(x2 + padding, y1)
-                                       ), NULL);
-                       driver->draw2DRectangle(c_outside,
-                                       core::rect<s32>(
-                                               v2s32(x1 - padding, y2),
-                                               v2s32(x2 + padding, y2 + padding)
-                                       ), NULL);
-                       driver->draw2DRectangle(c_outside,
-                                       core::rect<s32>(
-                                               v2s32(x1 - padding, y1),
-                                               v2s32(x1, y2)
-                                       ), NULL);
-                       driver->draw2DRectangle(c_outside,
-                                       core::rect<s32>(
-                                               v2s32(x2, y1),
-                                               v2s32(x2 + padding, y2)
-                                       ), NULL);
-                       /*// Light inside borders
-                       driver->draw2DRectangle(c_inside,
-                                       core::rect<s32>(
-                                               v2s32(x1 - padding/2, y1 - padding/2),
-                                               v2s32(x2 + padding/2, y1)
-                                       ), NULL);
-                       driver->draw2DRectangle(c_inside,
-                                       core::rect<s32>(
-                                               v2s32(x1 - padding/2, y2),
-                                               v2s32(x2 + padding/2, y2 + padding/2)
-                                       ), NULL);
-                       driver->draw2DRectangle(c_inside,
-                                       core::rect<s32>(
-                                               v2s32(x1 - padding/2, y1),
-                                               v2s32(x1, y2)
-                                       ), NULL);
-                       driver->draw2DRectangle(c_inside,
-                                       core::rect<s32>(
-                                               v2s32(x2, y1),
-                                               v2s32(x2 + padding/2, y2)
-                                       ), NULL);
-                       */
-               }
-
-               video::SColor bgcolor2(128,0,0,0);
-               driver->draw2DRectangle(bgcolor2, rect, NULL);
-               drawItemStack(driver, font, item, rect, NULL, gamedef);
-       }
-}
-
-/*
-       Statbar draw routine
-*/
-void draw_statbar(video::IVideoDriver *driver, gui::IGUIFont *font, IGameDef *gamedef,
-               v2s32 upperleftpos, std::string texture, s32 count)
-               //NOTE: selectitem = 0 -> no selected; selectitem 1-based
-               //NOTE: direction: 0-> left-right, 1-> right-left, 2->top-bottom, 3->bottom-top
-{
-       video::ITexture *stat_texture =
-               gamedef->getTextureSource()->getTextureRaw(texture);
-       if(stat_texture)
-       {
-               v2s32 p = upperleftpos;
-               for(s32 i=0; i<count/2; i++)
-               {
-                       core::dimension2di srcd(stat_texture->getOriginalSize());
-                       const video::SColor color(255,255,255,255);
-                       const video::SColor colors[] = {color,color,color,color};
-                       core::rect<s32> rect(0,0,srcd.Width,srcd.Height);
-                       rect += p;
-                       driver->draw2DImage(stat_texture, rect,
-                               core::rect<s32>(core::position2d<s32>(0,0), srcd),
-                               NULL, colors, true);
-                       p += v2s32(srcd.Width,0);
-               }
-               if(count % 2 == 1)
-               {
-                       core::dimension2di srcd(stat_texture->getOriginalSize());
-                       const video::SColor color(255,255,255,255);
-                       const video::SColor colors[] = {color,color,color,color};
-                       core::rect<s32> rect(0,0,srcd.Width/2,srcd.Height);
-                       rect += p;
-                       srcd.Width /= 2;
-                       driver->draw2DImage(stat_texture, rect,
-                               core::rect<s32>(core::position2d<s32>(0,0), srcd),
-                               NULL, colors, true);
-                       p += v2s32(srcd.Width*2,0);
-               }
-       }
-}
-
-/*
-       Hotbar draw routine
-*/
-void draw_hotbar(video::IVideoDriver *driver, gui::IGUIFont *font,
-               IGameDef *gamedef,
-               v2s32 centerlowerpos, s32 imgsize, s32 itemcount,
-               Inventory *inventory, s32 halfheartcount, u16 playeritem)
-{
-       InventoryList *mainlist = inventory->getList("main");
-       if(mainlist == NULL)
-       {
-               errorstream<<"draw_hotbar(): mainlist == NULL"<<std::endl;
-               return;
-       }
-#if 0
-       s32 padding = imgsize/12;
-       //s32 height = imgsize + padding*2;
-       s32 width = itemcount*(imgsize+padding*2);
-       
-       // Position of upper left corner of bar
-       v2s32 pos = centerlowerpos - v2s32(width/2, imgsize+padding*2);
-       
-       // Draw background color
-       /*core::rect<s32> barrect(0,0,width,height);
-       barrect += pos;
-       video::SColor bgcolor(255,128,128,128);
-       driver->draw2DRectangle(bgcolor, barrect, NULL);*/
-
-       core::rect<s32> imgrect(0,0,imgsize,imgsize);
-
-       for(s32 i=0; i<itemcount; i++)
-       {
-               const ItemStack &item = mainlist->getItem(i);
-               
-               core::rect<s32> rect = imgrect + pos
-                               + v2s32(padding+i*(imgsize+padding*2), padding);
-               
-               if(playeritem == i)
-               {
-                       video::SColor c_outside(255,255,0,0);
-                       //video::SColor c_outside(255,0,0,0);
-                       //video::SColor c_inside(255,192,192,192);
-                       s32 x1 = rect.UpperLeftCorner.X;
-                       s32 y1 = rect.UpperLeftCorner.Y;
-                       s32 x2 = rect.LowerRightCorner.X;
-                       s32 y2 = rect.LowerRightCorner.Y;
-                       // Black base borders
-                       driver->draw2DRectangle(c_outside,
-                                       core::rect<s32>(
-                                               v2s32(x1 - padding, y1 - padding),
-                                               v2s32(x2 + padding, y1)
-                                       ), NULL);
-                       driver->draw2DRectangle(c_outside,
-                                       core::rect<s32>(
-                                               v2s32(x1 - padding, y2),
-                                               v2s32(x2 + padding, y2 + padding)
-                                       ), NULL);
-                       driver->draw2DRectangle(c_outside,
-                                       core::rect<s32>(
-                                               v2s32(x1 - padding, y1),
-                                               v2s32(x1, y2)
-                                       ), NULL);
-                       driver->draw2DRectangle(c_outside,
-                                       core::rect<s32>(
-                                               v2s32(x2, y1),
-                                               v2s32(x2 + padding, y2)
-                                       ), NULL);
-                       /*// Light inside borders
-                       driver->draw2DRectangle(c_inside,
-                                       core::rect<s32>(
-                                               v2s32(x1 - padding/2, y1 - padding/2),
-                                               v2s32(x2 + padding/2, y1)
-                                       ), NULL);
-                       driver->draw2DRectangle(c_inside,
-                                       core::rect<s32>(
-                                               v2s32(x1 - padding/2, y2),
-                                               v2s32(x2 + padding/2, y2 + padding/2)
-                                       ), NULL);
-                       driver->draw2DRectangle(c_inside,
-                                       core::rect<s32>(
-                                               v2s32(x1 - padding/2, y1),
-                                               v2s32(x1, y2)
-                                       ), NULL);
-                       driver->draw2DRectangle(c_inside,
-                                       core::rect<s32>(
-                                               v2s32(x2, y1),
-                                               v2s32(x2 + padding/2, y2)
-                                       ), NULL);
-                       */
-               }
-
-               video::SColor bgcolor2(128,0,0,0);
-               driver->draw2DRectangle(bgcolor2, rect, NULL);
-               drawItemStack(driver, font, item, rect, NULL, gamedef);
-       }
-#else
-       s32 padding = imgsize/12;
-       s32 width = itemcount*(imgsize+padding*2);
-       v2s32 pos = centerlowerpos - v2s32(width/2, imgsize+padding*2);
-       draw_item(driver, font, gamedef, pos, imgsize, itemcount,
-                               mainlist, playeritem + 1, 0);
-#endif
-#if 0
-       /*
-               Draw hearts
-       */
-       video::ITexture *heart_texture =
-               gamedef->getTextureSource()->getTextureRaw("heart.png");
-       if(heart_texture)
-       {
-               v2s32 p = pos + v2s32(0, -20);
-               for(s32 i=0; i<halfheartcount/2; i++)
-               {
-                       const video::SColor color(255,255,255,255);
-                       const video::SColor colors[] = {color,color,color,color};
-                       core::rect<s32> rect(0,0,16,16);
-                       rect += p;
-                       driver->draw2DImage(heart_texture, rect,
-                               core::rect<s32>(core::position2d<s32>(0,0),
-                               core::dimension2di(heart_texture->getOriginalSize())),
-                               NULL, colors, true);
-                       p += v2s32(16,0);
-               }
-               if(halfheartcount % 2 == 1)
-               {
-                       const video::SColor color(255,255,255,255);
-                       const video::SColor colors[] = {color,color,color,color};
-                       core::rect<s32> rect(0,0,16/2,16);
-                       rect += p;
-                       core::dimension2di srcd(heart_texture->getOriginalSize());
-                       srcd.Width /= 2;
-                       driver->draw2DImage(heart_texture, rect,
-                               core::rect<s32>(core::position2d<s32>(0,0), srcd),
-                               NULL, colors, true);
-                       p += v2s32(16,0);
-               }
-       }
-#else
-       draw_statbar(driver, font, gamedef, pos + v2s32(0, -20),
-               "heart.png", halfheartcount);
-#endif
-}
-
 /*
        Check if a node is pointable
 */
@@ -1103,14 +814,8 @@ void the_game(
        // Calculate text height using the font
        u32 text_height = font->getDimension(L"Random test string").Height;
 
-       v2u32 screensize(0,0);
        v2u32 last_screensize(0,0);
-       screensize = driver->getScreenSize();
-
-       const s32 hotbar_itemcount = 8;
-       //const s32 hotbar_imagesize = 36;
-       //const s32 hotbar_imagesize = 64;
-       s32 hotbar_imagesize = 48;
+       v2u32 screensize = driver->getScreenSize();
        
        /*
                Draw "Loading" screen
@@ -1534,6 +1239,12 @@ void the_game(
        LocalPlayer* player = client.getEnv().getLocalPlayer();
        player->hurt_tilt_timer = 0;
        player->hurt_tilt_strength = 0;
+       
+       /*
+               HUD object
+       */
+       Hud hud(driver, guienv, font, text_height,
+                       gamedef, player, &local_inventory);
 
        for(;;)
        {
@@ -1707,13 +1418,11 @@ void the_game(
                v2s32 displaycenter(screensize.X/2,screensize.Y/2);
                //bool screensize_changed = screensize != last_screensize;
 
-               // Resize hotbar
-               if(screensize.Y <= 800)
-                       hotbar_imagesize = 32;
-               else if(screensize.Y <= 1280)
-                       hotbar_imagesize = 48;
-               else
-                       hotbar_imagesize = 64;
+                       
+               // Update HUD values
+               hud.screensize    = screensize;
+               hud.displaycenter = displaycenter;
+               hud.resizeHotbar();
                
                // Hilight boxes collected during the loop and displayed
                std::vector<aabb3f> hilightboxes;
@@ -2077,7 +1786,7 @@ void the_game(
                {
                        s32 wheel = input->getMouseWheel();
                        u16 max_item = MYMIN(PLAYER_INVENTORY_SIZE-1,
-                                       hotbar_itemcount-1);
+                                       hud.hotbar_itemcount-1);
 
                        if(wheel < 0)
                        {
@@ -2101,7 +1810,7 @@ void the_game(
                        const KeyPress *kp = NumberKey + (i + 1) % 10;
                        if(input->wasKeyDown(*kp))
                        {
-                               if(i < PLAYER_INVENTORY_SIZE && i < hotbar_itemcount)
+                               if(i < PLAYER_INVENTORY_SIZE && i < hud.hotbar_itemcount)
                                {
                                        new_playeritem = i;
 
@@ -2390,8 +2099,18 @@ void the_game(
                                }
                                else if (event.type == CE_HUDADD)
                                {
-                                       HudElement* e = new HudElement;
-                                       e->type   = event.hudadd.type;
+                                       u32 id = event.hudadd.id;
+                                       size_t nhudelem = player->hud.size();
+                                       if (id > nhudelem || (id < nhudelem && player->hud[id])) {
+                                               delete event.hudadd.pos;
+                                               delete event.hudadd.name;
+                                               delete event.hudadd.scale;
+                                               delete event.hudadd.text;
+                                               continue;
+                                       }
+                                       
+                                       HudElement *e = new HudElement;
+                                       e->type   = (HudElementType)event.hudadd.type;
                                        e->pos    = *event.hudadd.pos;
                                        e->name   = *event.hudadd.name;
                                        e->scale  = *event.hudadd.scale;
@@ -2399,33 +2118,61 @@ void the_game(
                                        e->number = event.hudadd.number;
                                        e->item   = event.hudadd.item;
                                        e->dir    = event.hudadd.dir;
-                                       player->hud[event.hudadd.id] = e;
-                                       delete(event.hudadd.pos);
-                                       delete(event.hudadd.name);
-                                       delete(event.hudadd.scale);
-                                       delete(event.hudadd.text);
+                                       
+                                       if (id == nhudelem)
+                                               player->hud.push_back(e);
+                                       else
+                                               player->hud[id] = e;
+
+                                       delete event.hudadd.pos;
+                                       delete event.hudadd.name;
+                                       delete event.hudadd.scale;
+                                       delete event.hudadd.text;
                                }
                                else if (event.type == CE_HUDRM)
                                {
-                                       player->hud.erase(event.hudrm.id);
+                                       u32 id = event.hudrm.id;
+                                       if (id < player->hud.size() && player->hud[id]) {
+                                               delete player->hud[id];
+                                               player->hud[id] = NULL;
+                                       }
                                }
                                else if (event.type == CE_HUDCHANGE)
                                {
-                                       HudElement* e = player->hud[event.hudchange.id];
-                                       if(event.hudchange.stat == 0)
-                                               e->pos = *event.hudchange.v2fdata;
-                                       else if(event.hudchange.stat == 1)
-                                               e->name = *event.hudchange.sdata;
-                                       else if(event.hudchange.stat == 2)
-                                               e->scale = *event.hudchange.v2fdata;
-                                       else if(event.hudchange.stat == 3)
-                                               e->text = *event.hudchange.sdata;
-                                       else if(event.hudchange.stat == 4)
-                                               e->number = event.hudchange.data;
-                                       else if(event.hudchange.stat == 5)
-                                               e->item = event.hudchange.data;
-                                       else if(event.hudchange.stat == 6)
-                                               e->dir = event.hudchange.data;
+                                       u32 id = event.hudchange.id;
+                                       if (id >= player->hud.size() || !player->hud[id]) {
+                                               delete event.hudchange.v2fdata;
+                                               delete event.hudchange.sdata;
+                                               continue;
+                                       }
+                                               
+                                       HudElement* e = player->hud[id];
+                                       switch (event.hudchange.stat) {
+                                               case HUD_STAT_POS:
+                                                       e->pos = *event.hudchange.v2fdata;
+                                                       break;
+                                               case HUD_STAT_NAME:
+                                                       e->name = *event.hudchange.sdata;
+                                                       break;
+                                               case HUD_STAT_SCALE:
+                                                       e->scale = *event.hudchange.v2fdata;
+                                                       break;
+                                               case HUD_STAT_TEXT:
+                                                       e->text = *event.hudchange.sdata;
+                                                       break;
+                                               case HUD_STAT_NUMBER:
+                                                       e->number = event.hudchange.data;
+                                                       break;
+                                               case HUD_STAT_ITEM:
+                                                       e->item = event.hudchange.data;
+                                                       break;
+                                               case HUD_STAT_DIR:
+                                                       e->dir = event.hudchange.data;
+                                                       break;
+                                       }
+                                       
+                                       delete event.hudchange.v2fdata;
+                                       delete event.hudchange.sdata;
                                }
                        }
                }
@@ -3203,7 +2950,6 @@ void the_game(
                */
 
                TimeTaker tt_draw("mainloop: draw");
-
                
                {
                        TimeTaker timer("beginScene");
@@ -3307,26 +3053,8 @@ void the_game(
 
                driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
 
-               if(show_hud)
-               {
-                       v3f selectionbox_color = g_settings->getV3F("selectionbox_color");
-                       u32 selectionbox_color_r = rangelim(myround(selectionbox_color.X), 0, 255);
-                       u32 selectionbox_color_g = rangelim(myround(selectionbox_color.Y), 0, 255);
-                       u32 selectionbox_color_b = rangelim(myround(selectionbox_color.Z), 0, 255);
-
-                       for(std::vector<aabb3f>::const_iterator
-                                       i = hilightboxes.begin();
-                                       i != hilightboxes.end(); i++)
-                       {
-                               /*infostream<<"hilightbox min="
-                                               <<"("<<i->MinEdge.X<<","<<i->MinEdge.Y<<","<<i->MinEdge.Z<<")"
-                                               <<" max="
-                                               <<"("<<i->MaxEdge.X<<","<<i->MaxEdge.Y<<","<<i->MaxEdge.Z<<")"
-                                               <<std::endl;*/
-                               driver->draw3DBox(*i, video::SColor(255,selectionbox_color_r,selectionbox_color_g,selectionbox_color_b));
-                       }
-               }
-
+               if (show_hud)
+                       hud.drawSelectionBoxes(hilightboxes);
                /*
                        Wielded tool
                */
@@ -3354,22 +3082,9 @@ void the_game(
                /*
                        Draw crosshair
                */
-               if(show_hud)
-               {
-                       v3f crosshair_color = g_settings->getV3F("crosshair_color");
-                       u32 crosshair_color_r = rangelim(myround(crosshair_color.X), 0, 255);
-                       u32 crosshair_color_g = rangelim(myround(crosshair_color.Y), 0, 255);
-                       u32 crosshair_color_b = rangelim(myround(crosshair_color.Z), 0, 255);
-                       u32 crosshair_alpha = rangelim(g_settings->getS32("crosshair_alpha"), 0, 255);
-
-                       driver->draw2DLine(displaycenter - core::vector2d<s32>(10,0),
-                                       displaycenter + core::vector2d<s32>(10,0),
-                                       video::SColor(crosshair_alpha,crosshair_color_r,crosshair_color_g,crosshair_color_b));
-                       driver->draw2DLine(displaycenter - core::vector2d<s32>(0,10),
-                                       displaycenter + core::vector2d<s32>(0,10),
-                                       video::SColor(crosshair_alpha,crosshair_color_r,crosshair_color_g,crosshair_color_b));
-               }
-
+               if (show_hud)
+                       hud.drawCrosshair();
+                       
                } // timer
 
                //timer10.stop();
@@ -3379,11 +3094,9 @@ void the_game(
                /*
                        Draw hotbar
                */
-               if(show_hud)
+               if (show_hud)
                {
-                       draw_hotbar(driver, font, gamedef,
-                                       v2s32(displaycenter.X, screensize.Y),
-                                       hotbar_imagesize, hotbar_itemcount, &local_inventory,
+                       hud.drawHotbar(v2s32(displaycenter.X, screensize.Y),
                                        client.getHP(), client.getPlayerItem());
                }
 
@@ -3413,54 +3126,8 @@ void the_game(
                /*
                        Draw lua hud items
                */
-               std::deque<gui::IGUIStaticText *> luaguitexts;
-               if(show_hud)
-               {
-                       for(std::map<u32, HudElement*>::iterator it = player->hud.begin();
-                               it != player->hud.end(); ++it)
-                       {
-                               HudElement* e = it->second;
-                               v2f posp(e->pos * v2f(screensize.X, screensize.Y));
-                               core::vector2d<s32> pos(posp.X, posp.Y);
-                               if(e->type == 'I'){         //Img
-                                       video::ITexture *texture =
-                                               gamedef->getTextureSource()->getTextureRaw(e->text);
-                                       const video::SColor color(255,255,255,255);
-                                       const video::SColor colors[] = {color,color,color,color};
-                                       core::dimension2di imgsize(texture->getOriginalSize());
-                                       core::rect<s32> rect(0, 0, imgsize.Width*e->scale.X,
-                                                                                               imgsize.Height*e->scale.X);
-                                       rect += pos;
-                                       driver->draw2DImage(texture, rect,
-                                               core::rect<s32>(core::position2d<s32>(0,0), imgsize),
-                                               NULL, colors, true);
-                               } else if(e->type == 'T') { //Text
-                                       std::wstring t;
-                                       t.assign(e->text.begin(), e->text.end());
-                                       gui::IGUIStaticText *luaguitext = guienv->addStaticText(
-                                                       t.c_str(),
-                                                       core::rect<s32>(0, 0, e->scale.X, text_height*(e->scale.Y))+pos,
-                                                       false, false);
-                                       luaguitexts.push_back(luaguitext);
-                               } else if(e->type == 'S') { //Statbar
-                                       draw_statbar(driver, font, gamedef, pos, e->text, e->number);
-                               } else if(e->type == 's') { //Non-conflict Statbar
-                                       v2s32 p(displaycenter.X - 143, screensize.Y - 76);
-                                       p.X += e->pos.X*173;
-                                       p.Y += e->pos.X*20;
-                                       p.Y -= e->pos.Y*20;
-                                       draw_statbar(driver, font, gamedef, p, e->text, e->number);
-                               } else if(e->type == 'i') { //Inv
-                                       InventoryList* inv = local_inventory.getList(e->text);
-                                       draw_item(driver, font, gamedef, pos, hotbar_imagesize,
-                                                               e->number, inv, e->item, e->dir);
-                               } else {
-                                       actionstream<<"luadraw: ignoring drawform "<<it->second<<
-                                               "of key "<<it->first<<" due to incorrect command."<<std::endl;
-                                       continue;
-                               }
-                       }
-               }
+               if (show_hud)
+                       hud.drawLuaElements();
 
                /*
                        Draw gui
@@ -3468,13 +3135,6 @@ void the_game(
                // 0-1ms
                guienv->drawAll();
 
-               /*
-                       Remove lua-texts
-               */
-               for(std::deque<gui::IGUIStaticText *>::iterator it = luaguitexts.begin();
-                       it != luaguitexts.end(); ++it)
-                       (*it)->remove();
-
                /*
                        End scene
                */
@@ -3517,11 +3177,11 @@ void the_game(
        /*
                Drop stuff
        */
-       if(clouds)
+       if (clouds)
                clouds->drop();
-       if(gui_chat_console)
+       if (gui_chat_console)
                gui_chat_console->drop();
-       clear_particles ();
+       clear_particles();
        
        /*
                Draw a "shutting down" screen, which will be shown while the map
diff --git a/src/hud.cpp b/src/hud.cpp
new file mode 100644 (file)
index 0000000..349c55a
--- /dev/null
@@ -0,0 +1,291 @@
+/*
+Minetest
+Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
+Copyright (C) 2010-2013 blue42u, Jonathon Anderson <anderjon@umail.iu.edu>
+Copyright (C) 2010-2013 kwolekr, Ryan Kwolek <kwolekr@minetest.net>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <IGUIStaticText.h>
+
+#include "guiFormSpecMenu.h"
+#include "main.h"
+#include "util/numeric.h"
+#include "log.h"
+#include "client.h"
+#include "hud.h"
+
+
+Hud::Hud(video::IVideoDriver *driver, gui::IGUIEnvironment* guienv,
+               gui::IGUIFont *font, u32 text_height, IGameDef *gamedef,
+               LocalPlayer *player, Inventory *inventory) {
+       this->driver      = driver;
+       this->guienv      = guienv;
+       this->font        = font;
+       this->text_height = text_height;
+       this->gamedef     = gamedef;
+       this->player      = player;
+       this->inventory   = inventory;
+       
+       screensize       = v2u32(0, 0);
+       displaycenter    = v2s32(0, 0);
+       hotbar_imagesize = 48;
+       hotbar_itemcount = 8;
+       
+       v3f crosshair_color = g_settings->getV3F("crosshair_color");
+       u32 cross_r = rangelim(myround(crosshair_color.X), 0, 255);
+       u32 cross_g = rangelim(myround(crosshair_color.Y), 0, 255);
+       u32 cross_b = rangelim(myround(crosshair_color.Z), 0, 255);
+       u32 cross_a = rangelim(g_settings->getS32("crosshair_alpha"), 0, 255);
+       crosshair_argb = video::SColor(cross_a, cross_r, cross_g, cross_b);
+       
+       v3f selectionbox_color = g_settings->getV3F("selectionbox_color");
+       u32 sbox_r = rangelim(myround(selectionbox_color.X), 0, 255);
+       u32 sbox_g = rangelim(myround(selectionbox_color.Y), 0, 255);
+       u32 sbox_b = rangelim(myround(selectionbox_color.Z), 0, 255);
+       selectionbox_argb = video::SColor(255, sbox_r, sbox_g, sbox_b);
+}
+
+
+//NOTE: selectitem = 0 -> no selected; selectitem 1-based
+void Hud::drawItem(v2s32 upperleftpos, s32 imgsize, s32 itemcount,
+               InventoryList *mainlist, u16 selectitem, u16 direction)
+{
+       s32 padding = imgsize / 12;
+       s32 height  = imgsize + padding * 2;
+       s32 width   = itemcount * (imgsize + padding * 2);
+       if (direction == HUD_DIR_TOP_BOTTOM || direction == HUD_DIR_BOTTOM_TOP) {
+               width  = imgsize + padding * 2;
+               height = itemcount * (imgsize + padding * 2);
+       }
+       s32 fullimglen = imgsize + padding * 2;
+
+       // Position of upper left corner of bar
+       v2s32 pos = upperleftpos;
+
+       // Draw background color
+       /*core::rect<s32> barrect(0,0,width,height);
+       barrect += pos;
+       video::SColor bgcolor(255,128,128,128);
+       driver->draw2DRectangle(bgcolor, barrect, NULL);*/
+
+       core::rect<s32> imgrect(0, 0, imgsize, imgsize);
+
+       for (s32 i = 0; i < itemcount; i++)
+       {
+               const ItemStack &item = mainlist->getItem(i);
+
+               v2s32 steppos;
+               switch (direction) {
+                       case HUD_DIR_RIGHT_LEFT:
+                               steppos = v2s32(-(padding + i * fullimglen), padding);
+                               break;
+                       case HUD_DIR_TOP_BOTTOM:
+                               steppos = v2s32(padding, padding + i * fullimglen);
+                               break;
+                       case HUD_DIR_BOTTOM_TOP:
+                               steppos = v2s32(padding, -(padding + i * fullimglen));
+                               break;
+                       default:
+                               steppos = v2s32(padding + i * fullimglen, padding);     
+               }
+                       
+               core::rect<s32> rect = imgrect + pos + steppos;
+
+               if (selectitem == i + 1)
+               {
+                       video::SColor c_outside(255,255,0,0);
+                       //video::SColor c_outside(255,0,0,0);
+                       //video::SColor c_inside(255,192,192,192);
+                       s32 x1 = rect.UpperLeftCorner.X;
+                       s32 y1 = rect.UpperLeftCorner.Y;
+                       s32 x2 = rect.LowerRightCorner.X;
+                       s32 y2 = rect.LowerRightCorner.Y;
+                       // Black base borders
+                       driver->draw2DRectangle(c_outside,
+                                       core::rect<s32>(
+                                               v2s32(x1 - padding, y1 - padding),
+                                               v2s32(x2 + padding, y1)
+                                       ), NULL);
+                       driver->draw2DRectangle(c_outside,
+                                       core::rect<s32>(
+                                               v2s32(x1 - padding, y2),
+                                               v2s32(x2 + padding, y2 + padding)
+                                       ), NULL);
+                       driver->draw2DRectangle(c_outside,
+                                       core::rect<s32>(
+                                               v2s32(x1 - padding, y1),
+                                               v2s32(x1, y2)
+                                       ), NULL);
+                       driver->draw2DRectangle(c_outside,
+                                       core::rect<s32>(
+                                               v2s32(x2, y1),
+                                               v2s32(x2 + padding, y2)
+                                       ), NULL);
+                       /*// Light inside borders
+                       driver->draw2DRectangle(c_inside,
+                                       core::rect<s32>(
+                                               v2s32(x1 - padding/2, y1 - padding/2),
+                                               v2s32(x2 + padding/2, y1)
+                                       ), NULL);
+                       driver->draw2DRectangle(c_inside,
+                                       core::rect<s32>(
+                                               v2s32(x1 - padding/2, y2),
+                                               v2s32(x2 + padding/2, y2 + padding/2)
+                                       ), NULL);
+                       driver->draw2DRectangle(c_inside,
+                                       core::rect<s32>(
+                                               v2s32(x1 - padding/2, y1),
+                                               v2s32(x1, y2)
+                                       ), NULL);
+                       driver->draw2DRectangle(c_inside,
+                                       core::rect<s32>(
+                                               v2s32(x2, y1),
+                                               v2s32(x2 + padding/2, y2)
+                                       ), NULL);
+                       */
+               }
+
+               video::SColor bgcolor2(128, 0, 0, 0);
+               driver->draw2DRectangle(bgcolor2, rect, NULL);
+               drawItemStack(driver, font, item, rect, NULL, gamedef);
+       }
+}
+
+
+void Hud::drawLuaElements() {
+       for (size_t i = 0; i != player->hud.size(); i++) {
+               HudElement *e = player->hud[i];
+               if (!e)
+                       continue;
+               
+               v2s32 pos(e->pos.X * screensize.X, e->pos.Y * screensize.Y);
+               switch (e->type) {
+                       case HUD_ELEM_IMAGE: {
+                               video::ITexture *texture =
+                                       gamedef->getTextureSource()->getTextureRaw(e->text);
+                               if (!texture)
+                                       continue;
+
+                               const video::SColor color(255, 255, 255, 255);
+                               const video::SColor colors[] = {color, color, color, color};
+                               core::dimension2di imgsize(texture->getOriginalSize());
+                               core::rect<s32> rect(0, 0, imgsize.Width  * e->scale.X,
+                                                                              imgsize.Height * e->scale.X);
+                               rect += pos;
+                               driver->draw2DImage(texture, rect,
+                                       core::rect<s32>(core::position2d<s32>(0,0), imgsize),
+                                       NULL, colors, true);
+                               break; }
+                       case HUD_ELEM_TEXT: {
+                               video::SColor color(255, (e->number >> 16) & 0xFF,
+                                                                                (e->number >> 8)  & 0xFF,
+                                                                                (e->number >> 0)  & 0xFF);
+                               core::rect<s32> size(0, 0, e->scale.X, text_height * e->scale.Y);
+                               font->draw(narrow_to_wide(e->text).c_str(), size + pos, color);
+                               break; }
+                       case HUD_ELEM_STATBAR:
+                               drawStatbar(pos, e->text, e->number);
+                               break;
+                       case HUD_ELEM_INVENTORY: {
+                               InventoryList *inv = inventory->getList(e->text);
+                               drawItem(pos, hotbar_imagesize, e->number, inv, e->item, e->dir);
+                               break; }
+                       default:
+                               infostream << "Hud::drawLuaElements: ignoring drawform " << e->type <<
+                                       "of hud element ID " << i << " due to unrecognized type" << std::endl;
+               }
+       }
+}
+
+
+void Hud::drawStatbar(v2s32 upperleftpos, std::string texture, s32 count) {
+       video::ITexture *stat_texture =
+               gamedef->getTextureSource()->getTextureRaw(texture);
+       if (!stat_texture)
+               return;
+
+       v2s32 p = upperleftpos;
+       for (s32 i = 0; i < count / 2; i++)
+       {
+               core::dimension2di srcd(stat_texture->getOriginalSize());
+               const video::SColor color(255, 255, 255, 255);
+               const video::SColor colors[] = {color, color, color, color};
+               core::rect<s32> rect(0, 0, srcd.Width, srcd.Height);
+               rect += p;
+               driver->draw2DImage(stat_texture, rect,
+                       core::rect<s32>(core::position2d<s32>(0, 0), srcd),
+                       NULL, colors, true);
+               p += v2s32(srcd.Width, 0);
+       }
+       
+       if (count % 2 == 1)
+       {
+               core::dimension2di srcd(stat_texture->getOriginalSize());
+               const video::SColor color(255, 255, 255, 255);
+               const video::SColor colors[] = {color, color, color, color};
+               core::rect<s32> rect(0, 0, srcd.Width / 2, srcd.Height);
+               rect += p;
+               srcd.Width /= 2;
+               driver->draw2DImage(stat_texture, rect,
+                       core::rect<s32>(core::position2d<s32>(0, 0), srcd),
+                       NULL, colors, true);
+               p += v2s32(srcd.Width * 2, 0);
+       }
+}
+
+
+void Hud::drawHotbar(v2s32 centerlowerpos, s32 halfheartcount, u16 playeritem) {
+       InventoryList *mainlist = inventory->getList("main");
+       if (mainlist == NULL) {
+               errorstream << "draw_hotbar(): mainlist == NULL" << std::endl;
+               return;
+       }
+       
+       s32 padding = hotbar_imagesize / 12;
+       s32 width = hotbar_itemcount * (hotbar_imagesize + padding * 2);
+       v2s32 pos = centerlowerpos - v2s32(width / 2, hotbar_imagesize + padding * 2);
+       
+       drawItem(pos, hotbar_imagesize, hotbar_itemcount, mainlist, playeritem + 1, 0);
+       drawStatbar(pos + v2s32(0, -20), "heart.png", halfheartcount);
+}
+
+
+void Hud::drawCrosshair() {
+       driver->draw2DLine(displaycenter - v2s32(10,0),
+                       displaycenter + v2s32(10, 0), crosshair_argb);
+       driver->draw2DLine(displaycenter - v2s32(0,10),
+                       displaycenter + v2s32(0, 10), crosshair_argb);
+}
+
+
+void Hud::drawSelectionBoxes(std::vector<aabb3f> &hilightboxes) {
+       for (std::vector<aabb3f>::const_iterator
+                       i = hilightboxes.begin();
+                       i != hilightboxes.end(); i++) {
+               driver->draw3DBox(*i, selectionbox_argb);
+       }
+}
+
+
+void Hud::resizeHotbar() {
+       if (screensize.Y <= 800)
+               hotbar_imagesize = 32;
+       else if (screensize.Y <= 1280)
+               hotbar_imagesize = 48;
+       else
+               hotbar_imagesize = 64;
+}
diff --git a/src/hud.h b/src/hud.h
new file mode 100644 (file)
index 0000000..7e00a94
--- /dev/null
+++ b/src/hud.h
@@ -0,0 +1,116 @@
+/*
+Minetest
+Copyright (C) 2010-2013 kwolekr, Ryan Kwolek <kwolekr@minetest.net>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef HUD_HEADER
+#define HUD_HEADER
+
+#include "irrlichttypes_extrabloated.h"
+
+#define HUD_DIR_LEFT_RIGHT 0
+#define HUD_DIR_RIGHT_LEFT 1
+#define HUD_DIR_TOP_BOTTOM 2
+#define HUD_DIR_BOTTOM_TOP 3
+
+class Player;
+
+enum HudElementType {
+       HUD_ELEM_IMAGE     = 0,
+       HUD_ELEM_TEXT      = 1,
+       HUD_ELEM_STATBAR   = 2,
+       HUD_ELEM_INVENTORY = 3
+};
+
+enum HudElementStat {
+       HUD_STAT_POS,
+       HUD_STAT_NAME,
+       HUD_STAT_SCALE,
+       HUD_STAT_TEXT,
+       HUD_STAT_NUMBER,
+       HUD_STAT_ITEM,
+       HUD_STAT_DIR
+};
+
+struct HudElement {
+       HudElementType type;
+       v2f pos;
+       std::string name;
+       v2f scale;
+       std::string text;
+       u32 number;
+       u32 item;
+       u32 dir;
+};
+
+
+inline u32 hud_get_free_id(Player *player) {
+       size_t size = player->hud.size();
+       for (size_t i = 0; i != size; i++) {
+               if (!player->hud[i])
+                       return i;
+       }
+       return size;
+}
+
+#ifndef SERVER
+
+#include <deque>
+
+#include <IGUIFont.h>
+
+#include "gamedef.h"
+#include "inventory.h"
+#include "localplayer.h"
+
+class Hud {
+public:
+       video::IVideoDriver *driver;
+       gui::IGUIEnvironment *guienv;
+       gui::IGUIFont *font;
+       u32 text_height;
+       IGameDef *gamedef;
+       LocalPlayer *player;
+       Inventory *inventory;
+       
+       v2u32 screensize;
+       v2s32 displaycenter;
+       s32 hotbar_imagesize;
+       s32 hotbar_itemcount;
+       
+       video::SColor crosshair_argb;
+       video::SColor selectionbox_argb;
+       
+       Hud(video::IVideoDriver *driver, gui::IGUIEnvironment* guienv,
+               gui::IGUIFont *font, u32 text_height, IGameDef *gamedef,
+               LocalPlayer *player, Inventory *inventory);
+       
+       void drawItem(v2s32 upperleftpos, s32 imgsize, s32 itemcount,
+               InventoryList *mainlist, u16 selectitem, u16 direction);
+       void drawLuaElements();
+       void drawStatbar(v2s32 upperleftpos, std::string texture, s32 count);
+       
+       void drawHotbar(v2s32 centerlowerpos, s32 halfheartcount, u16 playeritem);
+       void resizeHotbar();
+       
+       void drawCrosshair();
+       void drawSelectionBoxes(std::vector<aabb3f> &hilightboxes);
+};
+
+#endif
+
+#endif
index fc80769c2cfeb233740a3a4369dadefac537c386..d0e50d2c36a494aea07259626b41e5103e78bfad 100644 (file)
@@ -87,7 +87,7 @@ class Map;
 class IGameDef;
 struct CollisionInfo;
 class PlayerSAO;
-struct HudElement;
+class HudElement;
 
 class Player
 {
@@ -243,9 +243,8 @@ public:
        }
        
        u32 keyPressed;
-
-       std::map<u32, HudElement*> hud;
-       std::map<u8, u32> hud_bars;
+       
+       std::vector<HudElement *> hud;
 
 protected:
        IGameDef *m_gamedef;
@@ -257,17 +256,6 @@ protected:
        v3f m_position;
 };
 
-struct HudElement {
-       u8 type;
-       core::vector2df pos;
-       std::string name;
-
-       core::vector2df scale;
-       std::string text;
-       u32 number;
-       u32 item;
-       u32 dir;
-};
 
 /*
        Player on the server
index 8f92ca439ccd2bf64adb9d49724f30c71459b6a0..531bb7a58ddf2d8dc1f4650c8b6b058d5e021e54 100644 (file)
@@ -26,6 +26,30 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "scriptapi_item.h"
 #include "scriptapi_entity.h"
 #include "scriptapi_common.h"
+#include "hud.h"
+
+
+struct EnumString es_HudElementType[] =
+{
+       {HUD_ELEM_IMAGE,     "image"},
+       {HUD_ELEM_TEXT,      "text"},
+       {HUD_ELEM_STATBAR,   "statbar"},
+       {HUD_ELEM_INVENTORY, "inventory"},
+       {0, NULL},
+};
+
+struct EnumString es_HudElementStat[] =
+{
+       {HUD_STAT_POS,    "pos"},
+       {HUD_STAT_NAME,   "name"},
+       {HUD_STAT_SCALE,  "scale"},
+       {HUD_STAT_TEXT,   "text"},
+       {HUD_STAT_NUMBER, "number"},
+       {HUD_STAT_ITEM,   "item"},
+       {HUD_STAT_DIR,    "direction"},
+       {0, NULL},
+};
+
 
 /*
        ObjectRef
@@ -705,205 +729,161 @@ int ObjectRef::l_hud_add(lua_State *L)
 {
        ObjectRef *ref = checkobject(L, 1);
        Player *player = getplayer(ref);
-       if(player == NULL) return 0;
+       if (player == NULL)
+               return 0;
 
-       u32 id = hud_get_next_id(L);
-       HudElement* form = new HudElement;
-       std::string SS = getstringfield_default(L, 3, "type", "I");
-       form->type = SS[0];
-       lua_getfield(L, 3, "position");
-       if(lua_istable(L, -1))
-               form->pos = read_v2f(L, -1);
-       else
-               form->pos = v2f();
+       HudElement *elem = new HudElement;
+       
+       elem->type = (HudElementType)getenumfield(L, 2, "hud_elem_type",
+                                                               es_HudElementType, HUD_ELEM_TEXT);
+       
+       lua_getfield(L, 2, "position");
+       elem->pos = lua_istable(L, -1) ? read_v2f(L, -1) : v2f();
        lua_pop(L, 1);
-       form->name = getstringfield_default(L, 3, "name", "");
-
-       lua_getfield(L, 3, "scale");
-       if(lua_istable(L, -1))
-               form->scale = read_v2f(L, -1);
-       else
-               form->scale = v2f();
+       
+       lua_getfield(L, 2, "scale");
+       elem->scale = lua_istable(L, -1) ? read_v2f(L, -1) : v2f();
        lua_pop(L, 1);
+       
+       elem->name   = getstringfield_default(L, 2, "name", "");
+       elem->text   = getstringfield_default(L, 2, "text", "");
+       elem->number = getintfield_default(L, 2, "number", 0);
+       elem->item   = getintfield_default(L, 2, "item", 0);
+       elem->dir    = getintfield_default(L, 2, "dir", 0);
+
+       u32 id = get_server(L)->hudAdd(player, elem);
+       if (id == (u32)-1) {
+               delete elem;
+               return 0;
+       }
 
-       form->text = getstringfield_default(L, 3, "text", "");
-       form->number = getintfield_default(L, 3, "number", 0);
-       form->item = getintfield_default(L, 3, "item", 0);
-       form->dir = getintfield_default(L, 3, "dir", 0);
-
-       get_server(L)->hudadd(player->getName(), id, form);
-       player->hud[id] = form;
        lua_pushnumber(L, id);
        return 1;
 }
 
-// hud_rm(self, id)
-int ObjectRef::l_hud_rm(lua_State *L)
+// hud_remove(self, id)
+int ObjectRef::l_hud_remove(lua_State *L)
 {
        ObjectRef *ref = checkobject(L, 1);
        Player *player = getplayer(ref);
-       if(player == NULL) return 0;
+       if (player == NULL)
+               return 0;
 
        u32 id = -1;
-       if(!lua_isnil(L, 2))
+       if (!lua_isnil(L, 2))
                id = lua_tonumber(L, 2);
-       get_server(L)->hudrm(player->getName(), id);
-       player->hud.at(id)->type = (u8)NULL;
+       
+       if (!get_server(L)->hudRemove(player, id))
+               return 0;
+
        lua_pushboolean(L, true);
        return 1;
 }
 
-
 // hud_change(self, id, stat, data)
 int ObjectRef::l_hud_change(lua_State *L)
 {
        ObjectRef *ref = checkobject(L, 1);
        Player *player = getplayer(ref);
-       if(player == NULL) return 0;
+       if (player == NULL)
+               return 0;
 
        u32 id = -1;
-       if(!lua_isnil(L, 2))
+       if (!lua_isnil(L, 2))
                id = lua_tonumber(L, 2);
-       u8 stat = -1;
-       if(!lua_isnil(L, 3))
-               stat = lua_tonumber(L, 3);
-       if(stat == 0 || stat == 2) {
-               get_server(L)->hudchange(player->getName(), id, stat, read_v2f(L, 4));
-       } else if(stat == 1 || stat == 3) {
-               get_server(L)->hudchange(player->getName(), id, stat, lua_tostring(L, 4));
-       } else {
-               get_server(L)->hudchange(player->getName(), id, stat, lua_tonumber(L, 4));
-       }
-
-       HudElement* e = player->hud[id];
-       switch(stat) {
-               case HUD_STAT_POS:    e->pos = read_v2f(L, 4);
-               case HUD_STAT_NAME:   e->name = lua_tostring(L, 4);
-               case HUD_STAT_SCALE:  e->scale = read_v2f(L, 4);
-               case HUD_STAT_TEXT:   e->text = lua_tostring(L, 4);
-               case HUD_STAT_NUMBER: e->number = lua_tonumber(L, 4);
-               case HUD_STAT_ITEM:   e->item = lua_tonumber(L, 4);
-               case HUD_STAT_DIR:    e->dir = lua_tonumber(L, 4);
+       
+       HudElementStat stat = (HudElementStat)getenumfield(L, 3, "stat",
+                                                               es_HudElementStat, HUD_STAT_NUMBER);
+       
+       if (id >= player->hud.size())
+               return 0;
+       
+       void *value = NULL;
+       HudElement *e = player->hud[id];
+       if (!e)
+               return 0;
+       
+       switch (stat) {
+               case HUD_STAT_POS:
+                       e->pos = read_v2f(L, 4);
+                       value = &e->pos;
+                       break;
+               case HUD_STAT_NAME:
+                       e->name = lua_tostring(L, 4);
+                       value = &e->name;
+                       break;
+               case HUD_STAT_SCALE:
+                       e->scale = read_v2f(L, 4);
+                       value = &e->scale;
+                       break;
+               case HUD_STAT_TEXT:
+                       e->text = lua_tostring(L, 4);
+                       value = &e->text;
+                       break;
+               case HUD_STAT_NUMBER:
+                       e->number = lua_tonumber(L, 4);
+                       value = &e->number;
+                       break;
+               case HUD_STAT_ITEM:
+                       e->item = lua_tonumber(L, 4);
+                       value = &e->item;
+                       break;
+               case HUD_STAT_DIR:
+                       e->dir = lua_tonumber(L, 4);
+                       value = &e->dir;
        }
+       
+       get_server(L)->hudChange(player, id, stat, value);
 
        lua_pushboolean(L, true);
        return 1;
 }
 
-u32 ObjectRef::hud_get_next_id(lua_State *L)
-{
-       ObjectRef *ref = checkobject(L, 1);
-       Player *player = getplayer(ref);
-
-       for(std::map<u32, HudElement*>::iterator it=player->hud.begin();
-               it!=player->hud.end();it++) {
-               if(it->second->type == (u8)NULL) {
-                       return it->first;
-               }
-       }
-       return player->hud.size();
-}
-
 // hud_get(self, id)
 int ObjectRef::l_hud_get(lua_State *L)
 {
        ObjectRef *ref = checkobject(L, 1);
        Player *player = getplayer(ref);
-       if(player == NULL) return 0;
+       if (player == NULL)
+               return 0;
 
-       HudElement* e = player->hud.at(lua_tonumber(L, -1));
+       u32 id = lua_tonumber(L, -1);
+       if (id >= player->hud.size())
+               return 0;
+       
+       HudElement *e = player->hud[id];
+       if (!e)
+               return 0;
+       
        lua_newtable(L);
-       lua_pushstring(L, std::string(1, e->type).c_str());
+       
+       lua_pushstring(L, es_HudElementType[(u8)e->type].str);
        lua_setfield(L, -2, "type");
+       
        push_v2f(L, e->pos);
        lua_setfield(L, -2, "position");
+       
        lua_pushstring(L, e->name.c_str());
        lua_setfield(L, -2, "name");
+       
        push_v2f(L, e->scale);
        lua_setfield(L, -2, "scale");
+       
        lua_pushstring(L, e->text.c_str());
        lua_setfield(L, -2, "text");
+       
        lua_pushnumber(L, e->number);
        lua_setfield(L, -2, "number");
+       
        lua_pushnumber(L, e->item);
        lua_setfield(L, -2, "item");
+       
        lua_pushnumber(L, e->dir);
        lua_setfield(L, -2, "dir");
 
        return 1;
 }
 
-// hud_lock_next_bar(self, texture, right)
-// return id on success, false otherwise
-int ObjectRef::l_hud_lock_next_bar(lua_State *L)
-{
-       ObjectRef *ref = checkobject(L, 1);
-       Player *player = getplayer(ref);
-       if(player == NULL) return 0;
-
-       bool right = false;
-       if(!lua_isnil(L, 2))
-               right = lua_toboolean(L, 2);
-       v2f pos(0, 0);
-       u8 i = 0;
-       if(right)
-               pos.X = 1;
-               i += 3;
-       for(u8 it = 0; it < 4; it++) {
-               if(player->hud_bars.count(i+it) == 1) {
-                       if(it == 3) {
-                               lua_pushboolean(L, false);
-                               return 1;
-                       }
-               } else {
-                       i += it;
-                       pos.Y = it;
-                       break;
-               }
-       }
-       HudElement* form = new HudElement;
-       form->type = 's';
-       form->pos = pos;
-       form->name = "";
-       form->scale = v2f();
-       form->text = "";
-       form->number = 0;
-       form->item = 0;
-       form->dir = 0;
-
-       u32 id = hud_get_next_id(L);
-       get_server(L)->hudadd(player->getName(), id, form);
-       player->hud[id] = form;
-       player->hud_bars[i] = id;
-       lua_pushnumber(L, id);
-       return 1;
-}
-
-// hud_unlock_bar(self, id)
-int ObjectRef::l_hud_unlock_bar(lua_State *L)
-{
-       ObjectRef *ref = checkobject(L, 1);
-       Player *player = getplayer(ref);
-       if(player == NULL) return 0;
-
-       u32 id = 0;
-       if(!lua_isnil(L, 2))
-               id = lua_tonumber(L, 2);
-
-       for(std::map<u8, u32>::iterator it=player->hud_bars.begin();
-               it!=player->hud_bars.end();it++) {
-               if(it->second == id) {
-                       player->hud_bars.erase(it->first);
-                       get_server(L)->hudrm(player->getName(), id);
-                       player->hud.at(id)->type = (u8)NULL;
-                       lua_pushboolean(L, true);
-                       return 1;
-               }
-       }
-       lua_pushboolean(L, false);
-       return 1;
-}
-
 ObjectRef::ObjectRef(ServerActiveObject *object):
        m_object(object)
 {
@@ -1011,11 +991,11 @@ const luaL_reg ObjectRef::methods[] = {
        luamethod(ObjectRef, get_player_control),
        luamethod(ObjectRef, get_player_control_bits),
        luamethod(ObjectRef, hud_add),
-       luamethod(ObjectRef, hud_rm),
+       luamethod(ObjectRef, hud_remove),
        luamethod(ObjectRef, hud_change),
        luamethod(ObjectRef, hud_get),
-       luamethod(ObjectRef, hud_lock_next_bar),
-       luamethod(ObjectRef, hud_unlock_bar),
+       //luamethod(ObjectRef, hud_lock_next_bar),
+       //luamethod(ObjectRef, hud_unlock_bar),
        {0,0}
 };
 
index 6df4366bbd5429c01b957eeae7349ec25be2f332..fd46f2cf60739141fe91e1083fde7f64a3936e7a 100644 (file)
@@ -29,14 +29,6 @@ extern "C" {
 #include "content_sao.h"
 #include "player.h"
 
-#define HUD_STAT_POS    0
-#define HUD_STAT_NAME   1
-#define HUD_STAT_SCALE  2
-#define HUD_STAT_TEXT   3
-#define HUD_STAT_NUMBER 4
-#define HUD_STAT_ITEM   5
-#define HUD_STAT_DIR    6
-
 /*
        ObjectRef
 */
@@ -202,23 +194,14 @@ private:
        static int l_hud_add(lua_State *L);
 
        // hud_rm(self, id)
-       static int l_hud_rm(lua_State *L);
+       static int l_hud_remove(lua_State *L);
 
        // hud_change(self, id, stat, data)
        static int l_hud_change(lua_State *L);
 
-       // hud_get_next_id(self)
-       static u32 hud_get_next_id(lua_State *L);
-
        // hud_get(self, id)
        static int l_hud_get(lua_State *L);
 
-       // hud_lock_next_bar(self, right)
-       static int l_hud_lock_next_bar(lua_State *L);
-
-       // hud_unlock_bar(self, id)
-       static int l_hud_unlock_bar(lua_State *L);
-
 public:
        ObjectRef(ServerActiveObject *object);
 
index a9632c93c6ce0fa23a5a9e8e64f7c53daacf7a85..241826ba21c516159da139d70623cac4cc91864d 100644 (file)
@@ -3449,7 +3449,9 @@ void Server::SendChatMessage(u16 peer_id, const std::wstring &message)
        // Send as reliable
        m_con.Send(peer_id, 0, data, true);
 }
-void Server::SendShowFormspecMessage(u16 peer_id, const std::string formspec, const std::string formname)
+
+void Server::SendShowFormspecMessage(u16 peer_id, const std::string formspec,
+                                       const std::string formname)
 {
        DSTACK(__FUNCTION_NAME);
 
@@ -3470,7 +3472,9 @@ void Server::SendShowFormspecMessage(u16 peer_id, const std::string formspec, co
 }
 
 // Spawns a particle on peer with peer_id
-void Server::SendSpawnParticle(u16 peer_id, v3f pos, v3f velocity, v3f acceleration, float expirationtime, float size, bool collisiondetection, std::string texture)
+void Server::SendSpawnParticle(u16 peer_id, v3f pos, v3f velocity, v3f acceleration,
+                               float expirationtime, float size, bool collisiondetection,
+                               std::string texture)
 {
        DSTACK(__FUNCTION_NAME);
 
@@ -3492,7 +3496,9 @@ void Server::SendSpawnParticle(u16 peer_id, v3f pos, v3f velocity, v3f accelerat
 }
 
 // Spawns a particle on all peers
-void Server::SendSpawnParticleAll(v3f pos, v3f velocity, v3f acceleration, float expirationtime, float size, bool collisiondetection, std::string texture)
+void Server::SendSpawnParticleAll(v3f pos, v3f velocity, v3f acceleration,
+                               float expirationtime, float size, bool collisiondetection,
+                               std::string texture)
 {
        for(std::map<u16, RemoteClient*>::iterator
                i = m_clients.begin();
@@ -3595,22 +3601,18 @@ void Server::SendDeleteParticleSpawnerAll(u32 id)
        }
 }
 
-void Server::SendHUDAdd(u16 peer_id, const u32 id, HudElement* form)
+void Server::SendHUDAdd(u16 peer_id, u32 id, HudElement *form)
 {
-       DSTACK(__FUNCTION_NAME);
-
        std::ostringstream os(std::ios_base::binary);
-       u8 buf[12];
 
        // Write command
-       writeU16(buf, TOCLIENT_HUDADD);
-       os.write((char*)buf, 2);
+       writeU16(os, TOCLIENT_HUDADD);
        writeU32(os, id);
-       writeU8(os, form->type);
+       writeU8(os, (u8)form->type);
        writeV2F1000(os, form->pos);
-       os<<serializeString(form->name);
+       os << serializeString(form->name);
        writeV2F1000(os, form->scale);
-       os<<serializeString(form->text);
+       os << serializeString(form->text);
        writeU32(os, form->number);
        writeU32(os, form->item);
        writeU32(os, form->dir);
@@ -3622,16 +3624,12 @@ void Server::SendHUDAdd(u16 peer_id, const u32 id, HudElement* form)
        m_con.Send(peer_id, 0, data, true);
 }
 
-void Server::SendHUDRm(u16 peer_id, const u32 id)
+void Server::SendHUDRemove(u16 peer_id, u32 id)
 {
-       DSTACK(__FUNCTION_NAME);
-
        std::ostringstream os(std::ios_base::binary);
-       u8 buf[12];
 
        // Write command
-       writeU16(buf, TOCLIENT_HUDRM);
-       os.write((char*)buf, 2);
+       writeU16(os, TOCLIENT_HUDRM);
        writeU32(os, id);
 
        // Make data buffer
@@ -3641,67 +3639,36 @@ void Server::SendHUDRm(u16 peer_id, const u32 id)
        m_con.Send(peer_id, 0, data, true);
 }
 
-void Server::SendHUDChange(u16 peer_id, const u32 id, const u8 stat, v2f data)
+void Server::SendHUDChange(u16 peer_id, u32 id, HudElementStat stat, void *value)
 {
-       DSTACK(__FUNCTION_NAME);
-
        std::ostringstream os(std::ios_base::binary);
-       u8 buf[12];
 
        // Write command
-       writeU16(buf, TOCLIENT_HUDCHANGE);
-       os.write((char*)buf, 2);
+       writeU16(os, TOCLIENT_HUDCHANGE);
        writeU32(os, id);
-       writeU8(os, stat);
-       writeV2F1000(os, data);
-
-       // Make data buffer
-       std::string s = os.str();
-       SharedBuffer<u8> ddata((u8*)s.c_str(), s.size());
-       // Send as reliable
-       m_con.Send(peer_id, 0, ddata, true);
-}
-
-void Server::SendHUDChange(u16 peer_id, const u32 id, const u8 stat, std::string data)
-{
-       DSTACK(__FUNCTION_NAME);
-
-       std::ostringstream os(std::ios_base::binary);
-       u8 buf[12];
-
-       // Write command
-       writeU16(buf, TOCLIENT_HUDCHANGE);
-       os.write((char*)buf, 2);
-       writeU32(os, id);
-       writeU8(os, stat);
-       os<<serializeString(data);
-
-       // Make data buffer
-       std::string s = os.str();
-       SharedBuffer<u8> ddata((u8*)s.c_str(), s.size());
-       // Send as reliable
-       m_con.Send(peer_id, 0, ddata, true);
-}
-
-void Server::SendHUDChange(u16 peer_id, const u32 id, const u8 stat, u32 data)
-{
-       DSTACK(__FUNCTION_NAME);
-
-       std::ostringstream os(std::ios_base::binary);
-       u8 buf[12];
-
-       // Write command
-       writeU16(buf, TOCLIENT_HUDCHANGE);
-       os.write((char*)buf, 2);
-       writeU32(os, id);
-       writeU8(os, stat);
-       writeU32(os, data);
+       writeU8(os, (u8)stat);
+       switch (stat) {
+               case HUD_STAT_POS:
+               case HUD_STAT_SCALE:
+                       writeV2F1000(os, *(v2f *)value);
+                       break;
+               case HUD_STAT_NAME:
+               case HUD_STAT_TEXT:
+                       os << serializeString(*(std::string *)value);
+                       break;
+               case HUD_STAT_NUMBER:
+               case HUD_STAT_ITEM:
+               case HUD_STAT_DIR:
+               default:
+                       writeU32(os, *(u32 *)value);
+                       break;
+       }
 
        // Make data buffer
        std::string s = os.str();
-       SharedBuffer<u8> ddata((u8*)s.c_str(), s.size());
+       SharedBuffer<u8> data((u8 *)s.c_str(), s.size());
        // Send as reliable
-       m_con.Send(peer_id, 0, ddata, true);
+       m_con.Send(peer_id, 0, data, true);
 }
 
 void Server::BroadcastChatMessage(const std::wstring &message)
@@ -4657,71 +4624,34 @@ bool Server::showFormspec(const char *playername, const std::string &formspec, c
        return true;
 }
 
-bool Server::hudadd(const char *playername, const u32 &id, HudElement* form)
-{
-       Player *player = m_env->getPlayer(playername);
-
-       if(!player)
-       {
-               infostream<<"hudadd: couldn't find player:"<<playername<<std::endl;
-               return false;
-       }
+u32 Server::hudAdd(Player *player, HudElement *form) {
+       if (!player)
+               return -1;
 
+       u32 id = hud_get_free_id(player);
+       if (id < player->hud.size())
+               player->hud[id] = form;
+       else
+               player->hud.push_back(form);
+       
        SendHUDAdd(player->peer_id, id, form);
-       return true;
-}
-
-bool Server::hudrm(const char *playername, const u32 &id)
-{
-       Player *player = m_env->getPlayer(playername);
-
-       if(!player)
-       {
-               infostream<<"hudrm: couldn't find player:"<<playername<<std::endl;
-               return false;
-       }
-
-       SendHUDRm(player->peer_id, id);
-       return true;
-}
-
-bool Server::hudchange(const char *playername, const u32 &id, const u8 &stat, v2f data)
-{
-       Player *player = m_env->getPlayer(playername);
-
-       if(!player)
-       {
-               infostream<<"hudchange: couldn't find player:"<<playername<<std::endl;
-               return false;
-       }
-
-       SendHUDChange(player->peer_id, id, stat, data);
-       return true;
+       return id;
 }
 
-bool Server::hudchange(const char *playername, const u32 &id, const u8 &stat, std::string data)
-{
-       Player *player = m_env->getPlayer(playername);
-
-       if(!player)
-       {
-               infostream<<"hudchange: couldn't find player:"<<playername<<std::endl;
+bool Server::hudRemove(Player *player, u32 id) {
+       if (!player || id >= player->hud.size() || !player->hud[id])
                return false;
-       }
 
-       SendHUDChange(player->peer_id, id, stat, data);
+       delete player->hud[id];
+       player->hud[id] = NULL;
+       
+       SendHUDRemove(player->peer_id, id);
        return true;
 }
 
-bool Server::hudchange(const char *playername, const u32 &id, const u8 &stat, u32 data)
-{
-       Player *player = m_env->getPlayer(playername);
-
-       if(!player)
-       {
-               infostream<<"hudchange: couldn't find player:"<<playername<<std::endl;
+bool Server::hudChange(Player *player, u32 id, HudElementStat stat, void *data) {
+       if (!player)
                return false;
-       }
 
        SendHUDChange(player->peer_id, id, stat, data);
        return true;
index ef0c45a6ae0a096f62e4bdbf74191700afe8e4aa..52606b0cb75f7fc2d6255e4e273bb344b6229f01 100644 (file)
@@ -28,6 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "map.h"
 #include "inventory.h"
 #include "ban.h"
+#include "hud.h"
 #include "gamedef.h"
 #include "serialization.h" // For SER_FMT_VER_INVALID
 #include "mods.h"
@@ -51,6 +52,7 @@ class EventManager;
 class PlayerSAO;
 class IRollbackManager;
 class EmergeManager;
+//struct HudElement;
 
 class ServerError : public std::exception
 {
@@ -534,11 +536,11 @@ public:
        }
 
        bool showFormspec(const char *name, const std::string &formspec, const std::string &formname);
-       bool hudadd(const char *pname, const u32 &id, HudElement *element);
-       bool hudrm(const char *pname, const u32 &id);
-       bool hudchange(const char *pname, const u32 &id, const u8 &stat, v2f data);
-       bool hudchange(const char *pname, const u32 &id, const u8 &stat, std::string data);
-       bool hudchange(const char *pname, const u32 &id, const u8 &stat, u32 data);
+       
+       u32 hudAdd(Player *player, HudElement *element);
+       bool hudRemove(Player *player, u32 id);
+       bool hudChange(Player *player, u32 id, HudElementStat stat, void *value);
+       
 private:
 
        // con::PeerHandler implementation.
@@ -578,11 +580,9 @@ private:
        void SendPlayerPrivileges(u16 peer_id);
        void SendPlayerInventoryFormspec(u16 peer_id);
        void SendShowFormspecMessage(u16 peer_id, const std::string formspec, const std::string formname);
-       void SendHUDAdd(u16 peer_id, const u32 id, HudElement* form);
-       void SendHUDRm(u16 peer_id, const u32 id);
-       void SendHUDChange(u16 peer_id, const u32 id, const u8 stat, v2f data);
-       void SendHUDChange(u16 peer_id, const u32 id, const u8 stat, std::string data);
-       void SendHUDChange(u16 peer_id, const u32 id, const u8 stat, u32 data);
+       void SendHUDAdd(u16 peer_id, u32 id, HudElement *form);
+       void SendHUDRemove(u16 peer_id, u32 id);
+       void SendHUDChange(u16 peer_id, u32 id, HudElementStat stat, void *value);
        /*
                Send a node removal/addition event to all clients except ignore_id.
                Additionally, if far_players!=NULL, players further away than