[MOD 0.14.x] Water maze
Re: [MOD 0.13.x] Water maze
Quick updates... for most of the mods today
Re: [MOD 0.13.x] Water maze
Any chance of a 0.14 version?
Re: [MOD 0.14.x] Water maze
Done. I only tested it long enough to make sure it didn't crash or any obvious problems. Let me know if you encounter problems.
Re: [MOD 0.14.x] Water maze
I am amazed how fast that was.
Oh on the mod portal page, why not set the homepage to the forum post?
Oh on the mod portal page, why not set the homepage to the forum post?
Re: [MOD 0.14.x] Water maze
I've been playing with no mods for a while (trying to get all the achievements), and been busy with not-Factorio, so it hadn't occurred to me to update my mods for 0.14. (Although I am proud to say I updated to 0.13 within something like 30 minutes or an hour of its release, I was trying to be the first mod on the mod portal )
Re: [MOD 0.14.x] Water maze
Cool mod. How do you do the "Mandelbrot" from the screenshots?
Edit: Found it:
Mandelbrot(size)
Edit: Found it:
Mandelbrot(size)
Re: [MOD 0.14.x] Water maze
Added 2 new functions:
Added type to the Islandify, you can now have circles in addition to the squares.
Add jitter to borders near water. - Note, this is randomized and will probably not be synced in multiplay.
Example of pattern in config.lua
swini, feel free to add these to the mod if you wish.
Might release more in the future.
Edit: Random should be synced:
viewtopic.php?f=25&t=19353#p123629
Added type to the Islandify, you can now have circles in addition to the squares.
Code: Select all
function Islandify(pattern, islandradius, bridgelength, bridgewidth, spawntype)
local pattern_get = pattern.get
local r = islandradius or 32
local k = bridgelength or 48
local w = bridgewidth or 2
local t = spawntype or "square"
local n = 2 * r + w + k
local function create()
return pattern.create()
end
local function reload(d)
pattern.reload(d)
end
local function get(x, y)
local px = math.floor((x + r) / n)
local py = math.floor((y + r) / n)
if not pattern_get(px, py) then
return false
end
x = x % n
y = y % n
if (x < w and pattern_get(px, py + 1)) or (y < w and pattern_get(px + 1, py)) then
return true
else
if t == "square" then
x = (x + r) % n
y = (y + r) % n
return (x < 2 * r + w) and (y < 2 * r + w)
elseif t == "circle" then
x = (x + r) % n - r - (w / 2) + 0.5
y = (y + r) % n - r - (w / 2) + 0.5
return (x * x) + (y * y) < (r + (w / 2) + 1) * (r + (w / 2) + 1)
end
end
end
return {
create = create,
reload = reload,
get = get,
lua = 'Islandify(' .. pattern.lua .. ', ' .. r .. ', ' .. k .. ', ' .. w .. ', ' .. t .. ')'
}
end
Code: Select all
function JaggedBorder(pattern, chance, distance)
local pattern_get = pattern.get
local c = chance or 30
local d = distance or 2
local function create()
return pattern.create()
end
local function reload(d)
pattern.reload(d)
end
local function get(x, y)
if math.random(100) < c and not pattern_get(x - d, y) then
return false
elseif math.random(100) < c and not pattern_get(x + d, y) then
return false
elseif math.random(100) < c and not pattern_get(x, y - d) then
return false
elseif math.random(100) < c and not pattern_get(x, y + d) then
return false
else
return pattern_get(x, y)
end
end
return {
create = create,
reload = reload,
get = get,
lua = 'JaggedBorder(' .. pattern.lua .. ', ' .. c .. ', ' .. d .. ')'
}
end
Example of pattern in config.lua
Code: Select all
local pattern = JaggedBorder(Union(Islandify(Maze2(), 24, 8, 16, "circle"), Circle(80)), 30, 5)
Might release more in the future.
Edit: Random should be synced:
viewtopic.php?f=25&t=19353#p123629
- Attachments
-
- Round.png (52.13 KiB) Viewed 8473 times
Re: [MOD 0.14.x] Water maze
Just found out that Water Maze is somewhat incompatible with Factorissimo.
Edit:
Made a fix: In control.lua:
Find function:
Insert in the beginning:
Edit:
Made a fix: In control.lua:
Find function:
Code: Select all
local function make_chunk(event)
Code: Select all
if event.surface.name ~= "nauvis" then
return
end
- Attachments
-
- incomp.jpg (504.94 KiB) Viewed 8465 times
- GeekinaCave
- Inserter
- Posts: 39
- Joined: Tue Jun 14, 2016 5:14 pm
- Contact:
Re: [MOD 0.14.x] Water maze
Hi, does any know how create a pattern which make random craters with water using mandelbrot or something else?
Re: [MOD 0.14.x] Water maze
For some reason I stopped getting notifications (even though I am subscribed to this topic)....
EldVarg, thanks for the feedback and cool suggestions. I may include some of your ideas if I have time. Just a note, JaggedBorder as you wrote it might have interesting effects in some combinations that assume the pattern being combined returns the same value for get(x, y) every time (like Zoom).
GeekinaCave, not sure what you're looking for with random craters, do you want randomly scattered circular lakes? Currently there's no way to do that in the mod but I can add it fairly easily.
EldVarg, thanks for the feedback and cool suggestions. I may include some of your ideas if I have time. Just a note, JaggedBorder as you wrote it might have interesting effects in some combinations that assume the pattern being combined returns the same value for get(x, y) every time (like Zoom).
GeekinaCave, not sure what you're looking for with random craters, do you want randomly scattered circular lakes? Currently there's no way to do that in the mod but I can add it fairly easily.
- GeekinaCave
- Inserter
- Posts: 39
- Joined: Tue Jun 14, 2016 5:14 pm
- Contact:
Re: [MOD 0.14.x] Water maze
that will be great, since i want to play with several mods including angels ores and i want to give to all the crushed stone a reasonable use (filling the land for necessary expansion).swni wrote:For some reason I stopped getting notifications (even though I am subscribed to this topic)....
EldVarg, thanks for the feedback and cool suggestions. I may include some of your ideas if I have time. Just a note, JaggedBorder as you wrote it might have interesting effects in some combinations that assume the pattern being combined returns the same value for get(x, y) every time (like Zoom).
GeekinaCave, not sure what you're looking for with random craters, do you want randomly scattered circular lakes? Currently there's no way to do that in the mod but I can add it fairly easily.
Re: [MOD 0.14.x] Water maze
New version 0.1.0 out with a ton of new patterns.
If you want regularly spaced circular lakes, you can try something like Invert(Tile(Translate(Circle(32), 32, 32), 64, 64)). Throw on some Jitter or Distort to make the lakes more irregularly shaped.
If you want regularly spaced circular lakes, you can try something like Invert(Tile(Translate(Circle(32), 32, 32), 64, 64)). Throw on some Jitter or Distort to make the lakes more irregularly shaped.
Re: [MOD 0.14.x] Water maze
Got to say, this mod is really neat. Currently trying to set up a train focused island map with RSO.
It seems some of the example patterns in config.lua are broken though? (Invalid argument to the Distort ones and Islandify not being included in the release?)
Anyway with regards to RSO integration (or any other resource/enemy spawn mod for that matter) I'd propose a simple callback system. Here is what I'm currently trying to make RSO play nice with (haven't had time to do the RSO part yet). in control.lua:
This should allow other mods to instead of setting up a call back for on_chunk_generated do one for water maze instead:
Haven't had a chance to test this properly yet, will probably get to do that tomorrow. However, feel free to add it if you like. Hopefully I'll manage to get it to run with RSO but at the moment I'm not really sure how to change it to not break if water maze is not installed.
It seems some of the example patterns in config.lua are broken though? (Invalid argument to the Distort ones and Islandify not being included in the release?)
Anyway with regards to RSO integration (or any other resource/enemy spawn mod for that matter) I'd propose a simple callback system. Here is what I'm currently trying to make RSO play nice with (haven't had time to do the RSO part yet). in control.lua:
Code: Select all
local function make_chunk(event)
--same as usual, cut to save post length
--do renmote callbacks
for k,v in pairs(global.saved_config.callback) do
remote.call(k, v, event)
end
end
Code: Select all
local function on_init(event)
global.saved_config = config
config.tp_data = config.terrain_pattern.create()
config.tp_lua = config.terrain_pattern.lua
terrain_pattern_get = config.terrain_pattern.get
config.terrain_pattern = nil
config.callback = {} --store registered callback functions
on_load(nil)
end
--[[
Add callback functionality.
Callbacks will be made to registered remote functions after on_chunk_generated is finished.
Use to replace on_chunk_generated callbacks in resource generation mods
to ensure that terrain is generated before resources.
Callbacks look like: 'remote.call(interface, name, event)'
where 'interface' is the interface exposed by the mod,
'name' is the name of the function to call
and 'event' is passed from on_chunk_generated
Basically, expose the existing on_chunk_generated function
--]]
remote.add_interface("water_maze", {
--[[
Register or update callback. Only allows one registered functon per interface.
remote.call("water_maze", "add_callback", interface, name)
--]]
add_callback = function(interface, name)
global.saved_config.callback.interface = name
end,
--[[
Remove callback from interface
remote.call("water_maze", "remove_callback", interface)
--]]
remove_callback = function(interface)
global.saved_config.callback.interface = nil
end
})
script.on_init(on_init)
script.on_load(on_load)
Code: Select all
instread of:
script.on_event(defines.events.on_chunk_generated, some_function)
do:
remote.call("water_maze", "add_callback", "MYMOD", "CALLBACK")
and:
remote.add_interface("MYMOD", {
CALLBACK = some_function
})
Re: [MOD 0.14.x] Water maze
From what devs said this should be much easier in 0.15 so I didn't try to do stuff like this in RSO.
They are planning to make sure that event calls are using mod load order if I recall Rsending91 correctly.
This would allow for water maze being always called before RSO for example to make sure terrain is ready before the ores are spawned.
There will be still some issues even with that approach - sometimes ores go out of the chunk that has been generated now and things will still break there. There are was to fix this but that would be for RSO and it's potentially a lot of work to do it properly.
They are planning to make sure that event calls are using mod load order if I recall Rsending91 correctly.
This would allow for water maze being always called before RSO for example to make sure terrain is ready before the ores are spawned.
There will be still some issues even with that approach - sometimes ores go out of the chunk that has been generated now and things will still break there. There are was to fix this but that would be for RSO and it's potentially a lot of work to do it properly.
Re: [MOD 0.14.x] Water maze
Oh, those weren't meant to be example patterns, they were leftover from testing. I'll clean up the examples and maybe make new screenshots at some point. Thanks for letting me know.
It would probably make more sense for my mod to call RSO than vice versa since RSO is the more popular, but either way can work. Also fine with waiting for 0.15, especially if things will just get easier
orzelek, to what extent does RSO care about what is land vs water? Presumably RSO only tries to place resources on land (with the effect that the density of resources / land square goes up as the amount of land goes down)? So in vanilla Factorio how does RSO handle placing resources on a chunk that hasn't been generated yet? I'm not sure why this interaction should be different in vanilla Factorio compared to with my mod active.
It would probably make more sense for my mod to call RSO than vice versa since RSO is the more popular, but either way can work. Also fine with waiting for 0.15, especially if things will just get easier
orzelek, to what extent does RSO care about what is land vs water? Presumably RSO only tries to place resources on land (with the effect that the density of resources / land square goes up as the amount of land goes down)? So in vanilla Factorio how does RSO handle placing resources on a chunk that hasn't been generated yet? I'm not sure why this interaction should be different in vanilla Factorio compared to with my mod active.
Re: [MOD 0.14.x] Water maze
Tbh... I don't know for sure. It looks like base game method that checks for entity placement can work on not yet generated chunks since RSO uses can_place_entity to see if ore can be placed. It might be that it says that placement is forbidden there and it would cause the ore patch to move a bit to try and find better location - there is a +/- 1 chunk on patch placement to find better location (reduces ore/water overlaps). So presence/absence of water and/or other resources might have an actual influence on ore spawning.swni wrote:...
orzelek, to what extent does RSO care about what is land vs water? Presumably RSO only tries to place resources on land (with the effect that the density of resources / land square goes up as the amount of land goes down)? So in vanilla Factorio how does RSO handle placing resources on a chunk that hasn't been generated yet? I'm not sure why this interaction should be different in vanilla Factorio compared to with my mod active.
It seems to work most of the time and writing delayed ore spawning was on my list of things nice to have but it adds a lot of complexity. It would be a proper solution for issues like this where different mods try to modify terrain.
From my point of view it would be better for RSO to provide the callback that other mods can register to if they update terrain. Then RSO would be able to call it before it's own handling of chunk generation event. If I understood changes for 0.15 correctly it might be enough to setup optional dependency there to guarantee the event order - currently it's alphabetical I think.
Re: [MOD 0.14.x] Water maze
*Spoiled kid voice*: I don't care! I want to play now!orzelek and swni wrote:*reasonable arguments to wait for .15*
... and with that said here's what I have running at the moment. For those of us who can't wait, feel free to "steal" if you want to
Firstly a minor bug on the water maze side of things. In the remote interface:
Code: Select all
global.saved_config.callback.interface = name
and
global.saved_config.callback.interface = nil
should be
global.saved_config.callback[interface] = name
and
global.saved_config.callback[interface] = nil
Code: Select all
... --rest of function
checkForBobEnemies()
--new
--handle water mod chunk generation
if remote.interfaces["water_maze"] ~= nil then
script.on_event(defines.events.on_chunk_generated, nil)
remote.call("water_maze", "add_callback", "RSO", "chunk_generation_callback")
local surface = game.surfaces['nauvis']
regenerate_everything(surface)
end
--/new
initDone = true
... --rest of function
Code: Select all
local function gen_chunk(event)
--lots of code
end
--script.on_init(delayedInit) - no longer required
script.on_load(delayedInit)
script.on_event(defines.events.on_chunk_generated, gen_chunk)
Code: Select all
...--other remote interfaces
saveLog = function()
l:dump()
end,
--callback method for custom chunk generation
chunk_generation_callback = gen_chunk
})
Now I just need to mess a bit with the region and starting area settings in RSO and I'll soon be able to actually start playing on my hacky ribbon world (attached).
Anyways, these mods are awesome, keep up the good work people.
Cheers!
- Attachments
-
- water.png (149.19 KiB) Viewed 7941 times
Re: [MOD 0.14.x] Water maze
orzelek, did you have in mind something like the following: keep track of which chunks have been generated and only when a chunk and its 8 neighbors have all been generated do you then run the RSO generation code on it? If so, that sounds not too hard to patch up by recording a table which stores for each chunk the number of it and its neighbors that have been generated, and then call the appropriate code and drop it from the table when it hits 9. Something like
Totally untested of course... and you would know better than I if that would work with the rest of your code.
aaargha, can I ask what happens if you combine the two mods out of the box? Is the problem that some resource patches get spawned in places that get turned into water, or something worse than that? Also did you manage to make that ribbon using the provided patterns or did you code it up yourself? And, did you manage to get Distort and Islandify to work (the README and mod info page should both show correct usage)?
Code: Select all
function chunk_generated_callback(event)
for k, v in global.chunk_generated_hooks_pre
remote.call(k, v, event)
end
for i = -1, 2 do
for j = -1, 2 do
maybe_generate_chunk(event.area.left_top.x + i * CHUNK, event.area.left_top.y + j * CHUNK, event)
end
end
end
function maybe_generate_chunk(x, y, event)
if x == 0 then x = 0 end -- These checks are probably not necessary but I'm not sure
if y == 0 then y = 0 end
local key = x .. '#' .. y
local c = global.chunks_seen
if c[key] == nil then
c[key] = 1
else
c[key] = c[key] + 1
if c[key] == 9 then
c[key] = nil
do_actual_chunk_generation_code(event)
for k, v in global.chunk_generated_hooks_post(event) do
remote.call(k, v, event)
end
end
end
end
aaargha, can I ask what happens if you combine the two mods out of the box? Is the problem that some resource patches get spawned in places that get turned into water, or something worse than that? Also did you manage to make that ribbon using the provided patterns or did you code it up yourself? And, did you manage to get Distort and Islandify to work (the README and mod info page should both show correct usage)?
Re: [MOD 0.14.x] Water maze
It was mostly just resource patches that got split in half, or just small patches next to the shores. Now that RSO can move the patches to avoid water there is a lot less of that, and a lot more usable resource fields (without plastering them everywhere). Didn't notice anything more problematic than that.
The ribbon world is made with the default patterns, just a lot of them.
And that's why it's hacky If you know a more efficient way of doing this I'd appreciate it, this one is pretty slow. Also while I'm at it, feature request: a mirror transformation. Rotating 180 degrees does not really work as it introduces too many rounding errors meaning that straight edges do not stay straight. Also perhaps a cache for Tile would help performance wise for patterns like this.
Trying
results in
The ribbon world is made with the default patterns, just a lot of them.
Code: Select all
--"node" attributes
local half_square = 64
local bridge_l = 32
local bridge_w = 8 --comfortably fit two rails
local node_size = half_square * 2 + bridge_l
--"trunk" attributes
local trunk_w = 40
--generate
local node = SquaresAndBridges(half_square, bridge_l, bridge_w) --make base
node = Intersection(node, Translate(Cross(half_square * 2), half_square, node_size)) --strip side bridges
local side1 = Intersection(Tile(node, node_size, node_size), Translate(Strip(node_size), 0, -node_size / 2)) --bottom
local side2 = Intersection(Tile(Translate(node, 0, bridge_l), node_size, node_size), Translate(Strip(node_size), 0, node_size / 2)) --top
local pattern = Union(Translate(side1, -half_square, -trunk_w / 2), Union(Translate(side2, -half_square, trunk_w / 2), Strip(trunk_w))) --add sides to trunk
pattern = Union(pattern, Square(half_square)) --add a bit of starting area
pattern = Translate(pattern, 64, 0) --align to RSO regions
Trying
Code: Select all
pattern = Islandify(Maze2)
Haven't tried Distort as I've not really needed it, just noticed the broken patterns included in the config and I just figured that the examples weren't updated.__water-maze__/control.lua:2: __water-maze__/config.lua:44: attempt to call global 'Islandify' (a nil value)
Re: [MOD 0.14.x] Water maze
Bah, looks like I uploaded the wrong version. Islandify was called "ConvolveBridges" before I decided that that was misleading and confusing.
I considered providing a Memoize transformer that caches a given pattern, but I figured that all of the existing patterns are fast enough (some of them internally memoize) that wouldn't be necessary... however I did not anticipate that a sufficiently complicated and nested combination of patterns would be too slow even if all the parts are individually reasonable Memoizing adds significant overhead so I don't want to do it by default unless it is necessary.
I think I'll add a Rectangle(x1, y1, x2, y2) method and maybe let Circle take an optional center argument and let Union and Intersection have any number of arguments... that should help a bit with this sort of stuff. Then you can union together three rectangles, tile it, and union with a strip and starting area.
To do a 180 rotation you should be able to do Affine(pattern, -1, 0, 0, -1). It should keep everything as integers and therefore avoid rounding. Let me know if that doesn't work well. To do a mirror do Affine(pattern, -1, 0, 0, 1) or Affine(pattern, 1, 0, 0, -1) for x and y respectively. (Also, I'd be curious to know which pattern you tried that caused Rotate to round poorly so that I can fix that one.)
I considered providing a Memoize transformer that caches a given pattern, but I figured that all of the existing patterns are fast enough (some of them internally memoize) that wouldn't be necessary... however I did not anticipate that a sufficiently complicated and nested combination of patterns would be too slow even if all the parts are individually reasonable Memoizing adds significant overhead so I don't want to do it by default unless it is necessary.
I think I'll add a Rectangle(x1, y1, x2, y2) method and maybe let Circle take an optional center argument and let Union and Intersection have any number of arguments... that should help a bit with this sort of stuff. Then you can union together three rectangles, tile it, and union with a strip and starting area.
To do a 180 rotation you should be able to do Affine(pattern, -1, 0, 0, -1). It should keep everything as integers and therefore avoid rounding. Let me know if that doesn't work well. To do a mirror do Affine(pattern, -1, 0, 0, 1) or Affine(pattern, 1, 0, 0, -1) for x and y respectively. (Also, I'd be curious to know which pattern you tried that caused Rotate to round poorly so that I can fix that one.)