Post your modding questions here

Locked
prestidigitator
Member
Posts: 647
Joined: Thu Feb 21, 2013 23:54

Re: Post your modding questions here

by prestidigitator » Post

yaman wrote:Topic - How do you get the player's position, or better, the position of the block they are standing on?
Reason - I am making a gold touch mod: it makes blocks the player walks on into gold blocks
More Info - I really want to get into coding mods and I want to succeed in making this one so I can get my self esteem up.
If you have a player object (like from a parameter to a registered callback function), you can get the player's position by calling the getpos() method on it:

Code: Select all

local pos = player:getpos();
...
If you only have the player's name, you can try to get the player object using minetest.get_player_by_name():

Code: Select all

local player = minetest.get_player_by_name(player_name);
if not player then error("player "..player_name.." not found"); end
local pos = player:getpos()
...
The player's position will generally be about one unit higher (the y direction is up) than the block he or she is standing on, if standing rather than jumping or flying or falling or swimming or whatever. So given the above two examples, you might be interested in the position "{x=pos.x, y=pos.y-1, z=pos.z}".

User avatar
LionsDen
Member
Posts: 530
Joined: Thu Jun 06, 2013 03:19

Re: Gracefully replace node upon digging?

by LionsDen » Post

drkwv wrote:
prestidigitator wrote:you might need to us on_dig() instead.
I have copied on_dig from builtin/item.lua and set it for my needs, but lag is still there (pushed this code to github). I have found out that even with an empty function passed to on_dig, minetest client is removing node then setting it back instead of simply doing nothing. Is there anything else I can do to get rid of the lag?
If you simply want the node to never be able to be dug then add diggable = false, to the node definition. If you want it to be dug and then replaced, I'm not sure how to optimize that because I only play single player and haven't tried to do anything for servers.

User avatar
paramat
Developer
Posts: 3700
Joined: Sun Oct 28, 2012 00:05
GitHub: paramat
IRC: paramat
Location: UK

Re: Post your modding questions here

by paramat » Post

Thanks everyone.
srifqi wrote:How to create my own map gen?
See this thread viewtopic.php?f=18&t=6396
I also have a few simplified lua mapgens meant to help people learn the methods, the most useful one is here viewtopic.php?f=11&t=8628

User avatar
srifqi
Member
Posts: 570
Joined: Sat Jun 28, 2014 04:31
GitHub: srifqi
IRC: srifqi
In-game: srifqi
Location: Indonesia

Re: Post your modding questions here

by srifqi » Post

paramat wrote:See this thread viewtopic.php?f=18&t=6396
I also have a few simplified lua mapgens meant to help people learn the methods, the most useful one is here viewtopic.php?f=11&t=8628
Thanks, paramat!
Saya dari Indonesia! · Terjemahkan Minetest! · my mods · My nickname in IPA: /es.rif.qi/

User avatar
Mitroman
Member
Posts: 62
Joined: Thu Apr 03, 2014 19:47
GitHub: Mitroman
In-game: Mitroman15

Re: Post your modding questions here

by Mitroman » Post

Hi. I wanted to have the Itemstack of the wielded item of the player. But here is the problem:
There is a function (player:get_wielded_item() ) that should return the Itemstack, but it returns userdata and I have no idea how to change / use it into an itemstack. Thanks :).

prestidigitator
Member
Posts: 647
Joined: Thu Feb 21, 2013 23:54

Re: Post your modding questions here

by prestidigitator » Post

Mitroman wrote:Hi. I wanted to have the Itemstack of the wielded item of the player. But here is the problem:
There is a function (player:get_wielded_item() ) that should return the Itemstack, but it returns userdata and I have no idea how to change / use it into an itemstack. Thanks :).
Itemstacks ARE userdata objects. Userdata objects can have methods associated with them. Try some of the Itemstack methods (e.g. player:get_wielded_item():get_name()) on the returned userdata object and you should get what you expect from an Itemstack.

prestidigitator
Member
Posts: 647
Joined: Thu Feb 21, 2013 23:54

Re: Post your modding questions here

by prestidigitator » Post

paramat wrote:Thanks everyone.
srifqi wrote:How to create my own map gen?
See this thread viewtopic.php?f=18&t=6396
I also have a few simplified lua mapgens meant to help people learn the methods, the most useful one is here viewtopic.php?f=11&t=8628
Here's a little more about mapgens: Development Wiki Modding FAQ: How Do I Generate a Custom Map?

UtahTeapot
New member
Posts: 1
Joined: Wed Jul 09, 2014 17:37
In-game: UtahTeapot

Re: Post your modding questions here

by UtahTeapot » Post

Title: How can I change the default font?
I've saw people change their default font, i wanna do it myself!

OffT: Hi! I'm new here!

User avatar
kidmondo
Member
Posts: 130
Joined: Sun May 11, 2014 07:56
IRC: kidmondo
In-game: kidmondo
Location: New Zealand

Re: Post your modding questions here

by kidmondo » Post

Would someone be able to make a minetest version of Flan's WW2 mod?

User avatar
philipbenr
Member
Posts: 1897
Joined: Fri Jun 14, 2013 01:56
GitHub: philipbenr
IRC: philipbenr
In-game: robinspi
Location: United States

Re: Post your modding questions here

by philipbenr » Post

I just replaced the font files in the fonts folder and renamed them to liberationsans.ttf and whatever. Just replace them is what I'd suggest.

User avatar
Calinou
Moderator
Posts: 3169
Joined: Mon Aug 01, 2011 14:26
GitHub: Calinou
IRC: Calinou
In-game: Calinou
Location: Troyes, France
Contact:

Re: Post your modding questions here

by Calinou » Post

UtahTeapot wrote:Title: How can I change the default font?
I've saw people change their default font, i wanna do it myself!

OffT: Hi! I'm new here!
This has nothing to do with modding, but put this in minetest.conf and replace the font path with something else (or nothing if you have no font around, to use the default one):

This changes font settings which work only with Freetype-enabled builds, not with bitmap fonts.

Code: Select all

font_path = /usr/share/fonts/truetype/droid/DroidSans.ttf
font_size = 18
font_shadow_alpha = 255
mono_font_size = 16
fallback_font_size = 18
fallback_font_shadow_alpha = 255

User avatar
Krock
Developer
Posts: 4649
Joined: Thu Oct 03, 2013 07:48
GitHub: SmallJoker
Location: Switzerland
Contact:

Re: Post your modding questions here

by Krock » Post

UtahTeapot wrote:Title: How can I change the default font?
I've saw people change their default font, i wanna do it myself!

OffT: Hi! I'm new here!
Addition for builds without freetype:
https://github.com/minetest/minetest/bl ... s.cpp#L181

Code: Select all

font_path = fonts/fontlucida.png
mono_font_path = fonts/fontdejavusansmono.png
Look, I programmed a bug for you. >> Mod Search Engine << - Mods by Krock - DuckDuckGo mod search bang: !mtmod <keyword here>

User avatar
Mitroman
Member
Posts: 62
Joined: Thu Apr 03, 2014 19:47
GitHub: Mitroman
In-game: Mitroman15

Re: Post your modding questions here

by Mitroman » Post

Itemstacks ARE userdata objects. Userdata objects can have methods associated with them. Try some of the Itemstack methods (e.g. player:get_wielded_item():get_name()) on the returned userdata object and you should get what you expect from an Itemstack.[/quote]
Thanks. =)

TeTpaAka
Member
Posts: 141
Joined: Sat Dec 28, 2013 21:54

Re: Post your modding questions here

by TeTpaAka » Post

I have a question: When there are multiple minetest.register_on_generated() calls, which one is called first?
I mean, by combining multiple mods with map-manipulating calls, which mod sees the changes of the others?

User avatar
rubenwardy
Moderator
Posts: 6972
Joined: Tue Jun 12, 2012 18:11
GitHub: rubenwardy
IRC: rubenwardy
In-game: rubenwardy
Location: Bristol, United Kingdom
Contact:

Re: Post your modding questions here

by rubenwardy » Post

It is a FIFO* stack. The first minetest.register_on_generated() call is run first, and then the second is etc.

This means mods see the changes of the mods loaded before it. Use depends.txt to force a mod to load before your mod.

* - First In First Out.
Renewed Tab (my browser add-on) | Donate | Mods | Minetest Modding Book

Hello profile reader

User avatar
Esteban
Member
Posts: 873
Joined: Sun Sep 08, 2013 13:26
In-game: Esteban
Contact:

Re: Post your modding questions here

by Esteban » Post

I am trying to finish an NPC, my question is how I can make that when you left-click the NPC it disappear and give me its spawner back? Here is the code:
Spoiler

Code: Select all

npcf = {}
NPCF_ANIM_STAND = 1
NPCF_ANIM_SIT = 2
NPCF_ANIM_LAY = 3
NPCF_ANIM_WALK = 4
NPCF_ANIM_WALK_MINE = 5
NPCF_ANIM_MINE = 6
NPCF_SHOW_IN_CREATIVE = true
NPCF_SHOW_NAMETAGS = true
NPCF_BUILDER_REQ_MATERIALS = false
NPCF_DECO_FREE_ROAMING = true
NPCF_GUARD_ATTACK_PLAYERS = true
NPCF_DUPLICATE_REMOVAL_TIME = 10

local input = io.open(NPCF_MODPATH.."/npcf.conf", "r")
if input then
	dofile(NPCF_MODPATH.."/npcf.conf")
	input:close()
	input = nil
end
local timer = 0
local index = {}
input = io.open(NPCF_DATADIR.."/index.txt", "r")
if input then
	index = minetest.deserialize(input:read('*all'))
	io.close(input)
else
	os.execute("mkdir \""..NPCF_DATADIR.."\"")
	local output = io.open(NPCF_DATADIR.."/index.txt", 'w')
	if output then
		output:write(minetest.serialize(index))
		io.close(output)
	end
end
local default_npc = {
	hp_max = 1,
	physical = true,
	weight = 5,
	collisionbox = {-0.5,-0.5,-0.5, 0.5,0.5,0.5},
	visual = "sprite",
	visual_size = {x=1, y=1},
	initial_sprite_basepos = {x=0, y=0},
	textures = {"character.png"},
	colors = {},
	is_visible = true,
	makes_footstep_sound = true,
	automatic_rotate = false,
	stepheight = 0,
	automatic_face_movement_dir = false,
	armor_groups = {inmortal=1},
	animation = {
		stand_START = 0,
		stand_END = 79,
		sit_START = 81,
		sit_END = 160,
		lay_START = 162,
		lay_END = 166,
		walk_START = 168,
		walk_END = 187,
		mine_START = 189,
		mine_END = 198,
		walk_mine_START = 200,
		walk_mine_END = 219,
	},
	animation_speed = 30,
	decription = "Default NPC",
	inventory_image = "npcf_inv_top.png",
	show_nametag = true,
	nametag_color = "white",
	metadata = {},
	var = {},
}
local nametag = {
	npcf_id = "nametag",
	physical = false,
	collisionbox = {x=0, y=0, z=0},
	visual = "sprite",
	textures = {"npcf_tag_bg.png"},
	visual_size = {x=0.72, y=0.12, z=0.72},
	npc_name = nil,
	on_activate = function(self, staticdata, dtime_s)
		if staticdata == "expired" then
			self.object:remove()
		end
	end,
	get_staticdata = function(self)
		return "expired"
	end,
}
local form_reg = "size[8,3]"
	.."label[0,0;NPC Name, max 12 characters (A-Za-z0-9_-)]"
	.."field[0.5,1.5;7.5,0.5;name;Name;]"
	.."button_exit[5,2.5;2,0.5;cancel;Cancel]"
	.."button_exit[7,2.5;1,0.5;submit;Ok]"

local function get_valid_player_name(player)
	if player then
		if player:is_player() then
			local player_name = player:get_player_name()
			if minetest.get_player_by_name(player_name) then
				return player_name
			end
		end
	end
end

local function get_valid_npc_name(npc_name)
	return npc_name:len() <= 12 and npc_name:match("^[A-Za-z0-9%_%-]+$")
end

local function get_valid_entity(luaentity)
	if luaentity then
		if luaentity.name and luaentity.owner and luaentity.origin then
			return true
		end
	end
end

local function add_nametag(parent)
	if parent.npc_name then
		local pos = parent.object:getpos()
		local tag = minetest.add_entity(pos, "npcf:nametag")
		if tag then
			local color = "W"
			if minetest.get_modpath("textcolors") then
				local c = string.upper(parent.nametag_color:sub(1,1))
				if string.match("RGBCYMW", c) then
					color = c
				end
			end
			local texture = "npcf_tag_bg.png"
			local x = math.floor(66 - ((parent.npc_name:len() * 11) / 2))
			local i = 0
			parent.npc_name:gsub(".", function(char)
				if char:byte() > 64 and char:byte() < 91 then
					char = "U"..char
				end
				texture = texture.."^[combine:84x14:"..(x+i)..",0="..color.."_"..char..".png"
				i = i + 11
			end)
			tag:set_attach(parent.object, "", {x=0,y=9,z=0}, {x=0,y=0,z=0})
			tag = tag:get_luaentity() 
			tag.npc_name = parent.npc_name
			tag.object:set_properties({textures={texture}})
		end
	end
end

function npcf:register_npc(name, def)
	for k,v in pairs(default_npc) do
		if not def[k] then
			def[k] = v
		end
	end
	minetest.register_entity(name, {
		hp_max = def.hp_max,
		physical = def.physical,
		weight = def.weight,
		collisionbox = def.collisionbox,
		visual = def.visual,
		visual_size = def.visual_size,
		textures = def.textures,
		colors = def.colors,
		is_visible = def.is_visible,
		makes_footstep_sound = def.makes_footstep_sound,
		automatic_rotate = def.automatic_rotate,
		stepheight = def.stepheight,
		automatic_face_movement_dir = def.automatic_face_movement_dir,
		armor_groups = def.armor_groups,
		on_receive_fields = def.on_receive_fields,
		animation = def.animation,
		animation_speed = def.animation_speed,
		decription = def.description,
		show_nametag = def.show_nametag,
		nametag_color = def.nametag_color,
		metadata = def.metadata,
		properties = {textures = def.textures},
		var = def.var,
		npcf_id = "npc",
		npc_name = nil,
		owner = nil,
		origin = {},
		timer = 0,
		state = NPCF_ANIM_STAND,
		on_activate = function(self, staticdata, dtime_s)
			self.object:set_armor_groups(self.armor_groups)
			if staticdata then
				local npc = minetest.deserialize(staticdata)
				if npc then
					if npc.npc_name and npc.owner and npc.origin then
						self.npc_name = npc.npc_name
						self.owner = npc.owner
						self.origin = npc.origin
						if npc.origin.pos then
							self.object:setpos(npc.origin.pos)
						end
					else
						self.object:remove()
						minetest.log("action", "Removed unknown npc")
						return
					end
					if npc.metadata then
						self.metadata = npc.metadata
					end
					if npc.properties then
						self.properties = npc.properties
						self.object:set_properties(npc.properties)
					end
					if NPCF_SHOW_NAMETAGS == true and self.show_nametag == true then
						add_nametag(self)
					end
				end
			end
			local x = self.animation.stand_START
			local y = self.animation.stand_END
			local speed = self.animation_speed
			if x and y then
				self.object:set_animation({x=x, y=y}, speed)
			end
			if type(def.on_construct) == "function" then
				def.on_construct(self)
			end
			minetest.after(0.5, function()
				if get_valid_entity(self) then
					if type(def.on_activate) == "function" then
						def.on_activate(self, staticdata, dtime_s)
					end
				else
					self.object:remove()
				end
			end)
		end,
		on_rightclick = function(self, clicker)
			if get_valid_entity(self) then
				local player_name = get_valid_player_name(clicker)
				if player_name then
					local ctrl = clicker:get_player_control()
					if ctrl.sneak then
						local yaw = npcf:get_face_direction(self.object:getpos(), clicker:getpos())
						self.object:setyaw(yaw)
						self.origin.yaw = yaw
						return
					end
					minetest.chat_send_player(player_name, self.npc_name)
					if type(def.on_rightclick) == "function" then
						def.on_rightclick(self, clicker)
					end
				end
			end
		end,
		on_punch = function(self, hitter)
			if get_valid_entity(self) then
				if hitter:is_player() then
					local player_name = get_valid_player_name(hitter)
					if player_name == self.owner then
						local ctrl = hitter:get_player_control()
						if ctrl.sneak then
							local yaw = hitter:get_look_yaw() - math.pi * 0.5
							local v = npcf:get_walk_velocity(0.1,0, yaw)
							local pos = self.object:getpos()
							pos = vector.add(v, pos)
							self.object:setpos(pos)
							self.origin.pos = pos
						end
					end
				end
				if type(def.on_punch) == "function" then
					def.on_punch(self, hitter)
				end
			end
		end,
		on_step = function(self, dtime)
			self.timer = self.timer + dtime
			if type(def.on_step) == "function" and get_valid_entity(self) then
				def.on_step(self, dtime)
			end
		end,
		get_staticdata = function(self)
			local npc_data = {
				name = self.name,
				npc_name = self.npc_name,
				owner = self.owner,
				origin = self.origin,
				pos = self.object:getpos(),
				properties = self.properties,
				metadata = self.metadata,
			}
			return minetest.serialize(npc_data)
		end,
	})
	local groups = {falling_node=1}
	if NPCF_SHOW_IN_CREATIVE == false then
		groups.not_in_creative_inventory=1
	end
	minetest.register_node(name.."_spawner", {
		description = def.description,
		inventory_image = def.inventory_image,  
		wield_image = "ball.png",
		stack_max = 1,  
		tiles = {"ball_top.png", "ball_bottom.png", "ball_side.png", "ball_side.png", "ball_side.png", "ball_front.png",},
		drawtype = "nodebox",
		paramtype = "light",
		paramtype2 = "facedir",
		node_box = {
		type = "fixed",
		fixed = {
			{-0.1875, -0.5, -0.1875,  0.1785, -0.125, 0.1785},
		},
	},
		groups = groups,
		sounds = default.node_sound_defaults(),
		on_construct = function(pos)
			local meta = minetest.get_meta(pos)
			meta:set_string("formspec", form_reg)
			meta:set_string("infotext", def.description.." spawner")
		end,
		after_place_node = function(pos, placer, itemstack)
			local meta = minetest.get_meta(pos)
			meta:set_string("owner", placer:get_player_name())
			itemstack:take_item()
			return itemstack
		end,
		on_punch = function(pos, node, puncher)
			local meta = minetest.get_meta(pos)
			local owner = meta:get_string("owner")
			local player_name = puncher:get_player_name()
			local admin = minetest.check_player_privs(player_name, {server=true})
			if admin or player_name == owner then
				minetest.dig_node(pos)
				if player_name == owner then
					puncher:get_inventory():add_item("main", node)
				end
			end
		end,
		on_receive_fields = function(pos, formname, fields, sender)
			if fields.cancel then
				return
			end
			local meta = minetest.get_meta(pos)
			local owner = meta:get_string("owner")
			local player_name = sender:get_player_name()
			if player_name == owner then
				if get_valid_npc_name(fields.name) then
					if index[fields.name] then
						minetest.chat_send_player(player_name, "Error: Name Already Taken!")
						return
					end
				else
					minetest.chat_send_player(player_name, "Error: Invalid NPC Name!")
					return
				end
				minetest.dig_node(pos)
				local npc_pos = {x=pos.x, y=pos.y + 0.5, z=pos.z}
				local yaw = sender:get_look_yaw() + math.pi * 0.5
				local luaentity = npcf:spawn(npc_pos, name, {
					owner = player_name,
					npc_name = fields.name,
					origin = {pos=npc_pos, yaw=yaw}
				})
				if luaentity and type(def.on_registration) == "function" then
					def.on_registration(luaentity, pos, sender)
				end
			end
		end,
	})
end

function npcf:spawn(pos, name, def)
	if pos and name and def.npc_name and def.owner then
		if get_valid_npc_name(def.npc_name) and index[def.npc_name] == nil then
			local entity = minetest.add_entity(pos, name)
			if entity then
				local luaentity = entity:get_luaentity()
				if luaentity then
					index[def.npc_name] = def.owner
					luaentity.owner = def.owner 
					luaentity.npc_name = def.npc_name
					luaentity.origin = def.origin or {pos=pos, yaw=0}
					if def.origin then
						luaentity.object:setyaw(luaentity.origin.yaw)
					end
					if npcf:save(luaentity) then
						local output = io.open(NPCF_DATADIR.."/index.txt", 'w')
						if output then
							output:write(minetest.serialize(index))
							io.close(output)
							if NPCF_SHOW_NAMETAGS == true and luaentity.show_nametag == true then
								add_nametag(luaentity)
							end
							return luaentity
						else
							minetest.log("error", "Failed to add "..def.npc_name.." to NPC index")
						end
					else
						minetest.log("error", "Failed to save NPC "..def.npc_name)
					end
				end
			end
		end
	end
end

function npcf:clear(npc_name)
	if get_valid_npc_name(npc_name) then
		for _,ref in pairs(minetest.luaentities) do
			if ref.object and ref.npc_name == npc_name then
				ref.object:remove()
			end
		end
	end
end

function npcf:load(npc_name, pos)
	if get_valid_npc_name(npc_name) then
		npcf:clear(npc_name)
		local input = io.open(NPCF_DATADIR.."/"..npc_name..".npc", "r")
		if input then
			local data = minetest.deserialize(input:read('*all'))
			io.close(input)
			if data then
				if pos and data.origin then
					data.origin.pos = pos
				end
				if data.origin.pos then
					local npc = minetest.add_entity(data.origin.pos, data.name)
					if npc then
						local luaentity = npc:get_luaentity()
						if luaentity then
							luaentity.owner = data.owner
							luaentity.npc_name = npc_name
							luaentity.origin = data.origin
							luaentity.animation = data.animation
							luaentity.metadata = data.metadata
							luaentity.object:setyaw(data.origin.yaw)
							luaentity.properties = data.properties
							luaentity.object:set_properties(data.properties)
							if NPCF_SHOW_NAMETAGS == true and luaentity.show_nametag == true then
								add_nametag(luaentity)
							end
							return 1
						end
					end
				end
			end
		end
		minetest.log("error", "Failed to load "..npc_name)
		return
	end
	minetest.log("error", "Attempt to load invalid NPC")
end

function npcf:save(luaentity)
	if get_valid_entity(luaentity) then
		local npc = {
			name = luaentity.name,
			owner = luaentity.owner,
			origin = luaentity.origin,
			animation = luaentity.animation,
			metadata = luaentity.metadata,
			properties = luaentity.properties,
		}
		local npc_name = luaentity.npc_name
		local output = io.open(NPCF_DATADIR.."/"..npc_name..".npc", 'w')
		if output then
			output:write(minetest.serialize(npc))
			io.close(output)
			return 1
		end
		minetest.log("error", "Failed to save NPC "..npc_name)
		return
	end
	minetest.log("error", "Attempt to save invalid NPC")
end

function npcf:set_animation(luaentity, state)
	if get_valid_entity(luaentity) and state then
		if state ~= luaentity.state then
			local speed = luaentity.animation_speed
			local anim = luaentity.animation
			if speed and anim then
				if state == NPCF_ANIM_STAND and anim.stand_START and anim.stand_END then
					luaentity.object:set_animation({x=anim.stand_START, y=anim.stand_END}, speed)
				elseif state == NPCF_ANIM_SIT and anim.sit_START and anim.sit_END then
					luaentity.object:set_animation({x=anim.sit_START, y=anim.sit_END}, speed)
				elseif state == NPCF_ANIM_LAY and anim.lay_START and anim.lay_END then
					luaentity.object:set_animation({x=anim.lay_START, y=anim.lay_END}, speed)
				elseif state == NPCF_ANIM_WALK and anim.walk_START and anim.walk_END then
					luaentity.object:set_animation({x=anim.walk_START, y=anim.walk_END}, speed)
				elseif state == NPCF_ANIM_WALK_MINE and anim.walk_mine_START and anim.walk_mine_END then
					luaentity.object:set_animation({x=anim.walk_mine_START, y=anim.walk_mine_END}, speed)
				elseif state == NPCF_ANIM_MINE and anim.mine_START and anim.mine_END then
					luaentity.object:set_animation({x=anim.mine_START, y=anim.mine_END}, speed)
				end
				luaentity.state = state
			end
		end
	end
end

function npcf:get_index()
	return index
end

function npcf:get_luaentity(npc_name)
	if get_valid_npc_name(npc_name) then
		for _,ref in pairs(minetest.luaentities) do
			if ref.object then
				if ref.npcf_id == "npc" and ref.npc_name == npc_name then
					return ref.object:get_luaentity()
				end
			end
		end
	end
end

function npcf:get_face_direction(v1, v2)
	if v1 and v2 then
		if v1.x and v2.x and v1.z and v2.z then
			dx = v1.x - v2.x
			dz = v2.z - v1.z
			return math.atan2(dx, dz)
		end
	end
end

function npcf:get_walk_velocity(speed, y, yaw)
	if speed and y and yaw then
		if speed > 0 then
			yaw = yaw + math.pi * 0.5
			local x = math.cos(yaw) * speed
			local z = math.sin(yaw) * speed
			return {x=x, y=y, z=z}
		end
		return {x=0, y=y, z=0}
	end
end

function npcf:show_formspec(player_name, npc_name, formspec)
	if player_name and npc_name and formspec then
		minetest.show_formspec(player_name, "npcf_"..npc_name, formspec)
	end
end

minetest.register_on_player_receive_fields(function(player, formname, fields)
	if formname then
		local npc_name = formname:gsub("npcf_", "")
		if npc_name ~= formname then
			local luaentity = npcf:get_luaentity(npc_name)
			if luaentity then
				for k,v in pairs(fields) do
					if k ~= "" then
						v = string.gsub(v, "^CHG:", "")
						luaentity.metadata[k] = v
					end
				end
				if type(luaentity.on_receive_fields) == "function" then
					luaentity.on_receive_fields(luaentity, fields, player)
				end
			end
		end
	end
end)

minetest.register_entity("npcf:nametag", nametag)

-- Duplicate Entity Removal (experimental)

if NPCF_DUPLICATE_REMOVAL_TIME > 0 then
	minetest.register_globalstep(function(dtime)
		timer = timer + dtime
		if timer > NPCF_DUPLICATE_REMOVAL_TIME then
			timer = 0
			local dupes = {}
			for _,ref in pairs(minetest.luaentities) do
				local to_remove = false
				if ref.object then
					if ref.npcf_id == "npc" then
						if ref.owner == nil or ref.npc_name == nil then
							to_remove = true
						elseif dupes[ref.npc_name] then
							to_remove = true
						else
							dupes[ref.npc_name] = 1
						end
					end
					local pos = ref.object:getpos()
					if to_remove == true then
						ref.object:remove()
						local pos_str = minetest.pos_to_string(pos)
						minetest.log("action", "Removed duplicate npc at "..pos_str)
						if NPCF_SHOW_NAMETAGS == true then
							for _,object in ipairs(minetest.get_objects_inside_radius(pos, 1)) do
								local luaentity = object:get_luaentity()
								if luaentity then
									if luaentity.npcf_id == "nametag" then
										luaentity.object:remove()
										minetest.log("action", "Removed duplicate nametag at "..pos_str)
										break
									end
								end
							end
						end
					end
				end
			end
		end
	end)
end


User avatar
philipbenr
Member
Posts: 1897
Joined: Fri Jun 14, 2013 01:56
GitHub: philipbenr
IRC: philipbenr
In-game: robinspi
Location: United States

Re: Post your modding questions here

by philipbenr » Post

Topic: How to generate trees normally
--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=
Reason: I want to make a forest with birch trees/ oak trees
--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=
More info: I looked into farming_plus, and I saw that I could easily make saplings grow, and that I had no problem with that. But then I thought 'If I have saplings of birch or oak trees, then I will need a good birch/oak forest.' So, I need to be able to generate forests, thickets, and the like, mainly because I think the mod (for a subgame) I am making will not look good. Anybody able to explain how to do so? I can use a simple bit of code to get trees to spawn randomly, but that isn't good enough...

[Edit] I looked at plants_lib documentation, and it was rather complicated and helped my mind swim even more.

User avatar
HeroOfTheWinds
Member
Posts: 470
Joined: Wed Apr 23, 2014 23:16
GitHub: HeroOfTheWinds
IRC: WindHero
Location: Hawaii

Re: Post your modding questions here

by HeroOfTheWinds » Post

There are a few ways to go about this, and since mgv7 is not stable at the minute, I'll take the more catch-all approach. Lua Voxel Manipulator is the short answer. There are two ways to make forests via LVM:
1. Have it spawn special saplings that grow via abm 1 second after chunk gen, by placing premade schematics of the trees (save them with WorldEdit).
2. Have it use functions to procedurally generate the trees.

That there is the heart of it. You will also need to implement a simple for loop to search for the ground level at any given area, and see if it is of suitable material (e.g. default:dirt_with_grass). A small example could be like this:

Code: Select all

--make variables to condense the edges of the generated chunk
local x0 = minp.x
local x1 = maxp.x
local y0 = minp.y
local y1 = maxp.y
local z0 = minp.z
local z1 = maxp.z

--loop through the x and z planes first
for x = x0, x1 do
    for z = z0, z1 do
        --loop from the top to the bottom, and stop when the node isn't ground.
        for y = y1, y0, -1 do
            local vi = area:get_data(x,y,z)
            if data[vi] ~= c_air then
                --grab the index of y+1, place your tree generator or else call your function to gen the tree.  break afterward.
            end
        end
    end
end
Just a very rough idea. I left out the bits about initializing the LVM and closing it down, look at either paramat or my own mods to get an idea how to start and stop them.
Nam ex spatio, omnes res venire possunt.
Why let the ground limit you when you can reach for the sky?
Back to college now, yay for sophomore year schedules. :P

User avatar
philipbenr
Member
Posts: 1897
Joined: Fri Jun 14, 2013 01:56
GitHub: philipbenr
IRC: philipbenr
In-game: robinspi
Location: United States

Re: Post your modding questions here

by philipbenr » Post

Thanks. Will do.

I do wish mgv7 was stable and complete... :/ Oh well. c55 will work at his own pace.

User avatar
HeroOfTheWinds
Member
Posts: 470
Joined: Wed Apr 23, 2014 23:16
GitHub: HeroOfTheWinds
IRC: WindHero
Location: Hawaii

Re: Post your modding questions here

by HeroOfTheWinds » Post

philipbenr wrote:Thanks. Will do.

I do wish mgv7 was stable and complete... :/ Oh well. c55 will work at his own pace.
Happy to help. :)

So do I.... Also, it's hmmm's jurisdiction, I believe, not c55's.
Nam ex spatio, omnes res venire possunt.
Why let the ground limit you when you can reach for the sky?
Back to college now, yay for sophomore year schedules. :P

User avatar
philipbenr
Member
Posts: 1897
Joined: Fri Jun 14, 2013 01:56
GitHub: philipbenr
IRC: philipbenr
In-game: robinspi
Location: United States

Re: Post your modding questions here

by philipbenr » Post

@ HeroOfTheWinds: I heard that it was c55 (I think from paramat...). It may be both.

User avatar
paramat
Developer
Posts: 3700
Joined: Sun Oct 28, 2012 00:05
GitHub: paramat
IRC: paramat
Location: UK

Re: Post your modding questions here

by paramat » Post

Mgv7 is entirely hmmmm / kwolekr's work. He was recently trying to rewrite it but is frustrated with the difficult progress so is taking a break from mapgen (i can confirm it drives you crazy very quickly, it's common to waste 2 days of full time work adjusting parameters, generating huge amounts of terrain and not getting anywhere), he's also going through 'real life' stuff too like illness. So don't expect anything soon. Celeron55 wants to work on the 3D noise mgv5 of MT 0.3.0 and re-introduce that into Minetest.

User avatar
philipbenr
Member
Posts: 1897
Joined: Fri Jun 14, 2013 01:56
GitHub: philipbenr
IRC: philipbenr
In-game: robinspi
Location: United States

Re: Post your modding questions here

by philipbenr » Post

Okay... Kinda confused, I heard that c55 was doing work on something, but I wasn't sure what...

User avatar
addi
Member
Posts: 666
Joined: Thu Sep 20, 2012 03:16
GitHub: adrido
Location: Black-Forest, Germany

How does the Lua Table formspec works?

by addi » Post

How does the Lua Table formspec works?

How can i send that formspec to a player?
minetest.show_formspec(playername, formname, formspec)
seems not to work, it requires a string not a table?

User avatar
Bas080
Member
Posts: 398
Joined: Mon May 21, 2012 15:54
GitHub: bas080
IRC: bas080
In-game: bas080
Location: Netherlands

Re: Post your modding questions here

by Bas080 » Post

addi, that's because the formspec is defined with a string. The api documentation helped me. Also looking at mods that alter the player formspec should give you the solution.

https://github.com/minetest/minetest/bl ... i.txt#L922

Locked

Who is online

Users browsing this forum: No registered users and 1 guest