aboutsummaryrefslogtreecommitdiff
path: root/src/script/lua_api/l_settings.cpp
blob: 9c88a3e05e7c64dd1bdf94d5e0a9600e0e4d1b14 (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
# Test Tools readme

Test Tools is a mod for developers that adds a bunch of tools to directly manipulate nodes and entities. This is great for quickly testing out stuff.

Here's the list of tools:

## Remover
Removes nodes and non-player entities that you punch.

## Node Setter
Replace a node with another one.

First, punch a node you want to remember.
Then rightclick any other node to replace it with the node you remembered.

If you rightclick while pointing nothing, you can manually enter the node and param2.

## Param2 Tool
Change the value param2 of nodes.

* Punch: Add 1 to param2
* Sneak+Punch: Add 8 to param2
* Place: Subtract 1 from param2
* Sneak+Place: Subtract 8 from param2

Note: Use the debug screen (F5) to see the param2 of the pointed node.

## Falling Node Tool
Turns nodes into falling nodes.

Usage:

* Punch node: Make it fall
* Place: Try to teleport up to 2 units upwards, then make it fall

## Node Meta Editor
Edit and view metadata of nodes.

Usage:

* Punch: Open node metadata editor

## Entity Rotator
Changes the entity rotation (with `set_rotation`).

Usage:

* Punch entity: Rotate yaw
* Punch entity while holding down “Sneak” key: Rotate pitch
* Punch entity while holding down “Special” key (aka “Aux”): Rotate roll

Each usage rotates the entity by 22.5°.

## Entity Spawner
Spawns entities.

Usage:

* Punch to select entity or spawn one directly
* Place to place selected entity

## Object Property Editor
Edits properties of objects.

Usage:

* Punch object to open a formspec that allows you to view and edit properties
* Punch air to edit properties of your own player object

To edit a property, select it in the list, enter a new value (in Lua syntax)
and hit “Submit”.

## Object Attacher
Allows you to attach an object to another one.

Basic usage:
* First select the parent object, then the child object that should be attached
* Selecting an object is done by punching it
* Sneak+punch to detach selected object
* If you punch air, you select yourself

Configuration:
* Place: Increase attachment Y position
* Sneak+place: decrease attachment Y posi/*
Minetest
Copyright (C) 2013 PilzAdam <pilzadam@minetest.net>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include "lua_api/l_settings.h"
#include "lua_api/l_internal.h"
#include "settings.h"
#include "log.h"

// garbage collector
int LuaSettings::gc_object(lua_State* L)
{
	LuaSettings* o = *(LuaSettings **)(lua_touserdata(L, 1));
	delete o;
	return 0;
}

// get(self, key) -> value
int LuaSettings::l_get(lua_State* L)
{
	NO_MAP_LOCK_REQUIRED;
	LuaSettings* o = checkobject(L, 1);

	std::string key = std::string(luaL_checkstring(L, 2));
	if (o->m_settings->exists(key)) {
		std::string value = o->m_settings->get(key);
		lua_pushstring(L, value.c_str());
	} else {
		lua_pushnil(L);
	}

	return 1;
}

// get_bool(self, key) -> boolean
int LuaSettings::l_get_bool(lua_State* L)
{
	NO_MAP_LOCK_REQUIRED;
	LuaSettings* o = checkobject(L, 1);

	std::string key = std::string(luaL_checkstring(L, 2));
	if (o->m_settings->exists(key)) {
		bool value = o->m_settings->getBool(key);
		lua_pushboolean(L, value);
	} else {
		lua_pushnil(L);
	}

	return 1;
}

// set(self, key, value)
int LuaSettings::l_set(lua_State* L)
{
	NO_MAP_LOCK_REQUIRED;
	LuaSettings* o = checkobject(L, 1);

	std::string key = std::string(luaL_checkstring(L, 2));
	const char* value = luaL_checkstring(L, 3);

	if (!o->m_settings->set(key, value))
		throw LuaError("Invalid sequence found in setting parameters");

	return 0;
}

// remove(self, key) -> success
int LuaSettings::l_remove(lua_State* L)
{
	NO_MAP_LOCK_REQUIRED;
	LuaSettings* o = checkobject(L, 1);

	std::string key = std::string(luaL_checkstring(L, 2));

	bool success = o->m_settings->remove(key);
	lua_pushboolean(L, success);

	return 1;
}

// get_names(self) -> {key1, ...}
int LuaSettings::l_get_names(lua_State* L)
{
	NO_MAP_LOCK_REQUIRED;
	LuaSettings* o = checkobject(L, 1);

	std::vector<std::string> keys = o->m_settings->getNames();

	lua_newtable(L);
	for (unsigned int i=0; i < keys.size(); i++)
	{
		lua_pushstring(L, keys[i].c_str());
		lua_rawseti(L, -2, i + 1);
	}

	return 1;
}

// write(self) -> success
int LuaSettings::l_write(lua_State* L)
{
	NO_MAP_LOCK_REQUIRED;
	LuaSettings* o = checkobject(L, 1);

	bool success = o->m_settings->updateConfigFile(o->m_filename.c_str());
	lua_pushboolean(L, success);

	return 1;
}

// to_table(self) -> {[key1]=value1,...}
int LuaSettings::l_to_table(lua_State* L)
{
	NO_MAP_LOCK_REQUIRED;
	LuaSettings* o = checkobject(L, 1);

	std::vector<std::string> keys = o->m_settings->getNames();

	lua_newtable(L);
	for (unsigned int i=0; i < keys.size(); i++)
	{
		lua_pushstring(L, o->m_settings->get(keys[i]).c_str());
		lua_setfield(L, -2, keys[i].c_str());
	}

	return 1;
}

LuaSettings::LuaSettings(const char* filename)
{
	m_filename = std::string(filename);

	m_settings = new Settings();
	m_settings->readConfigFile(m_filename.c_str());
}

LuaSettings::~LuaSettings()
{
	delete m_settings;
}

void LuaSettings::Register(lua_State* L)
{
	lua_newtable(L);
	int methodtable = lua_gettop(L);
	luaL_newmetatable(L, className);
	int metatable = lua_gettop(L);

	lua_pushliteral(L, "__metatable");
	lua_pushvalue(L, methodtable);
	lua_settable(L, metatable);  // hide metatable from Lua getmetatable()

	lua_pushliteral(L, "__index");
	lua_pushvalue(L, methodtable);
	lua_settable(L, metatable);

	lua_pushliteral(L, "__gc");
	lua_pushcfunction(L, gc_object);
	lua_settable(L, metatable);

	lua_pop(L, 1);  // drop metatable

	luaL_openlib(L, 0, methods, 0);  // fill methodtable
	lua_pop(L, 1);  // drop methodtable

	// Can be created from Lua (Settings(filename))
	lua_register(L, className, create_object);
}

// LuaSettings(filename)
// Creates an LuaSettings and leaves it on top of stack
int LuaSettings::create_object(lua_State* L)
{
	NO_MAP_LOCK_REQUIRED;
	const char* filename = luaL_checkstring(L, 1);
	LuaSettings* o = new LuaSettings(filename);
	*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
	luaL_getmetatable(L, className);
	lua_setmetatable(L, -2);
	return 1;
}

LuaSettings* LuaSettings::checkobject(lua_State* L, int narg)
{
	NO_MAP_LOCK_REQUIRED;
	luaL_checktype(L, narg, LUA_TUSERDATA);
	void *ud = luaL_checkudata(L, narg, className);
	if(!ud) luaL_typerror(L, narg, className);
	return *(LuaSettings**)ud;  // unbox pointer
}

const char LuaSettings::className[] = "Settings";
const luaL_reg LuaSettings::methods[] = {
	luamethod(LuaSettings, get),
	luamethod(LuaSettings, get_bool),
	luamethod(LuaSettings, set),
	luamethod(LuaSettings, remove),
	luamethod(LuaSettings, get_names),
	luamethod(LuaSettings, write),
	luamethod(LuaSettings, to_table),
	{0,0}
};