aboutsummaryrefslogtreecommitdiff
path: root/src/script/cpp_api/s_mainmenu.cpp
blob: 1e9ba3a41cf9cb95fad57f65c790fbf03f27cf13 (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
/*
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 "cpp_api/s_mainmenu.h"
#include "cpp_api/s_internal.h"
#include "common/c_converter.h"

void ScriptApiMainMenu::setMainMenuData(MainMenuDataForScript *data)
{
	SCRIPTAPI_PRECHECKHEADER

	lua_getglobal(L, "gamedata");
	int gamedata_idx = lua_gettop(L);
	lua_pushstring(L, "errormessage");
	if (!data->errormessage.empty()) {
		lua_pushstring(L, data->errormessage.c_str());
	} else {
		lua_pushnil(L);
	}
	lua_settable(L, gamedata_idx);
	setboolfield(L, gamedata_idx, "reconnect_requested", data->reconnect_requested);
	lua_pop(L, 1);
}

void ScriptApiMainMenu::handleMainMenuEvent(std::string text)
{
	SCRIPTAPI_PRECHECKHEADER

	int error_handler = PUSH_ERROR_HANDLER(L);

	// Get handler function
	lua_getglobal(L, "core");
	lua_getfield(L, -1, "event_handler");
	lua_remove(L, -2); // Remove core
	if (lua_isnil(L, -1)) {
		lua_pop(L, 1); // Pop event_handler
		return;
	}
	luaL_checktype(L, -1, LUA_TFUNCTION);

	// Call it
	lua_pushstring(L, text.c_str());
	PCALL_RES(lua_pcall(L, 1, 0, error_handler));
	lua_pop(L, 1); // Pop error handler
}

void ScriptApiMainMenu::handleMainMenuButtons(const StringMap &fields)
{
	SCRIPTAPI_PRECHECKHEADER

	int error_handler = PUSH_ERROR_HANDLER(L);

	// Get handler function
	lua_getglobal(L, "core");
	lua_getfield(L, -1, "button_handler");
	lua_remove(L, -2); // Remove core
	if (lua_isnil(L, -1)) {
		lua_pop(L, 1); // Pop button handler
		return;
	}
	luaL_checktype(L, -1, LUA_TFUNCTION);

	// Convert fields to a Lua table
	lua_newtable(L);
	StringMap::const_iterator it;
	for (it = fields.begin(); it != fields.end(); ++it) {
		const std::string &name = it->first;
		const std::string &value = it->second;
		lua_pushstring(L, name.c_str());
		lua_pushlstring(L, value.c_str(), value.size());
		lua_settable(L, -3);
	}

	// Call it
	PCALL_RES(lua_pcall(L, 1, 0, error_handler));
	lua_pop(L, 1); // Pop error handler
}
/span> for index, ppos in pairs(train.path) do if vector.equals(advtrains.round_vector_floor_y(ppos), pos) then advtrains.trains[train_id].atc_arrow = vector.equals( advtrains.dirCoordSet(pos, arrowconn), advtrains.round_vector_floor_y(train.path[index+train.movedir]) ) advtrains.trains[train_id].atc_command=atc.controllers[pts].command atprint("Sending ATC Command: ", atc.controllers[pts].command) return true end end atwarn("ATC rail at", pos, ": Rail not on train's path! Can't determine arrow direction. Assuming +!") advtrains.trains[train_id].atc_arrow=true advtrains.trains[train_id].atc_command=atc.controllers[pts].command atprint("Sending ATC Command: ", atc.controllers[pts].command) else atwarn("ATC rail at", pos, ": Sending command failed: The train",train_id,"does not exist. This seems to be a bug.") end else atwarn("ATC rail at", pos, ": Sending command failed: There's no train at this position. This seems to be a bug.") end else atwarn("ATC rail at", pos, ": Sending command failed: Entry for controller not found.") atwarn("ATC rail at", pos, ": Please visit controller and click 'Save'") end return false end function atc.train_reset_command(train_id) advtrains.trains[train_id].atc_command=nil advtrains.trains[train_id].atc_delay=0 advtrains.trains[train_id].atc_brake_target=nil advtrains.trains[train_id].atc_wait_finish=nil advtrains.trains[train_id].atc_arrow=nil end --nodes local idxtrans={static=1, mesecon=2, digiline=3} local apn_func=function(pos, node) advtrains.ndb.update(pos, node) local meta=minetest.get_meta(pos) if meta then meta:set_string("infotext", attrans("ATC controller, unconfigured.")) meta:set_string("formspec", atc.get_atc_controller_formspec(pos, meta)) end end advtrains.atc_function = function(def, preset, suffix, rotation) return { after_place_node=apn_func, after_dig_node=function(pos) return advtrains.pcall(function() advtrains.invalidate_all_paths(pos) advtrains.ndb.clear(pos) local pts=minetest.pos_to_string(pos) atc.controllers[pts]=nil end) end, on_receive_fields = function(pos, formname, fields, player) return advtrains.pcall(function() if advtrains.is_protected(pos, player:get_player_name()) then minetest.record_protection_violation(pos, player:get_player_name()) return end local meta=minetest.get_meta(pos) if meta then if not fields.save then --maybe only the dropdown changed if fields.mode then meta:set_string("mode", idxtrans[fields.mode]) if fields.mode=="digiline" then meta:set_string("infotext", attrans("ATC controller, mode @1\nChannel: @2", fields.mode, meta:get_string("command")) ) else meta:set_string("infotext", attrans("ATC controller, mode @1\nCommand: @2", fields.mode, meta:get_string("command")) ) end meta:set_string("formspec", atc.get_atc_controller_formspec(pos, meta)) end return end meta:set_string("mode", idxtrans[fields.mode]) meta:set_string("command", fields.command) meta:set_string("command_on", fields.command_on) meta:set_string("channel", fields.channel) if fields.mode=="digiline" then meta:set_string("infotext", attrans("ATC controller, mode @1\nChannel: @2", fields.mode, meta:get_string("command")) ) else meta:set_string("infotext", attrans("ATC controller, mode @1\nCommand: @2", fields.mode, meta:get_string("command")) ) end meta:set_string("formspec", atc.get_atc_controller_formspec(pos, meta)) local pts=minetest.pos_to_string(pos) local _, conn1=advtrains.get_rail_info_at(pos, advtrains.all_tracktypes) atc.controllers[pts]={command=fields.command, arrowconn=conn1} if advtrains.detector.on_node[pts] then atc.send_command(pos) end end end) end, advtrains = { on_train_enter = function(pos, train_id) atc.send_command(pos) end, }, } end function atc.get_atc_controller_formspec(pos, meta) local mode=tonumber(meta:get_string("mode")) or 1 local command=meta:get_string("command") local command_on=meta:get_string("command_on") local channel=meta:get_string("channel") local formspec="size[8,6]".. "dropdown[0,0;3;mode;static,mesecon,digiline;"..mode.."]" if mode<3 then formspec=formspec.."field[0.5,1.5;7,1;command;"..attrans("Command")..";"..minetest.formspec_escape(command).."]" if tonumber(mode)==2 then formspec=formspec.."field[0.5,3;7,1;command_on;"..attrans("Command (on)")..";"..minetest.formspec_escape(command_on).."]" end else formspec=formspec.."field[0.5,1.5;7,1;channel;"..attrans("Digiline channel")..";"..minetest.formspec_escape(channel).."]" end return formspec.."button_exit[0.5,4.5;7,1;save;"..attrans("Save").."]" end --from trainlogic.lua train step local matchptn={ ["SM"]=function(id, train) train.tarvelocity=train.max_speed return 2 end, ["S([0-9]+)"]=function(id, train, match) train.tarvelocity=tonumber(match) return #match+1 end, ["B([0-9]+)"]=function(id, train, match) if train.velocity>tonumber(match) then train.atc_brake_target=tonumber(match) if train.tarvelocity>train.atc_brake_target then train.tarvelocity=train.atc_brake_target end end return #match+1 end, ["W"]=function(id, train) train.atc_wait_finish=true return 1 end, ["D([0-9]+)"]=function(id, train, match) train.atc_delay=tonumber(match) return #match+1 end, ["R"]=function(id, train) if train.velocity<=0 then train.movedir=train.movedir*-1 train.atc_arrow = not train.atc_arrow else atwarn(sid(id), attrans("ATC Reverse command warning: didn't reverse train, train moving!")) end return 1 end, ["O([LRC])"]=function(id, train, match) local tt={L=-1, R=1, C=0} local arr=train.atc_arrow and 1 or -1 train.door_open = tt[match]*arr*train.movedir return 2 end, } function atc.execute_atc_command(id, train) --strip whitespaces local command=string.match(train.atc_command, "^%s*(.*)$") if string.match(command, "^%s*$") then train.atc_command=nil return end --conditional statement? local is_cond, cond_applies, compare local cond, rest=string.match(command, "^I([%+%-])(.+)$") if cond then is_cond=true if cond=="+" then cond_applies=train.atc_arrow end if cond=="-" then cond_applies=not train.atc_arrow end else cond, compare, rest=string.match(command, "^I([<>]=?)([0-9]+)(.+)$") if cond and compare then is_cond=true if cond=="<" then cond_applies=train.velocity<tonumber(compare) end if cond==">" then cond_applies=train.velocity>tonumber(compare) end if cond=="<=" then cond_applies=train.velocity<=tonumber(compare) end if cond==">=" then cond_applies=train.velocity>=tonumber(compare) end end end if is_cond then atprint("Evaluating if statement: "..command) atprint("Cond: "..(cond or "nil")) atprint("Applies: "..(cond_applies and "true" or "false")) atprint("Rest: "..rest) --find end of conditional statement local nest, pos, elsepos=0, 1 while nest>=0 do if pos>#rest then atwarn(sid(id), attrans("ATC command syntax error: I statement not closed: @1",command)) atc.train_reset_command(id) return end local char=string.sub(rest, pos, pos) if char=="I" then nest=nest+1 end if char==";" then nest=nest-1 end if nest==0 and char=="E" then elsepos=pos+0 end pos=pos+1 end if not elsepos then elsepos=pos-1 end if cond_applies then command=string.sub(rest, 1, elsepos-1)..string.sub(rest, pos) else command=string.sub(rest, elsepos+1, pos-2)..string.sub(rest, pos) end atprint("Result: "..command) train.atc_command=command atc.execute_atc_command(id, train) return else for pattern, func in pairs(matchptn) do local match=string.match(command, "^"..pattern) if match then local patlen=func(id, train, match) atprint("Executing: "..string.sub(command, 1, patlen)) train.atc_command=string.sub(command, patlen+1) if train.atc_delay<=0 and not train.atc_wait_finish then --continue (recursive, cmds shouldn't get too long, and it's a end-recursion.) atc.execute_atc_command(id, train) end return end end end atwarn(sid(id), attrans("ATC command parse error: Unknown command: @1", command)) atc.train_reset_command(id) end --move table to desired place advtrains.atc=atc