mirror of
https://github.com/minetest/minetest.git
synced 2024-11-27 01:53:45 +01:00
Lua HUD
This commit is contained in:
parent
1f42479e0c
commit
49f6e347f0
@ -1379,7 +1379,20 @@ 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()
|
||||
|
||||
InvRef: Reference to an inventory
|
||||
methods:
|
||||
- is_empty(listname): return true if list is empty
|
||||
@ -1802,3 +1815,20 @@ Detached inventory callbacks
|
||||
^ No return value
|
||||
}
|
||||
|
||||
HUD Definition (hud_add)
|
||||
{
|
||||
type = "I", -- One of "I"(image), "S"(statbar),
|
||||
^ "T"(text), "i"(inv)
|
||||
position = {x=0.5, y=0.5}, -- Left corner position
|
||||
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
|
||||
dir = 0,
|
||||
^ dir/inv direction: 0/left-right, 1/right-left,
|
||||
^ 2/top-bottom, 3/bottom-top
|
||||
}
|
||||
|
@ -2040,6 +2040,73 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
||||
|
||||
m_client_event_queue.push_back(event);
|
||||
}
|
||||
else if(command == TOCLIENT_HUDADD)
|
||||
{
|
||||
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);
|
||||
|
||||
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.number = number;
|
||||
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::istringstream is(datastring, std::ios_base::binary);
|
||||
|
||||
u32 id = readU32(is);
|
||||
|
||||
ClientEvent event;
|
||||
event.type = CE_HUDRM;
|
||||
event.hudrm.id = id;
|
||||
m_client_event_queue.push_back(event);
|
||||
}
|
||||
else if(command == TOCLIENT_HUDCHANGE)
|
||||
{
|
||||
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) {
|
||||
v2fdata = readV2F1000(is);
|
||||
} else if(stat == 1 || stat == 3) {
|
||||
sdata = deSerializeString(is);
|
||||
} else {
|
||||
data = readU32(is);
|
||||
}
|
||||
|
||||
ClientEvent event;
|
||||
event.type = CE_HUDCHANGE;
|
||||
event.hudchange.id = id;
|
||||
event.hudchange.stat = stat;
|
||||
event.hudchange.v2fdata = new v2f(v2fdata);
|
||||
event.hudchange.sdata = new std::string(sdata);
|
||||
event.hudchange.data = data;
|
||||
m_client_event_queue.push_back(event);
|
||||
}
|
||||
else
|
||||
{
|
||||
infostream<<"Client: Ignoring unknown command "
|
||||
|
26
src/client.h
26
src/client.h
@ -160,7 +160,10 @@ enum ClientEventType
|
||||
CE_SHOW_FORMSPEC,
|
||||
CE_SPAWN_PARTICLE,
|
||||
CE_ADD_PARTICLESPAWNER,
|
||||
CE_DELETE_PARTICLESPAWNER
|
||||
CE_DELETE_PARTICLESPAWNER,
|
||||
CE_HUDADD,
|
||||
CE_HUDRM,
|
||||
CE_HUDCHANGE
|
||||
};
|
||||
|
||||
struct ClientEvent
|
||||
@ -217,6 +220,27 @@ struct ClientEvent
|
||||
struct{
|
||||
u32 id;
|
||||
} delete_particlespawner;
|
||||
struct{
|
||||
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;
|
||||
v2f* v2fdata;
|
||||
std::string* sdata;
|
||||
u32 data;
|
||||
} hudchange;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -90,9 +90,13 @@ SharedBuffer<u8> makePacket_TOCLIENT_TIME_OF_DAY(u16 time, float time_speed);
|
||||
sound_place added to ItemDefinition
|
||||
PROTOCOL_VERSION 19:
|
||||
GENERIC_CMD_SET_PHYSICS_OVERRIDE
|
||||
PROTOCOL_VERSION 20:
|
||||
TOCLIENT_HUD_ADD
|
||||
TOCLIENT_HUD_RM
|
||||
TOCLIENT_HUD_CHANGE
|
||||
*/
|
||||
|
||||
#define LATEST_PROTOCOL_VERSION 19
|
||||
#define LATEST_PROTOCOL_VERSION 20
|
||||
|
||||
// Server's supported network protocol range
|
||||
#define SERVER_PROTOCOL_VERSION_MIN 13
|
||||
@ -433,6 +437,39 @@ enum ToClientCommand
|
||||
u16 command
|
||||
u32 id
|
||||
*/
|
||||
|
||||
TOCLIENT_HUDADD = 0x49,
|
||||
/*
|
||||
u16 command
|
||||
u32 id
|
||||
u8 type
|
||||
v2f1000 pos
|
||||
u32 len
|
||||
u8[len] name
|
||||
v2f1000 scale
|
||||
u32 len2
|
||||
u8[len2] text
|
||||
u32 number
|
||||
u32 item
|
||||
u32 dir
|
||||
*/
|
||||
|
||||
TOCLIENT_HUDRM = 0x50,
|
||||
/*
|
||||
u16 command
|
||||
u32 id
|
||||
*/
|
||||
|
||||
TOCLIENT_HUDCHANGE = 0x51,
|
||||
/*
|
||||
u16 command
|
||||
u32 id
|
||||
u8 stat
|
||||
[v2f1000 data |
|
||||
u32 len
|
||||
u8[len] data |
|
||||
u32 data]
|
||||
*/
|
||||
};
|
||||
|
||||
enum ToServerCommand
|
||||
|
261
src/game.cpp
261
src/game.cpp
@ -228,6 +228,154 @@ public:
|
||||
std::string m_formspec;
|
||||
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
|
||||
*/
|
||||
@ -242,7 +390,7 @@ void draw_hotbar(video::IVideoDriver *driver, gui::IGUIFont *font,
|
||||
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);
|
||||
@ -323,7 +471,14 @@ void draw_hotbar(video::IVideoDriver *driver, gui::IGUIFont *font,
|
||||
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
|
||||
*/
|
||||
@ -358,6 +513,10 @@ void draw_hotbar(video::IVideoDriver *driver, gui::IGUIFont *font,
|
||||
p += v2s32(16,0);
|
||||
}
|
||||
}
|
||||
#else
|
||||
draw_statbar(driver, font, gamedef, pos + v2s32(0, -20),
|
||||
"heart.png", halfheartcount);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2229,6 +2388,45 @@ void the_game(
|
||||
{
|
||||
delete_particlespawner (event.delete_particlespawner.id);
|
||||
}
|
||||
else if (event.type == CE_HUDADD)
|
||||
{
|
||||
HudElement* e = new HudElement;
|
||||
e->type = event.hudadd.type;
|
||||
e->pos = *event.hudadd.pos;
|
||||
e->name = *event.hudadd.name;
|
||||
e->scale = *event.hudadd.scale;
|
||||
e->text = *event.hudadd.text;
|
||||
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);
|
||||
}
|
||||
else if (event.type == CE_HUDRM)
|
||||
{
|
||||
player->hud.erase(event.hudrm.id);
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3212,12 +3410,71 @@ void the_game(
|
||||
player->hurt_tilt_strength = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Draw gui
|
||||
*/
|
||||
// 0-1ms
|
||||
guienv->drawAll();
|
||||
|
||||
/*
|
||||
Remove lua-texts
|
||||
*/
|
||||
for(std::deque<gui::IGUIStaticText *>::iterator it = luaguitexts.begin();
|
||||
it != luaguitexts.end(); ++it)
|
||||
(*it)->remove();
|
||||
|
||||
/*
|
||||
End scene
|
||||
*/
|
||||
|
16
src/player.h
16
src/player.h
@ -87,6 +87,7 @@ class Map;
|
||||
class IGameDef;
|
||||
struct CollisionInfo;
|
||||
class PlayerSAO;
|
||||
struct HudElement;
|
||||
|
||||
class Player
|
||||
{
|
||||
@ -243,6 +244,9 @@ public:
|
||||
|
||||
u32 keyPressed;
|
||||
|
||||
std::map<u32, HudElement*> hud;
|
||||
std::map<u8, u32> hud_bars;
|
||||
|
||||
protected:
|
||||
IGameDef *m_gamedef;
|
||||
|
||||
@ -253,6 +257,18 @@ 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
|
||||
*/
|
||||
|
@ -700,6 +700,209 @@ int ObjectRef::l_get_player_control_bits(lua_State *L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
// hud_add(self, form)
|
||||
int ObjectRef::l_hud_add(lua_State *L)
|
||||
{
|
||||
ObjectRef *ref = checkobject(L, 1);
|
||||
Player *player = getplayer(ref);
|
||||
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();
|
||||
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_pop(L, 1);
|
||||
|
||||
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)
|
||||
{
|
||||
ObjectRef *ref = checkobject(L, 1);
|
||||
Player *player = getplayer(ref);
|
||||
if(player == NULL) return 0;
|
||||
|
||||
u32 id = -1;
|
||||
if(!lua_isnil(L, 2))
|
||||
id = lua_tonumber(L, 2);
|
||||
get_server(L)->hudrm(player->getName(), id);
|
||||
player->hud.at(id)->type = (u8)NULL;
|
||||
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;
|
||||
|
||||
u32 id = -1;
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
HudElement* e = player->hud.at(lua_tonumber(L, -1));
|
||||
lua_newtable(L);
|
||||
lua_pushstring(L, std::string(1, e->type).c_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)
|
||||
@ -807,6 +1010,12 @@ const luaL_reg ObjectRef::methods[] = {
|
||||
luamethod(ObjectRef, get_inventory_formspec),
|
||||
luamethod(ObjectRef, get_player_control),
|
||||
luamethod(ObjectRef, get_player_control_bits),
|
||||
luamethod(ObjectRef, hud_add),
|
||||
luamethod(ObjectRef, hud_rm),
|
||||
luamethod(ObjectRef, hud_change),
|
||||
luamethod(ObjectRef, hud_get),
|
||||
luamethod(ObjectRef, hud_lock_next_bar),
|
||||
luamethod(ObjectRef, hud_unlock_bar),
|
||||
{0,0}
|
||||
};
|
||||
|
||||
|
@ -29,6 +29,14 @@ 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
|
||||
*/
|
||||
@ -190,6 +198,27 @@ private:
|
||||
// get_player_control_bits(self)
|
||||
static int l_get_player_control_bits(lua_State *L);
|
||||
|
||||
// hud_add(self, id, form)
|
||||
static int l_hud_add(lua_State *L);
|
||||
|
||||
// hud_rm(self, id)
|
||||
static int l_hud_rm(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);
|
||||
|
||||
|
@ -42,6 +42,15 @@ void push_v3f(lua_State *L, v3f p)
|
||||
lua_setfield(L, -2, "z");
|
||||
}
|
||||
|
||||
void push_v2f(lua_State *L, v2f p)
|
||||
{
|
||||
lua_newtable(L);
|
||||
lua_pushnumber(L, p.X);
|
||||
lua_setfield(L, -2, "x");
|
||||
lua_pushnumber(L, p.Y);
|
||||
lua_setfield(L, -2, "y");
|
||||
}
|
||||
|
||||
v2s16 read_v2s16(lua_State *L, int index)
|
||||
{
|
||||
v2s16 p;
|
||||
|
@ -81,6 +81,7 @@ std::vector<aabb3f>
|
||||
void push_v3s16 (lua_State *L, v3s16 p);
|
||||
void pushFloatPos (lua_State *L, v3f p);
|
||||
void push_v3f (lua_State *L, v3f p);
|
||||
void push_v2f (lua_State *L, v2f p);
|
||||
|
||||
|
||||
MapNode readnode(lua_State *L, int index, INodeDefManager *ndef);
|
||||
|
179
src/server.cpp
179
src/server.cpp
@ -3595,6 +3595,115 @@ void Server::SendDeleteParticleSpawnerAll(u32 id)
|
||||
}
|
||||
}
|
||||
|
||||
void Server::SendHUDAdd(u16 peer_id, const 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);
|
||||
writeU32(os, id);
|
||||
writeU8(os, form->type);
|
||||
writeV2F1000(os, form->pos);
|
||||
os<<serializeString(form->name);
|
||||
writeV2F1000(os, form->scale);
|
||||
os<<serializeString(form->text);
|
||||
writeU32(os, form->number);
|
||||
writeU32(os, form->item);
|
||||
writeU32(os, form->dir);
|
||||
|
||||
// Make data buffer
|
||||
std::string s = os.str();
|
||||
SharedBuffer<u8> data((u8*)s.c_str(), s.size());
|
||||
// Send as reliable
|
||||
m_con.Send(peer_id, 0, data, true);
|
||||
}
|
||||
|
||||
void Server::SendHUDRm(u16 peer_id, const 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);
|
||||
writeU32(os, id);
|
||||
|
||||
// Make data buffer
|
||||
std::string s = os.str();
|
||||
SharedBuffer<u8> data((u8*)s.c_str(), s.size());
|
||||
// Send as reliable
|
||||
m_con.Send(peer_id, 0, data, true);
|
||||
}
|
||||
|
||||
void Server::SendHUDChange(u16 peer_id, const u32 id, const u8 stat, v2f 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);
|
||||
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);
|
||||
|
||||
// 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::BroadcastChatMessage(const std::wstring &message)
|
||||
{
|
||||
for(std::map<u16, RemoteClient*>::iterator
|
||||
@ -4548,6 +4657,76 @@ 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
return false;
|
||||
}
|
||||
|
||||
SendHUDChange(player->peer_id, id, stat, data);
|
||||
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;
|
||||
return false;
|
||||
}
|
||||
|
||||
SendHUDChange(player->peer_id, id, stat, data);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Server::notifyPlayers(const std::wstring msg)
|
||||
{
|
||||
BroadcastChatMessage(msg);
|
||||
|
10
src/server.h
10
src/server.h
@ -534,6 +534,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);
|
||||
private:
|
||||
|
||||
// con::PeerHandler implementation.
|
||||
@ -573,6 +578,11 @@ 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);
|
||||
/*
|
||||
Send a node removal/addition event to all clients except ignore_id.
|
||||
Additionally, if far_players!=NULL, players further away than
|
||||
|
Loading…
Reference in New Issue
Block a user