aboutsummaryrefslogtreecommitdiff
path: root/src/script/lua_api/l_craft.cpp
blob: 18622ee00826faf939986a6a29e32fb233788cbc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
/*
Minetest
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>

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 "lua_api/l_craft.h"
#include "lua_api/l_internal.h"
#include "lua_api/l_item.h"
#include "common/c_converter.h"
#include "common/c_content.h"
#include "server.h"
#include "craftdef.h"

struct EnumString ModApiCraft::es_CraftMethod[] =
{
	{CRAFT_METHOD_NORMAL, "normal"},
	{CRAFT_METHOD_COOKING, "cooking"},
	{CRAFT_METHOD_FUEL, "fuel"},
	{0, NULL},
};

// helper for register_craft
bool ModApiCraft::readCraftRecipeShaped(lua_State *L, int index,
		int &width, std::vector<std::string> &recipe)
{
	if(index < 0)
		index = lua_gettop(L) + 1 + index;

	if(!lua_istable(L, index))
		return false;

	lua_pushnil(L);
	int rowcount = 0;
	while(lua_next(L, index) != 0){
		int colcount = 0;
		// key at index -2 and value at index -1
		if(!lua_istable(L, -1))
			return false;
		int table2 = lua_gettop(L);
		lua_pushnil(L);
		while(lua_next(L, table2) != 0){
			// key at index -2 and value at index -1
			if(!lua_isstring(L, -1))
				return false;
			recipe.emplace_back(readParam<std::string>(L, -1));
			// removes value, keeps key for next iteration
			lua_pop(L, 1);
			colcount++;
		}
		if(rowcount == 0){
			width = colcount;
		} else {
			if(colcount != width)
				return false;
		}
		// removes value, keeps key for next iteration
		lua_pop(L, 1);
		rowcount++;
	}
	return width != 0;
}

// helper for register_craft
bool ModApiCraft::readCraftRecipeShapeless(lua_State *L, int index,
		std::vector<std::string> &recipe)
{
	if(index < 0)
		index = lua_gettop(L) + 1 + index;

	if(!lua_istable(L, index))
		return false;

	lua_pushnil(L);
	while(lua_next(L, index) != 0){
		// key at index -2 and value at index -1
		if(!lua_isstring(L, -1))
			return false;
		recipe.emplace_back(readParam<std::string>(L, -1));
		// removes value, keeps key for next iteration
		lua_pop(L, 1);
	}
	return true;
}

// helper for register_craft
bool ModApiCraft::readCraftReplacements(lua_State *L, int index,
		CraftReplacements &replacements)
{
	if(index < 0)
		index = lua_gettop(L) + 1 + index;

	if(!lua_istable(L, index))
		return false;

	lua_pushnil(L);
	while(lua_next(L, index) != 0){
		// key at index -2 and value at index -1
		if(!lua_istable(L, -1))
			return false;
		lua_rawgeti(L, -1, 1);
		if(!lua_isstring(L, -1))
			return false;
		std::string replace_from = readParam<std::string>(L, -1);
		lua_pop(L, 1);
		lua_rawgeti(L, -1, 2);
		if(!lua_isstring(L, -1))
			return false;
		std::string replace_to = readParam<std::string>(L, -1);
		lua_pop(L, 1);
		replacements.pairs.emplace_back(replace_from, replace_to);
		// removes value, keeps key for next iteration
		lua_pop(L, 1);
	}
	return true;
}
// register_craft({output=item, recipe={{item00,item10},{item01,item11}})
int ModApiCraft::l_register_craft(lua_State *L)
{
	NO_MAP_LOCK_REQUIRED;
	//infostream<<"register_craft"<<std::endl;
	luaL_checktype(L, 1, LUA_TTABLE);
	int table = 1;

	// Get the writable craft definition manager from the server
	IWritableCraftDefManager *craftdef =
			getServer(L)->getWritableCraftDefManager();

	std::string type = getstringfield_default(L, table, "type", "shaped");

	/*
		CraftDefinitionShaped
	*/
	if(type == "shaped"){
		std::string output = getstringfield_default(L, table, "output", "");
		if (output.empty())
			throw LuaError("Crafting definition is missing an output");

		int width = 0;
		std::vector<std::string> recipe;
		lua_getfield(L, table, "recipe");
		if(lua_isnil(L, -1))
			throw LuaError("Crafting definition is missing a recipe"
					" (output=\"" + output + "\")");
		if(!readCraftRecipeShaped(L, -1, width, recipe))
			throw LuaError("Invalid crafting recipe"
					" (output=\"" + output + "\")");

		CraftReplacements replacements;
		lua_getfield(L, table, "replacements");
		if(!lua_isnil(L, -1))
		{
			if(!readCraftReplacements(L, -1, replacements))
				throw LuaError("Invalid replacements"
						" (output=\"" + output + "\")");
		}

		CraftDefinition *def = new CraftDefinitionShaped(
				output, width, recipe, replacements);
		craftdef->registerCraft(def, getServer(L));
	}
	/*
		CraftDefinitionShapeless
	*/
	else if(type == "shapeless"){
		std::string output = getstringfield_default(L, table, "output", "");
		if (output.empty())
			throw LuaError("Crafting definition (shapeless)"
					" is missing an output");

		std::vector<std::string> recipe;
		lua_getfield(L, table, "recipe");
		if(lua_isnil(L, -1))
			throw LuaError("Crafting definition (shapeless)"
					" is missing a recipe"
					" (output=\"" + output + "\")");
		if(!readCraftRecipeShapeless(L, -1, recipe))
			throw LuaError("Invalid crafting recipe"
					" (output=\"" + output + "\")");

		CraftReplacements replacements;
		lua_getfield(L, table, "replacements");
		if(!lua_isnil(L, -1))
		{
			if(!readCraftReplacements(L, -1, replacements))
				throw LuaError("Invalid replacements"
						" (output=\"" + output + "\")");
		}

		CraftDefinition *def = new CraftDefinitionShapeless(
				output, recipe, replacements);
		craftdef->registerCraft(def, getServer(L));
	}
	/*
		CraftDefinitionToolRepair
	*/
	else if(type == "toolrepair"){
		float additional_wear = getfloatfield_default(L, table,
				"additional_wear", 0.0);

		CraftDefinition *def = new CraftDefinitionToolRepair(
				additional_wear);
		craftdef->registerCraft(def, getServer(L));
	}
	/*
		CraftDefinitionCooking
	*/
	else if(type == "cooking"){
		std::string output = getstringfield_default(L, table, "output", "");
		if (output.empty())
			throw LuaError("Crafting definition (cooking)"
					" is missing an output");

		std::string recipe = getstringfield_default(L, table, "recipe", "");
		if (recipe.empty())
			throw LuaError("Crafting definition (cooking)"
					" is missing a recipe"
					" (output=\"" + output + "\")");

		float cooktime = getfloatfield_default(L, table, "cooktime", 3.0);

		CraftReplacements replacements;
		lua_getfield(L, table, "replacements");
		if(!lua_isnil(L, -1))
		{
			if(!readCraftReplacements(L, -1, replacements))
				throw LuaError("Invalid replacements"
						" (cooking output=\"" + output + "\")");
		}

		CraftDefinition *def = new CraftDefinitionCooking(
				output, recipe, cooktime, replacements);
		craftdef->registerCraft(def, getServer(L));
	}
	/*
		CraftDefinitionFuel
	*/
	else if(type == "fuel"){
		std::string recipe = getstringfield_default(L, table, "recipe", "");
		if (recipe.empty())
			throw LuaError("Crafting definition (fuel)"
					" is missing a recipe");

		float burntime = getfloatfield_default(L, table, "burntime", 1.0);

		CraftReplacements replacements;
		lua_getfield(L, table, "replacements");
		if(!lua_isnil(L, -1))
		{
			if(!readCraftReplacements(L, -1, replacements))
				throw LuaError("Invalid replacements"
						" (fuel recipe=\"" + recipe + "\")");
		}

		CraftDefinition *def = new CraftDefinitionFuel(
				recipe, burntime, replacements);
		craftdef->registerCraft(def, getServer(L));
	}
	else
	{
		throw LuaError("Unknown crafting definition type: \"" + type + "\"");
	}

	lua_pop(L, 1);
	return 0; /* number of results */
}

// clear_craft({[output=item], [recipe={{item00,item10},{item01,item11}}])
int ModApiCraft::l_clear_craft(lua_State *L)
{
	NO_MAP_LOCK_REQUIRED;
	luaL_checktype(L, 1, LUA_TTABLE);
	int table = 1;

	// Get the writable craft definition manager from the server
	IWritableCraftDefManager *craftdef =
			getServer(L)->getWritableCraftDefManager();

	std::string output = getstringfield_default(L, table, "output", "");
	std::string type = getstringfield_default(L, table, "type", "shaped");
	CraftOutput c_output(output, 0);
	if (!output.empty()) {
		if (craftdef->clearCraftsByOutput(c_output, getServer(L))) {
			lua_pushboolean(L, true);
			return 1;
		}

		warningstream << "No craft recipe known for output" << std::endl;
		lua_pushboolean(L, false);
		return 1;
	}
	std::vector<std::string> recipe;
	int width = 0;
	CraftMethod method = CRAFT_METHOD_NORMAL;
	/*
		CraftDefinitionShaped
	*/
	if (type == "shaped") {
		lua_getfield(L, table, "recipe");
		if (lua_isnil(L, -1))
			throw LuaError("Either output or recipe has to be defined");
		if (!readCraftRecipeShaped(L, -1, width, recipe))
			throw LuaError("Invalid crafting recipe");
	}
	/*
		CraftDefinitionShapeless
	*/
	else if (type == "shapeless") {
		lua_getfield(L, table, "recipe");
		if (lua_isnil(L, -1))
			throw LuaError("Either output or recipe has to be defined");
		if (!readCraftRecipeShapeless(L, -1, recipe))
			throw LuaError("Invalid crafting recipe");
	}
	/*
		CraftDefinitionCooking
	*/
	else if (type == "cooking") {
		method = CRAFT_METHOD_COOKING;
		std::string rec = getstringfield_default(L, table, "recipe", "");
		if (rec.empty())
			throw LuaError("Crafting definition (cooking)"
					" is missing a recipe");
		recipe.push_back(rec);
	}
	/*
		CraftDefinitionFuel
	*/
	else if (type == "fuel") {
		method = CRAFT_METHOD_FUEL;
		std::string rec = getstringfield_default(L, table, "recipe", "");
		if (rec.empty())
			throw LuaError("Crafting definition (fuel)"
					" is missing a recipe");
		recipe.push_back(rec);
	} else {
		throw LuaError("Unknown crafting definition type: \"" + type + "\"");
	}

	std::vector<ItemStack> items;
	items.reserve(recipe.size());
	for (const auto &item : recipe)
		items.emplace_back(item, 1, 0, getServer(L)->idef());
	CraftInput input(method, width, items);

	if (!craftdef->clearCraftsByInput(input, getServer(L))) {
		warningstream << "No craft recipe matches input" << std::endl;
		lua_pushboolean(L, false);
		return 1;
	}

	lua_pushboolean(L, true);
	return 1;
}

// get_craft_result(input)
int ModApiCraft::l_get_craft_result(lua_State *L)
{
	NO_MAP_LOCK_REQUIRED;

	int input_i = 1;
	std::string method_s = getstringfield_default(L, input_i, "method", "normal");
	enum CraftMethod method = (CraftMethod)getenumfield(L, input_i, "method",
				es_CraftMethod, CRAFT_METHOD_NORMAL);
	int width = 1;
	lua_getfield(L, input_i, "width");
	if(lua_isnumber(L, -1))
		width = luaL_checkinteger(L, -1);
	lua_pop(L, 1);
	lua_getfield(L, input_i, "items");
	std::vector<ItemStack> items = read_items(L, -1,getServer(L));
	lua_pop(L, 1); // items

	IGameDef *gdef = getServer(L);
	ICraftDefManager *cdef = gdef->cdef();
	CraftInput input(method, width, items);
	CraftOutput output;
	std::vector<ItemStack> output_replacements;
	bool got = cdef->getCraftResult(input, output, output_replacements, true, gdef);
	lua_newtable(L); // output table
	if (got) {
		ItemStack item;
		item.deSerialize(output.item, gdef->idef());
		LuaItemStack::create(L, item);
		lua_setfield(L, -2, "item");
		setintfield(L, -1, "time", output.time);
		push_items(L, output_replacements);
		lua_setfield(L, -2, "replacements");
	} else {
		LuaItemStack::create(L, ItemStack());
		lua_setfield(L, -2, "item");
		setintfield(L, -1, "time", 0);
		lua_newtable(L);
		lua_setfield(L, -2, "replacements");
	}
	lua_newtable(L); // decremented input table
	lua_pushstring(L, method_s.c_str());
	lua_setfield(L, -2, "method");
	lua_pushinteger(L, width);
	lua_setfield(L, -2, "width");
	push_items(L, input.items);
	lua_setfield(L, -2, "items");
	return 2;
}


static void push_craft_recipe(lua_State *L, IGameDef *gdef,
		const CraftDefinition *recipe,
		const CraftOutput &tmpout)
{
	CraftInput input = recipe->getInput(tmpout, gdef);
	CraftOutput output = recipe->getOutput(input, gdef);

	lua_newtable(L); // items
	std::vector<ItemStack>::const_iterator iter = input.items.begin();
	for (u16 j = 1; iter != input.items.end(); ++iter, j++) {
		if (iter->empty())
			continue;
		lua_pushstring(L, iter->name.c_str());
		lua_rawseti(L, -2, j);
	}
	lua_setfield(L, -2, "items");
	setintfield(L, -1, "width", input.width);

	std::string method_s;
	switch (input.method) {
	case CRAFT_METHOD_NORMAL:
		method_s = "normal";
		break;
	case CRAFT_METHOD_COOKING:
		method_s = "cooking";
		break;
	case CRAFT_METHOD_FUEL:
		method_s = "fuel";
		break;
	default:
		method_s = "unknown";
	}
	lua_pushstring(L, method_s.c_str());
	lua_setfield(L, -2, "method");

	// Deprecated, only for compatibility's sake
	lua_pushstring(L, method_s.c_str());
	lua_setfield(L, -2, "type");

	lua_pushstring(L, output.item.c_str());
	lua_setfield(L, -2, "output");
}

static void push_craft_recipes(lua_State *L, IGameDef *gdef,
		const std::vector<CraftDefinition*> &recipes,
		const CraftOutput &output)
{
	lua_createtable(L, recipes.size(), 0);

	if (recipes.empty()) {
		lua_pushnil(L);
		return;
	}

	std::vector<CraftDefinition*>::const_iterator it = recipes.begin();
	for (unsigned i = 0; it != recipes.end(); ++it) {
		lua_newtable(L);
		push_craft_recipe(L, gdef, *it, output);
		lua_rawseti(L, -2, ++i);
	}
}


// get_craft_recipe(result item)
int ModApiCraft::l_get_craft_recipe(lua_State *L)
{
	NO_MAP_LOCK_REQUIRED;

	std::string item = luaL_checkstring(L, 1);
	Server *server = getServer(L);
	CraftOutput output(item, 0);
	std::vector<CraftDefinition*> recipes = server->cdef()
			->getCraftRecipes(output, server, 1);

	lua_createtable(L, 1, 0);

	if (recipes.empty()) {
		lua_pushnil(L);
		lua_setfield(L, -2, "items");
		setintfield(L, -1, "width", 0);
		return 1;
	}
	push_craft_recipe(L, server, recipes[0], output);
	return 1;
}

// get_all_craft_recipes(result item)
int ModApiCraft::l_get_all_craft_recipes(lua_State *L)
{
	NO_MAP_LOCK_REQUIRED;

	std::string item = luaL_checkstring(L, 1);
	Server *server = getServer(L);
	CraftOutput output(item, 0);
	std::vector<CraftDefinition*> recipes = server->cdef()
			->getCraftRecipes(output, server);

	push_craft_recipes(L, server, recipes, output);
	return 1;
}

void ModApiCraft::Initialize(lua_State *L, int top)
{
	API_FCT(get_all_craft_recipes);
	API_FCT(get_craft_recipe);
	API_FCT(get_craft_result);
	API_FCT(register_craft);
	API_FCT(clear_craft);
}
opt">("Trilinear filtering"); gettext("Use trilinear filtering when scaling textures."); gettext("Clean transparent textures"); gettext("Filtered textures can blend RGB values with fully-transparent neighbors,\nwhich PNG optimizers usually discard, often resulting in dark or\nlight edges to transparent textures. Apply a filter to clean that up\nat texture load time. This is automatically enabled if mipmapping is enabled."); gettext("Minimum texture size"); gettext("When using bilinear/trilinear/anisotropic filters, low-resolution textures\ncan be blurred, so automatically upscale them with nearest-neighbor\ninterpolation to preserve crisp pixels. This sets the minimum texture size\nfor the upscaled textures; higher values look sharper, but require more\nmemory. Powers of 2 are recommended. This setting is ONLY applied if\nbilinear/trilinear/anisotropic filtering is enabled.\nThis is also used as the base node texture size for world-aligned\ntexture autoscaling."); gettext("FSAA"); gettext("Use multi-sample antialiasing (MSAA) to smooth out block edges.\nThis algorithm smooths out the 3D viewport while keeping the image sharp,\nbut it doesn't affect the insides of textures\n(which is especially noticeable with transparent textures).\nVisible spaces appear between nodes when shaders are disabled.\nIf set to 0, MSAA is disabled.\nA restart is required after changing this option."); gettext("Undersampling"); gettext("Undersampling is similar to using a lower screen resolution, but it applies\nto the game world only, keeping the GUI intact.\nIt should give a significant performance boost at the cost of less detailed image.\nHigher values result in a less detailed image."); gettext("Shaders"); gettext("Shaders"); gettext("Shaders allow advanced visual effects and may increase performance on some video\ncards.\nThis only works with the OpenGL video backend."); gettext("Shader path"); gettext("Path to shader directory. If no path is defined, default location will be used."); gettext("Tone Mapping"); gettext("Filmic tone mapping"); gettext("Enables Hable's 'Uncharted 2' filmic tone mapping.\nSimulates the tone curve of photographic film and how this approximates the\nappearance of high dynamic range images. Mid-range contrast is slightly\nenhanced, highlights and shadows are gradually compressed."); gettext("Waving Nodes"); gettext("Waving liquids"); gettext("Set to true to enable waving liquids (like water).\nRequires shaders to be enabled."); gettext("Waving liquids wave height"); gettext("The maximum height of the surface of waving liquids.\n4.0 = Wave height is two nodes.\n0.0 = Wave doesn't move at all.\nDefault is 1.0 (1/2 node).\nRequires waving liquids to be enabled."); gettext("Waving liquids wavelength"); gettext("Length of liquid waves.\nRequires waving liquids to be enabled."); gettext("Waving liquids wave speed"); gettext("How fast liquid waves will move. Higher = faster.\nIf negative, liquid waves will move backwards.\nRequires waving liquids to be enabled."); gettext("Waving leaves"); gettext("Set to true to enable waving leaves.\nRequires shaders to be enabled."); gettext("Waving plants"); gettext("Set to true to enable waving plants.\nRequires shaders to be enabled."); gettext("Dynamic shadows"); gettext("Dynamic shadows"); gettext("Set to true to enable Shadow Mapping.\nRequires shaders to be enabled."); gettext("Shadow strength"); gettext("Set the shadow strength.\nLower value means lighter shadows, higher value means darker shadows."); gettext("Shadow map max distance in nodes to render shadows"); gettext("Maximum distance to render shadows."); gettext("Shadow map texture size"); gettext("Texture size to render the shadow map on.\nThis must be a power of two.\nBigger numbers create better shadows but it is also more expensive."); gettext("Shadow map texture in 32 bits"); gettext("Sets shadow texture quality to 32 bits.\nOn false, 16 bits texture will be used.\nThis can cause much more artifacts in the shadow."); gettext("Poisson filtering"); gettext("Enable Poisson disk filtering.\nOn true uses Poisson disk to make \"soft shadows\". Otherwise uses PCF filtering."); gettext("Shadow filter quality"); gettext("Define shadow filtering quality.\nThis simulates the soft shadows effect by applying a PCF or Poisson disk\nbut also uses more resources."); gettext("Colored shadows"); gettext("Enable colored shadows.\nOn true translucent nodes cast colored shadows. This is expensive."); gettext("Map shadows update frames"); gettext("Spread a complete update of shadow map over given amount of frames.\nHigher values might make shadows laggy, lower values\nwill consume more resources.\nMinimum value: 1; maximum value: 16"); gettext("Soft shadow radius"); gettext("Set the soft shadow radius size.\nLower values mean sharper shadows, bigger values mean softer shadows.\nMinimum value: 1.0; maximum value: 10.0"); gettext("Sky Body Orbit Tilt"); gettext("Set the tilt of Sun/Moon orbit in degrees.\nValue of 0 means no tilt / vertical orbit.\nMinimum value: 0.0; maximum value: 60.0"); gettext("Advanced"); gettext("Arm inertia"); gettext("Arm inertia, gives a more realistic movement of\nthe arm when the camera moves."); gettext("Maximum FPS"); gettext("If FPS would go higher than this, limit it by sleeping\nto not waste CPU power for no benefit."); gettext("FPS when unfocused or paused"); gettext("Maximum FPS when the window is not focused, or when the game is paused."); gettext("Pause on lost window focus"); gettext("Open the pause menu when the window's focus is lost. Does not pause if a formspec is\nopen."); gettext("Viewing range"); gettext("View distance in nodes."); gettext("Near plane"); gettext("Camera 'near clipping plane' distance in nodes, between 0 and 0.25\nOnly works on GLES platforms. Most users will not need to change this.\nIncreasing can reduce artifacting on weaker GPUs.\n0.1 = Default, 0.25 = Good value for weaker tablets."); gettext("Screen width"); gettext("Width component of the initial window size. Ignored in fullscreen mode."); gettext("Screen height"); gettext("Height component of the initial window size. Ignored in fullscreen mode."); gettext("Autosave screen size"); gettext("Save window size automatically when modified."); gettext("Full screen"); gettext("Fullscreen mode."); gettext("VSync"); gettext("Vertical screen synchronization."); gettext("Field of view"); gettext("Field of view in degrees."); gettext("Light curve gamma"); gettext("Alters the light curve by applying 'gamma correction' to it.\nHigher values make middle and lower light levels brighter.\nValue '1.0' leaves the light curve unaltered.\nThis only has significant effect on daylight and artificial\nlight, it has very little effect on natural night light."); gettext("Light curve low gradient"); gettext("Gradient of light curve at minimum light level.\nControls the contrast of the lowest light levels."); gettext("Light curve high gradient"); gettext("Gradient of light curve at maximum light level.\nControls the contrast of the highest light levels."); gettext("Light curve boost"); gettext("Strength of light curve boost.\nThe 3 'boost' parameters define a range of the light\ncurve that is boosted in brightness."); gettext("Light curve boost center"); gettext("Center of light curve boost range.\nWhere 0.0 is minimum light level, 1.0 is maximum light level."); gettext("Light curve boost spread"); gettext("Spread of light curve boost range.\nControls the width of the range to be boosted.\nStandard deviation of the light curve boost Gaussian."); gettext("Texture path"); gettext("Path to texture directory. All textures are first searched from here."); gettext("Video driver"); gettext("The rendering back-end.\nA restart is required after changing this.\nNote: On Android, stick with OGLES1 if unsure! App may fail to start otherwise.\nOn other platforms, OpenGL is recommended.\nShaders are supported by OpenGL (desktop only) and OGLES2 (experimental)"); gettext("Cloud radius"); gettext("Radius of cloud area stated in number of 64 node cloud squares.\nValues larger than 26 will start to produce sharp cutoffs at cloud area corners."); gettext("View bobbing factor"); gettext("Enable view bobbing and amount of view bobbing.\nFor example: 0 for no view bobbing; 1.0 for normal; 2.0 for double."); gettext("Fall bobbing factor"); gettext("Multiplier for fall bobbing.\nFor example: 0 for no view bobbing; 1.0 for normal; 2.0 for double."); gettext("3D mode"); gettext("3D support.\nCurrently supported:\n- none: no 3d output.\n- anaglyph: cyan/magenta color 3d.\n- interlaced: odd/even line based polarisation screen support.\n- topbottom: split screen top/bottom.\n- sidebyside: split screen side by side.\n- crossview: Cross-eyed 3d\n- pageflip: quadbuffer based 3d.\nNote that the interlaced mode requires shaders to be enabled."); gettext("3D mode parallax strength"); gettext("Strength of 3D mode parallax."); gettext("Console height"); gettext("In-game chat console height, between 0.1 (10%) and 1.0 (100%)."); gettext("Console color"); gettext("In-game chat console background color (R,G,B)."); gettext("Console alpha"); gettext("In-game chat console background alpha (opaqueness, between 0 and 255)."); gettext("Formspec Full-Screen Background Opacity"); gettext("Formspec full-screen background opacity (between 0 and 255)."); gettext("Formspec Full-Screen Background Color"); gettext("Formspec full-screen background color (R,G,B)."); gettext("Formspec Default Background Opacity"); gettext("Formspec default background opacity (between 0 and 255)."); gettext("Formspec Default Background Color"); gettext("Formspec default background color (R,G,B)."); gettext("Selection box color"); gettext("Selection box border color (R,G,B)."); gettext("Selection box width"); gettext("Width of the selection box lines around nodes."); gettext("Crosshair color"); gettext("Crosshair color (R,G,B).\nAlso controls the object crosshair color"); gettext("Crosshair alpha"); gettext("Crosshair alpha (opaqueness, between 0 and 255).\nThis also applies to the object crosshair."); gettext("Recent Chat Messages"); gettext("Maximum number of recent chat messages to show"); gettext("Desynchronize block animation"); gettext("Whether node texture animations should be desynchronized per mapblock."); gettext("Maximum hotbar width"); gettext("Maximum proportion of current window to be used for hotbar.\nUseful if there's something to be displayed right or left of hotbar."); gettext("HUD scale factor"); gettext("Modifies the size of the HUD elements."); gettext("Mesh cache"); gettext("Enables caching of facedir rotated meshes."); gettext("Mapblock mesh generation delay"); gettext("Delay between mesh updates on the client in ms. Increasing this will slow\ndown the rate of mesh updates, thus reducing jitter on slower clients."); gettext("Mapblock mesh generator's MapBlock cache size in MB"); gettext("Size of the MapBlock cache of the mesh generator. Increasing this will\nincrease the cache hit %, reducing the data being copied from the main\nthread, thus reducing jitter."); gettext("Minimap"); gettext("Enables minimap."); gettext("Round minimap"); gettext("Shape of the minimap. Enabled = round, disabled = square."); gettext("Minimap scan height"); gettext("True = 256\nFalse = 128\nUsable to make minimap smoother on slower machines."); gettext("Colored fog"); gettext("Make fog and sky colors depend on daytime (dawn/sunset) and view direction."); gettext("Ambient occlusion gamma"); gettext("The strength (darkness) of node ambient-occlusion shading.\nLower is darker, Higher is lighter. The valid range of values for this\nsetting is 0.25 to 4.0 inclusive. If the value is out of range it will be\nset to the nearest valid value."); gettext("Inventory items animations"); gettext("Enables animation of inventory items."); gettext("Fog start"); gettext("Fraction of the visible distance at which fog starts to be rendered"); gettext("Opaque liquids"); gettext("Makes all liquids opaque"); gettext("World-aligned textures mode"); gettext("Textures on a node may be aligned either to the node or to the world.\nThe former mode suits better things like machines, furniture, etc., while\nthe latter makes stairs and microblocks fit surroundings better.\nHowever, as this possibility is new, thus may not be used by older servers,\nthis option allows enforcing it for certain node types. Note though that\nthat is considered EXPERIMENTAL and may not work properly."); gettext("Autoscaling mode"); gettext("World-aligned textures may be scaled to span several nodes. However,\nthe server may not send the scale you want, especially if you use\na specially-designed texture pack; with this option, the client tries\nto determine the scale automatically basing on the texture size.\nSee also texture_min_size.\nWarning: This option is EXPERIMENTAL!"); gettext("Show entity selection boxes"); gettext("Show entity selection boxes\nA restart is required after changing this."); gettext("Menus"); gettext("Clouds in menu"); gettext("Use a cloud animation for the main menu background."); gettext("GUI scaling"); gettext("Scale GUI by a user specified value.\nUse a nearest-neighbor-anti-alias filter to scale the GUI.\nThis will smooth over some of the rough edges, and blend\npixels when scaling down, at the cost of blurring some\nedge pixels when images are scaled by non-integer sizes."); gettext("GUI scaling filter"); gettext("When gui_scaling_filter is true, all GUI images need to be\nfiltered in software, but some images are generated directly\nto hardware (e.g. render-to-texture for nodes in inventory)."); gettext("GUI scaling filter txr2img"); gettext("When gui_scaling_filter_txr2img is true, copy those images\nfrom hardware to software for scaling. When false, fall back\nto the old scaling method, for video drivers that don't\nproperly support downloading textures back from hardware."); gettext("Tooltip delay"); gettext("Delay showing tooltips, stated in milliseconds."); gettext("Append item name"); gettext("Append item name to tooltip."); gettext("FreeType fonts"); gettext("Whether FreeType fonts are used, requires FreeType support to be compiled in.\nIf disabled, bitmap and XML vectors fonts are used instead."); gettext("Font bold by default"); gettext("Font italic by default"); gettext("Font shadow"); gettext("Shadow offset (in pixels) of the default font. If 0, then shadow will not be drawn."); gettext("Font shadow alpha"); gettext("Opaqueness (alpha) of the shadow behind the default font, between 0 and 255."); gettext("Font size"); gettext("Font size of the default font in point (pt)."); gettext("Regular font path"); gettext("Path to the default font.\nIf “freetype” setting is enabled: Must be a TrueType font.\nIf “freetype” setting is disabled: Must be a bitmap or XML vectors font.\nThe fallback font will be used if the font cannot be loaded."); gettext("Bold font path"); gettext("Italic font path"); gettext("Bold and italic font path"); gettext("Monospace font size"); gettext("Font size of the monospace font in point (pt)."); gettext("Monospace font path"); gettext("Path to the monospace font.\nIf “freetype” setting is enabled: Must be a TrueType font.\nIf “freetype” setting is disabled: Must be a bitmap or XML vectors font.\nThis font is used for e.g. the console and profiler screen."); gettext("Bold monospace font path"); gettext("Italic monospace font path"); gettext("Bold and italic monospace font path"); gettext("Fallback font path"); gettext("Path of the fallback font.\nIf “freetype” setting is enabled: Must be a TrueType font.\nIf “freetype” setting is disabled: Must be a bitmap or XML vectors font.\nThis font will be used for certain languages or if the default font is unavailable."); gettext("Chat font size"); gettext("Font size of the recent chat text and chat prompt in point (pt).\nValue 0 will use the default font size."); gettext("Screenshot folder"); gettext("Path to save screenshots at. Can be an absolute or relative path.\nThe folder will be created if it doesn't already exist."); gettext("Screenshot format"); gettext("Format of screenshots."); gettext("Screenshot quality"); gettext("Screenshot quality. Only used for JPEG format.\n1 means worst quality; 100 means best quality.\nUse 0 for default quality."); gettext("Advanced"); gettext("DPI"); gettext("Adjust dpi configuration to your screen (non X11/Android only) e.g. for 4k screens."); gettext("Display Density Scaling Factor"); gettext("Adjust the detected display density, used for scaling UI elements."); gettext("Enable console window"); gettext("Windows systems only: Start Minetest with the command line window in the background.\nContains the same information as the file debug.txt (default name)."); gettext("Sound"); gettext("Sound"); gettext("Enables the sound system.\nIf disabled, this completely disables all sounds everywhere and the in-game\nsound controls will be non-functional.\nChanging this setting requires a restart."); gettext("Volume"); gettext("Volume of all sounds.\nRequires the sound system to be enabled."); gettext("Mute sound"); gettext("Whether to mute sounds. You can unmute sounds at any time, unless the\nsound system is disabled (enable_sound=false).\nIn-game, you can toggle the mute state with the mute key or by using the\npause menu."); gettext("Client"); gettext("Chat weblinks"); gettext("Clickable weblinks (middle-click or Ctrl+left-click) enabled in chat console output."); gettext("Weblink color"); gettext("Optional override for chat weblink color."); gettext("Network"); gettext("Server address"); gettext("Address to connect to.\nLeave this blank to start a local server.\nNote that the address field in the main menu overrides this setting."); gettext("Remote port"); gettext("Port to connect to (UDP).\nNote that the port field in the main menu overrides this setting."); gettext("Prometheus listener address"); gettext("Prometheus listener address.\nIf Minetest is compiled with ENABLE_PROMETHEUS option enabled,\nenable metrics listener for Prometheus on that address.\nMetrics can be fetched on http://127.0.0.1:30000/metrics"); gettext("Saving map received from server"); gettext("Save the map received by the client on disk."); gettext("Connect to external media server"); gettext("Enable usage of remote media server (if provided by server).\nRemote servers offer a significantly faster way to download media (e.g. textures)\nwhen connecting to the server."); gettext("Client modding"); gettext("Enable Lua modding support on client.\nThis support is experimental and API can change."); gettext("Serverlist URL"); gettext("URL to the server list displayed in the Multiplayer Tab."); gettext("Serverlist file"); gettext("File in client/serverlist/ that contains your favorite servers displayed in the\nMultiplayer Tab."); gettext("Maximum size of the out chat queue"); gettext("Maximum size of the out chat queue.\n0 to disable queueing and -1 to make the queue size unlimited."); gettext("Enable register confirmation"); gettext("Enable register confirmation when connecting to server.\nIf disabled, new account will be registered automatically."); gettext("Advanced"); gettext("Mapblock unload timeout"); gettext("Timeout for client to remove unused map data from memory."); gettext("Mapblock limit"); gettext("Maximum number of mapblocks for client to be kept in memory.\nSet to -1 for unlimited amount."); gettext("Show debug info"); gettext("Whether to show the client debug info (has the same effect as hitting F5)."); gettext("Server / Singleplayer"); gettext("Server name"); gettext("Name of the server, to be displayed when players join and in the serverlist."); gettext("Server description"); gettext("Description of server, to be displayed when players join and in the serverlist."); gettext("Server address"); gettext("Domain name of server, to be displayed in the serverlist."); gettext("Server URL"); gettext("Homepage of server, to be displayed in the serverlist."); gettext("Announce server"); gettext("Automatically report to the serverlist."); gettext("Serverlist URL"); gettext("Announce to this serverlist."); gettext("Strip color codes"); gettext("Remove color codes from incoming chat messages\nUse this to stop players from being able to use color in their messages"); gettext("Network"); gettext("Server port"); gettext("Network port to listen (UDP).\nThis value will be overridden when starting from the main menu."); gettext("Bind address"); gettext("The network interface that the server listens on."); gettext("Strict protocol checking"); gettext("Enable to disallow old clients from connecting.\nOlder clients are compatible in the sense that they will not crash when connecting\nto new servers, but they may not support all new features that you are expecting."); gettext("Remote media"); gettext("Specifies URL from which client fetches media instead of using UDP.\n$filename should be accessible from $remote_media$filename via cURL\n(obviously, remote_media should end with a slash).\nFiles that are not present will be fetched the usual way."); gettext("IPv6 server"); gettext("Enable/disable running an IPv6 server.\nIgnored if bind_address is set.\nNeeds enable_ipv6 to be enabled."); gettext("Advanced"); gettext("Maximum simultaneous block sends per client"); gettext("Maximum number of blocks that are simultaneously sent per client.\nThe maximum total count is calculated dynamically:\nmax_total = ceil((#clients + max_users) * per_client / 4)"); gettext("Delay in sending blocks after building"); gettext("To reduce lag, block transfers are slowed down when a player is building something.\nThis determines how long they are slowed down after placing or removing a node."); gettext("Max. packets per iteration"); gettext("Maximum number of packets sent per send step, if you have a slow connection\ntry reducing it, but don't reduce it to a number below double of targeted\nclient number."); gettext("Map Compression Level for Network Transfer"); gettext("Compression level to use when sending mapblocks to the client.\n-1 - use default compression level\n0 - least compression, fastest\n9 - best compression, slowest"); gettext("Game"); gettext("Default game"); gettext("Default game when creating a new world.\nThis will be overridden when creating a world from the main menu."); gettext("Message of the day"); gettext("Message of the day displayed to players connecting."); gettext("Maximum users"); gettext("Maximum number of players that can be connected simultaneously."); gettext("Map directory"); gettext("World directory (everything in the world is stored here).\nNot needed if starting from the main menu."); gettext("Item entity TTL"); gettext("Time in seconds for item entity (dropped items) to live.\nSetting it to -1 disables the feature."); gettext("Default stack size"); gettext("Specifies the default stack size of nodes, items and tools.\nNote that mods or games may explicitly set a stack for certain (or all) items."); gettext("Damage"); gettext("Enable players getting damage and dying."); gettext("Creative"); gettext("Enable creative mode for all players"); gettext("Fixed map seed"); gettext("A chosen map seed for a new map, leave empty for random.\nWill be overridden when creating a new world in the main menu."); gettext("Default password"); gettext("New users need to input this password."); gettext("Default privileges"); gettext("The privileges that new users automatically get.\nSee /privs in game for a full list on your server and mod configuration."); gettext("Basic privileges"); gettext("Privileges that players with basic_privs can grant"); gettext("Unlimited player transfer distance"); gettext("Whether players are shown to clients without any range limit.\nDeprecated, use the setting player_transfer_distance instead."); gettext("Player transfer distance"); gettext("Defines the maximal player transfer distance in blocks (0 = unlimited)."); gettext("Player versus player"); gettext("Whether to allow players to damage and kill each other."); gettext("Mod channels"); gettext("Enable mod channels support."); gettext("Static spawnpoint"); gettext("If this is set, players will always (re)spawn at the given position."); gettext("Disallow empty passwords"); gettext("If enabled, new players cannot join with an empty password."); gettext("Disable anticheat"); gettext("If enabled, disable cheat prevention in multiplayer."); gettext("Rollback recording"); gettext("If enabled, actions are recorded for rollback.\nThis option is only read when server starts."); gettext("Chat message format"); gettext("Format of player chat messages. The following strings are valid placeholders:\n@name, @message, @timestamp (optional)"); gettext("Chat command time message threshold"); gettext("If the execution of a chat command takes longer than this specified time in\nseconds, add the time information to the chat command message"); gettext("Shutdown message"); gettext("A message to be displayed to all clients when the server shuts down."); gettext("Crash message"); gettext("A message to be displayed to all clients when the server crashes."); gettext("Ask to reconnect after crash"); gettext("Whether to ask clients to reconnect after a (Lua) crash.\nSet this to true if your server is set up to restart automatically."); gettext("Active object send range"); gettext("From how far clients know about objects, stated in mapblocks (16 nodes).\n\nSetting this larger than active_block_range will also cause the server\nto maintain active objects up to this distance in the direction the\nplayer is looking. (This can avoid mobs suddenly disappearing from view)"); gettext("Active block range"); gettext("The radius of the volume of blocks around every player that is subject to the\nactive block stuff, stated in mapblocks (16 nodes).\nIn active blocks objects are loaded and ABMs run.\nThis is also the minimum range in which active objects (mobs) are maintained.\nThis should be configured together with active_object_send_range_blocks."); gettext("Max block send distance"); gettext("From how far blocks are sent to clients, stated in mapblocks (16 nodes)."); gettext("Maximum forceloaded blocks"); gettext("Maximum number of forceloaded mapblocks."); gettext("Time send interval"); gettext("Interval of sending time of day to clients."); gettext("Time speed"); gettext("Controls length of day/night cycle.\nExamples:\n72 = 20min, 360 = 4min, 1 = 24hour, 0 = day/night/whatever stays unchanged."); gettext("World start time"); gettext("Time of day when a new world is started, in millihours (0-23999)."); gettext("Map save interval"); gettext("Interval of saving important changes in the world, stated in seconds."); gettext("Chat message max length"); gettext("Set the maximum character length of a chat message sent by clients."); gettext("Chat message count limit"); gettext("Amount of messages a player may send per 10 seconds."); gettext("Chat message kick threshold"); gettext("Kick players who sent more than X messages per 10 seconds."); gettext("Physics"); gettext("Default acceleration"); gettext("Horizontal and vertical acceleration on ground or when climbing,\nin nodes per second per second."); gettext("Acceleration in air"); gettext("Horizontal acceleration in air when jumping or falling,\nin nodes per second per second."); gettext("Fast mode acceleration"); gettext("Horizontal and vertical acceleration in fast mode,\nin nodes per second per second."); gettext("Walking speed"); gettext("Walking and flying speed, in nodes per second."); gettext("Sneaking speed"); gettext("Sneaking speed, in nodes per second."); gettext("Fast mode speed"); gettext("Walking, flying and climbing speed in fast mode, in nodes per second."); gettext("Climbing speed"); gettext("Vertical climbing speed, in nodes per second."); gettext("Jumping speed"); gettext("Initial vertical speed when jumping, in nodes per second."); gettext("Liquid fluidity"); gettext("Decrease this to increase liquid resistance to movement."); gettext("Liquid fluidity smoothing"); gettext("Maximum liquid resistance. Controls deceleration when entering liquid at\nhigh speed."); gettext("Liquid sinking"); gettext("Controls sinking speed in liquid."); gettext("Gravity"); gettext("Acceleration of gravity, in nodes per second per second."); gettext("Advanced"); gettext("Deprecated Lua API handling"); gettext("Handling for deprecated Lua API calls:\n- none: Do not log deprecated calls\n- log: mimic and log backtrace of deprecated call (default).\n- error: abort on usage of deprecated call (suggested for mod developers)."); gettext("Max. clearobjects extra blocks"); gettext("Number of extra blocks that can be loaded by /clearobjects at once.\nThis is a trade-off between SQLite transaction overhead and\nmemory consumption (4096=100MB, as a rule of thumb)."); gettext("Unload unused server data"); gettext("How much the server will wait before unloading unused mapblocks.\nHigher value is smoother, but will use more RAM."); gettext("Maximum objects per block"); gettext("Maximum number of statically stored objects in a block."); gettext("Synchronous SQLite"); gettext("See https://www.sqlite.org/pragma.html#pragma_synchronous"); gettext("Map Compression Level for Disk Storage"); gettext("Compression level to use when saving mapblocks to disk.\n-1 - use default compression level\n0 - least compression, fastest\n9 - best compression, slowest"); gettext("Dedicated server step"); gettext("Length of a server tick and the interval at which objects are generally updated over\nnetwork."); gettext("Active block management interval"); gettext("Length of time between active block management cycles"); gettext("ABM interval"); gettext("Length of time between Active Block Modifier (ABM) execution cycles"); gettext("ABM time budget"); gettext("The time budget allowed for ABMs to execute on each step\n(as a fraction of the ABM Interval)"); gettext("NodeTimer interval"); gettext("Length of time between NodeTimer execution cycles"); gettext("Ignore world errors"); gettext("If enabled, invalid world data won't cause the server to shut down.\nOnly enable this if you know what you are doing."); gettext("Liquid loop max"); gettext("Max liquids processed per step."); gettext("Liquid queue purge time"); gettext("The time (in seconds) that the liquids queue may grow beyond processing\ncapacity until an attempt is made to decrease its size by dumping old queue\nitems. A value of 0 disables the functionality."); gettext("Liquid update tick"); gettext("Liquid update interval in seconds."); gettext("Block send optimize distance");