Skip to content

Commit 2323842

Browse files
authoredMar 28, 2018
Add formspec theming using prepended strings
1 parent 040b878 commit 2323842

16 files changed

+150
-18
lines changed
 

Diff for: ‎doc/lua_api.txt

+15
Original file line numberDiff line numberDiff line change
@@ -2001,6 +2001,10 @@ supported. It is a string, with a somewhat strange format.
20012001
Spaces and newlines can be inserted between the blocks, as is used in the
20022002
examples.
20032003

2004+
WARNING: Minetest allows you to add elements to every single formspec instance
2005+
using player:set_formspec_prepend(), which may be the reason backgrounds are
2006+
appearing when you don't expect them to. See `no_prepend[]`
2007+
20042008
### Examples
20052009

20062010
#### Chest
@@ -2053,6 +2057,10 @@ examples.
20532057
* `position` and `anchor` elements need suitable values to avoid a formspec
20542058
extending off the game window due to particular game window sizes.
20552059

2060+
#### `no_prepend[]`
2061+
* Must be used after the `size`, `position`, and `anchor` elements (if present).
2062+
* Disables player:set_formspec_prepend() from applying to this formspec.
2063+
20562064
#### `container[<X>,<Y>]`
20572065
* Start of a container block, moves all physical elements in the container by
20582066
(X, Y).
@@ -4046,6 +4054,13 @@ This is basically a reference to a C++ `ServerActiveObject`
40464054
* Redefine player's inventory form
40474055
* Should usually be called in `on_joinplayer`
40484056
* `get_inventory_formspec()`: returns a formspec string
4057+
* `set_formspec_prepend(formspec)`:
4058+
* the formspec string will be added to every formspec shown to the user,
4059+
except for those with a no_prepend[] tag.
4060+
* This should be used to set style elements such as background[] and
4061+
bgcolor[], any non-style elements (eg: label) may result in weird behaviour.
4062+
* Only affects formspecs shown after this is called.
4063+
* `get_formspec_prepend(formspec)`: returns a formspec string.
40494064
* `get_player_control()`: returns table with player pressed keys
40504065
* The table consists of fields with boolean value representing the pressed
40514066
keys, the fields are jump, right, left, LMB, RMB, sneak, aux1, down, up.

Diff for: ‎src/client.h

+6-1
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,8 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef
224224
void handleCommand_UpdatePlayerList(NetworkPacket* pkt);
225225
void handleCommand_ModChannelMsg(NetworkPacket *pkt);
226226
void handleCommand_ModChannelSignal(NetworkPacket *pkt);
227-
void handleCommand_SrpBytesSandB(NetworkPacket* pkt);
227+
void handleCommand_SrpBytesSandB(NetworkPacket *pkt);
228+
void handleCommand_FormspecPrepend(NetworkPacket *pkt);
228229
void handleCommand_CSMFlavourLimits(NetworkPacket *pkt);
229230

230231
void ProcessData(NetworkPacket *pkt);
@@ -432,6 +433,10 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef
432433
bool sendModChannelMessage(const std::string &channel, const std::string &message);
433434
ModChannel *getModChannel(const std::string &channel);
434435

436+
const std::string &getFormspecPrepend() const
437+
{
438+
return m_env.getLocalPlayer()->formspec_prepend;
439+
}
435440
private:
436441
void loadMods();
437442
bool checkBuiltinIntegrity();

Diff for: ‎src/clientenvironment.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ class ClientEnvironment : public Environment
7878
void step(f32 dtime);
7979

8080
virtual void setLocalPlayer(LocalPlayer *player);
81-
LocalPlayer *getLocalPlayer() { return m_local_player; }
81+
LocalPlayer *getLocalPlayer() const { return m_local_player; }
8282

8383
/*
8484
ClientSimpleObjects

Diff for: ‎src/game.cpp

+7-5
Original file line numberDiff line numberDiff line change
@@ -2028,7 +2028,7 @@ void Game::openInventory()
20282028
|| !client->getScript()->on_inventory_open(fs_src->m_client->getInventory(inventoryloc))) {
20292029
TextDest *txt_dst = new TextDestPlayerInventory(client);
20302030
GUIFormSpecMenu::create(current_formspec, client, &input->joystick, fs_src,
2031-
txt_dst);
2031+
txt_dst, client->getFormspecPrepend());
20322032
cur_formname = "";
20332033
current_formspec->setFormSpec(fs_src->getForm(), inventoryloc);
20342034
}
@@ -2535,7 +2535,7 @@ void Game::handleClientEvent_ShowFormSpec(ClientEvent *event, CameraOrientation
25352535
new TextDestPlayerInventory(client, *(event->show_formspec.formname));
25362536

25372537
GUIFormSpecMenu::create(current_formspec, client, &input->joystick,
2538-
fs_src, txt_dst);
2538+
fs_src, txt_dst, client->getFormspecPrepend());
25392539
cur_formname = *(event->show_formspec.formname);
25402540
}
25412541

@@ -2548,7 +2548,8 @@ void Game::handleClientEvent_ShowLocalFormSpec(ClientEvent *event, CameraOrienta
25482548
FormspecFormSource *fs_src = new FormspecFormSource(*event->show_formspec.formspec);
25492549
LocalFormspecHandler *txt_dst =
25502550
new LocalFormspecHandler(*event->show_formspec.formname, client);
2551-
GUIFormSpecMenu::create(current_formspec, client, &input->joystick, fs_src, txt_dst);
2551+
GUIFormSpecMenu::create(current_formspec, client, &input->joystick,
2552+
fs_src, txt_dst, client->getFormspecPrepend());
25522553

25532554
delete event->show_formspec.formspec;
25542555
delete event->show_formspec.formname;
@@ -3210,7 +3211,7 @@ void Game::handlePointingAtNode(const PointedThing &pointed,
32103211
TextDest *txt_dst = new TextDestNodeMetadata(nodepos, client);
32113212

32123213
GUIFormSpecMenu::create(current_formspec, client, &input->joystick, fs_src,
3213-
txt_dst);
3214+
txt_dst, client->getFormspecPrepend());
32143215
cur_formname.clear();
32153216

32163217
current_formspec->setFormSpec(meta->getString("formspec"), inventoryloc);
@@ -4105,7 +4106,8 @@ void Game::showPauseMenu()
41054106
FormspecFormSource *fs_src = new FormspecFormSource(os.str());
41064107
LocalFormspecHandler *txt_dst = new LocalFormspecHandler("MT_PAUSE_MENU");
41074108

4108-
GUIFormSpecMenu::create(current_formspec, client, &input->joystick, fs_src, txt_dst);
4109+
GUIFormSpecMenu::create(current_formspec, client, &input->joystick,
4110+
fs_src, txt_dst, client->getFormspecPrepend());
41094111
current_formspec->setFocus("btn_continue");
41104112
current_formspec->doPause = true;
41114113
}

Diff for: ‎src/gui/guiEngine.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ GUIEngine::GUIEngine(JoystickController *joystick,
165165
m_texture_source,
166166
m_formspecgui,
167167
m_buttonhandler,
168+
"",
168169
false);
169170

170171
m_menu->allowClose(false);

Diff for: ‎src/gui/guiFormSpecMenu.cpp

+29-7
Original file line numberDiff line numberDiff line change
@@ -86,11 +86,13 @@ inline u32 clamp_u8(s32 value)
8686
GUIFormSpecMenu::GUIFormSpecMenu(JoystickController *joystick,
8787
gui::IGUIElement *parent, s32 id, IMenuManager *menumgr,
8888
Client *client, ISimpleTextureSource *tsrc, IFormSource *fsrc, TextDest *tdst,
89-
bool remap_dbl_click) :
89+
std::string formspecPrepend,
90+
bool remap_dbl_click):
9091
GUIModalMenu(RenderingEngine::get_gui_env(), parent, id, menumgr),
9192
m_invmgr(client),
9293
m_tsrc(tsrc),
9394
m_client(client),
95+
m_formspec_prepend(formspecPrepend),
9496
m_form_src(fsrc),
9597
m_text_dst(tdst),
9698
m_joystick(joystick),
@@ -128,11 +130,12 @@ GUIFormSpecMenu::~GUIFormSpecMenu()
128130
}
129131

130132
void GUIFormSpecMenu::create(GUIFormSpecMenu *&cur_formspec, Client *client,
131-
JoystickController *joystick, IFormSource *fs_src, TextDest *txt_dest)
133+
JoystickController *joystick, IFormSource *fs_src, TextDest *txt_dest,
134+
const std::string &formspecPrepend)
132135
{
133136
if (cur_formspec == nullptr) {
134137
cur_formspec = new GUIFormSpecMenu(joystick, guiroot, -1, &g_menumgr,
135-
client, client->getTextureSource(), fs_src, txt_dest);
138+
client, client->getTextureSource(), fs_src, txt_dest, formspecPrepend);
136139
cur_formspec->doPause = false;
137140

138141
/*
@@ -144,6 +147,7 @@ void GUIFormSpecMenu::create(GUIFormSpecMenu *&cur_formspec, Client *client,
144147
*/
145148

146149
} else {
150+
cur_formspec->setFormspecPrepend(formspecPrepend);
147151
cur_formspec->setFormSource(fs_src);
148152
cur_formspec->setTextDest(txt_dest);
149153
}
@@ -2008,7 +2012,6 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
20082012
);
20092013
}
20102014

2011-
20122015
m_slotbg_n = video::SColor(255,128,128,128);
20132016
m_slotbg_h = video::SColor(255,192,192,192);
20142017

@@ -2040,7 +2043,7 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
20402043

20412044
/* try to read version from first element only */
20422045
if (!elements.empty()) {
2043-
if ( parseVersionDirect(elements[0]) ) {
2046+
if (parseVersionDirect(elements[0])) {
20442047
i++;
20452048
}
20462049
}
@@ -2067,6 +2070,18 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
20672070
}
20682071
}
20692072

2073+
/* "no_prepend" element is always after "position" (or "size" element) if it used */
2074+
bool enable_prepends = true;
2075+
for (; i < elements.size(); i++) {
2076+
if (elements[i].empty())
2077+
break;
2078+
2079+
std::vector<std::string> parts = split(elements[i], '[');
2080+
if (parts[0] == "no_prepend")
2081+
enable_prepends = false;
2082+
else
2083+
break;
2084+
}
20702085

20712086
if (mydata.explicit_size) {
20722087
// compute scaling for specified form size
@@ -2120,7 +2135,7 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
21202135
// multiplied by gui_scaling, even if this means
21212136
// the form doesn't fit the screen.
21222137
double prefer_imgsize = mydata.screensize.Y / 15 *
2123-
gui_scaling;
2138+
gui_scaling;
21242139
double fitx_imgsize = mydata.screensize.X /
21252140
((5.0/4.0) * (0.5 + mydata.invsize.X));
21262141
double fity_imgsize = mydata.screensize.Y /
@@ -2173,12 +2188,19 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
21732188
mydata.basepos = getBasePos();
21742189
m_tooltip_element->setOverrideFont(m_font);
21752190

2176-
gui::IGUISkin* skin = Environment->getSkin();
2191+
gui::IGUISkin *skin = Environment->getSkin();
21772192
sanity_check(skin);
21782193
gui::IGUIFont *old_font = skin->getFont();
21792194
skin->setFont(m_font);
21802195

21812196
pos_offset = v2s32();
2197+
2198+
if (enable_prepends) {
2199+
std::vector<std::string> prepend_elements = split(m_formspec_prepend, ']');
2200+
for (const auto &element : prepend_elements)
2201+
parseElement(&mydata, element);
2202+
}
2203+
21822204
for (; i< elements.size(); i++) {
21832205
parseElement(&mydata, elements[i]);
21842206
}

Diff for: ‎src/gui/guiFormSpecMenu.h

+9-1
Original file line numberDiff line numberDiff line change
@@ -287,12 +287,14 @@ class GUIFormSpecMenu : public GUIModalMenu
287287
ISimpleTextureSource *tsrc,
288288
IFormSource* fs_src,
289289
TextDest* txt_dst,
290+
std::string formspecPrepend,
290291
bool remap_dbl_click = true);
291292

292293
~GUIFormSpecMenu();
293294

294295
static void create(GUIFormSpecMenu *&cur_formspec, Client *client,
295-
JoystickController *joystick, IFormSource *fs_src, TextDest *txt_dest);
296+
JoystickController *joystick, IFormSource *fs_src, TextDest *txt_dest,
297+
const std::string &formspecPrepend);
296298

297299
void setFormSpec(const std::string &formspec_string,
298300
const InventoryLocation &current_inventory_location)
@@ -302,6 +304,11 @@ class GUIFormSpecMenu : public GUIModalMenu
302304
regenerateGui(m_screensize_old);
303305
}
304306

307+
void setFormspecPrepend(const std::string &formspecPrepend)
308+
{
309+
m_formspec_prepend = formspecPrepend;
310+
}
311+
305312
// form_src is deleted by this GUIFormSpecMenu
306313
void setFormSource(IFormSource *form_src)
307314
{
@@ -378,6 +385,7 @@ class GUIFormSpecMenu : public GUIModalMenu
378385
Client *m_client;
379386

380387
std::string m_formspec_string;
388+
std::string m_formspec_prepend;
381389
InventoryLocation m_current_inventory_location;
382390

383391
std::vector<ListDrawSpec> m_inventorylists;

Diff for: ‎src/network/clientopcodes.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ const ToClientCommandHandler toClientCommandTable[TOCLIENT_NUM_MSG_TYPES] =
121121
null_command_handler,
122122
null_command_handler,
123123
{ "TOCLIENT_SRP_BYTES_S_B", TOCLIENT_STATE_NOT_CONNECTED, &Client::handleCommand_SrpBytesSandB }, // 0x60
124+
{ "TOCLIENT_FORMSPEC_PREPEND", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_FormspecPrepend }, // 0x61,
124125
};
125126

126127
const static ServerCommandFactory null_command_factory = { "TOSERVER_NULL", 0, false };

Diff for: ‎src/network/clientpackethandler.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -1324,6 +1324,15 @@ void Client::handleCommand_SrpBytesSandB(NetworkPacket* pkt)
13241324
Send(&resp_pkt);
13251325
}
13261326

1327+
void Client::handleCommand_FormspecPrepend(NetworkPacket *pkt)
1328+
{
1329+
LocalPlayer *player = m_env.getLocalPlayer();
1330+
assert(player != NULL);
1331+
1332+
// Store formspec in LocalPlayer
1333+
*pkt >> player->formspec_prepend;
1334+
}
1335+
13271336
void Client::handleCommand_CSMFlavourLimits(NetworkPacket *pkt)
13281337
{
13291338
*pkt >> m_csm_flavour_limits >> m_csm_noderange_limit;

Diff for: ‎src/network/networkprotocol.h

+8-2
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
187187
'zoom_fov'.
188188
Nodebox version 5
189189
Add disconnected nodeboxes
190+
Add TOCLIENT_FORMSPEC_PREPEND
190191
*/
191192

192193
#define LATEST_PROTOCOL_VERSION 36
@@ -644,7 +645,13 @@ enum ToClientCommand
644645
std::string bytes_B
645646
*/
646647

647-
TOCLIENT_NUM_MSG_TYPES = 0x61,
648+
TOCLIENT_FORMSPEC_PREPEND = 0x61,
649+
/*
650+
u16 len
651+
u8[len] formspec
652+
*/
653+
654+
TOCLIENT_NUM_MSG_TYPES = 0x62,
648655
};
649656

650657
enum ToServerCommand
@@ -930,4 +937,3 @@ enum CSMFlavourLimit : u64 {
930937
CSM_FL_LOOKUP_NODES = 0x00000010, // Limit node lookups
931938
CSM_FL_ALL = 0xFFFFFFFF,
932939
};
933-

Diff for: ‎src/network/serveropcodes.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -210,4 +210,5 @@ const ClientCommandFactory clientCommandFactoryTable[TOCLIENT_NUM_MSG_TYPES] =
210210
null_command_factory,
211211
null_command_factory,
212212
{ "TOSERVER_SRP_BYTES_S_B", 0, true }, // 0x60
213+
{ "TOCLIENT_FORMSPEC_PREPEND", 0, true }, // 0x61
213214
};

Diff for: ‎src/player.h

+1
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ class Player
148148
float local_animation_speed;
149149

150150
std::string inventory_formspec;
151+
std::string formspec_prepend;
151152

152153
PlayerControl control;
153154
const PlayerControl& getPlayerControl() { return control; }

Diff for: ‎src/script/lua_api/l_object.cpp

+33
Original file line numberDiff line numberDiff line change
@@ -1244,6 +1244,37 @@ int ObjectRef::l_get_inventory_formspec(lua_State *L)
12441244
return 1;
12451245
}
12461246

1247+
// set_formspec_prepend(self, formspec)
1248+
int ObjectRef::l_set_formspec_prepend(lua_State *L)
1249+
{
1250+
NO_MAP_LOCK_REQUIRED;
1251+
ObjectRef *ref = checkobject(L, 1);
1252+
RemotePlayer *player = getplayer(ref);
1253+
if (player == NULL)
1254+
return 0;
1255+
1256+
std::string formspec = luaL_checkstring(L, 2);
1257+
1258+
player->formspec_prepend = formspec;
1259+
getServer(L)->reportFormspecPrependModified(player->getName());
1260+
lua_pushboolean(L, true);
1261+
return 1;
1262+
}
1263+
1264+
// get_formspec_prepend(self) -> formspec
1265+
int ObjectRef::l_get_formspec_prepend(lua_State *L)
1266+
{
1267+
NO_MAP_LOCK_REQUIRED;
1268+
ObjectRef *ref = checkobject(L, 1);
1269+
RemotePlayer *player = getplayer(ref);
1270+
if (player == NULL)
1271+
return 0;
1272+
1273+
std::string formspec = player->formspec_prepend;
1274+
lua_pushlstring(L, formspec.c_str(), formspec.size());
1275+
return 1;
1276+
}
1277+
12471278
// get_player_control(self)
12481279
int ObjectRef::l_get_player_control(lua_State *L)
12491280
{
@@ -1817,6 +1848,8 @@ const luaL_Reg ObjectRef::methods[] = {
18171848
luamethod(ObjectRef, set_attribute),
18181849
luamethod(ObjectRef, set_inventory_formspec),
18191850
luamethod(ObjectRef, get_inventory_formspec),
1851+
luamethod(ObjectRef, set_formspec_prepend),
1852+
luamethod(ObjectRef, get_formspec_prepend),
18201853
luamethod(ObjectRef, get_player_control),
18211854
luamethod(ObjectRef, get_player_control_bits),
18221855
luamethod(ObjectRef, set_physics_override),

Diff for: ‎src/script/lua_api/l_object.h

+6
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,12 @@ class ObjectRef : public ModApiBase {
253253
// get_inventory_formspec(self) -> formspec
254254
static int l_get_inventory_formspec(lua_State *L);
255255

256+
// set_formspec_prepend(self, formspec)
257+
static int l_set_formspec_prepend(lua_State *L);
258+
259+
// get_formspec_prepend(self) -> formspec
260+
static int l_get_formspec_prepend(lua_State *L);
261+
256262
// get_player_control(self)
257263
static int l_get_player_control(lua_State *L);
258264

0 commit comments

Comments
 (0)
Please sign in to comment.