placing a node randomly

Post Reply
blert2112
Member
Posts: 244
Joined: Sat Apr 25, 2015 04:05
GitHub: blert2112

placing a node randomly

by blert2112 » Post

I have a need to place a single node in a random position. This position may not even be in a generated part of the map but it must be a position that a player can stand on (without dying) and could even be underground. I am having a horrible time trying to figure out the VoxelManip and I can't seem to grok perlin noise stuffs. Is this possible? Any help would be appreciated. Thanks.

User avatar
ArguablySane
Member
Posts: 116
Joined: Sun Oct 12, 2014 21:29

Re: placing a node randomly

by ArguablySane » Post

When do you need to place the node? While generating the map, or later?

Do you only want to place a single node once, or do you want many of these nodes randomly distributed throughout the world?
The above post and any ideas expressed therein are released to the public domain under a Creative Commons CC0 license.

blert2112
Member
Posts: 244
Joined: Sat Apr 25, 2015 04:05
GitHub: blert2112

Re: placing a node randomly

by blert2112 » Post

Only place the node once. Triggering the placement of the node would be dependent on a player placing a certain node. So, player places SomeNode which triggers AnotherNode to be placed in the world at a random position. The random position must be safe for a player... inside a cave, on the surface.

User avatar
ArguablySane
Member
Posts: 116
Joined: Sun Oct 12, 2014 21:29

Re: placing a node randomly

by ArguablySane » Post

Here's a function for spawning the player in a random position:
https://github.com/CasimirKaPazi/spawna ... r/init.lua
What you're trying to do is very similar, so take a look at that code.

Basically, calculate random x, y, and z coordinates within some volume, use minetest.forceload_block(pos) to load that position, then use minetest.get_node(pos) to check if it's a valid location. If it is a valid location, create your block, otherwise call minetest.forceload_free_block(pos) and repeat the process again.
The above post and any ideas expressed therein are released to the public domain under a Creative Commons CC0 license.

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

Re: placing a node randomly

by rubenwardy » Post

It would be better to choose a random XYZ, then use LVM to find the nearest surface.
Renewed Tab (my browser add-on) | Donate | Mods | Minetest Modding Book

Hello profile reader

blert2112
Member
Posts: 244
Joined: Sat Apr 25, 2015 04:05
GitHub: blert2112

Re: placing a node randomly

by blert2112 » Post

ArguablySane wrote:Here's a function for spawning the player in a random position:
https://github.com/CasimirKaPazi/spawna ... r/init.lua
What you're trying to do is very similar, so take a look at that code.

Basically, calculate random x, y, and z coordinates within some volume, use minetest.forceload_block(pos) to load that position, then use minetest.get_node(pos) to check if it's a valid location. If it is a valid location, create your block, otherwise call minetest.forceload_free_block(pos) and repeat the process again.
Thanks, I will look into this later today.
rubenwardy wrote:It would be better to choose a random XYZ, then use LVM to find the nearest surface.
I spent some time with the LVM last night. I think I figured some of it out but I always get a load of "ignore"s returned to me. I think I must be missing a step or not doing something right. I'll get the code cleaned up later today and post it to see if someone can spot my error.

User avatar
ArguablySane
Member
Posts: 116
Joined: Sun Oct 12, 2014 21:29

Re: placing a node randomly

by ArguablySane » Post

blert2112 wrote:I always get a load of "ignore"s returned to me. I think I must be missing a step or not doing something right.
You're probably missing the minetest.forceload_block(pos) part. If you try to get map data from a section of the map which isn't loaded then you'll just get a load of "ignore"s as you observed. Just don't forget to minetest.forceload_free_block(pos) after you have finished with the LVM.
The above post and any ideas expressed therein are released to the public domain under a Creative Commons CC0 license.

blert2112
Member
Posts: 244
Joined: Sat Apr 25, 2015 04:05
GitHub: blert2112

Re: placing a node randomly

by blert2112 » Post

ArguablySane wrote:You're probably missing the minetest.forceload_block(pos) part. If you try to get map data from a section of the map which isn't loaded then you'll just get a load of "ignore"s as you observed. Just don't forget to minetest.forceload_free_block(pos) after you have finished with the LVM.
So far as I have read/found, forceload is unnecessary when working with the LVM. Anyway... Worked some more on my LVM test code and I think I may have gotten it to work. I am no longer getting "ignore"s. Now to sort out the data.

edit: Nope. :( Still getting "ignore"s. Even tried it with forceload.

User avatar
BrandonReese
Member
Posts: 839
Joined: Wed Sep 12, 2012 00:44
GitHub: bremaweb
IRC: BrandonReese
In-game: BrandonReese
Location: USA

Re: placing a node randomly

by BrandonReese » Post

If you get ignores when using LVM it means the area hasn't been generated. In that case you will need to place your node during mapgen.

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

Re: placing a node randomly

by rubenwardy » Post

LVM should force the MapBlocks to generate though.

It has whenever I've used it.
Renewed Tab (my browser add-on) | Donate | Mods | Minetest Modding Book

Hello profile reader

User avatar
BrandonReese
Member
Posts: 839
Joined: Wed Sep 12, 2012 00:44
GitHub: bremaweb
IRC: BrandonReese
In-game: BrandonReese
Location: USA

Re: placing a node randomly

by BrandonReese » Post

rubenwardy wrote:LVM should force the MapBlocks to generate though.

It has whenever I've used it.
Maybe it does and I've just been interpreting the results wrong...

So if you have something like this

Code: Select all

local vm = VoxelManip()
local e1, e2 = vm:read_from_map(minp, maxp)
local area = VoxelArea:new({MinEdge=e1, MaxEdge=e2})
local data = vm:get_data()
Do you know where mapgen is triggered (I assume in vm:read_from_map?). In this block of code should "data" contain the results of what the mapgen just created?

blert2112
Member
Posts: 244
Joined: Sat Apr 25, 2015 04:05
GitHub: blert2112

Re: placing a node randomly

by blert2112 » Post

That code is, of course, basically what I had. 'Data' only contains "ignore"s, unless I luck into the random position being in a previously visited area (which almost never happens).

blert2112
Member
Posts: 244
Joined: Sat Apr 25, 2015 04:05
GitHub: blert2112

Re: placing a node randomly

by blert2112 » Post

After much hacking I have determined (and currently believe until someone shows me otherwise) that it is not possible to force a chunk to generate without actually moving the player to that chunk. The random spawn mod linked above does not work as I need it to... It will only try and pick a random spot in an already generated area or, if it fails, spawns at 0,SomeY,0. LVM won't force a chunk generation either. Oh well.

I have worked around this and have a working solution to my problem that should suffice for now. Now to get back on with this mod so I can put it into my server and seriously mess with my kids... They are going to hate me when this is done. :D

Thanks for the help.

User avatar
TenPlus1
Member
Posts: 3722
Joined: Mon Jul 29, 2013 13:38
In-game: TenPlus1
Contact:

Re: placing a node randomly

by TenPlus1 » Post

This seemed to work for me blert, used axe at 0,0,0 and a mese block appeared at 2000,10,2000 when I teleported there:

Code: Select all

minetest.register_craftitem("test:axe", {
	description = "Test Axe",
	inventory_image = "default_tool_steelaxe.png",
	on_use = function(itemstack, user, pointed_thing)
		if not pointed_thing or pointed_thing.type ~= "node" then return end
		local pos = pointed_thing.under

		pos.x = pos.x + 2000
		pos.z = pos.z + 2000
		pos.y = pos.y + 10

		minetest.forceload_block(pos)
		minetest.set_node(pos, {name = "default:mese"})

	end,
})

User avatar
ArguablySane
Member
Posts: 116
Joined: Sun Oct 12, 2014 21:29

Re: placing a node randomly

by ArguablySane » Post

TenPlus1 wrote:This seemed to work for me...
That works fine for placing a block in a known location, but does it actually generate the chunk? Could you, for example, modify it to spawn the mese block at ground level by reading from the map?
The above post and any ideas expressed therein are released to the public domain under a Creative Commons CC0 license.

User avatar
TenPlus1
Member
Posts: 3722
Joined: Mon Jul 29, 2013 13:38
In-game: TenPlus1
Contact:

Re: placing a node randomly

by TenPlus1 » Post

It wont generate the chunk in question, only buffer nodes ready to place when you DO visit... I tried voxelmanip and it only finds 'ignore' nodes when checking the area from afar (unless I've placed the mese block, then it will report that one back correctly)...

If I may ask, what exactly are you trying to place from afar ??

blert2112
Member
Posts: 244
Joined: Sat Apr 25, 2015 04:05
GitHub: blert2112

Re: placing a node randomly

by blert2112 » Post

TenPlus1 wrote:...
If I may ask, what exactly are you trying to place from afar ??
A door.

Here's the backstory...
I was watching PopularMMOs with my son. Pat was reviewing a MC mod that created doors that would randomly teleport you somewhere. One of the doors was short-range and would place another door at the random position that, if you walked back through, would take you back to the first door. Another door was long-range and also has a return door spawned at the random location. The third door was all-range and had no return door.

The code is pretty straight-forward except for creating the randomly spawned door (in a safe location) in the first place. I pretty much have it worked out, using a method similar to the WorldEdge mod, except I get an error every so often. I should be able to deal with that with a little more error checking. I figure I could mess with my kids by placing a few of these doors into their world.

User avatar
TenPlus1
Member
Posts: 3722
Joined: Mon Jul 29, 2013 13:38
In-game: TenPlus1
Contact:

Re: placing a node randomly

by TenPlus1 » Post

you could make an abm for the 1st door which when entered, teleport player, clear area around player and place return door...

blert2112
Member
Posts: 244
Joined: Sat Apr 25, 2015 04:05
GitHub: blert2112

Re: placing a node randomly

by blert2112 » Post

TenPlus1 wrote:you could make an abm for the 1st door which when entered, teleport player, clear area around player and place return door...
This is what I currently do, sort of...
1 - player opens and walks through door.
2 - ABM checks if there is a stored location in meta. If there is just teleport player. If not, fire off the following...
a - get random x and z coordinants.
b - create an entity at x,0,z and lock the player to it so they can't move around while a good position is found.
c - use minetest.find_nodes_in_area_under_air() to get a table of possible positions at x, 300 thru -300, z.
d - choose a random position from that table, here is where I get an occasional nil error, need to add error checking.
e - use LVM to prep the area so heads are not accidentally spawned in a rock and place the second door.
f - store the positions in the meta of the doors to "link" them.
g - move the player to the final position and remove the "lock" entity.

I do it this way because I want the position to either be on the surface or in a cave. I don't want to overly-manipulate the map or have the position end up in a 3x3x3 box underground or a 3x3 floating platform in the air or ocean.

blert2112
Member
Posts: 244
Joined: Sat Apr 25, 2015 04:05
GitHub: blert2112

Re: placing a node randomly

by blert2112 » Post

ARG!! I'm pulling my hair out with a problem here. :(

The code seems to work just fine but... Every so often (usually on about the fifth or sixth "jump") the player wont be moved to the proper position. I have the position being reported in the terminal but the player ends up being moved somewhere else (very close to where it's supposed to be but off by enough to place me in a rock or something).

If someone could put another set of eyes on this and try to find an error I cannot, I would appreciate it.
https://github.com/blert2112/troll_doors.git

Here's what I have been doing to test this bit of code:
-Place the test block (troll_doors:temp),
-Hop on top of the block and give it a second or two,
-Check the terminal output and compare the reported position with the player's position. You can end up in a dark cave so take some torches,
-Repeat until you end up positioned inside solid ground or under water,
-Notice, at this time the reported position in the terminal will not match the player position. If you enable noclip and move to the proper reported position you will see that it is a valid position.

Any help would be very appreciated. It's probably some mundane thing that I am just not seeing but I can't see how it can work a handful of times and the fail to move the player to the position. Going to keep hammering on it tonight, I think I will start rewriting the whole thing one step at a time. Thanks.

edit: I may have found the problem while rewriting... I think the ABM and GlobalStep were "colliding" if things happened at the "wrong" time.

edit-2: Nope. Rewrote the whole thing so the ABM and GlobalStep cannot "collide". Still, every few "jumps" the player will not be teleported to the position given to it. It is usually 'y' that is off. Instead of the proper value, the value of 'y' is somehow 0 (zero, or actually 0.5 as I add 0.5 to 'y' so the player is not knee deep in dirt/rock).

User avatar
SegFault22
Member
Posts: 872
Joined: Mon May 21, 2012 03:17
Location: NaN

Re: placing a node randomly

by SegFault22 » Post

It may be possible to use a non-player bot entity to "go" to that region, forcing it to generate and load, before the block is placed. Either that, or use code from the method used to generate a region when a player gets near - which might be part of the Lua player function scripts (like many other, more basic and more often used functions) unless they just decided to leave that (and almost no other player functions?) in the C++ part.
If you can't make a bot entity that simulates the effect of a player entering the region (due to limitations in the core), then it may be possible to use a player entity with a special name (that can't be created by a regular user when joining server) as the bot - but that would be somewhat hackish.

Regardless, it would not be good to teleport the player to the position (even temporarily) - that is if the purpose of making the node generate at a random location, is to make it so that the player can not "just know" exactly where to go in order to find the node (which could happen if the player can see the position of the region where the node is placed, even if it is random)

blert2112
Member
Posts: 244
Joined: Sat Apr 25, 2015 04:05
GitHub: blert2112

Re: placing a node randomly

by blert2112 » Post

Moving the player to initiate chunk generation is not a big deal as the player will just be teleported to the position anyway. I may try spawning a "fake" entity and see if that forces map generation, I don't think you can spawn a "fake" player.

What's causing me grief right now is I do not understand how the position is getting changed. As an example:

Code: Select all

local selected_pos = positions[math.random(pos_count)]
selected_pos = {
	x=selected_pos.x,
	y=selected_pos.y + 0.5,
	z=selected_pos.z
}
print("SELECTED POSITION: "..minetest.pos_to_string(selected_pos))
working.lock_ent:setpos(selected_pos)
Somehow, between the print statement (which prints the correct position in the terminal) and setpos(), the position is getting out of whack. It does not happen every time, the longest chain of "jumps" I got up to without the error was 16 but it usually happens around the fifth or sixth "jump". For instance, the terminal output will show a selected position of {x=-2500, y=15.5, z=5000} but the player will end up at {x=-2500, y=0.5, z=5000}.

Last night I tried a number of rewrites, different step times, different order of doing things. I even rewrote it a number of times step-by-step, confirming each step was working before adding in the next step. No matter what I did it still did the same thing.

Post Reply

Who is online

Users browsing this forum: No registered users and 10 guests