aboutsummaryrefslogtreecommitdiff
path: root/src/script/lua_api
ModeNameSize
-rw-r--r--CMakeLists.txt1436logplain
-rw-r--r--l_areastore.cpp9052logplain
-rw-r--r--l_areastore.h1764logplain
-rw-r--r--l_base.cpp2199logplain
-rw-r--r--l_base.h2052logplain
-rw-r--r--l_camera.cpp5439logplain
-rw-r--r--l_camera.h1730logplain
-rw-r--r--l_client.cpp9071logplain
-rw-r--r--l_client.h2557logplain
-rw-r--r--l_craft.cpp14134logplain
-rw-r--r--l_craft.h1583logplain
-rw-r--r--l_env.cpp32602logplain
-rw-r--r--l_env.h8265logplain
-rw-r--r--l_http.cpp5685logplain
-rw-r--r--l_http.h1486logplain
-rw-r--r--l_internal.h1870logplain
-rw-r--r--l_inventory.cpp13636logplain
-rw-r--r--l_inventory.h3738logplain
-rw-r--r--l_item.cpp16193logplain
-rw-r--r--l_item.h4438logplain
-rw-r--r--l_itemstackmeta.cpp3902logplain
-rw-r--r--l_itemstackmeta.h1974logplain
-rw-r--r--l_localplayer.cpp10027logplain
-rw-r--r--l_localplayer.h2666logplain
-rw-r--r--l_mainmenu.cpp30321logplain
-rw-r--r--l_mainmenu.h3901logplain
-rw-r--r--l_mapgen.cpp45603logplain
-rw-r--r--l_mapgen.h4594logplain
-rw-r--r--l_metadata.cpp6905logplain
-rw-r--r--l_metadata.h2101logplain
-rw-r--r--l_minimap.cpp5196logplain
-rw-r--r--l_minimap.h1673logplain
-rw-r--r--l_modchannels.cpp4070logplain
-rw-r--r--l_modchannels.h1726logplain
-rw-r--r--l_nodemeta.cpp7334logplain
-rw-r--r--l_nodemeta.h3050logplain
-rw-r--r--l_nodetimer.cpp4426logplain
-rw-r--r--l_nodetimer.h1729logplain
-rw-r--r--l_noise.cpp15715logplain
-rw-r--r--l_noise.h4559logplain
-rw-r--r--l_object.cpp48020logplain
-rw-r--r--l_object.h9403logplain
-rw-r--r--l_particles.cpp8404logplain
-rw-r--r--l_particles.h1084logplain
-rw-r--r--l_particles_local.cpp7213logplain
-rw-r--r--l_particles_local.h1123logplain
-rw-r--r--l_playermeta.cpp3311logplain
-rw-r--r--l_playermeta.h1702logplain
-rw-r--r--l_rollback.cpp3552logplain
-rw-r--r--l_rollback.h1219logplain
-rw-r--r--l_server.cpp13916logplain
-rw-r--r--l_server.h2974logplain
-rw-r--r--l_settings.cpp7518logplain
-rw-r--r--l_settings.h2342logplain
-rw-r--r--l_sound.cpp1432logplain
-rw-r--r--l_sound.h1086logplain
-rw-r--r--l_storage.cpp3902logplain
-rw-r--r--l_storage.h1657logplain
-rw-r--r--l_util.cpp12903logplain
-rw-r--r--l_util.h2973logplain
-rw-r--r--l_vmanip.cpp10491logplain
-rw-r--r--l_vmanip.h2239logplain
78'>978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107
--trainlogic.lua
--controls train entities stuff about connecting/disconnecting/colliding trains and other things


local benchmark=false
local bm={}
local bmlt=0
local bmsteps=0
local bmstepint=200
atprintbm=function(action, ta)
	if not benchmark then return end
	local t=(os.clock()-ta)*1000
	if not bm[action] then
		bm[action]=t
	else
		bm[action]=bm[action]+t
	end
	bmlt=bmlt+t
end
function endstep()
	if not benchmark then return end
	bmsteps=bmsteps-1
	if bmsteps<=0 then
		bmsteps=bmstepint
		for key, value in pairs(bm) do
			minetest.chat_send_all(key.." "..(value/bmstepint).." ms avg.")
		end
		minetest.chat_send_all("Total time consumed by all advtrains actions per step: "..(bmlt/bmstepint).." ms avg.")
		bm={}
		bmlt=0
	end
end

--acceleration for lever modes (trainhud.lua), per wagon
local t_accel_all={
	[0] = -10,
	[1] = -3,
	[2] = -0.5,
	[4] = 0.5,
}
--acceleration per engine
local t_accel_eng={
	[0] = 0,
	[1] = 0,
	[2] = 0,
	[4] = 1.5,
}

tp_player_tmr = 0

advtrains.mainloop_trainlogic=function(dtime)
	--build a table of all players indexed by pts. used by damage and door system.
	advtrains.playersbypts={}
	for _, player in pairs(minetest.get_connected_players()) do
		if not advtrains.player_to_train_mapping[player:get_player_name()] then
			--players in train are not subject to damage
			local ptspos=minetest.pos_to_string(vector.round(player:getpos()))
			advtrains.playersbypts[ptspos]=player
		end
	end
	
	if tp_player_tmr<=0 then
		-- teleport players to their train every 2 seconds
		for _, player in pairs(minetest.get_connected_players()) do
			advtrains.tp_player_to_train(player)
		end
		tp_player_tmr = 2
	else
		tp_player_tmr = tp_player_tmr - dtime
	end
	--regular train step
	--[[ structure:
	1. make trains calculate their occupation windows when needed (a)
	2. when occupation tells us so, restore the occupation tables (a)
	4. make trains move and update their new occupation windows and write changes
	   to occupation tables (b)
	5. make trains do other stuff (c)
	]]--
	local t=os.clock()
	
	for k,v in pairs(advtrains.trains) do
		advtrains.atprint_context_tid=k
		advtrains.train_ensure_init(k, v)
	end
	
	for k,v in pairs(advtrains.trains) do
		advtrains.atprint_context_tid=k
		advtrains.train_step_b(k, v, dtime)
	end
	
	for k,v in pairs(advtrains.trains) do
		advtrains.atprint_context_tid=k
		advtrains.train_step_c(k, v, dtime)
	end
	
	advtrains.atprint_context_tid=nil
	
	atprintbm("trainsteps", t)
	endstep()
end

function advtrains.tp_player_to_train(player)
	local pname = player:get_player_name()
	local id=advtrains.player_to_train_mapping[pname]
	if id then
		local train=advtrains.trains[id]
		if not train then advtrains.player_to_train_mapping[pname]=nil return end
		--set the player to the train position.
		--minetest will emerge the area and load the objects, which then will call reattach_all().
		--because player is in mapping, it will not be subject to dying.
		player:setpos(train.last_pos_prev)
	end
end
minetest.register_on_joinplayer(function()
	return advtrains.pcall(function()
		--independent of this, cause all wagons of the train which are loaded to reattach their players
		--needed because already loaded wagons won't call reattach_all()
		for _,wagon in pairs(minetest.luaentities) do
			if wagon.is_wagon and wagon.initialized and wagon.train_id==id then
				wagon:reattach_all()
			end
		end
	end)
end)


minetest.register_on_dieplayer(function(player)
	return advtrains.pcall(function()
		local pname=player:get_player_name()
		local id=advtrains.player_to_train_mapping[pname]
		if id then
			local train=advtrains.trains[id]
			if not train then advtrains.player_to_train_mapping[pname]=nil return end
			for _,wagon in pairs(minetest.luaentities) do
				if wagon.is_wagon and wagon.initialized and wagon.train_id==id then
					--when player dies, detach him from the train
					--call get_off_plr on every wagon since we don't know which one he's on.
					wagon:get_off_plr(pname)
				end
			end
		end
	end)
end)

--[[

Zone diagram of a train (copy from occupation.lua!):
              |___| |___| --> Direction of travel
              oo oo+oo oo
=|=======|===|===========|===|=======|===================|========|===
 |SafetyB|CpB|   Train   |CpF|SafetyF|        Brake      |Aware   |
[1]     [2] [3]         [4] [5]     [6]                 [7]      [8]
This mapping from indices in occwindows to zone ids is contained in WINDOW_ZONE_IDS


The occupation system has been abandoned. The constants will still be used
to determine the couple distance
(because of the reverse lookup, the couple system simplifies a lot...)

]]--
-- unless otherwise stated, in meters.
local SAFETY_ZONE = 10
local COUPLE_ZONE = 2 --value in index positions!
local BRAKE_SPACE = 10
local AWARE_ZONE = 10
local WINDOW_ZONE_IDS = {
	2, -- 1 - SafetyB
	4, -- 2 - CpB
	1, -- 3 - Train
	5, -- 4 - CpF
	3, -- 5 - SafetyF
	6, -- 6 - Brake
	7, -- 7 - Aware
}


-- If a variable does not exist in the table, it is assigned the default value
local function assertdef(tbl, var, def)
	if not tbl[var] then
		tbl[var] = def
	end
end

function advtrains.get_acceleration(train, lever)
	local acc_all = t_accel_all[lever]
	local acc_eng = t_accel_eng[lever]
	local nwagons = #train.trainparts
	local acc = acc_all + (acc_eng*train.locomotives_in_train)/nwagons
	return acc
end

-- Small local util function to recalculate train's end index
local function recalc_end_index(train)
	train.end_index = advtrains.path_get_index_by_offset(train, train.index, -train.trainlen)
end

-- Occupation Callback system
-- see occupation.lua
-- signature is advtrains.te_register_on_<?>(function(id, train) ... end)

local function mkcallback(name)
	local callt = {}
	advtrains["te_register_on_"..name] = function(func)
		assertt(func, "function")
		table.insert(callt, func)
	end
	return callt, function(id, train)
		for _,f in ipairs(callt) do
			f(id, train)
		end
	end
end

local callbacks_new_path, run_callbacks_new_path = mkcallback("new_path")
local callbacks_update, run_callbacks_update = mkcallback("update")
local callbacks_create, run_callbacks_create = mkcallback("create")
local callbacks_remove, run_callbacks_remove = mkcallback("remove")


-- train_ensure_init: responsible for creating a state that we can work on, after one of the following events has happened:
-- - the train's path got cleared
-- - save files were loaded
-- Additionally, this gets called outside the step cycle to initialize and/or remove a train, then occ_write_mode is set.
function advtrains.train_ensure_init(id, train)
	train.dirty = true
	if train.no_step then return end

	assertdef(train, "velocity", 0)
	--assertdef(train, "tarvelocity", 0)
	assertdef(train, "acceleration", 0)
	assertdef(train, "id", id)
	assertdef(train, "ctrl", {})
	
	
	if not train.drives_on or not train.max_speed then
		advtrains.update_trainpart_properties(id)
	end
	
	--restore path
	if not train.path then
		if not train.last_pos then
			atwarn("Train",id,": Restoring path failed, no last_pos set! Train will be disabled. You can try to fix the issue in the save file.")
			train.no_step = true
			return
		end
		if not train.last_connid then
			atwarn("Train",id,": Restoring path: no last_connid set! Will assume 1")
		end
		
		local result = advtrains.path_create(train, train.last_pos, train.last_connid or 1, train.last_frac or 0)
		
		if result==false then
			atwarn("Train",id,": Restoring path failed, node at",train.last_pos,"is gone! Train will be disabled. You can try to fix the issue in the save file.")
			train.no_step = true
			return
		elseif result==nil then
			if not train.wait_for_path then
				atwarn("Train",id,": Can't initialize: Waiting for the (yet unloaded) node at",train.last_pos," to be loaded.")
			end
			train.wait_for_path = true
		end
		-- by now, we should have a working initial path
		train.wait_for_path = false
		
		advtrains.update_trainpart_properties(id)
		recalc_end_index(train)
		
		--atdebug("Train",id,": Successfully restored path at",train.last_pos," connid",train.last_connid," frac",train.last_frac)
		
		-- run on_new_path callbacks
		run_callbacks_new_path(id, train)
	end
	
	train.dirty = false -- TODO einbauen!
end

function advtrains.train_step_b(id, train, dtime)
	if train.no_step or train.wait_for_path then return end
	
	-- in this code, we check variables such as path_trk_? and path_dist. We need to ensure that the path is known for the whole 'Train' zone
	advtrains.path_get(train, atfloor(train.index + 2))
	advtrains.path_get(train, atfloor(train.end_index - 1))
	
	--- 3. handle velocity influences ---
	local train_moves=(train.velocity~=0)
	local tarvel_cap = train.speed_restriction
	
	if train.recently_collided_with_env then
		tarvel_cap=0
		if not train_moves then
			train.recently_collided_with_env=nil--reset status when stopped
		end
	end
	if train.locomotives_in_train==0 then
		tarvel_cap=0
	end
	
	--- 3a. this can be useful for debugs/warnings and is used for check_trainpartload ---
	local t_info, train_pos=sid(id), advtrains.path_get(train, atfloor(train.index))
	if train_pos then
		t_info=t_info.." @"..minetest.pos_to_string(train_pos)
		--atprint("train_pos:",train_pos)
	end
	
	--apply off-track handling:
	local front_off_track = train.index>train.path_trk_f
	local back_off_track=train.end_index<train.path_trk_b
	train.off_track = front_off_track or back_off_track
	
	if front_off_track then
		tarvel_cap=0
	end
	if back_off_track then -- eventually overrides front_off_track restriction
		tarvel_cap=1
	end