aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main.cpp193
1 files changed, 34 insertions, 159 deletions
diff --git a/src/main.cpp b/src/main.cpp
index 2dfef7d1b..af94387f6 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -336,7 +336,7 @@ MapDrawControl draw_control;
*/
Settings g_settings;
-
+// This is located in defaultsettings.cpp
extern void set_default_settings();
/*
@@ -346,12 +346,6 @@ extern void set_default_settings();
IrrlichtDevice *g_device = NULL;
Client *g_client = NULL;
-/*const s16 quickinv_size = 40;
-const s16 quickinv_padding = 8;
-const s16 quickinv_spacing = quickinv_size + quickinv_padding;
-const s16 quickinv_outer_padding = 4;
-const s16 quickinv_itemcount = 8;*/
-
const s32 hotbar_itemcount = 8;
const s32 hotbar_imagesize = 36;
@@ -362,6 +356,8 @@ const s32 hotbar_imagesize = 36;
gui::IGUIEnvironment* guienv = NULL;
gui::IGUIStaticText *guiroot = NULL;
+// Handler for the modal menus
+
class MainMenuManager : public IMenuManager
{
public:
@@ -421,11 +417,16 @@ bool noMenuActive()
return (g_menumgr.menuCount() == 0);
}
-bool g_disconnect_requested = false;
+// Passed to menus to allow disconnecting and exiting
class MainGameCallback : public IGameCallback
{
public:
+ MainGameCallback():
+ disconnect_requested(false)
+ {
+ }
+
virtual void exitToOS()
{
g_device->closeDevice();
@@ -433,23 +434,25 @@ public:
virtual void disconnect()
{
- g_disconnect_requested = true;
+ disconnect_requested = true;
}
+
+ bool disconnect_requested;
};
MainGameCallback g_gamecallback;
+/*
+ Inventory stuff
+*/
+
// Inventory actions from the menu are buffered here before sending
-// TODO: Get rid of this
Queue<InventoryAction*> inventory_action_queue;
// This is a copy of the inventory that the client's environment has
Inventory local_inventory;
u16 g_selected_item = 0;
-/*bool g_show_map_plot = false;
-bool g_refresh_map_plot = false;*/
-
/*
Debug streams
*/
@@ -562,6 +565,10 @@ struct TextDestSignNode : public TextDest
Client *m_client;
};
+/*
+ Event handler for Irrlicht
+*/
+
class MyEventReceiver : public IEventReceiver
{
public:
@@ -801,6 +808,10 @@ private:
IrrlichtDevice *m_device;
};
+/*
+ Separated input handler
+*/
+
class InputHandler
{
public:
@@ -1072,6 +1083,10 @@ private:
bool rightreleased;
};
+/*
+ Render distance feedback loop
+*/
+
void updateViewingRange(f32 frametime_in, Client *client)
{
if(draw_control.range_all == true)
@@ -1203,6 +1218,10 @@ void updateViewingRange(f32 frametime_in, Client *client)
frametime_old = frametime;
}
+/*
+ Hotbar draw routine
+*/
+
void draw_hotbar(video::IVideoDriver *driver, gui::IGUIFont *font,
v2s32 centerlowerpos, s32 imgsize, s32 itemcount,
Inventory *inventory, s32 halfheartcount)
@@ -1290,150 +1309,6 @@ void draw_hotbar(video::IVideoDriver *driver, gui::IGUIFont *font,
}
}
-#if 0
-video::ITexture *g_map_plot_texture = NULL;
-float g_map_plot_texture_scale = 4;
-
-void updateMapPlotTexture(v2f centerpos, video::IVideoDriver* driver,
- Client *client)
-{
- assert(driver);
- assert(client);
-
- core::dimension2d<u32> dim(640,480);
- video::IImage *img = driver->createImage(video::ECF_A8R8G8B8, dim);
- assert(img);
- for(u32 y=0; y<dim.Height; y++)
- for(u32 x=0; x<dim.Width; x++)
- {
- v2f pf = v2f(x, dim.Height-y) - v2f(dim.Width, dim.Height)/2;
- pf *= g_map_plot_texture_scale;
- pf += centerpos;
- double h = base_rock_level_2d(client->getMapSeed(), pf);
- video::SColor c;
- //double d1 = 50;
- /*s32 ux = x - centerpos.X / g_map_plot_texture_scale;
- s32 uy = y - centerpos.Y / g_map_plot_texture_scale;*/
-
- // Screen coordinates that are based on multiples of
- // 1000/g_map_plot_texture_scale and never negative
- u32 ux = x + (u32)(1000/g_map_plot_texture_scale) * 10;
- u32 uy = y + (u32)(1000/g_map_plot_texture_scale) * 10;
- // Offset to center of image
- ux -= dim.Width/2;
- uy -= dim.Height/2;
-
- if(uy % (u32)(1000/g_map_plot_texture_scale) == 0
- || ux % (u32)(1000/g_map_plot_texture_scale) == 0)
- c.set(255, 255, 255, 255);
- else if(uy % (u32)(100/g_map_plot_texture_scale) == 0
- || ux % (u32)(100/g_map_plot_texture_scale) == 0)
- c.set(255, 160, 160, 160);
- else if(h < WATER_LEVEL - 0.5) // Water
- c.set(255, 50, 50, 255);
-#if 0
- else if(get_have_sand_ground(client->getMapSeed(), pf)
- || (h < WATER_LEVEL + 2
- && get_have_sand_coast(client->getMapSeed(), pf)))
- {
- h -= WATER_LEVEL;
- h /= 50.0;
- h = 1.0 - exp(-h);
-
- video::SColor c1(255,237,201,175);
- //video::SColor c2(255,20,20,20);
- video::SColor c2(255,150,0,0);
- c = c2.getInterpolated(c1, h);
- }
- else
- {
- h -= WATER_LEVEL;
- h /= 50.0;
- h = 1.0 - exp(-h);
-
- video::SColor c1(255,110,185,90);
- //video::SColor c2(255,20,20,20);
- video::SColor c2(255,150,0,0);
- c = c2.getInterpolated(c1, h);
- }
-#endif
-#if 1
-#if 0
- else if(get_have_sand_ground(client->getMapSeed(), pf))
- {
- h -= WATER_LEVEL;
- h /= 20.0;
- h = 1.0 - exp(-h);
-
- video::SColor c1(255,237,201,175);
- //video::SColor c2(255,20,20,20);
- video::SColor c2(255,150,0,0);
- c = c2.getInterpolated(c1, h);
- }
-#endif
- // Sand
- else if(h < WATER_LEVEL + 2
- && get_have_sand_coast(client->getMapSeed(), pf))
- c.set(255, 237, 201, 175);
-#if 1
- else if(h < WATER_LEVEL + 10)
- c.set(255, 50, 150, 50); // Green
- else if(h < WATER_LEVEL + 20)
- c.set(255, 110, 185, 50); // Yellowish green
- else if(h < WATER_LEVEL + 40)
- c.set(255, 180, 210, 50); // Greenish yellow
- else if(h < WATER_LEVEL + 60)
- c.set(255, 220, 220, 50); // Yellow
- else if(h < WATER_LEVEL + 80)
- c.set(255, 200, 200, 110); // Yellowish white
- else if(h < WATER_LEVEL + 100)
- c.set(255, 190, 190, 190); // Grey
- else
- c.set(255, 255, 255, 255); // White
-#endif
-#endif
-#if 0
- else
- {
- h -= WATER_LEVEL;
- h /= 20.0;
- h = 1.0 - exp(-h);
-
- video::SColor c1(255,200,200,50);
- video::SColor c2(255,0,150,0);
- c = c1.getInterpolated(c2, h);
-
- /*u32 a = (u32)(h*255);
- if(a > 255)
- a = 255;
- a = 255-a;
- c.set(255, a, a, a);*/
- }
-#endif
-#if 1
- if(h >= WATER_LEVEL - 0.5
- && get_have_sand_ground(client->getMapSeed(), pf))
- {
- video::SColor c1(255,237,201,175);
- c = c.getInterpolated(c1, 0.5);
- }
-#endif
-#if 1
- double tf = get_turbulence_factor_2d(client->getMapSeed(), pf);
- if(tf > 0.001)
- {
- video::SColor c1(255,255,0,0);
- c = c.getInterpolated(c1, 1.0-(0.5*tf));
- }
-#endif
- img->setPixel(x, y, c);
- }
- g_map_plot_texture = driver->addTexture("map_plot", img);
- img->drop();
- assert(g_map_plot_texture);
-}
-#endif
-
// Chat data
struct ChatLine
{
@@ -2456,9 +2331,9 @@ int main(int argc, char *argv[])
while(device->run() && kill == false)
{
- if(g_disconnect_requested)
+ if(g_gamecallback.disconnect_requested)
{
- g_disconnect_requested = false;
+ g_gamecallback.disconnect_requested = false;
break;
}
'n462' href='#n462'>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 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570
--Minetest
--Copyright (C) 2013 sapier
--
--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.

--------------------------------------------------------------------------------
function get_mods(path,retval,modpack)
	local mods = core.get_dir_list(path, true)

	for _, name in ipairs(mods) do
		if name:sub(1, 1) ~= "." then
			local prefix = path .. DIR_DELIM .. name .. DIR_DELIM
			local toadd = {}
			retval[#retval + 1] = toadd

			local mod_conf = Settings(prefix .. "mod.conf"):to_table()
			if mod_conf.name then
				name = mod_conf.name
			end

			toadd.name = name
			toadd.path = prefix

			if modpack ~= nil and modpack ~= "" then
				toadd.modpack = modpack
			else
				local modpackfile = io.open(prefix .. "modpack.txt")
				if modpackfile then
					modpackfile:close()
					toadd.is_modpack = true
					get_mods(prefix, retval, name)
				end
			end
		end
	end
end

--modmanager implementation
modmgr = {}

--------------------------------------------------------------------------------
function modmgr.extract(modfile)
	if modfile.type == "zip" then
		local tempfolder = os.tempfolder()

		if tempfolder ~= nil and
			tempfolder ~= "" then
			core.create_dir(tempfolder)
			if core.extract_zip(modfile.name,tempfolder) then
				return tempfolder
			end
		end
	end
	return nil
end

-------------------------------------------------------------------------------
function modmgr.getbasefolder(temppath)

	if temppath == nil then
		return {
		type = "invalid",
		path = ""
		}
	end

	local testfile = io.open(temppath .. DIR_DELIM .. "init.lua","r")
	if testfile ~= nil then
		testfile:close()
		return {
				type="mod",
				path=temppath
				}
	end

	testfile = io.open(temppath .. DIR_DELIM .. "modpack.txt","r")
	if testfile ~= nil then
		testfile:close()
		return {
				type="modpack",
				path=temppath
				}
	end

	local subdirs = core.get_dir_list(temppath, true)

	--only single mod or modpack allowed
	if #subdirs ~= 1 then
		return {
			type = "invalid",
			path = ""
			}
	end

	testfile =
	io.open(temppath .. DIR_DELIM .. subdirs[1] ..DIR_DELIM .."init.lua","r")
	if testfile ~= nil then
		testfile:close()
		return {
			type="mod",
			path= temppath .. DIR_DELIM .. subdirs[1]
			}
	end

	testfile =
	io.open(temppath .. DIR_DELIM .. subdirs[1] ..DIR_DELIM .."modpack.txt","r")
	if testfile ~= nil then
		testfile:close()
		return {
			type="modpack",
			path=temppath ..  DIR_DELIM .. subdirs[1]
			}
	end

	return {
		type = "invalid",
		path = ""
		}
end

--------------------------------------------------------------------------------
function modmgr.isValidModname(modpath)
	if modpath:find("-") ~= nil then
		return false
	end

	return true
end

--------------------------------------------------------------------------------
function modmgr.parse_register_line(line)
	local pos1 = line:find("\"")
	local pos2 = nil
	if pos1 ~= nil then
		pos2 = line:find("\"",pos1+1)
	end

	if pos1 ~= nil and pos2 ~= nil then
		local item = line:sub(pos1+1,pos2-1)

		if item ~= nil and
			item ~= "" then
			local pos3 = item:find(":")

			if pos3 ~= nil then
				local retval = item:sub(1,pos3-1)
				if retval ~= nil and
					retval ~= "" then
					return retval
				end
			end
		end
	end
	return nil
end

--------------------------------------------------------------------------------
function modmgr.parse_dofile_line(modpath,line)
	local pos1 = line:find("\"")
	local pos2 = nil
	if pos1 ~= nil then
		pos2 = line:find("\"",pos1+1)
	end

	if pos1 ~= nil and pos2 ~= nil then
		local filename = line:sub(pos1+1,pos2-1)

		if filename ~= nil and
			filename ~= "" and
			filename:find(".lua") then
			return modmgr.identify_modname(modpath,filename)
		end
	end
	return nil
end

--------------------------------------------------------------------------------
function modmgr.identify_modname(modpath,filename)
	local testfile = io.open(modpath .. DIR_DELIM .. filename,"r")
	if testfile ~= nil then
		local line = testfile:read()

		while line~= nil do
			local modname = nil

			if line:find("minetest.register_tool") then
				modname = modmgr.parse_register_line(line)
			end

			if line:find("minetest.register_craftitem") then
				modname = modmgr.parse_register_line(line)
			end


			if line:find("minetest.register_node") then
				modname = modmgr.parse_register_line(line)
			end

			if line:find("dofile") then
				modname = modmgr.parse_dofile_line(modpath,line)
			end

			if modname ~= nil then
				testfile:close()
				return modname
			end

			line = testfile:read()
		end
		testfile:close()
	end

	return nil
end
--------------------------------------------------------------------------------
function modmgr.render_modlist(render_list)
	local retval = ""

	if render_list == nil then
		if modmgr.global_mods == nil then
			modmgr.refresh_globals()
		end
		render_list = modmgr.global_mods
	end

	local list = render_list:get_list()
	local last_modpack = nil
	local retval = {}
	for i, v in ipairs(list) do
		local color = ""
		if v.is_modpack then
			local rawlist = render_list:get_raw_list()
			color = mt_color_dark_green

			for j = 1, #rawlist, 1 do
				if rawlist[j].modpack == list[i].name and
						rawlist[j].enabled ~= true then
					-- Modpack not entirely enabled so showing as grey
					color = mt_color_grey
					break
				end
			end
		elseif v.is_game_content then
			color = mt_color_blue
		elseif v.enabled then
			color = mt_color_green
		end

		retval[#retval + 1] = color
		if v.modpack ~= nil or v.typ == "game_mod" then
			retval[#retval + 1] = "1"
		else
			retval[#retval + 1] = "0"
		end
		retval[#retval + 1] = core.formspec_escape(v.name)
	end

	return table.concat(retval, ",")
end

--------------------------------------------------------------------------------
function modmgr.get_dependencies(modfolder)
	local toadd_hard = ""
	local toadd_soft = ""
	if modfolder ~= nil then
		local filename = modfolder ..
					DIR_DELIM .. "depends.txt"

		local hard_dependencies = {}
		local soft_dependencies = {}
		local dependencyfile = io.open(filename,"r")
		if dependencyfile then
			local dependency = dependencyfile:read("*l")
			while dependency do
				dependency = dependency:gsub("\r", "")
				if string.sub(dependency, -1, -1) == "?" then
					table.insert(soft_dependencies, string.sub(dependency, 1, -2))
				else
					table.insert(hard_dependencies, dependency)
				end
				dependency = dependencyfile:read()
			end
			dependencyfile:close()
		end
		toadd_hard = table.concat(hard_dependencies, ",")
		toadd_soft = table.concat(soft_dependencies, ",")
	end

	return toadd_hard, toadd_soft
end

--------------------------------------------------------------------------------
function modmgr.get_worldconfig(worldpath)
	local filename = worldpath ..
				DIR_DELIM .. "world.mt"

	local worldfile = Settings(filename)

	local worldconfig = {}
	worldconfig.global_mods = {}
	worldconfig.game_mods = {}

	for key,value in pairs(worldfile:to_table()) do
		if key == "gameid" then
			worldconfig.id = value
		elseif key:sub(0, 9) == "load_mod_" then
			worldconfig.global_mods[key] = core.is_yes(value)
		else
			worldconfig[key] = value
		end
	end

	--read gamemods
	local gamespec = gamemgr.find_by_gameid(worldconfig.id)
	gamemgr.get_game_mods(gamespec, worldconfig.game_mods)

	return worldconfig
end

--------------------------------------------------------------------------------
function modmgr.installmod(modfilename,basename)
	local modfile = modmgr.identify_filetype(modfilename)
	local modpath = modmgr.extract(modfile)

	if modpath == nil then
		gamedata.errormessage = fgettext("Install Mod: file: \"$1\"", modfile.name) ..
			fgettext("\nInstall Mod: unsupported filetype \"$1\" or broken archive", modfile.type)
		return
	end

	local basefolder = modmgr.getbasefolder(modpath)

	if basefolder.type == "modpack" then
		local clean_path = nil

		if basename ~= nil then
			clean_path = "mp_" .. basename
		end

		if clean_path == nil then
			clean_path = get_last_folder(cleanup_path(basefolder.path))
		end

		if clean_path ~= nil then
			local targetpath = core.get_modpath() .. DIR_DELIM .. clean_path
			if not core.copy_dir(basefolder.path,targetpath) then
				gamedata.errormessage = fgettext("Failed to install $1 to $2", basename, targetpath)
			end
		else
			gamedata.errormessage = fgettext("Install Mod: unable to find suitable foldername for modpack $1", modfilename)
		end
	end

	if basefolder.type == "mod" then
		local targetfolder = basename

		if targetfolder == nil then
			targetfolder = modmgr.identify_modname(basefolder.path,"init.lua")
		end

		--if heuristic failed try to use current foldername
		if targetfolder == nil then
			targetfolder = get_last_folder(basefolder.path)
		end

		if targetfolder ~= nil and modmgr.isValidModname(targetfolder) then
			local targetpath = core.get_modpath() .. DIR_DELIM .. targetfolder
			core.copy_dir(basefolder.path,targetpath)
		else
			gamedata.errormessage = fgettext("Install Mod: unable to find real modname for: $1", modfilename)
		end
	end

	core.delete_dir(modpath)

	modmgr.refresh_globals()

end

--------------------------------------------------------------------------------
function modmgr.preparemodlist(data)
	local retval = {}

	local global_mods = {}
	local game_mods = {}

	--read global mods
	local modpath = core.get_modpath()

	if modpath ~= nil and
		modpath ~= "" then
		get_mods(modpath,global_mods)
	end

	for i=1,#global_mods,1 do
		global_mods[i].typ = "global_mod"
		retval[#retval + 1] = global_mods[i]
	end

	--read game mods
	local gamespec = gamemgr.find_by_gameid(data.gameid)
	gamemgr.get_game_mods(gamespec, game_mods)

	if #game_mods > 0 then
		-- Add title
		retval[#retval + 1] = {
			typ = "game",
			is_game_content = true,
			name = fgettext("Subgame Mods")
		}
	end

	for i=1,#game_mods,1 do
		game_mods[i].typ = "game_mod"
		game_mods[i].is_game_content = true
		retval[#retval + 1] = game_mods[i]
	end

	if data.worldpath == nil then
		return retval
	end

	--read world mod configuration
	local filename = data.worldpath ..
				DIR_DELIM .. "world.mt"

	local worldfile = Settings(filename)

	for key,value in pairs(worldfile:to_table()) do
		if key:sub(1, 9) == "load_mod_" then
			key = key:sub(10)
			local element = nil
			for i=1,#retval,1 do
				if retval[i].name == key and
					not retval[i].is_modpack then
					element = retval[i]
					break
				end
			end
			if element ~= nil then
				element.enabled = core.is_yes(value)
			else
				core.log("info", "Mod: " .. key .. " " .. dump(value) .. " but not found")
			end
		end
	end

	return retval
end

--------------------------------------------------------------------------------
function modmgr.comparemod(elem1,elem2)
	if elem1 == nil or elem2 == nil then
		return false
	end
	if elem1.name ~= elem2.name then
		return false
	end
	if elem1.is_modpack ~= elem2.is_modpack then
		return false
	end
	if elem1.typ ~= elem2.typ then
		return false
	end
	if elem1.modpack ~= elem2.modpack then
		return false
	end

	if elem1.path ~= elem2.path then
		return false
	end

	return true
end

--------------------------------------------------------------------------------
function modmgr.mod_exists(basename)

	if modmgr.global_mods == nil then
		modmgr.refresh_globals()
	end

	if modmgr.global_mods:raw_index_by_uid(basename) > 0 then
		return true
	end

	return false
end

--------------------------------------------------------------------------------
function modmgr.get_global_mod(idx)

	if modmgr.global_mods == nil then
		return nil
	end

	if idx == nil or idx < 1 or
		idx > modmgr.global_mods:size() then
		return nil
	end

	return modmgr.global_mods:get_list()[idx]
end

--------------------------------------------------------------------------------
function modmgr.refresh_globals()
	modmgr.global_mods = filterlist.create(
					modmgr.preparemodlist, --refresh
					modmgr.comparemod, --compare
					function(element,uid) --uid match
						if element.name == uid then
							return true
						end
					end,
					nil, --filter
					{}
					)