Infinite Scripter Plugin

Hi, thanks a lot for your contribution, it’s an amazing plug-in !
I’ve been using it for a couple of days to create a large map with different biomes having their own set of vegetation. I’m trying to see how far I can go with your plug in in terms of terrain complexity.
While I was doing a « jungle » biome I was messing around with the « model generation ».
I wanted something dense for the jungle so I’ve put a hight amount of models to load on large spaces
By doing so, when I tried the map on studio I got a warning« infinite yield possible on starterplayerscript » at launch probably due to #zdata in LoadMap function (I load the map for each biome with humanoids preset)
The map then never loads and I get an error. (Timeout error → exhaustion of allowed processing time by roblox core logic ? Would it mean that there is too much to load ?)

When I publish the game I get the same error, but the map loads (computer)
When I play the game on my phone some part of the map is missing and I can spot a lot of buggy voxels.
Do you have any idea how to solve this bug ? Or is there nothing to do ?

1 Like

if a thread takes to long to finish its work that thread will be stopped

1 Like

What would you advise me to do if I’m trying to load large maps (lets say around a 1000 modulesScripts) ?
I’m not super familiar with thread management but here’s what I tried so far :

I’ve tried to “wrap” a part of the LoadMap function in a coroutine and yield it every time it loads 100 items → didn’t work

module.LoadMap = function(folder, modules)
	ogTick = tick()
	local map = {}
	local coroutineFunc = coroutine.create(function()
		for n, child in ipairs(folder:GetChildren()) do
			if child.ClassName ~= "ModuleScript" then continue end
			local position = child:GetAttribute("Position")
			if position == nil then continue end
			local data = modules[child]
			for i = 1, #data, 2 do
				local x = position.X + data[i]
				local zData = data[i + 1]
				if map[x] == nil then map[x] = {} end
				for j = 1, #zData, 2 do
					local z = position.Y + zData[j]
					local value = zData[j + 1]
					map[x][z] = value
					if j > 100 then
						coroutine.yield()
					end
				end
				if i > 100 then
					coroutine.yield()
				end
			end
			if n > 100 then
				coroutine.yield()
			end
		end
	end)
	coroutine.resume(coroutineFunc)
	return map
end

I’ve tried to wrap the LoadMap function in a coroutine and yield when the thread took a set amount of time by starting a timer a the beginning of LoadMap and yielding every time the execution is going over 0.0001s → didn’t work

module.LoadMap = function(folder, modules)
	ogTick = tick()
	local map = {}
	local coroutineFunc = coroutine.create(function()
		for _, child in ipairs(folder:GetChildren()) do
			if child.ClassName ~= "ModuleScript" then continue end
			local position = child:GetAttribute("Position")
			if position == nil then continue end
			local data = modules[child]
			for i = 1, #data, 2 do
				local x = position.X + data[i]
				local zData = data[i + 1]
				if map[x] == nil then map[x] = {} end
				for j = 1, #zData, 2 do
					local z = position.Y + zData[j]
					local value = zData[j + 1]
					map[x][z] = value
					if ogTick - tick() > 0.0001 then
						print(tick() - ogTick.."ms")
						coroutine.yield()
					end
				end
				if ogTick - tick() > 0.0001 then
					print(tick() - ogTick.."ms")
					coroutine.yield()
				end
			end
			if ogTick - tick() > 0.0001 then
				print(tick() - ogTick.."ms")
				coroutine.yield()
			end
		end
	end)
	coroutine.resume(coroutineFunc)
	return map
end

I tried to spawn each LoadMap instruction → Didn’t work


module.Initialize = function(instance, modules)
	--Functions
	PerlinNoise = modules[instance.Functions].Noise
	RandomNoise = modules[instance.Functions].Random
	Magnitude = modules[instance.Functions].Magnitude
	LoadMap = modules[instance.Functions].LoadMap
	ScaleModel =  modules[instance.Functions].ScaleModel
	--Biomes
	spawn(function()
		Beachs = LoadMap(instance.Beachs,modules)
	end)
	spawn(function() 
		Cliffs = LoadMap(instance.Cliffs,modules)
	end)
	spawn(function() 
		Desert = LoadMap(instance.Desert,modules)
	end)

	spawn(function()
		Jungle =  LoadMap(instance.Jungle,modules)
	end)
	spawn(function()
		Mountain =  LoadMap(instance.Mountain,modules)	
	end)
...[Rest of the code]

I tried to “yield” with task.wait() before loading the biggest maps → didn’t work

module.Initialize = function(instance, modules)
	--Functions
	PerlinNoise = modules[instance.Functions].Noise
	RandomNoise = modules[instance.Functions].Random
	Magnitude = modules[instance.Functions].Magnitude
	LoadMap = modules[instance.Functions].LoadMap
	ScaleModel =  modules[instance.Functions].ScaleModel
	--Biomes
	Beachs = LoadMap(instance.Beachs,modules)
	Cliffs = LoadMap(instance.Cliffs,modules)
	Desert = LoadMap(instance.Desert,modules)
	task.wait()
	Jungle =  LoadMap(instance.Jungle,modules)
	Mountain =  LoadMap(instance.Mountain,modules)
...[Rest of the code]

I get this at start :

13:53:49.392 Infinite yield possible on ‘StarterPlayer:WaitForChild(“StarterPlayerScripts”)’ - Studio
13:53:49.392 Stack Begin - Studio
13:53:49.392 Script ‘CoreGui.RobloxGui.Modules.Settings.SettingsHub’, Line 1206 - function getOverridesPlayerScripts - CoreScript - SettingsHub:1206
13:53:49.392 Script ‘CoreGui.RobloxGui.Modules.Settings.SettingsHub’, Line 1268 - CoreScript - SettingsHub:1268
13:53:49.392 Stack End - Studio
13:54:03.323 Script timeout: exhausted allowed execution time - Client - -1,-2:65
13:54:03.325 Stack Begin - Studio
13:54:03.331 Script ‘ReplicatedFirst.Terrain.Humanoids.Actor.Humanoids.Jungle.-1,-2’, Line 65 - Studio - -1,-2:65
13:54:03.338 Stack End - Studio
13:54:03.339 Script timeout: exhausted allowed execution time - Client - CoreScripts/CoreScriptErrorReporter:132
13:54:03.339 Stack Begin - Studio
13:54:03.339 Script ‘CoreGui.RobloxGui.CoreScripts/CoreScriptErrorReporter’, Line 132 - CoreScript - CoreScripts/CoreScriptErrorReporter:132
13:54:03.340 Stack End - Studio

I guess it’s because no matter what, replicatedFirst has a limited time set to ends all its threads.

Maybe I should put the whole thing in replicatedStorage instead of ReplicatedFirst and create a custom Loading Screen that would make the player wait for the terrain threads to finish before starting to play ? What do you think ?

You can use task.wait() to wait till the next frame to continue the thread

1 Like

Applied it, worked like a charm.

local function ActorAmount(amount)
		while #actors < amount do
			local actor = Instance.new("Actor", script)
			actorScript:Clone().Parent = actor	
			actor.Initialize:Fire()
			table.insert(actors, actor)
			task.wait() -- Edited
		end
		while #actors > amount do
			local actor = table.remove(actors)
			actor:Destroy()
		end
	end

Thanks a lot, it looks amazing.

Is there a method to get the average slope of an entire chunk, or would I need to add in something to the generation to obtain it?

You would need to add that yourself

1 Like

could you please share how you managed to make it work on the serverside?

Update

image

Update to latest version to fix this error

How could I edit this to support terrain depth and caves? Currently it generates a layer of terrain, but I am hoping to generate terrain all the way down to a certain point.

Take a look at the 3d terrain preset

Okay, I got the depth working, now is there a way to add caves? I’ve heard of perlin worms, however I don’t think you can generate those on a chunk-by-chunk basis.

perlin worms is a option you can also use perlin on its own i think there is many options

How can I visually edit the “Steep” spline? I can’t seem to find an editor anywhere.
Edit: I found the editor lol

Hey, I absolutely love your exciting plugins and helpful videos and want to thank you for offering them!

Recently I was trying to use the Infinite Scripter plugin in a new project and ran into some problems.

Basically, the terrain is generated on the client and I want parts to be placed randomly on the terrain. (not as terrain models, but as collectable parts/loot) These parts are a crucial part of the gameplay, so they should be placed by the server. However, since the server does not generate the terrain, I’m not sure how to get the height of the terrain at a given location. I’m sure it’s possible somehow, but I couldn’t figure it out. Can you help me with this?

Also, I haven’t been able to create usable terrain, I don’t really understand the values that need to be put into the script. I tried to recreate the canyons example you provided for the Infinite Terrain plugin.
For example, why are these values added to data.Height here?
Do these values have to be in a certain order?
graphic

I have watched both the tutorial for Infinite Scripter & Infinite Terrain, but my configurations generate infinite vertical terrain (Studio even crashes). I use a preset because of this, but would appreciate some more explanation on the values.

Regardless of my struggles, you are truly one of the greatest and most talented programmers I know!

Thank you so much

1 Like

Yes it is possible to get the height on the server side you simple do the same things you do in the height function but just on the server side


when you do math.noise(x, y, z) you are getting a value at a specific position in 3d space and the space looks a little like this

the black parts are values < -1 and the white parts are values > 1 and grey parts are values = 0

now the goal is to use this noise to make terrain but its kind of tricky to explain how to do this
all I can say is that you have to keep experimenting with the noise like a artist experiments with paint there is not a exact science to it


it depends on how you use the values but if you just adding them then the order is not important

height = 0
height += noise(...) -- 1
height += noise(...) -- 2
height += noise(...) -- 1
-- height = 4

height = 0
height += noise(...) -- 1
height += noise(...) -- 1
height += noise(...) -- 2
-- height = 4

see the order we add them does not matter

but if we multiply then it can mater

height = 0
height += noise(...) -- 2
height *= noise(...) -- 2 multiply
height += noise(...) -- 1
-- height = 5

height = 0
height += noise(...) -- 2
height *= noise(...) -- 1 multiply
height += noise(...) -- 2
-- height = 4
2 Likes

what is this??