delete cozylights
This commit is contained in:
parent
7695674991
commit
214ebb3141
17 changed files with 0 additions and 3186 deletions
|
@ -1,13 +0,0 @@
|
|||
For code:
|
||||
Copyright 2024 SingleDigitIq
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
|
||||
Media licenses:
|
||||
default_glass.png is by Krock (CC0 1.0)
|
||||
my debug textures are WTFPL if anything
|
|
@ -1,256 +0,0 @@
|
|||
# Cozy Lights
|
||||
|
||||
Improves the way light sources(torches etc) behave and allows to create huge lights, literal projectors with just a mouse click, light map will be computed for you.
|
||||
|
||||
Early alpha, but at least NotSoWow, Sumi, MisterE, Agura and Sharp have expressed curiosity, that already makes six of us, good enough for release. Feedback, suggestions, bug reports are very welcome. At this dev stage Cozy Lights can be good for builders in creative mode, singleplayer survival is somewhat ok, multiplayer is not yet recommended, unless it's 2-5 players or just schematics with cozy lights and no functionality.
|
||||
|
||||
**Light sources illuminate bigger area with default settings:**
|
||||
|
||||

|
||||
|
||||
Voxel light maps are a complete game changer - it is almost like going from 2d to 3d in terms of depth. You now have 14 shades for every visible building block, and it does not have to register 14 versions of every building block. Cobble only challenge has got a whole lot easier, something fun to look at with the least fun texture is possible now with just this mod :> Disabling smooth lighting might can make for an interesting aesthetic in some cases.
|
||||
|
||||
You can also build these lights just like you do with any structures, in other words, place invisible blocks of light of all possible engine light levels block-by-block. Tools are coming soon to make this process more user-friendly, right now you will need to make them visible and interactable in debug mode.
|
||||
|
||||
It is eventually supposed to become accurate enough so that if you learn how to draw, you will have an easier time understanding how depth and shadows work and what can be done with them.
|
||||
|
||||
**Cozy wielded light:**
|
||||
|
||||

|
||||
|
||||
**WARNING:**
|
||||
|
||||
**1. after removing Cozy Lights from your world you will be left with spheres of unknown nodes. Easiest could be to reenable the mod and call ```/clearlights``` in all locations Cozy Lights are active.**
|
||||
|
||||
**2. if you have override_engine_lights enabled, then in case you ever remove Cozy Lights mod from your world, you will be left with broken lights. To fix it, you will need to use the mod fixmap or anything that updates/fixes engine lights. override_engine_lights is disabled by default, so it should be safe.**
|
||||
|
||||
## Known issues
|
||||
|
||||
1. worldedit:placeholder nodes can prevent light map from generating correctly and this currenly happens without notice or options provided. Current workaround is to define a worldedit region and run ```//replace worldedit:placeholder air``` before adding lights to the scene. This issue also involves cozy wielded light, wordedit placeholders can appear anywhere if the mod is active. There can be other invisible nodes from some mods and games which would interfere with light map.
|
||||
|
||||
2. You will have to disable K Ambient Light to use Cozy Lights, together, they are not recommended for now.
|
||||
|
||||
3. Light emitting liquids always straight up ignored, light emitting airlikes too
|
||||
|
||||
4. When there are too many light sources in a generated area, it gets ignored. If you run /rebuildlights in such area, it will attempt to do so, but probably would need too much time
|
||||
|
||||
5. If you are moving too fast(creative or falling from above) and its first time you visit many areas, generation will not look like it's immediate
|
||||
|
||||
6. Some lights are still being missed in generated mapblocks
|
||||
|
||||
*For what it does it's quite fast, it is supposed to somehow get even faster. I have recently discovered that my CPU is 10(!) years old and it's actually usable on my PC. Would appreciate if somebody with a beast PC would try this mod out and post a couple of benchmarks, and also if some phone poster will try to do the same*
|
||||
|
||||
## Light Brush
|
||||
|
||||

|
||||
|
||||
*Click or hold left mouse button* to draw light with given settings. Light Brush' reach is 100 nodes, so you can have perspective. Note: with radiuses over 30 nodes as of now mouse hold won't have an effect.
|
||||
|
||||
*On right click* settings menu opens up. The menu has hopefully useful tooltips for each setting. You can set radius, brightness, strength and draw mode. There are 6 draw modes so far: default, erase, override, lighten, darken and blend.
|
||||
|
||||

|
||||
|
||||
## Chat Commands
|
||||
|
||||
```/cozysettings``` opens a global settings menu for cozy lights, here you can adjust node light sources like torches, meselamps, fireflies, etc to make it work better with potato or make light reach mad far and stuff. Some settings which you can find in Minetest game settings for the mod are still not present here(like override_engine_lights which makes everything nicer). These changes persist after exiting and re-entering the world again.
|
||||
|
||||

|
||||
|
||||
Currently max radius is 120 for commands below, if your value is invalid it will adjust to closest valid or throw an error. Some potatoes might experience issues with big radiuses. Eventually max radius will be much bigger.
|
||||
|
||||
```/clearlights <number>``` removes invisible light nodes in area with specified radius. Helpful to remove lights created with light brush. Example usage: ```/clearlights 120```
|
||||
|
||||
```/rebuildlights <number>``` rebuilds light map in an area with specified radius. Useful in case you changed the settings or accidentally broke some lights by other commands or by mining in debug. This can be slow if there are lots of light sources in the area with far reaching light. Example usage: ```/rebuildlights 40```
|
||||
|
||||
```/fixedges <number>``` fixes obstacles' opposite edges for light map in an area with specified radius. Default algorithm sacrifices accuracy for speed, because of that the lights can still go through diagonal walls if they are only one node thick, and as of now they can sometimes light up an edge(1 block from a corner) of the opposite side of an obstacle. With this command you are supposed to be able to fix it, but currently it's weird, broken. You can use it but the result wont necessarily look good.
|
||||
|
||||
```/cozydebugon <number>``` makes all cozy light nodes visible and interactable in an area with a specified radius. With it you can also basically build lights just as you would with any other structures before the tools for that are available.
|
||||
|
||||
```/cozydebugoff <number>``` makes all cozy light nodes invisible and non-interactable again in an area with a specified radius.
|
||||
|
||||
```/optimizeformobile <number>``` removes all cozy light nodes which do not touch a surface of some visible node, like cobble for example. It is maybe useful, because default algo spreads light in a sphere and lights up the air above the ground too, which might be a bit challenging for potato and mobile to render reliably, they might experience FPS drops. Good if you are building a schematic for a multiplayer server. This option might slightly decrease the quality of light map, example: you have a light node with strength of 7 above the ground, and that ground is visible because of that, but after using this option that light node will be removed, so that part of the ground might be left in complete darkness. Basically might make some places darker.
|
||||
|
||||
```/spawnlight <brightness float> <reach_factor float> <dim_factor float>``` spawn a light at your position which does not use user friendly light brush algo, but ambient light algo. "float" means it can be with some arbitrary amount of decimals, or simple integer
|
||||
|
||||
```/daynightratio <ratio float>``` change Minetest engine day_night_ratio for the player who used the command. ```0``` is the darkest night possible, you can observe how dark it can be on the screenshots, was useful in testing, probably will help with building too. ```1``` is the brightest possible day. Some gradations in between are maybe under appreciated and seem pretty moody, I guess that would depend on a texture pack.
|
||||
|
||||
```/cozyadjust <size number> <adjust_by number> <keep_map number>``` change brightness of all cozy light nodes by adjust_by value in the area of size. Adjust_by can be negative. Keep_map is 1 by default and can be omitted, when it's 1 and adjust_by will result in a value out of bounds of 1-14(engine light levels) even for one node in the area, the command will revert(have no effect at all), so that light map will be preserved. If you are ok with breaking light map, type 0 for keep_map.
|
||||
|
||||
|
||||
Shortcuts for all commands follow a convention to easier memorize them:
|
||||
|
||||
```zcl``` - clearlights
|
||||
|
||||
```zrl``` - rebuildlights
|
||||
|
||||
```zfe``` - fixedges
|
||||
|
||||
```zdon``` - cozydebugon
|
||||
|
||||
```zdoff``` - cozydebugoff
|
||||
|
||||
```zofm``` - optimizeformobile
|
||||
|
||||
```zsl``` - spawnlight
|
||||
|
||||
```zs``` - cozysettings
|
||||
|
||||
```zdnr``` - daynightratio
|
||||
|
||||
```za``` - cozyadjust
|
||||
|
||||
## Supported mods and games
|
||||
|
||||
Most of the most popular ones on paper, but its early alpha, so it can still be broken. It's not just popular ones, actually no idea how many it supports, some of them are not even on ContentDB.
|
||||
|
||||
For definitely supported games, check the section of supported games on ContentDB, or mod.conf, if the game is in a list then support is full for what the mod can currently do, current *known* exceptions are:
|
||||
|
||||
**Nodecore** - partial support, light map does not update for dynamic light sources(the ones that change brightness over time)
|
||||
|
||||
**Age of Mending** - partial support, too many light sources in caves sometimes, and so far Cozy Lights cant process that without completely freezing everything for some time
|
||||
|
||||
**Piranesi** - does not seem to work at all, probably something schematic related
|
||||
|
||||
**Shadow Forest** - it works as intended, but there is only campfire to make cozy, wont feel like an upgrade
|
||||
|
||||
If a mod or a game you like is not supported or there are some problems not listed here, tell me immediately. You can just drop a list of games/mods you have issues with in review. Eventually cozy lights' support will attempt to balance the overall feel and look of the game/mod with meticulous consideration, but we are not at that stage yet.
|
||||
|
||||
## For Developers
|
||||
|
||||
There are like I think 5 algo versions of drawing lights or I refactored that, because I never heard of DRY, never happened. All algos sacrifice accuracy for speed and miss some nodes for huge spheres.
|
||||
|
||||
*Plans for API:*
|
||||
|
||||
- You will be able to override cozylights' global step, disable it and call it from your global step
|
||||
|
||||
- You will be able to override any default settings
|
||||
|
||||
- Register unique settings for specific nodes
|
||||
|
||||
## Todo
|
||||
|
||||
- is it possible to have trees grow within the radius of a light block like torches
|
||||
|
||||
- add undo
|
||||
|
||||
- figure out what to do about lights going through diagonal, one node thick walls. also still somehow manage to keep algo cheap
|
||||
|
||||
- Optimize memory usage, use several voxel manipulators for biggest lights, will be slower but much more stable, also increase max radius to even more mentally challenged value
|
||||
|
||||
- see what can be done with race condition of wielded light and node light
|
||||
|
||||
- save brush settings in item metadata and change icon somehow to resemble the settings
|
||||
|
||||
- add /disableongen
|
||||
|
||||
- all queues should be saved in case of server shutdown, so they can be resumed
|
||||
|
||||
- add /ignore certain block
|
||||
|
||||
- algo for many adjacent lights
|
||||
|
||||
- see what can be done about snow and slabs not passing the light through
|
||||
|
||||
- make dropped items emit cozy light if they have light_source above 0, just like in original wielded light mod
|
||||
|
||||
- make sure bigger lights wont go unnoticed in on_generated and schematic placement. apparnetly on generated can support lights up to 80 if max area radius is 120
|
||||
|
||||
- stress test it with heavily modded worlds, possible problem: luajit ram limit for default luajit on linux?
|
||||
|
||||
- illuminate transparent liquids too if possible without making it look weird, except dont make floodable light sources work underwater just like in original wielded light
|
||||
|
||||
- fix nodecore dynamic light source not updating the brightness/radius
|
||||
|
||||
- add privileges so schematics can be used on multiplayer server
|
||||
|
||||
- parse minetest forum for optional_depends
|
||||
|
||||
- add inventory images for lights and debug lights, make them only available in creative
|
||||
|
||||
- make darkness nodes, wielded darkness, Darkness Brush
|
||||
|
||||
- add static natural scene(stop the time, fix the sun/moon in one position, update the area accordingly)
|
||||
|
||||
- raytracing
|
||||
|
||||
- allow people to run cpu and memory-friendly minimal schematic support version, for multiplayer servers for example
|
||||
|
||||
- if certain treshold of light source commonality in an area is reached, those light sources should be ignored
|
||||
|
||||
- would it be possible without too much work to programatically determine global commonality of a node from mapgen?
|
||||
|
||||
- add optional more pleasant day/night cycle
|
||||
|
||||
- add optional sky textures
|
||||
|
||||
- add multiplayer/mobile settings(very little light nodes, very simple light map), and mid settings(more or less okayish), max is default
|
||||
|
||||
- move to base "unsafe" methods for tables? seems like luajit optimizes it all away and it's useless to bother?
|
||||
|
||||
- try spread work over several loops and try vector.add
|
||||
|
||||
- maybe three types of darkness nodes, ones that are completely overridable with cozylights, and ones that arent(make a darker light shade), and ones that completely ignore cozylights
|
||||
|
||||
- lights auto rebuild on first load after settings change?
|
||||
|
||||
- make a table for existing decoration nodes
|
||||
|
||||
- make sure spheres of big sizes dont miss too many blocks
|
||||
|
||||
- give light sources metadata, so when nearby light sources are destroyed you can find and rebuild easily, also give metadata to light brush epicenter for the same reason
|
||||
|
||||
- maintain files in which you record light source positions, which can be quickly grabbed to rebuild lights if there is a removal
|
||||
|
||||
- add cone light blocks, so those lights can be built on top of each other to make static lights from old games
|
||||
|
||||
- add light grabber tool, Light Excavation Tool 9000 TURBO V3, so that the light wont be selectable without it
|
||||
|
||||
- add Consumer Grade Reality Bending Device to create preset nodes with chosen qualities
|
||||
|
||||
- add global step override api, ability to implement cozylights global step into a game/other mod global step more efficiently, maybe add generic global step call like mainloop or mainstep, see what other games do with it, choose or create convention for this i guess
|
||||
|
||||
- add handle_async where it makes sense
|
||||
|
||||
- ci for optional_depends auto update according to content db mods/games updates and releases
|
||||
|
||||
### Some expensive notes stackoverflow will never tell about LuaJIT to you or to future me. Summing up my discord rambling because COVID made me forget some of Lua I tried before, so I am writing it down for now.
|
||||
|
||||
TLDR: LuaJIT is certainly impressive in some parts, however I would rather refrain from using it for absolutely anything that implies even a bit of performance, and unless there is no way to avoid it, deprecate Lua as a terrible inconvenience and never look back. It's too slow, and when you try to squeeze anything out of it, it loses most of its appeal/narrative, it even loses purpose. If still too many words, remember just this about Lua: never try to optimize Lua too much, it's never worth it, and, just let Lua iterate.
|
||||
|
||||
1. While being smol, it still fails to outperform another state of the art JIT - JS V8. And thats given that JS V8 is big tech kind state of the art, which means there is certainly at the very least a significant room for improvement. Advantage of Lua in comparison to V8: less RAM consuption for small programs, so it's reasonable to run a bit of LuaJIT on weak hardware, like phones, watches, some smart-whatever, robots. In that case it's not the worst choice.
|
||||
|
||||
2. Readability syntax is a meme, I am here to code, not to shitpost, I prefer completely different state of mind from that, something very different, like curly braces and what not.
|
||||
|
||||
3. Lua bytecode, same way as Python, keeps function and variable names uncompressed. You could argue but hey that means we can at least restore the original file almost one-to-one from bytecode? Who needs that really, when RAM efficiency is 25%(!) better after using a minifier, and if you use minifier, you abandon debugging and readability(just like in Python, which is a meme language too, and it's typical very readable one letter long variable names). This is how as codebase grows, Lua loses it's only advantage over V8. Hence technically peak Lua is a joke.
|
||||
|
||||
3. Peak performance Lua cant be, without a lot of effort, transpiled and rewritten into peak performance compiled language, since it's behavior and optimization techniques are drastically different and by that I mean next level drastically different. Therefore it's not as good for prototyping as JS V8, unless you denounce the very idea of optimizing Lua as heresy.
|
||||
|
||||
4. LuaJIT does so much behind your back, so that performance becomes exhaustingly unpredictable. Stuff that works in nearly any other language does not work here, and you will often have to rely on profiler no matter how good you are with Lua, rather than act according to assumptions based on fundamentals. You could even say that what you have to do when Lua performance is concerned, is literal trial and error. You then find a sweet spot and never touch that part of the code again, because it's impossible to reason with/reliably reproduce/improve upon.
|
||||
|
||||
5. While you could cope that CPU just does not have enough cache and all, clearly, LuaJIT is best at optimizing *simple* loops. Branches, hash look ups, math? Try your best to decrease the amount for all of those in a loop. It appears that Lua would rather iterate uselessly over and over again the same entries, than have a branch to cut amount of iterations/operations in general. Optimization tip is basically this: try to break down a complicated loop into several simpler loops. LuaJIT is ridiculously fast with simple loops.
|
||||
|
||||
6. It appears that most popular object positioned most efficiently in memory. I am not entirely certain how exactly does that happen, because I didn't study LuaJIT source much since it's underwhelming performance in anything remotely complicated leaves me feeling powerless, so it's not fun. A hack could be a loop that interacts with an object on startup, if you call/interact with the object enough times it will be slightly faster. It is noticeable in massively expensive loops.
|
||||
|
||||
7. If you know you are guaranteeed to have an object consume more RAM during runtime, you may want to preallocate if the codebase is complex enough. Well, at least this behavior can be fully expected based on fundamentals.
|
||||
|
||||
8. Refrain from having too many hash look-ups, it's not slow by itself, but apparently it clogs cache fast, so sometimes adding just one hash look-up can result in a massive drop in performance. Surprisingly, refrain from having too much of one of the most simplest parts of LuaJIT - math, best is to pull numbers out of Lua' ass, like in Cozy Lights. Luckily predictably this time, branches are the worst in a loop, however this time they are bad even if they cut a massive amount of operations. So you have to balance here, peak performance Lua demands abandoning DRY completely, but that also means you have to consume more RAM. Ideal Lua loop is when it does nothing at all, just iterates. Just let Lua iterate.
|
||||
|
||||
9. You can obviously somewhat control cache with local variables, but there is a catch, it only gives somewhat coherent performance results if the loop is very simple.
|
||||
|
||||
10. Apparently because of memory allocation being complex in LuaJIT, it can crash during trying to allocate too much in one go as if it's in the earliest dev stage and not ready for prod. JS V8 maybe leaks, but at least does not crash just like that.
|
||||
|
||||
11. To make any good use of ffi types, you have to be aware of the fact that amount of types in function context will affect it's performance. More types = slower. So same as V8, it might optimize smaller functions better, but not necessarily, it depends: if it's one lua type number and there is a lot of work to do for that type, then you better off having a big one surely. Ffi is not a simple plug-and-play for previously optimized pure Lua algo, you may need to restructure your code to ensure more types dont clog the cache. And with Minetest API it may end up being useless.
|
||||
|
||||
12. Offloading work to C has it's caveats. If you are doing it through ffi and need to manipulate a lot of data, like vm_data in Cozy Lights example, while your algorithm itself will be faster, if like with Minetest example, the api expects lua table and only that, you will have to interpret C results, run a loop to make a lua table, and that part is so extremely slow, you might end up with slower code overall. In less complicated cases it's useful.
|
||||
|
||||
## LICENSE
|
||||
|
||||
MIT+(you are not legally allowed to infect it with GPL, AGPL or EUPL) for my code.
|
||||
|
||||
Will appreciate reasonable attribution, as in, dont be a typical open source dev who takes a good part of some other open source project and only mentions it in code, so that not only most of the devs, users have no way of ever learning about that.
|
||||
|
||||
And there is a texture from MTG, which will be eventually replaced:
|
||||
|
||||
default_glass.png is by Krock (CC0 1.0)
|
||||
|
||||
my debug textures are WTFPL if anything
|
|
@ -1,536 +0,0 @@
|
|||
local c_air = minetest.get_content_id("air")
|
||||
local c_light1 = minetest.get_content_id("cozylights:light1")
|
||||
|
||||
local c_lights = { c_light1, c_light1 + 1, c_light1 + 2, c_light1 + 3, c_light1 + 4, c_light1 + 5, c_light1 + 6,
|
||||
c_light1 + 7, c_light1 + 8, c_light1 + 9, c_light1 + 10, c_light1 + 11, c_light1 + 12, c_light1 + 13 }
|
||||
local c_light14 = c_lights[14]
|
||||
local c_light_debug1 = minetest.get_content_id("cozylights:light_debug1")
|
||||
local c_light_debug14 = c_light_debug1 + 13
|
||||
|
||||
local mf = math.floor
|
||||
|
||||
local clearlights = {
|
||||
params = "<size>",
|
||||
description = "removes cozy and debug light nodes. max radius is 120 for now",
|
||||
func = function(name, param)
|
||||
local pos = vector.round(minetest.get_player_by_name(name):getpos())
|
||||
local size = tonumber(param) or cozylights.default_size
|
||||
minetest.log("action", name .. " uses /clearlights "..size.." at position: "..cozylights:dump(pos))
|
||||
if size > 120 then
|
||||
return false, "Radius is too big"
|
||||
end
|
||||
cozylights:clear(pos,size)
|
||||
return true, "Done."
|
||||
end,
|
||||
}
|
||||
|
||||
local rebuildlights = {
|
||||
params = "<size>",
|
||||
description = "force rebuilds lights in the area. max radius is 120 for now",
|
||||
func = function(name, param)
|
||||
local pos = vector.round(minetest.get_player_by_name(name):getpos())
|
||||
local size = tonumber(param) or cozylights.default_size
|
||||
minetest.log("action", name .. " uses /rebuildlights "..size.." at position: "..cozylights:dump(pos))
|
||||
if size > 120 then return false, "Radius is too big" end
|
||||
local minp,maxp,vm,data,param2data,a = cozylights:getVoxelManipData(pos, size)
|
||||
for i in a:iterp(minp,maxp) do
|
||||
local node_name = minetest.get_name_from_content_id(data[i])
|
||||
local cozy_item = cozylights.cozy_items[node_name]
|
||||
if cozy_item ~= nil then
|
||||
local radius, _ = cozylights:calc_dims(cozy_item)
|
||||
local posrebuild = a:position(i)
|
||||
if vector.in_area(vector.subtract(posrebuild, radius), minp, maxp)
|
||||
and vector.in_area(vector.add(posrebuild, radius), minp, maxp)
|
||||
then
|
||||
cozylights:draw_node_light(posrebuild, cozy_item, vm, a, data, param2data)
|
||||
else
|
||||
local single_light_queue = cozylights.single_light_queue
|
||||
single_light_queue[#single_light_queue+1] = {
|
||||
pos=posrebuild,
|
||||
cozy_item=cozy_item
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
cozylights:setVoxelManipData(vm,data,param2data,true)
|
||||
return true, "Done."
|
||||
end,
|
||||
}
|
||||
|
||||
local fixedges = {
|
||||
params = "<size>",
|
||||
description = "same as rebuild lights but additionally fixes edges for all lights in the area, regardless of always_fix_edges setting. max radius is 120",
|
||||
func = function(name, param)
|
||||
local pos = vector.round(minetest.get_player_by_name(name):getpos())
|
||||
local size = tonumber(param) or cozylights.default_size
|
||||
minetest.log("action", name .. " uses /fixedges "..size.." at position: "..cozylights:dump(pos))
|
||||
if size > 120 then return false, "Radius is too big" end
|
||||
local minp,maxp,vm,data,param2data,a = cozylights:getVoxelManipData(pos, size)
|
||||
for i in a:iterp(minp,maxp) do
|
||||
local node_name = minetest.get_name_from_content_id(data[i])
|
||||
local cozy_item = cozylights.cozy_items[node_name]
|
||||
if cozy_item ~= nil then
|
||||
local radius, _ = cozylights:calc_dims(cozy_item)
|
||||
local posrebuild = a:position(i)
|
||||
if vector.in_area(vector.subtract(posrebuild, radius), minp, maxp)
|
||||
and vector.in_area(vector.add(posrebuild, radius), minp, maxp)
|
||||
then
|
||||
cozylights:draw_node_light(posrebuild, cozy_item, vm, a, data, param2data, true)
|
||||
else
|
||||
local single_light_queue = cozylights.single_light_queue
|
||||
single_light_queue[#single_light_queue+1] = {
|
||||
pos=posrebuild,
|
||||
cozy_item=cozy_item
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
cozylights:setVoxelManipData(vm,data,param2data,true)
|
||||
return true, "Done."
|
||||
end,
|
||||
}
|
||||
|
||||
local cozydebugon = {
|
||||
params = "<size>",
|
||||
description = "replaces cozy light nodes with debug light nodes which are visible and interactable in an area",
|
||||
func = function(name, param)
|
||||
local pos = vector.round(minetest.get_player_by_name(name):getpos())
|
||||
local size = tonumber(param) or cozylights.default_size
|
||||
minetest.log("action", name .. " uses /cozydebugon "..size.." at position: "..cozylights:dump(pos))
|
||||
if size > 120 then
|
||||
return false, "Radius is too big"
|
||||
end
|
||||
local minp,maxp,vm,data,_,a = cozylights:getVoxelManipData(pos,size)
|
||||
for i in a:iterp(minp, maxp) do
|
||||
local cid = data[i]
|
||||
if cid >= c_light1 and cid <= c_light14 then
|
||||
data[i] = cid + 14
|
||||
end
|
||||
end
|
||||
cozylights:setVoxelManipData(vm,data)
|
||||
return true, "Done."
|
||||
end,
|
||||
}
|
||||
|
||||
local cozydebugoff = {
|
||||
params = "<size>",
|
||||
description = "replaces debug light nodes back with cozy light nodes in an area",
|
||||
func = function(name, param)
|
||||
local pos = vector.round(minetest.get_player_by_name(name):getpos())
|
||||
local size = tonumber(param) or cozylights.default_size
|
||||
minetest.log("action", name .. " uses /cozydebugoff "..size.." at position: "..cozylights:dump(pos))
|
||||
if size > 120 then
|
||||
return false, "Radius is too big"
|
||||
end
|
||||
local minp,maxp,vm,data,_,a = cozylights:getVoxelManipData(pos,size)
|
||||
for i in a:iterp(minp, maxp) do
|
||||
local cid = data[i]
|
||||
if cid >= c_light14 + 1 and cid <= c_light_debug14 then
|
||||
data[i] = cid - 14
|
||||
end
|
||||
end
|
||||
cozylights:setVoxelManipData(vm,data)
|
||||
return true, "Done."
|
||||
end,
|
||||
}
|
||||
|
||||
local optimizeformobile = {
|
||||
params = "<size>",
|
||||
description = "optimizes schematic for mobile and potato gpu",
|
||||
func = function(name, param)
|
||||
local pos = vector.round(minetest.get_player_by_name(name):getpos())
|
||||
local size = tonumber(param) or cozylights.default_size
|
||||
minetest.log("action", name .. " uses /optimizeformobile "..size.." at position: "..cozylights:dump(pos))
|
||||
if size > 120 then
|
||||
return false, "Radius is too big"
|
||||
end
|
||||
local minp,maxp,vm,data,param2data,a = cozylights:getVoxelManipData(pos,size)
|
||||
local zstride, ystride = a.zstride, a.ystride
|
||||
local function keep(i)
|
||||
local keep = false
|
||||
for inz = -1,1 do
|
||||
for iny = -1,1 do
|
||||
for inx = -1,1 do
|
||||
local inidx = i + inx + iny*ystride + inz*zstride
|
||||
if a:containsi(inidx) then
|
||||
local incid = data[inidx]
|
||||
if incid ~= c_air and (incid < c_light1 or incid > c_light14 + 14) then
|
||||
keep = true
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return keep
|
||||
end
|
||||
for i in a:iterp(minp, maxp) do
|
||||
local cid = data[i]
|
||||
if cid >= c_light1 and cid <= c_light14 + 14 then
|
||||
if not keep(i) then
|
||||
data[i] = c_air
|
||||
param2data[i] = 0
|
||||
end
|
||||
end
|
||||
end
|
||||
cozylights:setVoxelManipData(vm,data,param2data,true)
|
||||
return true, "Done."
|
||||
end,
|
||||
}
|
||||
|
||||
local spawnlight = {
|
||||
params = "<brightness> <radius> <strength>",
|
||||
description = "spawns light_brush-like light with given characteristics at player position",
|
||||
func = function(name, param)
|
||||
local brightness, radius, strength = string.match(param, "^([%d.~-]+)[, ] *([%d.~-]+)[, ] *([%d.~-]+)$")
|
||||
local pos = vector.round(minetest.get_player_by_name(name):getpos())
|
||||
minetest.log("action", name .. " uses /optimizeformobile "..brightness.." "..radius.." "..strength.." at position: "..cozylights:dump(pos))
|
||||
brightness = mf(tonumber(brightness) or 0)
|
||||
if brightness < 0 then brightness = 0 end
|
||||
if brightness > 14 then brightness = 14 end
|
||||
radius = tonumber(radius) or 0
|
||||
if radius < 0 then radius = 0 end
|
||||
if radius > 120 then radius = 120 end
|
||||
strength = tonumber(strength) or 0
|
||||
if strength < 0 then strength = 0 end
|
||||
if strength > 1 then strength = 1 end
|
||||
local lb = {brightness=brightness,radius=radius,strength=strength,mode=0,cover_only_surfaces=0}
|
||||
cozylights:draw_brush_light(pos, lb)
|
||||
return true, "Done."
|
||||
end,
|
||||
}
|
||||
|
||||
local cozysettingsgui = {
|
||||
privs = {},
|
||||
description = "changes global ambient light settings",
|
||||
func = function(name)
|
||||
local settings_formspec = {
|
||||
"formspec_version[4]",
|
||||
--"size[6,6.4]",
|
||||
"size[5.2,8.6]",
|
||||
"label[0.95,0.5;Global Cozy Lights Settings]",
|
||||
|
||||
"label[0.95,1.35;Wielded Light Radius]",
|
||||
"field[3.5,1.1;0.8,0.5;wielded_light_radius;;"..cozylights.max_wield_light_radius.."]",
|
||||
"tooltip[0.95,1.1;3.4,0.5;If radius is -1 cozy wielded light is disabled, if 0 then only one node will be lit up just like in familiar Minetest wielded light mod.\n"..
|
||||
"If not zero then it's a sphere of affected nodes with specified radius.\n"..
|
||||
"Max radius is 30 as of now. If you run a potato - you may want to decrease it.]",
|
||||
|
||||
"label[0.95,2.05;Wield Light Step]",
|
||||
"field[3.5,1.8;0.8,0.5;wield_step;;"..cozylights.wield_step.."]",
|
||||
"tooltip[0.95,1.8;3.4,0.5;Cozy Lights Wield Light step - smaller value will result in more frequent, fluid wield light update.\n"..
|
||||
"Smaller values might be too expensive for potato. Valid values are from 0.01 to 10.00]",
|
||||
|
||||
"label[0.95,2.75;Brush Hold Step]",
|
||||
"field[3.5,2.5;0.8,0.5;brush_hold_step;;"..cozylights.brush_hold_step.."]",
|
||||
"tooltip[0.95,2.5;3.4,0.5;Brush Hold Step - smaller value will result in more frequent, fluid light update for light brush on mouse hold.\n"..
|
||||
"Smaller values wont necessarily result in a more fluid update even on a beast PC, because Minetest architecture is too complicated for it to not be janky. Valid values are from 0.01 to 10.00]",
|
||||
|
||||
"label[0.95,3.45;On_Gen() Step]",
|
||||
"field[3.5,3.2;0.8,0.5;on_gen_step;;"..cozylights.on_gen_step.."]",
|
||||
"tooltip[0.95,3.2;3.4,0.5;Generated areas step - smaller value will result in more frequent, fluid light update for newly generated map chunks and schematics if they have light sources, it will also rebuild lights faster when something was destroyed.\n"..
|
||||
"Small values will be too expensive for potato. Valid values are from 0.01 to 10.00]",
|
||||
|
||||
"label[0.95,4.15;Brightness Factor]",
|
||||
"field[3.5,3.9;0.8,0.5;brightness_factor;;"..cozylights.brightness_factor.."]",
|
||||
"tooltip[0.95,3.9;3.4,0.5;Brightness factor determines how bright overall(relative to own light source brightness) the light will be.\n"..
|
||||
"Affects placed nodes(like torches, mese lamps, etc) and wielded light, but not light brush.\n"..
|
||||
"Valid values are from -10.0 to 10.0.\n"..
|
||||
"Brightness factor is not an equivalent of light source brightness(from 1 to 14), it is very low key, affects lights slightly.]",
|
||||
|
||||
"label[0.95,4.85;Reach Factor]",
|
||||
"field[3.5,4.6;0.8,0.5;reach_factor;;"..cozylights.reach_factor.."]",
|
||||
"tooltip[0.95,4.6;3.4,0.5;Reach factor determines how far light of all light source nodes will reach.\n"..
|
||||
"Affects placed nodes(like torches, mese lamps, etc) and wielded light, but not light brush.\n"..
|
||||
"Valid values are from 0.0 to 10.0.\n"..
|
||||
"Not recommended to change if you are not willing to spend probably a lot of time tuning lights.\n"..
|
||||
"Not recommended to Increase if you run a potato.]",
|
||||
|
||||
"label[0.95,5.55;Dim Factor]",
|
||||
"field[3.5,5.3;0.8,0.5;dim_factor;;"..cozylights.dim_factor.."]",
|
||||
"tooltip[0.95,5.3;3.4,0.5;Dim factor determines how quickly the light fades farther from the source.\n"..
|
||||
"Affects placed nodes(like torches, mese lamps, etc) and wielded light, but not light brush.\n"..
|
||||
"Valid values are from 0.0 to 10.0.\n"..
|
||||
"Not recommended to change if you are not willing to spend probably a lot of time tuning lights.\n"..
|
||||
"Not recommended to Decrease if you run a potato.]",
|
||||
|
||||
"label[0.95,6.25;Uncozy mode]",
|
||||
"field[3.5,6;0.8,0.5;uncozy_mode;;"..cozylights.uncozy_mode.."]",
|
||||
"tooltip[0.95,6;3.4,0.5;Uncozy mode if above 0 removes all cozy lights in an area with specified radius around all players continuously.\n"..
|
||||
"Useful before Cozy Lights mod uninstall. If you uninstall without prior running this, you will be left with spheres of unknown nodes in an area where Cozy Lights were active.\n"..
|
||||
"Valid values are from 0 to 120. As of now can crash with out of memory error if you move too fast and the radius is too high.]",
|
||||
|
||||
"label[0.95,6.95;Crispy Potato]",
|
||||
"checkbox[3.5,6.95;crispy_potato;;"..(cozylights.crispy_potato == true and "true" or "false").."]",
|
||||
"tooltip[0.95,6.7;3.4,0.4;Crispy Potato when checked will auto adjust wielded light and generated area step times to keep potato alive.]",
|
||||
|
||||
"button_exit[1.1,7.5;3,0.8;confirm;Confirm]",
|
||||
}
|
||||
minetest.show_formspec(name, "cozylights:settings",table.concat(settings_formspec, ""))
|
||||
return true
|
||||
end,
|
||||
}
|
||||
|
||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
if formname ~= ("cozylights:settings") then return end
|
||||
if player == nil then return end
|
||||
if fields.wielded_light_radius then
|
||||
local wielded_light_radius = tonumber(fields.wielded_light_radius) > 30 and 30 or tonumber(fields.wielded_light_radius)
|
||||
wielded_light_radius = wielded_light_radius < -1 and -1 or mf(wielded_light_radius or -1)
|
||||
cozylights:set_wielded_light_radius(wielded_light_radius)
|
||||
cozylights:switch_wielded_light(wielded_light_radius ~= -1)
|
||||
end
|
||||
if fields.wield_step then
|
||||
local wield_step = tonumber(fields.wield_step) > 1 and 1 or tonumber(fields.wield_step)
|
||||
wield_step = wield_step < 0.01 and 0.01 or wield_step
|
||||
cozylights:set_wield_step(wield_step)
|
||||
end
|
||||
if fields.brush_hold_step then
|
||||
local brush_hold_step = tonumber(fields.brush_hold_step) > 1 and 1 or tonumber(fields.brush_hold_step)
|
||||
brush_hold_step = brush_hold_step < 0.01 and 0.01 or brush_hold_step
|
||||
cozylights:set_brush_hold_step(brush_hold_step)
|
||||
end
|
||||
if fields.on_gen_step then
|
||||
local on_gen_step = tonumber(fields.on_gen_step) > 1 and 1 or tonumber(fields.on_gen_step)
|
||||
on_gen_step = on_gen_step < 0.01 and 0.01 or on_gen_step
|
||||
cozylights:set_on_gen_step(on_gen_step)
|
||||
end
|
||||
if fields.brightness_factor then
|
||||
local brightness_factor = tonumber(fields.brightness_factor) > 10 and 10 or tonumber(fields.brightness_factor)
|
||||
cozylights.brightness_factor = brightness_factor < -10 and -10 or brightness_factor or 3
|
||||
minetest.settings:set("cozylights_brightness_factor",cozylights.brightness_factor)
|
||||
end
|
||||
if fields.reach_factor then
|
||||
local reach_factor = tonumber(fields.reach_factor) > 10 and 10 or tonumber(fields.reach_factor)
|
||||
cozylights.reach_factor = reach_factor < 0 and 0 or reach_factor or 4
|
||||
minetest.settings:set("cozylights_reach_factor",cozylights.reach_factor)
|
||||
end
|
||||
if fields.dim_factor then
|
||||
local dim_factor = tonumber(fields.dim_factor) > 10 and 10 or tonumber(fields.dim_factor)
|
||||
cozylights.dim_factor = dim_factor < 0 and 0 or dim_factor or 9
|
||||
minetest.settings:set("cozylights_dim_factor",cozylights.dim_factor)
|
||||
end
|
||||
if fields.crispy_potato then
|
||||
cozylights.crispy_potato = fields.crispy_potato == "true" and true or false
|
||||
minetest.settings:set_bool("cozylights_crispy_potato", cozylights.crispy_potato)
|
||||
end
|
||||
if fields.uncozy_mode then
|
||||
local uncozy_mode = tonumber(fields.uncozy_mode) > 120 and 120 or tonumber(fields.uncozy_mode)
|
||||
cozylights.uncozy_mode = uncozy_mode < 0 and 0 or uncozy_mode
|
||||
minetest.settings:set("cozylights_uncozy_mode", cozylights.uncozy_mode)
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
local cozysettings = {
|
||||
params = "<brightness> <reach_factor> <dim_factor>",
|
||||
privs = {},
|
||||
description = "changes global ambient light settings",
|
||||
func = function(_, param)
|
||||
local brightness_, reach_factor_, dim_factor_ = string.match(param, "^([%d.~-]+)[, ] *([%d.~-]+)[, ] *([%d.~-]+)$")
|
||||
brightness_ = tonumber(brightness_)
|
||||
if brightness_ ~= nil then
|
||||
cozylights.brightness_factor = brightness_
|
||||
minetest.settings:set("cozylights_brightness_factor",brightness_)
|
||||
end
|
||||
reach_factor_ = tonumber(reach_factor_)
|
||||
if reach_factor_ ~= nil then
|
||||
cozylights.reach_factor = reach_factor_
|
||||
minetest.settings:set("cozylights_reach_factor",reach_factor_)
|
||||
end
|
||||
dim_factor_ = tonumber(dim_factor_)
|
||||
if dim_factor_ ~= nil then
|
||||
cozylights.dim_factor = dim_factor_
|
||||
minetest.settings:set("cozylights_dim_factor",dim_factor_)
|
||||
end
|
||||
return true, "set brightness as "..brightness_..", reach_factor as "..reach_factor_..", dim_factor as "..dim_factor_
|
||||
end,
|
||||
}
|
||||
|
||||
local daynightratio = {
|
||||
params = "<ratio>",
|
||||
description = "fixes old schematic torches alignment to walls and what not",
|
||||
func = function(name, param)
|
||||
local player = minetest.get_player_by_name(name)
|
||||
local pos = vector.round(player:getpos())
|
||||
local ratio = tonumber(param)
|
||||
minetest.log("action", name .. " uses /daynightratio "..ratio.." at position: "..cozylights:dump(pos))
|
||||
if ratio > 1.0 then ratio = 1 end
|
||||
if ratio < 0 then ratio = 0 end
|
||||
player:override_day_night_ratio(ratio)
|
||||
return true, "Done."
|
||||
end,
|
||||
}
|
||||
|
||||
local cozyadjust = {
|
||||
params = "<size> <adjust_by> <keep_map>",
|
||||
description = "adjust brightness of all light nodes in the area.\n"..
|
||||
"keep_map is 1 by default and can be omitted, when it's 1 and adjust_by will result in a value out of bounds of 1-14(engine light levels) "..
|
||||
"even for one node in the area, the command will revert(have no effect at all), so that light map will be preserved\n"..
|
||||
"if you are ok with breaking light map, type 0 for third value",
|
||||
func = function(name, param)
|
||||
local pos = vector.round(minetest.get_player_by_name(name):getpos())
|
||||
local size, adjust_by, keep_map = string.match(param, "^([%d.~-]+)[, ] *([%d.~-]+)[, ] *([%d.~-]+)$")
|
||||
size = mf(tonumber(size) or cozylights.default_size)
|
||||
adjust_by = mf(tonumber(adjust_by) or 1)
|
||||
keep_map = mf(tonumber(keep_map) or 1)
|
||||
minetest.log("action", name .. " uses /clearlights "..size.." at position: "..cozylights:dump(pos))
|
||||
if size > 120 then
|
||||
return false, "Radius is too big"
|
||||
end
|
||||
local minp,maxp,vm,data,param2data,a = cozylights:getVoxelManipData(pos,size)
|
||||
for i in a:iterp(minp, maxp) do
|
||||
local cid = data[i]
|
||||
if cid >= c_light1 and cid <= c_light14 then
|
||||
local precid = cid + adjust_by
|
||||
if precid >= c_light1 and precid <= c_light14 then
|
||||
data[i] = precid
|
||||
param2data[i] = precid
|
||||
elseif keep_map == 1 then
|
||||
return false, "Aborted to preserve light map."
|
||||
elseif precid > c_light14 then
|
||||
data[i] = c_light14
|
||||
param2data[i] = c_light14
|
||||
else
|
||||
data[i] = c_air
|
||||
param2data[i] = 0
|
||||
end
|
||||
elseif cid >= c_light_debug1 and cid <= c_light_debug14 then
|
||||
local precid = cid + adjust_by
|
||||
if precid >= c_light_debug1 and precid <= c_light_debug14 then
|
||||
data[i] = precid
|
||||
param2data[i] = precid
|
||||
elseif keep_map == 1 then
|
||||
return false, "Aborted to preserve light map."
|
||||
elseif precid > c_light_debug14 then
|
||||
data[i] = c_light_debug14
|
||||
param2data[i] = c_light_debug14
|
||||
else
|
||||
data[i] = c_air
|
||||
param2data[i] = 0
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
cozylights:setVoxelManipData(vm,data,param2data,true)
|
||||
return true, "Done."
|
||||
end,
|
||||
}
|
||||
|
||||
local fixtorches = {
|
||||
params = "<size>",
|
||||
description = "fixes old schematic torches alignment to walls and what not",
|
||||
func = function(name, param)
|
||||
local placer = minetest.get_player_by_name(name)
|
||||
local pos = vector.round(placer:getpos())
|
||||
local size = mf(tonumber(param) or cozylights.default_size)
|
||||
minetest.log("action", name .. " uses /fixtorches "..size.." at position: "..cozylights:dump(pos))
|
||||
if size > 120 then
|
||||
return false, "Radius is too big"
|
||||
end
|
||||
local minp,maxp,vm,data,param2data,a = cozylights:getVoxelManipData(pos,size)
|
||||
local c_torch = minetest.get_content_id("default:torch")
|
||||
local c_torch_wall = c_torch + 1
|
||||
local c_torch_ceiling = c_torch + 2
|
||||
local ystride, zstride = a.ystride, a.zstride
|
||||
for i in a:iterp(minp, maxp) do
|
||||
if data[i] == c_torch then
|
||||
local above = minetest.registered_nodes[minetest.get_name_from_content_id(data[i-ystride])]
|
||||
if above.walkable == true then
|
||||
data[i] = c_torch_ceiling
|
||||
param2data[i] = 0
|
||||
end
|
||||
|
||||
local below = minetest.registered_nodes[minetest.get_name_from_content_id(data[i-ystride])]
|
||||
if below.walkable == true then
|
||||
data[i] = c_torch
|
||||
param2data[i] = 1
|
||||
end
|
||||
|
||||
if above.walkable == false and below.walkable == false then
|
||||
local plusz = minetest.registered_nodes[minetest.get_name_from_content_id(data[i + zstride])]
|
||||
data[i] = c_torch_wall
|
||||
if plusz.walkable == true then param2data[i] = 4 end
|
||||
local minusz = minetest.registered_nodes[minetest.get_name_from_content_id(data[i - zstride])]
|
||||
if minusz.walkable == true then param2data[i] = 5 end
|
||||
local plusx = minetest.registered_nodes[minetest.get_name_from_content_id(data[i + 1])]
|
||||
if plusx.walkable == true then param2data[i] = 2 end
|
||||
local minusx = minetest.registered_nodes[minetest.get_name_from_content_id(data[i - 1])]
|
||||
if minusx.walkable == true then param2data[i] = 3 end
|
||||
end
|
||||
end
|
||||
end
|
||||
cozylights:setVoxelManipData(vm,data,param2data,true)
|
||||
return true, "Done."
|
||||
end,
|
||||
}
|
||||
|
||||
local uncozymode = {
|
||||
params = "<size>",
|
||||
description = "clears lights every 5 seconds around every player in area of given radius.\n "..
|
||||
"Useful before Cozy Lights uninstall or for those who is uncertain about the mod.\n",
|
||||
func = function(name, param)
|
||||
local placer = minetest.get_player_by_name(name)
|
||||
local pos = vector.round(placer:getpos())
|
||||
local size = mf(tonumber(param) or cozylights.default_size)
|
||||
minetest.log("action", name .. " uses /uncozymode "..size.." at position: "..cozylights:dump(pos))
|
||||
if size > 120 then
|
||||
return false, "Radius is too big"
|
||||
end
|
||||
cozylights.uncozy_mode = size
|
||||
minetest.settings:set("cozylights_uncozy_mode",size)
|
||||
return true, "Done."
|
||||
end,
|
||||
}
|
||||
|
||||
local cozymode = {
|
||||
description = "stops /uncozymode.",
|
||||
func = function(name)
|
||||
local placer = minetest.get_player_by_name(name)
|
||||
local pos = vector.round(placer:getpos())
|
||||
minetest.log("action", name .. " uses /cozymode at position: "..cozylights:dump(pos))
|
||||
cozylights.uncozy_mode = 0
|
||||
minetest.settings:set("cozylights_uncozy_mode",0)
|
||||
return true, "Done."
|
||||
end,
|
||||
}
|
||||
|
||||
|
||||
minetest.register_chatcommand("clearlights", clearlights)
|
||||
minetest.register_chatcommand("zcl", clearlights)
|
||||
|
||||
minetest.register_chatcommand("rebuildlights", rebuildlights)
|
||||
minetest.register_chatcommand("zrl", rebuildlights)
|
||||
|
||||
minetest.register_chatcommand("fixedges", fixedges)
|
||||
minetest.register_chatcommand("zfe", fixedges)
|
||||
|
||||
minetest.register_chatcommand("cozydebugon", cozydebugon)
|
||||
minetest.register_chatcommand("zdon", cozydebugon)
|
||||
|
||||
minetest.register_chatcommand("cozydebugoff", cozydebugoff)
|
||||
minetest.register_chatcommand("zdoff", cozydebugoff)
|
||||
|
||||
minetest.register_chatcommand("optimizeformobile", optimizeformobile)
|
||||
minetest.register_chatcommand("zofm", optimizeformobile)
|
||||
|
||||
minetest.register_chatcommand("spawnlight", spawnlight)
|
||||
minetest.register_chatcommand("zsl", spawnlight)
|
||||
|
||||
minetest.register_chatcommand("cozysettings", cozysettingsgui)
|
||||
minetest.register_chatcommand("zs", cozysettingsgui)
|
||||
|
||||
minetest.register_chatcommand("daynightratio", daynightratio)
|
||||
minetest.register_chatcommand("zdnr", daynightratio)
|
||||
|
||||
minetest.register_chatcommand("cozyadjust", cozyadjust)
|
||||
minetest.register_chatcommand("za", cozyadjust)
|
||||
|
||||
minetest.register_chatcommand("fixtorches", fixtorches)
|
||||
minetest.register_chatcommand("zft", fixtorches)
|
||||
|
||||
minetest.register_chatcommand("uncozymode", uncozymode)
|
||||
minetest.register_chatcommand("uzm", uncozymode)
|
||||
|
||||
minetest.register_chatcommand("cozymode", cozymode)
|
||||
minetest.register_chatcommand("zm", cozymode)
|
|
@ -1,41 +0,0 @@
|
|||
function cozylights:dump(o)
|
||||
if type(o) == 'table' then
|
||||
local s = '{ '
|
||||
for k,v in pairs(o) do
|
||||
if type(k) ~= 'number' then k = '"'..k..'"' end
|
||||
s = s .. '['..k..'] = ' .. cozylights:dump(v) .. ','
|
||||
end
|
||||
return s .. '} '
|
||||
else
|
||||
return tostring(o)
|
||||
end
|
||||
end
|
||||
|
||||
function cozylights:finalize(table)
|
||||
return setmetatable({}, {
|
||||
__index = table,
|
||||
__newindex = nil
|
||||
})
|
||||
end
|
||||
|
||||
function cozylights:prealloc(table, amount, default_val)
|
||||
for i = 1, amount do
|
||||
table[i] = default_val
|
||||
end
|
||||
end
|
||||
|
||||
function cozylights:mod_loaded(str)
|
||||
if minetest.get_modpath(str) ~= nil then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function cozylights:findIn(value,array)
|
||||
for i=1, #array do
|
||||
if array[i] == value then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
|
@ -1,691 +0,0 @@
|
|||
cozylights = {
|
||||
-- constant size values and tables
|
||||
version = "0.2.8",
|
||||
default_size = tonumber(minetest.settings:get("mapfix_default_size")) or 40,
|
||||
brightness_factor = tonumber(minetest.settings:get("cozylights_brightness_factor")) or 8,
|
||||
reach_factor = tonumber(minetest.settings:get("cozylights_reach_factor")) or 2,
|
||||
dim_factor = tonumber(minetest.settings:get("cozylights_dim_factor")) or 9.5,
|
||||
wield_step = tonumber(minetest.settings:get("cozylights_wield_step")) or 0.01,
|
||||
brush_hold_step = tonumber(minetest.settings:get("cozylights_brush_hold_step")) or 0.07,
|
||||
on_gen_step = tonumber(minetest.settings:get("cozylights_on_gen_step")) or 0.7,
|
||||
max_wield_light_radius = tonumber(minetest.settings:get("cozylights_wielded_light_radius")) or 17,
|
||||
override_engine_lights = minetest.settings:get_bool("cozylights_override_engine_lights", false),
|
||||
always_fix_edges = minetest.settings:get_bool("cozylights_always_fix_edges", false),
|
||||
uncozy_mode = tonumber(minetest.settings:get("cozylights_uncozy_mode")) or 0,
|
||||
crispy_potato = minetest.settings:get_bool("cozylights_crispy_potato", true),
|
||||
-- this is a table of modifiers for global light source settings.
|
||||
-- lowkeylike and dimlike usually assigned to decorations in hopes to make all ambient naturally occuring light sources weaker
|
||||
-- this is for two reasons:
|
||||
-- 1. performance: never know how many various nice looking blocks which emit light will be there, or for example computing lights for
|
||||
-- every node of a lava lake would be extremely expensive if those would reach far/would be very bright
|
||||
-- 2. looks: they were made with default engine lighting in mind, so usually are very frequent, with such frequency default cozylights
|
||||
-- settings will make the environment look blunt
|
||||
coziest_table = {
|
||||
--"dimlike"
|
||||
[1] = {
|
||||
brightness_factor = 0,
|
||||
reach_factor = 0,
|
||||
dim_factor = 0
|
||||
},
|
||||
--"lowkeylike" almost the same as dimlike, but reaches much farther with its barely visible light
|
||||
[2] = {
|
||||
brightness_factor = 0,
|
||||
reach_factor = 2,
|
||||
dim_factor = -3
|
||||
},
|
||||
-- "candlelike" something-something
|
||||
[3] = {
|
||||
brightness_factor = 0,
|
||||
reach_factor = 2,
|
||||
dim_factor = -3
|
||||
},
|
||||
-- "torchlike" torches, fires, flames. made much dimmer than what default engine lights makes them
|
||||
[4] = {
|
||||
brightness_factor = -2,
|
||||
reach_factor = 0,
|
||||
dim_factor = 0
|
||||
},
|
||||
-- "lamplike" a bright source, think mese lamp(actually turned out its like a projector, and below is even bigger projector)
|
||||
[5] = {
|
||||
brightness_factor = 0,
|
||||
reach_factor = 3,
|
||||
dim_factor = 4
|
||||
},
|
||||
-- "projectorlike" a bright source with massive reach
|
||||
[6] = {
|
||||
brightness_factor = 1,
|
||||
reach_factor = 3,
|
||||
dim_factor = 4
|
||||
},
|
||||
},
|
||||
-- appears nodes and items might not necessarily be the same array
|
||||
source_nodes = nil,
|
||||
cozy_items = nil,
|
||||
-- dynamic size tables, okay now what about functions
|
||||
cozycids_sunlight_propagates = {},
|
||||
cozycids_light_sources = {},
|
||||
cozyplayers = {},
|
||||
area_queue = {},
|
||||
single_light_queue = {},
|
||||
modpath = minetest.get_modpath(minetest.get_current_modname())
|
||||
}
|
||||
|
||||
local modpath = minetest.get_modpath(minetest.get_current_modname())
|
||||
dofile(modpath.."/helpers.lua")
|
||||
|
||||
-- backrooms test attempts to resolve mt engine lights problem with invisible lights, default settings will result
|
||||
-- in many places being very well lit
|
||||
-- me thinks ideal scenery with cozy lights in particular can be achieved with removal of all invisible lights
|
||||
-- it also looks interesting after maybe a two thirds of light sources are broken
|
||||
-- however the backrooms idea is not about broken windows theory at all, more about supernatural absence of any life
|
||||
-- in a seemingly perfectly functioning infinite manmade mess, or idk i am not mentally masturbating any further,
|
||||
-- some of the internets do that way too often, way too much
|
||||
if cozylights:mod_loaded("br_core") then
|
||||
cozylights.brightness_factor = cozylights.brightness_factor - 6
|
||||
end
|
||||
|
||||
--if cozylights:mod_loaded("default") then
|
||||
-- default.can_grow = function(pos)
|
||||
-- local node_under = minetest.get_node_or_nil({x = pos.x, y = pos.y - 1, z = pos.z})
|
||||
-- if not node_under then
|
||||
-- return false
|
||||
-- end
|
||||
-- if minetest.get_item_group(node_under.name, "soil") == 0 then
|
||||
-- return false
|
||||
-- end
|
||||
-- local light_level = minetest.get_node_light(pos)
|
||||
-- if not light_level or light_level < 13 then
|
||||
-- return false
|
||||
-- end
|
||||
-- return true
|
||||
-- end
|
||||
--end
|
||||
|
||||
|
||||
dofile(modpath.."/nodes.lua")
|
||||
dofile(modpath.."/shared.lua")
|
||||
dofile(modpath.."/chat_commands.lua")
|
||||
--ffi = require("ffi")
|
||||
dofile(modpath.."/wield_light.lua")
|
||||
dofile(modpath.."/node_light.lua")
|
||||
dofile(modpath.."/light_brush.lua")
|
||||
|
||||
local c_air = minetest.get_content_id("air")
|
||||
local c_light1 = minetest.get_content_id("cozylights:light1")
|
||||
|
||||
local c_lights = { c_light1, c_light1 + 1, c_light1 + 2, c_light1 + 3, c_light1 + 4, c_light1 + 5, c_light1 + 6,
|
||||
c_light1 + 7, c_light1 + 8, c_light1 + 9, c_light1 + 10, c_light1 + 11, c_light1 + 12, c_light1 + 13 }
|
||||
|
||||
local mf = math.floor
|
||||
|
||||
------------------------------------------
|
||||
|
||||
minetest.register_on_mods_loaded(function()
|
||||
local source_nodes = {}
|
||||
local cozy_items = {}
|
||||
local cozycids_sunlight_propagates = {}
|
||||
local cozycids_light_sources = {}
|
||||
local override = cozylights.override_engine_lights
|
||||
for _,def in pairs(minetest.registered_items) do
|
||||
if def.light_source and def.light_source > 1
|
||||
and def.drawtype ~= "airlike" and def.drawtype ~= "liquid"
|
||||
and string.find(def.name, "lava_flowing") == nil
|
||||
and string.find(def.name, "lava_source") == nil
|
||||
--and def.liquid_renewable == nil and def.drowning == nil
|
||||
then
|
||||
-- here we are going to define more specific skips and options for sus light sources
|
||||
local skip = false
|
||||
if string.find(def.name, "everness:") ~= nil and def.groups.vine ~= nil then
|
||||
skip = true -- like goto continue
|
||||
end
|
||||
if skip == false then
|
||||
local mods = nil
|
||||
--if def.drawtype == "plantlike" then
|
||||
-- mods = 1
|
||||
--end
|
||||
--if string.find(def.name,"torch") then
|
||||
-- mods = 3
|
||||
--end
|
||||
cozy_items[def.name] = {light_source= def.light_source or 0,floodable=def.floodable or false,modifiers=mods}
|
||||
if not string.find(def.name, "cozylights:light") then
|
||||
source_nodes[#source_nodes+1] = def.name
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
for node,def in pairs(minetest.registered_nodes) do
|
||||
if def.sunlight_propagates == true then
|
||||
local cid = minetest.get_content_id(def.name)
|
||||
cozycids_sunlight_propagates[cid] = true
|
||||
end
|
||||
if def.light_source and def.light_source > 1
|
||||
and def.drawtype ~= "airlike" and def.drawtype ~= "liquid"
|
||||
and not string.find(def.name, "lava_flowing")
|
||||
and not string.find(def.name, "lava_source")
|
||||
--and def.liquid_viscosity == nil and def.liquid_renewable == nil and def.drowning == nil
|
||||
then
|
||||
local cid = minetest.get_content_id(def.name)
|
||||
if cid < c_lights[1] or cid > c_lights[14]+14 then
|
||||
local skip = false
|
||||
if string.find(def.name, "everness:") ~= nil and def.groups.vine ~= nil then
|
||||
skip = true -- like goto :continue:
|
||||
end
|
||||
if skip == false then
|
||||
cozycids_light_sources[cid] = true
|
||||
if def.on_destruct then
|
||||
local base_on_destruct = def.on_destruct
|
||||
minetest.override_item(node,{
|
||||
on_destruct = function(pos)
|
||||
base_on_destruct(pos)
|
||||
print(cozylights:dump(pos))
|
||||
print(def.name.." is destroyed")
|
||||
cozylights:destroy_light(pos, cozy_items[def.name])
|
||||
end,
|
||||
})
|
||||
else
|
||||
minetest.override_item(node,{
|
||||
on_destruct = function(pos)
|
||||
print(cozylights:dump(pos))
|
||||
print(def.name.." is destroyed1")
|
||||
cozylights:destroy_light(pos, cozy_items[def.name])
|
||||
end,
|
||||
})
|
||||
end
|
||||
if def.on_construct ~= nil then
|
||||
local base_on_construct = def.on_construct
|
||||
local light = override == true and 1 or def.light_source
|
||||
if def.name == "br_core:ceiling_light_1" then
|
||||
light = def.light_source - 7
|
||||
end
|
||||
minetest.override_item(node,{
|
||||
light_source = light,
|
||||
use_texture_alpha= def.use_texture_alpha or "clip",
|
||||
on_construct = function(pos)
|
||||
base_on_construct(pos)
|
||||
cozylights:draw_node_light(pos, cozy_items[def.name])
|
||||
end,
|
||||
})
|
||||
else
|
||||
local light = override == true and 1 or def.light_source
|
||||
if def.name == "br_core:ceiling_light_1" then
|
||||
light = def.light_source - 7
|
||||
end
|
||||
minetest.override_item(node,{
|
||||
light_source = light,
|
||||
use_texture_alpha= def.use_texture_alpha or "clip",
|
||||
on_construct = function(pos)
|
||||
cozylights:draw_node_light(pos, cozy_items[def.name])
|
||||
end,
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
cozylights.source_nodes = source_nodes
|
||||
cozylights.cozy_items = cozy_items
|
||||
cozylights.cozycids_sunlight_propagates = cozycids_sunlight_propagates
|
||||
cozylights.cozycids_light_sources = cozycids_light_sources
|
||||
end)
|
||||
|
||||
--clean up possible stale wielded light on join, since on server shutdown we cant execute on_leave
|
||||
--todo: make it more normal and less of a hack
|
||||
function cozylights:on_join_cleanup(pos, radius)
|
||||
local vm = minetest.get_voxel_manip()
|
||||
local emin, emax = vm:read_from_map(vector.subtract(pos, radius+1), vector.add(pos, radius+1))
|
||||
local data = vm:get_data()
|
||||
local a = VoxelArea:new{
|
||||
MinEdge = emin,
|
||||
MaxEdge = emax
|
||||
}
|
||||
local param2data = vm:get_param2_data()
|
||||
local max_radius = radius * (radius + 1)
|
||||
for z = -radius, radius do
|
||||
for y = -radius, radius do
|
||||
for x = -radius, radius do
|
||||
--local p = vector.add(pos,{x=x,y=y,z=z})
|
||||
local p = {x=x+pos.x,y=y+pos.y,z=z+pos.z}
|
||||
local idx = a:indexp(p)
|
||||
local squared = x * x + y * y + z * z
|
||||
if data[idx] >= c_lights[1] and data[idx] <= c_lights[14] and param2data[idx] == 0 and squared <= max_radius then
|
||||
data[idx] = c_air
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
vm:set_data(data)
|
||||
vm:update_liquids()
|
||||
vm:write_to_map()
|
||||
end
|
||||
|
||||
minetest.register_on_joinplayer(function(player)
|
||||
if not player then return end
|
||||
local pos = vector.round(player:getpos())
|
||||
pos.y = pos.y + 1
|
||||
cozylights:on_join_cleanup(pos, 30)
|
||||
cozylights.cozyplayers[player:get_player_name()] = {
|
||||
name=player:get_player_name(),
|
||||
pos_hash=pos.x + (pos.y)*100 + pos.z*10000,
|
||||
wielded_item=0,
|
||||
last_pos=pos,
|
||||
last_wield="",
|
||||
prev_wielded_lights={},
|
||||
lbrush={
|
||||
brightness=6,
|
||||
radius=0,
|
||||
strength=0.5,
|
||||
mode=1,
|
||||
cover_only_surfaces=0,
|
||||
pos_hash=0,
|
||||
}
|
||||
}
|
||||
end)
|
||||
|
||||
minetest.register_on_leaveplayer(function(player)
|
||||
if not player then return end
|
||||
local name = player:get_player_name()
|
||||
for i=1,#cozylights.cozyplayers do
|
||||
if cozylights.cozyplayers[i].name == name then
|
||||
cozylights:wielded_light_cleanup(player,cozylights.cozyplayers[i],30)
|
||||
table.remove(cozylights.cozyplayers,i)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
minetest.register_on_shutdown(function()
|
||||
for i=1,#cozylights.cozyplayers do
|
||||
local player = minetest.get_player_by_name(cozylights.cozyplayers[i].name)
|
||||
if player ~= nil then
|
||||
cozylights:wielded_light_cleanup(player,cozylights.cozyplayers[i],30)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
local agent_total = 0
|
||||
local agent_count = 0
|
||||
local recently_updated = {}
|
||||
local function build_lights_after_generated(minp,maxp,sources)
|
||||
local t = os.clock()
|
||||
local vm = minetest.get_voxel_manip()
|
||||
local emin, emax = vm:read_from_map(vector.subtract(minp, 1), vector.add(maxp, 1))
|
||||
local data = vm:get_data()
|
||||
local param2data = vm:get_param2_data()
|
||||
local a = VoxelArea:new{
|
||||
MinEdge = emin,
|
||||
MaxEdge = emax
|
||||
}
|
||||
if sources then
|
||||
for i=1, #sources do
|
||||
local s = sources[i]
|
||||
--local hash = minetest.hash_node_position(s.pos)
|
||||
local hash = s.pos.x + (s.pos.y)*100 + s.pos.z*10000
|
||||
if recently_updated[hash] == nil then
|
||||
recently_updated[hash] = true
|
||||
cozylights:draw_node_light(s.pos, s.cozy_item, vm, a, data, param2data)
|
||||
end
|
||||
end
|
||||
else
|
||||
local cozycids_light_sources = cozylights.cozycids_light_sources
|
||||
for i in a:iterp(minp,maxp) do
|
||||
local cid = data[i]
|
||||
if cozycids_light_sources[cid] then
|
||||
local cozy_item = cozylights.cozy_items[minetest.get_name_from_content_id(cid)]
|
||||
-- check if radius is not too big
|
||||
local radius, _ = cozylights:calc_dims(cozy_item)
|
||||
local p = a:position(i)
|
||||
if a:containsp(vector.subtract(p,radius)) and a:containsp(vector.add(p,radius))
|
||||
then
|
||||
cozylights:draw_node_light(p,cozy_item,vm,a,data,param2data)
|
||||
else
|
||||
table.insert(cozylights.single_light_queue, { pos=p, cozy_item=cozy_item })
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
cozylights:setVoxelManipData(vm,data,param2data,true)
|
||||
agent_total = agent_total + mf((os.clock() - t) * 1000)
|
||||
agent_count = agent_count + 1
|
||||
--print("Av build after generated time: "..
|
||||
-- mf(agent_total/agent_count).." ms. Sample of: "..agent_count..". Areas left: "..#cozylights.area_queue
|
||||
--)
|
||||
end
|
||||
|
||||
--idk, size should be smarter than a constant
|
||||
local size = 85
|
||||
local function place_schem_but_real(pos, schematic, rotation, replacements, force_placement, flags)
|
||||
if tonumber(schematic) ~= nil or type(schematic) == "string" then -- schematic.data
|
||||
cozylights.area_queue[#cozylights.area_queue+1]={
|
||||
minp=vector.subtract(pos, size),
|
||||
maxp=vector.add(pos, size),
|
||||
sources=nil
|
||||
}
|
||||
return
|
||||
end
|
||||
local sd = schematic.data
|
||||
local update_needed = false
|
||||
for i, node in pairs(sd) do
|
||||
-- todo: account for replacements
|
||||
if cozylights.cozy_items[node.name] then
|
||||
-- rotation can be random so we cant know the position
|
||||
-- todo: account for faster cases when its not random
|
||||
update_needed = true
|
||||
break
|
||||
end
|
||||
end
|
||||
if update_needed == true then
|
||||
local cozycids_light_sources = cozylights.cozycids_light_sources
|
||||
print("UPDATE NEEDED")
|
||||
local minp,maxp,vm,data,param2data,a = cozylights:getVoxelManipData(pos, size)
|
||||
for i in a:iterp(minp, maxp) do
|
||||
local cid = data[i]
|
||||
if cozycids_light_sources[cid] then
|
||||
local cozy_item = cozylights.cozy_items[minetest.get_name_from_content_id(cid)]
|
||||
-- check if radius is not too big
|
||||
local radius, _ = cozylights:calc_dims(cozy_item)
|
||||
local p = a:position(i)
|
||||
if a:containsp(vector.subtract(p,radius)) and a:containsp(vector.add(p,radius))
|
||||
then
|
||||
cozylights:draw_node_light(p,cozy_item,vm,a,data,param2data)
|
||||
else
|
||||
table.insert(cozylights.single_light_queue, { pos=p, cozy_item=cozy_item })
|
||||
end
|
||||
end
|
||||
end
|
||||
cozylights:setVoxelManipData(vm,data,param2data,true)
|
||||
end
|
||||
end
|
||||
|
||||
--a feeble attempt to cover schematics placements
|
||||
local placeschemthatisnotreal = minetest.place_schematic
|
||||
--todo: if its a village(several schematics) dont rebuild same lights
|
||||
--todo: schematic exception table, if we have discovered for a fact somehow that a particular schematic
|
||||
--cant possibly have any kind of lights then we ignore
|
||||
--if not in runtime, then a constant table,
|
||||
--might require additional tools to load all schematics on contentdb to figure this out
|
||||
local schem_queue = {}
|
||||
minetest.place_schematic = function(pos, schematic, rotation, replacements, force_placement, flags)
|
||||
if not placeschemthatisnotreal(pos, schematic, rotation, replacements, force_placement, flags) then return end
|
||||
-- now totally real stuff starts to happen
|
||||
schem_queue[#schem_queue+1] = {
|
||||
pos = pos,
|
||||
schematic = schematic,
|
||||
rotation = rotation,
|
||||
replacements = replacements,
|
||||
force_placement = force_placement,
|
||||
flags = flags
|
||||
}
|
||||
end
|
||||
|
||||
local place_schematic_on_vmanip_nicely = minetest.place_schematic_on_vmanip
|
||||
minetest.place_schematic_on_vmanip = function(vmanip, minp, filename, rotation, replacements, force_placement,flags)
|
||||
if not place_schematic_on_vmanip_nicely(vmanip, minp, filename, rotation, replacements, force_placement,flags) then return end
|
||||
schem_queue[#schem_queue+1] = {
|
||||
pos = minp,
|
||||
schematic = filename,
|
||||
rotation = rotation,
|
||||
replacements = replacements,
|
||||
force_placement = force_placement,
|
||||
flags = flags
|
||||
}
|
||||
end
|
||||
|
||||
local createschemthatisveryreadable = minetest.create_schematic
|
||||
minetest.create_schematic = function(p1, p2, probability_list, filename, slice_prob_list)
|
||||
if not createschemthatisveryreadable(p1, p2, probability_list, filename, slice_prob_list) then return end
|
||||
-- unreadable stuff happens here
|
||||
cozylights.area_queue[#cozylights.area_queue+1] = {
|
||||
minp = p1,
|
||||
maxp = p2,
|
||||
sources = nil
|
||||
}
|
||||
end
|
||||
|
||||
local wield_light_enabled = cozylights.max_wield_light_radius > -1 and true or false
|
||||
local wield_step = cozylights.wield_step
|
||||
local brush_hold_step = cozylights.brush_hold_step
|
||||
local on_gen_step = cozylights.on_gen_step
|
||||
|
||||
function cozylights:switch_wielded_light(enabled)
|
||||
wield_light_enabled = enabled
|
||||
end
|
||||
|
||||
function cozylights:set_wield_step(_time)
|
||||
wield_step = _time
|
||||
minetest.settings:set("cozylights_wield_step",_time)
|
||||
cozylights.wield_step = _time
|
||||
end
|
||||
|
||||
function cozylights:set_brush_hold_step(_time)
|
||||
brush_hold_step = _time
|
||||
minetest.settings:set("cozylights_brush_hold_step",_time)
|
||||
cozylights.brush_hold_step = _time
|
||||
end
|
||||
|
||||
function cozylights:set_on_gen_step(_time)
|
||||
on_gen_step = _time
|
||||
minetest.settings:set("cozylights_on_gen_step",_time)
|
||||
cozylights.on_gen_step = _time
|
||||
end
|
||||
|
||||
local brush_hold_dtime = 0
|
||||
local wield_dtime = 0
|
||||
local on_gen_dtime = 0
|
||||
|
||||
local total_brush_hold_time = 0
|
||||
local total_brush_hold_step_count = 0
|
||||
local total_wield_time = 0
|
||||
local total_wield_step_count = 0
|
||||
local uncozy_queue = {}
|
||||
|
||||
local function on_brush_hold(player,cozyplayer,pos,t)
|
||||
local control_bits = player:get_player_control_bits()
|
||||
if control_bits < 128 or control_bits >= 256 then return end
|
||||
local lb = cozyplayer.lbrush
|
||||
if lb.radius > 10 then return end
|
||||
local look_dir = player:get_look_dir()
|
||||
local endpos = vector.add(pos, vector.multiply(look_dir, 100))
|
||||
local hit = minetest.raycast(pos, endpos, false, false):next()
|
||||
if not hit then return end
|
||||
local nodenameunder = minetest.get_node(hit.under).name
|
||||
local nodedefunder = minetest.registered_nodes[nodenameunder]
|
||||
local above = hit.above
|
||||
if nodedefunder.buildable_to == true then
|
||||
above.y = above.y - 1
|
||||
end
|
||||
local above_hash = above.x + (above.y)*100 + above.z*10000
|
||||
if above_hash ~= lb.pos_hash or lb.mode == 2 or lb.mode == 4 or lb.mode == 5 then
|
||||
lb.pos_hash = above_hash
|
||||
cozylights:draw_brush_light(above, lb)
|
||||
local exe_time = os.clock() - t
|
||||
total_brush_hold_time = total_brush_hold_time + mf(exe_time * 1000)
|
||||
total_brush_hold_step_count = total_brush_hold_step_count + 1
|
||||
print("Av cozy lights brush step time " .. mf(total_brush_hold_time/total_brush_hold_step_count) .. " ms. Sample of: "..total_brush_hold_step_count)
|
||||
--if exe_time > brush_hold_step then
|
||||
-- minetest.chat_send_all("brush hold step was adjusted to "..(exe_time*2).." secs to help crispy potato.")
|
||||
-- brush_hold_step = exe_time*2
|
||||
--end
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_globalstep(function(dtime)
|
||||
if wield_light_enabled then
|
||||
wield_dtime = wield_dtime + dtime
|
||||
if wield_dtime > wield_step then
|
||||
wield_dtime = 0
|
||||
for _,cozyplayer in pairs(cozylights.cozyplayers) do
|
||||
local t = os.clock()
|
||||
local player = minetest.get_player_by_name(cozyplayer.name)
|
||||
if player == nil then
|
||||
goto next_player
|
||||
end
|
||||
local pos = vector.round(player:getpos())
|
||||
pos.y = pos.y + 1
|
||||
local wield_name = player:get_wielded_item():get_name()
|
||||
-- simple hash, collision will result in a rare minor barely noticeable glitch if a user teleports:
|
||||
-- if in collision case right after teleport the player does not move, wielded light wont work until the player starts moving
|
||||
local pos_hash = pos.x + (pos.y)*100 + pos.z*10000
|
||||
if pos_hash == cozyplayer.pos_hash and cozyplayer.last_wield == wield_name then
|
||||
goto next_player
|
||||
end
|
||||
if cozylights.cozy_items[wield_name] ~= nil then
|
||||
local vel = vector.round(vector.multiply(player:get_velocity(),wield_step))
|
||||
cozylights:draw_wielded_light(
|
||||
pos,
|
||||
cozyplayer.last_pos,
|
||||
cozylights.cozy_items[wield_name],
|
||||
vel,
|
||||
cozyplayer
|
||||
)
|
||||
else
|
||||
cozylights:wielded_light_cleanup(player,cozyplayer,cozyplayer.last_wield_radius or 0)
|
||||
end
|
||||
cozyplayer.pos_hash = pos_hash
|
||||
cozyplayer.last_pos = pos
|
||||
cozyplayer.last_wield = wield_name
|
||||
local exe_time = (os.clock() - t)
|
||||
total_wield_time = total_wield_time + mf(exe_time * 1000)
|
||||
total_wield_step_count = total_wield_step_count + 1
|
||||
--print("Av wielded cozy light step time " .. mf(total_wield_time/total_wield_step_count) .. " ms. Sample of: "..total_wield_step_count)
|
||||
if cozylights.crispy_potato and exe_time > wield_step then
|
||||
cozylights:set_wielded_light_radius(cozylights.max_wield_light_radius - 1)
|
||||
minetest.chat_send_all("wield light step was adjusted to "..(exe_time*2).." secs to help crispy potato.")
|
||||
wield_step = exe_time*2
|
||||
end
|
||||
::next_player::
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
brush_hold_dtime = brush_hold_dtime + dtime
|
||||
if brush_hold_dtime > brush_hold_step then
|
||||
brush_hold_dtime = 0
|
||||
for _,cozyplayer in pairs(cozylights.cozyplayers) do
|
||||
local t = os.clock()
|
||||
local player = minetest.get_player_by_name(cozyplayer.name)
|
||||
local pos = vector.round(player:getpos())
|
||||
pos.y = pos.y + 1
|
||||
local wield_name = player:get_wielded_item():get_name()
|
||||
--todo: checking against a string is expensive, what do
|
||||
if wield_name == "cozylights:light_brush" then
|
||||
on_brush_hold(player,cozyplayer,pos,t)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
on_gen_dtime = on_gen_dtime + dtime
|
||||
if on_gen_dtime > on_gen_step then
|
||||
on_gen_dtime = 0
|
||||
if cozylights.uncozy_mode == 0 then
|
||||
if #schem_queue > 0 then
|
||||
local s = schem_queue[1]
|
||||
place_schem_but_real(s.pos, s.schematic, s.rotation, s.replacements, s.force_placement, s.flags)
|
||||
table.remove(schem_queue, 1)
|
||||
end
|
||||
if #cozylights.area_queue ~= 0 then
|
||||
local ar = cozylights.area_queue[1]
|
||||
table.remove(cozylights.area_queue, 1)
|
||||
print("build_lights_after_generated: "..cozylights:dump(ar.minp))
|
||||
build_lights_after_generated(ar.minp,ar.maxp,ar.sources)
|
||||
else
|
||||
cozylights:rebuild_light()
|
||||
if #recently_updated > 0 then
|
||||
recently_updated = {}
|
||||
end
|
||||
end
|
||||
else
|
||||
for _,cozyplayer in pairs(cozylights.cozyplayers) do
|
||||
local player = minetest.get_player_by_name(cozyplayer.name)
|
||||
local pos = vector.round(player:getpos())
|
||||
pos.y = pos.y + 1
|
||||
-- simple hash, collision will result in a rare minor barely noticeable glitch if a user teleports:
|
||||
-- if in collision case right after teleport the player does not move, wielded light wont work until the player starts moving
|
||||
local pos_hash = pos.x + (pos.y)*100 + pos.z*10000
|
||||
if pos_hash == cozyplayer.pos_hash then
|
||||
goto next_player
|
||||
end
|
||||
cozyplayer.pos_hash = pos_hash
|
||||
cozyplayer.last_pos = pos
|
||||
uncozy_queue[#uncozy_queue+1] = pos
|
||||
::next_player::
|
||||
end
|
||||
if #uncozy_queue > 0 then
|
||||
local exe_time = cozylights:clear(uncozy_queue[1], cozylights.uncozy_mode)
|
||||
table.remove(uncozy_queue, 1)
|
||||
if cozylights.crispy_potato and exe_time > on_gen_step then
|
||||
minetest.chat_send_all("on_generated step was adjusted to "..(exe_time*2).." secs to help crispy potato.")
|
||||
on_gen_step = exe_time*2
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
local gent_total = 0
|
||||
local gent_count = 0
|
||||
minetest.register_on_generated(function(minp, maxp)
|
||||
local pos = vector.add(minp, vector.floor(vector.divide(vector.subtract(maxp,minp), 2)))
|
||||
local light_sources = minetest.find_nodes_in_area(minp,maxp,cozylights.source_nodes)
|
||||
if #light_sources == 0 then return end
|
||||
if #light_sources > 1000 then
|
||||
--print("Error: too many light sources around "..cozylights:dump(pos).." Report this to Cozy Lights dev")
|
||||
return
|
||||
end
|
||||
--local minp_exp,maxp_exp,_,data,_,a = cozylights:getVoxelManipData(pos, size)
|
||||
--local t = os.clock()
|
||||
local sources = {}
|
||||
local a = VoxelArea:new{
|
||||
MinEdge = minp,
|
||||
MaxEdge = maxp
|
||||
}
|
||||
local minp_exp, maxp_exp = minp, maxp
|
||||
for _, p in pairs(light_sources) do
|
||||
local name = minetest.get_node(p).name--get_name_from_content_id(cid)
|
||||
local cozy_item = cozylights.cozy_items[name]
|
||||
local radius, _ = cozylights:calc_dims(cozy_item)
|
||||
local min_rad = vector.subtract(p,radius)
|
||||
local max_rad = vector.add(p,radius)
|
||||
if a:containsp(min_rad) and a:containsp(max_rad) then
|
||||
sources[#sources+1] = {
|
||||
pos=p,
|
||||
cozy_item=cozy_item
|
||||
}
|
||||
else
|
||||
minp_exp = {
|
||||
x = minp_exp.x > min_rad.x and min_rad.x or minp_exp.x,
|
||||
y = minp_exp.y > min_rad.y and min_rad.y or minp_exp.y,
|
||||
z = minp_exp.z > min_rad.z and min_rad.z or minp_exp.z,
|
||||
}
|
||||
maxp_exp = {
|
||||
x = maxp_exp.x < max_rad.x and max_rad.x or maxp_exp.x,
|
||||
y = maxp_exp.y < max_rad.y and max_rad.y or maxp_exp.y,
|
||||
z = maxp_exp.z < max_rad.z and max_rad.z or maxp_exp.z,
|
||||
}
|
||||
|
||||
a = VoxelArea:new{
|
||||
MinEdge = minp_exp,
|
||||
MaxEdge = maxp_exp
|
||||
}
|
||||
sources[#sources+1] = {
|
||||
pos=p,
|
||||
cozy_item=cozy_item
|
||||
}
|
||||
--print("adding "..name.." to single_light_queue")
|
||||
--table.insert(cozylights.single_light_queue, {
|
||||
-- pos=p,
|
||||
-- cozy_item=cozy_item
|
||||
--})
|
||||
end
|
||||
end
|
||||
--gent_total = gent_total + mf((os.clock() - t) * 1000)
|
||||
--gent_count = gent_count + 1
|
||||
--print("Av mapchunk generation time " .. mf(gent_total/gent_count) .. " ms. Sample of: "..gent_count)
|
||||
if #sources > 0 then
|
||||
print("on_generated adding area:"..cozylights:dump({minp=minp_exp,maxp=maxp_exp, volume=a:getVolume()}))
|
||||
cozylights.area_queue[#cozylights.area_queue+1]={
|
||||
minp=minp_exp,
|
||||
maxp=maxp_exp,
|
||||
sources=sources
|
||||
}
|
||||
end
|
||||
end)
|
||||
|
|
@ -1,341 +0,0 @@
|
|||
local mf = math.floor
|
||||
|
||||
local function on_secondary_use(user)
|
||||
local lb = cozylights.cozyplayers[user:get_player_name()].lbrush
|
||||
local settings_formspec = {
|
||||
"formspec_version[4]",
|
||||
--"size[6,6.4]",
|
||||
"size[5.2,5]",
|
||||
"label[1.45,0.5;Light Brush Settings]",
|
||||
|
||||
"label[0.95,1.35;Radius]",
|
||||
"field[3.6,1.1;0.7,0.5;radius;;"..lb.radius.."]",
|
||||
"tooltip[0.95,1.1;3.4,0.5;If radius is 0 then only one node will be affected by the brush.\n"..
|
||||
"If not zero then it's a sphere of affected nodes with specified radius.\n"..
|
||||
"As of now max radius is only 120.\n"..
|
||||
"With radiuses over 30 mouse hold as of now does not work, only point and click]",
|
||||
|
||||
"label[0.95,2.05;Brightness]",
|
||||
"field[3.6,1.8;0.7,0.5;brightness;;"..lb.brightness.."]",
|
||||
"tooltip[0.95,1.8;3.4,0.5;Brightness - for most brush modes values are from 1 to 14, corresponding to engine light levels.\n"..
|
||||
"If brush mode is 'darken' or 'override' then 0 will replace lowest light levels with air.]",
|
||||
|
||||
"label[0.95,2.75;Strength]",
|
||||
"field[3.6,2.5;0.7,0.5;strength;;"..lb.strength.."]",
|
||||
"tooltip[0.95,2.5;3.4,0.5;Strength, can be from 0 to 1, decimal values of any precision are valid.\n"..
|
||||
"Determines how bright(relative to brightness setting) light nodes in affected area will be.]",
|
||||
|
||||
"label[0.95,3.45;Brush Mode]",
|
||||
"dropdown[2.8,3.2;1.5,0.5;mode;default,erase,override,lighten,darken,blend;"..lb.mode.."]",
|
||||
"tooltip[0.95,3.2;3.4,0.5;\nDefault - replace only dimmer light nodes or air with brush.\n\n"..
|
||||
"Erase - inverse of default, replaces only lighter nodes with darker nodes or air if brightness is 0.\n\n"..
|
||||
"Override - set light nodes as brush settings dictate regardless of difference in brigthness.\n\n"..
|
||||
"Lighten - milder than default mode.\n\n"..
|
||||
"Darken - milder erase, does not darken below light 1(does not replace with air).\n\n"..
|
||||
"Blend - blend affected nodes' brigthness with brush brigthness.\n"..
|
||||
"Even though behaves correctly, as of now looks weird and unintuitive if radius is not 0.]",
|
||||
--"checkbox[1.7,4.6;cover_only_surfaces;cover only surfaces;"..(lb.cover_only_surfaces == 1 and "true" or "false").."]",
|
||||
--"tooltip[1.7,4.4;2.6,0.4;if enabled brush will not fill up the air with light above the ground;"..bgcolor..";#FFFFFF]",
|
||||
--"button_exit[1,5.1;4,0.8;confirm;Confirm]",
|
||||
"button_exit[1.1,4;3,0.8;confirm;Confirm]",
|
||||
}
|
||||
minetest.show_formspec(user:get_player_name(), "cozylights:brush_settings",table.concat(settings_formspec, ""))
|
||||
end
|
||||
|
||||
minetest.register_tool("cozylights:light_brush", {
|
||||
description = "Light Brush",
|
||||
inventory_image = "light_brush.png",
|
||||
wield_image = "light_brush.png^[transformR90",
|
||||
tool_capabilities = {
|
||||
full_punch_interval = 0.3,
|
||||
max_drop_level = 1,
|
||||
},
|
||||
range = 100.0,
|
||||
on_use = function(itemstack, user, pointed_thing)
|
||||
if pointed_thing.under then
|
||||
local nodenameunder = minetest.get_node(pointed_thing.under).name
|
||||
local nodedefunder = minetest.registered_nodes[nodenameunder]
|
||||
local lb = cozylights.cozyplayers[user:get_player_name()].lbrush
|
||||
local above = pointed_thing.above
|
||||
if nodenameunder ~= "air" and nodedefunder.buildable_to == true then
|
||||
above.y = above.y - 1
|
||||
end
|
||||
local above_hash = above.x + (above.y)*100 + above.z*10000
|
||||
lb.pos_hash = above_hash
|
||||
cozylights:draw_brush_light(pointed_thing.above, lb)
|
||||
end
|
||||
end,
|
||||
on_place = function(_, placer)
|
||||
on_secondary_use(placer)
|
||||
end,
|
||||
on_secondary_use = function(_, user)
|
||||
on_secondary_use(user)
|
||||
end,
|
||||
sound = {breaks = "default_tool_breaks"}
|
||||
})
|
||||
|
||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
if formname ~= ("cozylights:brush_settings") then return end
|
||||
if player == nil then return end
|
||||
local lb = cozylights.cozyplayers[player:get_player_name()].lbrush
|
||||
if fields.brightness then
|
||||
local brightness = tonumber(fields.brightness) > 14 and 14 or tonumber(fields.brightness)
|
||||
lb.brightness = brightness < 0 and 0 or mf(brightness or 0)
|
||||
end
|
||||
if fields.radius then
|
||||
local radius = tonumber(fields.radius) > 200 and 200 or tonumber(fields.radius)
|
||||
lb.radius = radius < 0 and 0 or mf(radius or 0)
|
||||
end
|
||||
if fields.strength then
|
||||
local strength = tonumber(fields.strength) > 1 and 1 or tonumber(fields.strength)
|
||||
lb.strength = strength < 0 and 0 or strength
|
||||
end
|
||||
if fields.mode then
|
||||
local mode = fields.mode
|
||||
local idx = 6
|
||||
if mode == "default" then
|
||||
idx = 1
|
||||
elseif mode == "erase" then
|
||||
idx = 2
|
||||
elseif mode == "override" then
|
||||
idx = 3
|
||||
elseif mode == "lighten" then
|
||||
idx = 4
|
||||
elseif mode == "darken" then
|
||||
idx = 5
|
||||
end
|
||||
lb.mode = idx
|
||||
end
|
||||
if fields.cover_only_surfaces then
|
||||
lb.cover_only_surfaces = fields.cover_only_surfaces == "true" and 1 or 0
|
||||
end
|
||||
end)
|
||||
|
||||
local function calc_dims_for_brush(brightness, radius, strength, even)
|
||||
local dim_levels = {}
|
||||
--- this gradient attempts to get more colors, but that looks like a super weird monochrome rainbow and immersion braking
|
||||
--strength = (strength+0.05)*2
|
||||
--
|
||||
--local current_brightness = brightness
|
||||
--local step = math.sqrt(radius/brightness)
|
||||
--local initial_step = step
|
||||
--for i = 1, radius do
|
||||
-- dim_levels[i] = current_brightness
|
||||
-- if i>step then
|
||||
-- step = step*strength + math.sqrt(i)
|
||||
-- current_brightness = current_brightness - 1
|
||||
-- end
|
||||
--end
|
||||
--- this gradient drops brightness fast but spreads dimmer lights over farther
|
||||
if strength == 1 then
|
||||
even = true
|
||||
end
|
||||
strength = strength*5
|
||||
dim_levels[1] = brightness
|
||||
if even ~= true then
|
||||
|
||||
for i = 2, radius do
|
||||
local dim = math.sqrt(math.sqrt(i)) * (6-strength)
|
||||
local light_i = mf(brightness - dim)
|
||||
if light_i > 0 then
|
||||
if light_i < 15 then
|
||||
dim_levels[i] = light_i
|
||||
else
|
||||
dim_levels[i] = 14
|
||||
end
|
||||
else
|
||||
dim_levels[i] = 1
|
||||
end
|
||||
end
|
||||
else
|
||||
for i = 2, radius do
|
||||
dim_levels[i] = brightness
|
||||
end
|
||||
end
|
||||
|
||||
return dim_levels
|
||||
end
|
||||
|
||||
local c_air = minetest.get_content_id("air")
|
||||
local c_light1 = minetest.get_content_id("cozylights:light1")
|
||||
local c_lights = { c_light1, c_light1 + 1, c_light1 + 2, c_light1 + 3, c_light1 + 4, c_light1 + 5, c_light1 + 6,
|
||||
c_light1 + 7, c_light1 + 8, c_light1 + 9, c_light1 + 10, c_light1 + 11, c_light1 + 12, c_light1 + 13 }
|
||||
local gent_total = 0
|
||||
local gent_count = 0
|
||||
|
||||
local function draw_one_node(pos,lb)
|
||||
local node = minetest.get_node(pos)
|
||||
local brightness = lb.brightness
|
||||
local new_node_name = "cozylights:light"..brightness
|
||||
if brightness == 0 then
|
||||
new_node_name = "air"
|
||||
end
|
||||
|
||||
if node.name == "air" and new_node_name ~= node.name then
|
||||
minetest.set_node(
|
||||
pos,
|
||||
{
|
||||
name=new_node_name,
|
||||
param2=brightness
|
||||
}
|
||||
)
|
||||
return
|
||||
end
|
||||
if string.find(node.name,"cozylights:") then
|
||||
if lb.mode == 1 and brightness <= node.param2 then return end
|
||||
if lb.mode == 2 and brightness >= node.param2 then return end
|
||||
if lb.mode == 4 then
|
||||
if brightness <= node.param2 then return end
|
||||
brightness = mf((brightness+node.param2)/2+0.5)
|
||||
if brightness < 1 then return end
|
||||
new_node_name = "cozylights:light"..brightness
|
||||
elseif lb.mode == 5 then
|
||||
if brightness >= node.param2 then return end
|
||||
brightness = mf((brightness+node.param2)/2)
|
||||
new_node_name = "cozylights:light"..brightness
|
||||
if brightness < 1 then
|
||||
brightness = 0
|
||||
new_node_name = "air"
|
||||
end
|
||||
elseif lb.mode == 6 then
|
||||
brightness = mf((brightness+node.param2)/2+0.5)
|
||||
new_node_name = "cozylights:light"..brightness
|
||||
if brightness < 0 then
|
||||
brightness = 0
|
||||
new_node_name = "air"
|
||||
end
|
||||
end
|
||||
minetest.set_node(
|
||||
pos,
|
||||
{
|
||||
name=new_node_name,
|
||||
param2=brightness
|
||||
}
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--this function pulls numbers out of its ass instead of seriously computing everything, so its faster
|
||||
--some nodes are being missed for big spheres
|
||||
function cozylights:draw_brush_light(pos, lb)
|
||||
local t = os.clock()
|
||||
local radius = lb.radius
|
||||
if radius == 0 then
|
||||
draw_one_node(pos,lb)
|
||||
return
|
||||
end
|
||||
local mode = lb.mode
|
||||
local brightness = lb.brightness
|
||||
local dim_levels = calc_dims_for_brush(brightness,radius,lb.strength, mode==2 and true or false)
|
||||
print("dim_levels:"..cozylights:dump(dim_levels))
|
||||
local vm = minetest.get_voxel_manip()
|
||||
local emin, emax = vm:read_from_map(vector.subtract(pos, radius+1), vector.add(pos, radius+1))
|
||||
local data = vm:get_data()
|
||||
local param2data = vm:get_param2_data()
|
||||
local a = VoxelArea:new{
|
||||
MinEdge = emin,
|
||||
MaxEdge = emax
|
||||
}
|
||||
local sphere_surface = cozylights:get_sphere_surface(radius)
|
||||
local ylvl = 1
|
||||
local cid = data[a:index(pos.x,pos.y-1,pos.z)]
|
||||
local cida = data[a:index(pos.x,pos.y+1,pos.z)]
|
||||
if cid and cida then
|
||||
if (cid == c_air or (cid >= c_lights[1] and cid <= c_lights[14]))
|
||||
and cida ~= c_air and (cida < c_lights[1] or cida > c_lights[14])
|
||||
then
|
||||
ylvl = -1
|
||||
end
|
||||
else
|
||||
return
|
||||
end
|
||||
pos.y = pos.y + ylvl
|
||||
|
||||
if mode == 1 then
|
||||
if cozylights.always_fix_edges == true then
|
||||
local visited_pos = {}
|
||||
for i,pos2 in ipairs(sphere_surface) do
|
||||
local end_pos = {x=pos.x+pos2.x,y=pos.y+pos2.y,z=pos.z+pos2.z}
|
||||
cozylights:lightcast_fix_edges(pos, vector.direction(pos, end_pos),radius,data,param2data,a,dim_levels,visited_pos)
|
||||
end
|
||||
else
|
||||
for i,pos2 in ipairs(sphere_surface) do
|
||||
local end_pos = {x=pos.x+pos2.x,y=pos.y+pos2.y,z=pos.z+pos2.z}
|
||||
cozylights:lightcast(pos, vector.direction(pos, end_pos),radius,data,param2data,a,dim_levels)
|
||||
end
|
||||
end
|
||||
elseif mode == 2 then
|
||||
if cozylights.always_fix_edges == true then
|
||||
local visited_pos = {}
|
||||
for i,pos2 in ipairs(sphere_surface) do
|
||||
local end_pos = {x=pos.x+pos2.x,y=pos.y+pos2.y,z=pos.z+pos2.z}
|
||||
cozylights:lightcast_erase_fix_edges(pos, vector.direction(pos, end_pos),radius,data,param2data,a,dim_levels,visited_pos)
|
||||
end
|
||||
else
|
||||
for i,pos2 in ipairs(sphere_surface) do
|
||||
local end_pos = {x=pos.x+pos2.x,y=pos.y+pos2.y,z=pos.z+pos2.z}
|
||||
cozylights:lightcast_erase(pos, vector.direction(pos, end_pos),radius,data,param2data,a,dim_levels)
|
||||
end
|
||||
end
|
||||
elseif mode == 3 then
|
||||
if cozylights.always_fix_edges == true then
|
||||
local visited_pos = {}
|
||||
for i,pos2 in ipairs(sphere_surface) do
|
||||
local end_pos = {x=pos.x+pos2.x,y=pos.y+pos2.y,z=pos.z+pos2.z}
|
||||
cozylights:lightcast_override_fix_edges(pos, vector.direction(pos, end_pos),radius,data,param2data,a,dim_levels,visited_pos)
|
||||
end
|
||||
else
|
||||
for i,pos2 in ipairs(sphere_surface) do
|
||||
local end_pos = {x=pos.x+pos2.x,y=pos.y+pos2.y,z=pos.z+pos2.z}
|
||||
cozylights:lightcast_override(pos, vector.direction(pos, end_pos),radius,data,param2data,a,dim_levels)
|
||||
end
|
||||
end
|
||||
elseif mode == 4 then
|
||||
if cozylights.always_fix_edges == true then
|
||||
local visited_pos = {}
|
||||
for i,pos2 in ipairs(sphere_surface) do
|
||||
local end_pos = {x=pos.x+pos2.x,y=pos.y+pos2.y,z=pos.z+pos2.z}
|
||||
cozylights:lightcast_lighten_fix_edges(pos, vector.direction(pos, end_pos),radius,data,param2data,a,dim_levels,visited_pos)
|
||||
end
|
||||
else
|
||||
for i,pos2 in ipairs(sphere_surface) do
|
||||
local end_pos = {x=pos.x+pos2.x,y=pos.y+pos2.y,z=pos.z+pos2.z}
|
||||
cozylights:lightcast_lighten(pos, vector.direction(pos, end_pos),radius,data,param2data,a,dim_levels)
|
||||
end
|
||||
end
|
||||
elseif mode == 5 then
|
||||
if cozylights.always_fix_edges == true then
|
||||
local visited_pos = {}
|
||||
for i,pos2 in ipairs(sphere_surface) do
|
||||
local end_pos = {x=pos.x+pos2.x,y=pos.y+pos2.y,z=pos.z+pos2.z}
|
||||
cozylights:lightcast_darken_fix_edges(pos, vector.direction(pos, end_pos),radius,data,param2data,a,dim_levels,visited_pos)
|
||||
end
|
||||
else
|
||||
for i,pos2 in ipairs(sphere_surface) do
|
||||
local end_pos = {x=pos.x+pos2.x,y=pos.y+pos2.y,z=pos.z+pos2.z}
|
||||
cozylights:lightcast_darken(pos, vector.direction(pos, end_pos),radius,data,param2data,a,dim_levels)
|
||||
end
|
||||
end
|
||||
else
|
||||
if cozylights.always_fix_edges == true then
|
||||
local visited_pos = {}
|
||||
for i,pos2 in ipairs(sphere_surface) do
|
||||
local end_pos = {x=pos.x+pos2.x,y=pos.y+pos2.y,z=pos.z+pos2.z}
|
||||
cozylights:lightcast_blend_fix_edges(pos, vector.direction(pos, end_pos),radius,data,param2data,a,dim_levels,visited_pos)
|
||||
end
|
||||
else
|
||||
for i,pos2 in ipairs(sphere_surface) do
|
||||
local end_pos = {x=pos.x+pos2.x,y=pos.y+pos2.y,z=pos.z+pos2.z}
|
||||
cozylights:lightcast_blend(pos, vector.direction(pos, end_pos),radius,data,param2data,a,dim_levels)
|
||||
end
|
||||
end
|
||||
end
|
||||
vm:set_data(data)
|
||||
vm:set_param2_data(param2data)
|
||||
vm:update_liquids()
|
||||
vm:write_to_map()
|
||||
gent_total = gent_total + mf((os.clock() - t) * 1000)
|
||||
gent_count = gent_count + 1
|
||||
print("Av draw time " .. mf(gent_total/gent_count) .. " ms. Sample of: "..gent_count)
|
||||
end
|
File diff suppressed because one or more lines are too long
|
@ -1,192 +0,0 @@
|
|||
local c_air = minetest.get_content_id("air")
|
||||
local c_light1 = minetest.get_content_id("cozylights:light1")
|
||||
|
||||
local c_lights = { c_light1, c_light1 + 1, c_light1 + 2, c_light1 + 3, c_light1 + 4, c_light1 + 5, c_light1 + 6,
|
||||
c_light1 + 7, c_light1 + 8, c_light1 + 9, c_light1 + 10, c_light1 + 11, c_light1 + 12, c_light1 + 13 }
|
||||
|
||||
local gent_total = 0
|
||||
local gent_count = 0
|
||||
|
||||
local remt_total = 0
|
||||
local remt_count = 0
|
||||
local mf = math.floor
|
||||
|
||||
local dirfloor = 0.5
|
||||
--- raycast but normal
|
||||
local function darknesscast(pos, dir, radius,data,param2data, a)
|
||||
local px, py, pz, dx, dy, dz = pos.x, pos.y, pos.z, dir.x, dir.y, dir.z
|
||||
local c_light1 = c_lights[1]
|
||||
local c_light14 = c_lights[14]
|
||||
for i = 1, radius do
|
||||
local x = mf(dx*i+dirfloor) + px
|
||||
local y = mf(dy*i+dirfloor) + py
|
||||
local z = mf(dz*i+dirfloor) + pz
|
||||
local idx = a:index(x,y,z)
|
||||
local cid = data[idx]
|
||||
if cid and (cid == c_air or (cid >= c_light1 and cid <= c_light14+14)) then
|
||||
data[idx] = c_air
|
||||
param2data[idx] = 0
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function cozylights:draw_node_light(pos,cozy_item,vm,a,data,param2data,fix_edges)
|
||||
local t = os.clock()
|
||||
local update_needed = 0
|
||||
local radius, dim_levels = cozylights:calc_dims(cozy_item)
|
||||
--print("cozy_item:"..cozylights:dump(cozy_item))
|
||||
--print("dim_levels: "..cozylights:dump(dim_levels))
|
||||
--print("spreading light over a sphere with radius of "..radius)
|
||||
if vm == nil then
|
||||
_,_,vm,data,param2data,a = cozylights:getVoxelManipData(pos,radius)
|
||||
update_needed = 1
|
||||
end
|
||||
local sphere_surface = cozylights:get_sphere_surface(radius)
|
||||
local ylvl = 1
|
||||
local cid = data[a:index(pos.x,pos.y-1,pos.z)]
|
||||
local cida = data[a:index(pos.x,pos.y+1,pos.z)]
|
||||
if cid and cida then
|
||||
if (cid == c_air or (cid >= c_lights[1] and cid <= c_lights[14]))
|
||||
and cida ~= c_air and (cida < c_lights[1] or cida > c_lights[14])
|
||||
then
|
||||
ylvl = -1
|
||||
end
|
||||
else
|
||||
return
|
||||
end
|
||||
pos.y = pos.y + ylvl
|
||||
fix_edges = fix_edges == nil and cozylights.always_fix_edges or fix_edges
|
||||
if fix_edges == true then
|
||||
local visited_pos = {}
|
||||
for i,pos2 in ipairs(sphere_surface) do
|
||||
local end_pos = {x=pos.x+pos2.x,y=pos.y+pos2.y,z=pos.z+pos2.z}
|
||||
cozylights:lightcast_fix_edges(pos, vector.direction(pos, end_pos),radius,data,param2data,a,dim_levels,visited_pos)
|
||||
end
|
||||
else
|
||||
for i,pos2 in ipairs(sphere_surface) do
|
||||
local end_pos = {x=pos.x+pos2.x,y=pos.y+pos2.y,z=pos.z+pos2.z}
|
||||
cozylights.dir = vector.direction(pos, end_pos)
|
||||
cozylights:lightcast(pos, vector.direction(pos, end_pos),radius,data,param2data,a,dim_levels)
|
||||
end
|
||||
end
|
||||
if update_needed == 1 then
|
||||
cozylights:setVoxelManipData(vm,data,param2data,true)
|
||||
end
|
||||
gent_total = gent_total + mf((os.clock() - t) * 1000)
|
||||
gent_count = gent_count + 1
|
||||
--print("Av illum time " .. mf(gent_total/gent_count) .. " ms. Sample of: "..gent_count)
|
||||
end
|
||||
|
||||
-- handle_async?
|
||||
function cozylights:rebuild_light()
|
||||
local single_light_queue = cozylights.single_light_queue
|
||||
if #single_light_queue == 0 then
|
||||
return
|
||||
end
|
||||
--print("#single_light_queue is: "..#single_light_queue)
|
||||
cozylights:draw_node_light(single_light_queue[1].pos, single_light_queue[1].cozy_item)
|
||||
table.remove(single_light_queue, 1)
|
||||
end
|
||||
|
||||
function cozylights:destroy_light(pos, cozy_item)
|
||||
local t = os.clock()
|
||||
local radius = cozylights:calc_dims(cozy_item)
|
||||
local _,_,vm,data,param2data,a = cozylights:getVoxelManipData(pos, radius)
|
||||
local sphere_surface = cozylights:get_sphere_surface(radius)
|
||||
local ylvl = 1
|
||||
local cid = data[a:index(pos.x,pos.y-1,pos.z)]
|
||||
local cida = data[a:index(pos.x,pos.y+1,pos.z)]
|
||||
if cid and cida then
|
||||
if (cid == c_air or (cid >= c_lights[1] and cid <= c_lights[14]))
|
||||
and cida ~= c_air and (cida < c_lights[1] or cida > c_lights[14])
|
||||
then
|
||||
ylvl = -1
|
||||
end
|
||||
else
|
||||
return
|
||||
end
|
||||
pos.y = pos.y + ylvl
|
||||
for i,pos2 in ipairs(sphere_surface) do
|
||||
local end_pos = {x=pos.x+pos2.x,y=pos.y+pos2.y,z=pos.z+pos2.z}
|
||||
darknesscast(pos, vector.direction(pos, end_pos),radius,data,param2data, a)
|
||||
end
|
||||
|
||||
cozylights:setVoxelManipData(vm,data,param2data)
|
||||
|
||||
local rebuild_range = 78
|
||||
local rebuild_minp = vector.subtract(pos, rebuild_range)
|
||||
local rebuild_maxp = vector.add(pos, rebuild_range)
|
||||
local posrebuilds = minetest.find_nodes_in_area(
|
||||
rebuild_minp,
|
||||
rebuild_maxp,
|
||||
cozylights.source_nodes
|
||||
)
|
||||
local pos_hash = pos.x + (pos.y-ylvl)*100 + pos.z*10000
|
||||
local sources = {}
|
||||
if #posrebuilds > 0 then
|
||||
local single_light_queue = cozylights.single_light_queue
|
||||
for i=1,#posrebuilds do
|
||||
local posrebuild = posrebuilds[i]
|
||||
local posrebuild_hash = posrebuild.x + posrebuild.y*100 + posrebuild.z*10000
|
||||
if posrebuild_hash ~= pos_hash then
|
||||
local node = minetest.get_node(posrebuild)
|
||||
local rebuild_radius, _ = cozylights:calc_dims(cozylights.cozy_items[node.name])
|
||||
local max_distance = rebuild_radius + radius
|
||||
if max_distance > vector.distance(pos,posrebuild) then
|
||||
if vector.in_area(vector.subtract(posrebuild,rebuild_radius), rebuild_minp, rebuild_maxp)
|
||||
and vector.in_area(vector.add(posrebuild,rebuild_radius), rebuild_minp, rebuild_maxp)
|
||||
then
|
||||
sources[#sources+1] = {
|
||||
pos=posrebuild,
|
||||
cozy_item=cozylights.cozy_items[node.name]
|
||||
}
|
||||
else
|
||||
cozylights.single_light_queue[#single_light_queue+1] = {
|
||||
pos=posrebuilds[i],
|
||||
cozy_item=cozylights.cozy_items[node.name]
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if #sources > 0 then
|
||||
cozylights.area_queue[#cozylights.area_queue+1]={
|
||||
minp=rebuild_minp,
|
||||
maxp=rebuild_maxp,
|
||||
sources=sources
|
||||
}
|
||||
end
|
||||
|
||||
remt_total = remt_total + mf((os.clock() - t) * 1000)
|
||||
remt_count = remt_count + 1
|
||||
print("Av light removal time " .. mf(remt_total/remt_count) .. " ms. Sample of: "..remt_count)
|
||||
end
|
||||
|
||||
--[[
|
||||
function cozylights:rebuild_light(pos, cozy_item,vm,a,data,param2data)
|
||||
local radius, dim_levels = cozylights:calc_dims(cozy_item)
|
||||
print("rebuilding light for position "..cozylights:dump(pos))
|
||||
local sphere_surface = cozylights:get_sphere_surface(radius)
|
||||
local ylvl = 1
|
||||
local cid = data[a:index(pos.x,pos.y-1,pos.z)]
|
||||
local cida = data[a:index(pos.x,pos.y+1,pos.z)]
|
||||
if cid and cida then
|
||||
if (cid == c_air or (cid >= c_lights[1] and cid <= c_lights[14]))
|
||||
and cida ~= c_air and (cida < c_lights[1] or cida > c_lights[14])
|
||||
then
|
||||
ylvl = -1
|
||||
end
|
||||
else
|
||||
return
|
||||
end
|
||||
pos.y = pos.y + ylvl
|
||||
for _,pos2 in ipairs(sphere_surface) do
|
||||
local end_pos = {x=pos.x+pos2.x,y=pos.y+pos2.y,z=pos.z+pos2.z}
|
||||
if a:containsp(end_pos) then
|
||||
cozylights:lightcast(pos, vector.direction(pos, end_pos),radius,data,param2data,a,dim_levels)
|
||||
end
|
||||
end
|
||||
end]]
|
|
@ -1,38 +0,0 @@
|
|||
-- All possible light levels
|
||||
for i=1, minetest.LIGHT_MAX do
|
||||
minetest.register_node("cozylights:light"..i, {
|
||||
description = "Light Source "..i,
|
||||
paramtype = "light",
|
||||
light_source = i,
|
||||
--tiles ={"invisible.png"},
|
||||
drawtype = "airlike",
|
||||
walkable = false,
|
||||
sunlight_propagates = true,
|
||||
is_ground_content = false,
|
||||
buildable_to = true,
|
||||
pointable = false,
|
||||
groups = {dig_immediate=3,not_in_creative_inventory=1},
|
||||
floodable = true,
|
||||
use_texture_alpha="clip",
|
||||
})
|
||||
|
||||
end
|
||||
|
||||
-- two separate loops to keep content ids in order
|
||||
for i=1, minetest.LIGHT_MAX do
|
||||
minetest.register_node("cozylights:light_debug"..i, {
|
||||
description = "Light Source "..i,
|
||||
paramtype = "light",
|
||||
light_source = i,
|
||||
tiles ={"default_glass.png"},
|
||||
drawtype = "glasslike",
|
||||
walkable = false,
|
||||
sunlight_propagates = true,
|
||||
is_ground_content = false,
|
||||
buildable_to = false,
|
||||
pointable = true,
|
||||
groups = {dig_immediate=3,not_in_creative_inventory=1},
|
||||
floodable = true,
|
||||
use_texture_alpha="clip",
|
||||
})
|
||||
end
|
|
@ -1,31 +0,0 @@
|
|||
[**Global Node Sources]
|
||||
|
||||
# if none given, this default value will be used
|
||||
cozylights_default_size (Default chat command radius) int 40 5 120
|
||||
|
||||
# max brightness of surrounding light. does not affect a light_source node base value. attention: if light is too bright, the scene can lose nuance
|
||||
cozylights_brightness_factor (Global ambient light source brightness modifier) float 3.0 -10.0 10.0
|
||||
|
||||
# affects max radius of the light but only when its bright enough, if its very dim the setting will do nothing
|
||||
cozylights_reach_factor (Global ambient light source reach factor) float 4.0 0.0 10.0
|
||||
|
||||
# how fast light dims further away from the source, higher means farther dim lights will persist for longer
|
||||
cozylights_dim_factor (Global ambient light source dim factor) float 9.0 0.0 10.0
|
||||
|
||||
# -1 means wielded light is disabled
|
||||
# 0 means only one node is affected, so it basically acts like typical wielded light in Minetest
|
||||
# if it's more than 0 then it's a sphere in which light will spread
|
||||
cozylights_wielded_light_radius (Cozy wielded light radius) int 19 -1 30
|
||||
|
||||
# sets all light sources to 1 so that the engine will not render anticlimactic squares for torches
|
||||
# and such. if a player removes cozylights from a world while this is set to true, fixmap mod for existing lights will be required, therefore default is set
|
||||
# to false, so you will need to enable it yourself after you decide that you like cozylights more.
|
||||
cozylights_override_engine_lights (Override engine light sources) bool false
|
||||
|
||||
# makes all edges stop lights properly, cozylights algo is much faster without it enabled, so if for example
|
||||
# you need to first place a lot of lights all over the place, it would be easier to first place those lights and then run
|
||||
# /fixedges manually
|
||||
cozylights_always_fix_edges (Override engine light sources) bool false
|
||||
|
||||
# if higher, then it will update slower and stress potato CPU less
|
||||
cozylights_step_time (Cozy Lights Global Step time) float 0.1 0.01 1.0
|
|
@ -1,649 +0,0 @@
|
|||
local sphere_surfaces = {[19]=nil}
|
||||
local c_light1 = minetest.get_content_id("cozylights:light1")
|
||||
local c_lights = { c_light1, c_light1 + 1, c_light1 + 2, c_light1 + 3, c_light1 + 4, c_light1 + 5, c_light1 + 6,
|
||||
c_light1 + 7, c_light1 + 8, c_light1 + 9, c_light1 + 10, c_light1 + 11, c_light1 + 12, c_light1 + 13 }
|
||||
local c_light14 = c_lights[14]
|
||||
local c_light_debug1 = c_light14 + 1
|
||||
local c_light_debug14 = c_light_debug1 + 13
|
||||
local c_air = minetest.get_content_id("air")
|
||||
local mf = math.floor
|
||||
|
||||
function cozylights:clear(pos,size)
|
||||
local t = os.clock()
|
||||
local minp,maxp,vm,data,param2data,a = cozylights:getVoxelManipData(pos,size)
|
||||
local count = 0
|
||||
for i in a:iterp(minp, maxp) do
|
||||
local cid = data[i]
|
||||
if cid >= c_light1 and cid <= c_light_debug14 then
|
||||
data[i] = c_air
|
||||
param2data[i] = 0
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
minetest.chat_send_all("cleared "..count.." cozy light nodes in area around pos: "..cozylights:dump(pos).." of radius: "..size)
|
||||
if count> 0 then
|
||||
cozylights:setVoxelManipData(vm,data,param2data,true)
|
||||
end
|
||||
return (os.clock() - t)
|
||||
end
|
||||
|
||||
function cozylights:getVoxelManipData(pos, size)
|
||||
local minp = vector.subtract(pos, size)
|
||||
local maxp = vector.add(pos, size)
|
||||
local vm = minetest.get_voxel_manip()
|
||||
local emin, emax = vm:read_from_map(vector.subtract(minp, 1), vector.add(maxp, 1))
|
||||
local data = vm:get_data()
|
||||
local param2data = vm:get_param2_data()
|
||||
local a = VoxelArea:new{
|
||||
MinEdge = emin,
|
||||
MaxEdge = emax
|
||||
}
|
||||
return minp,maxp,vm,data,param2data,a
|
||||
end
|
||||
|
||||
function cozylights:setVoxelManipData(vm,data,param2data,update_liquids)
|
||||
vm:set_data(data)
|
||||
if param2data ~= nil then
|
||||
vm:set_param2_data(param2data)
|
||||
end
|
||||
if update_liquids == true then
|
||||
vm:update_liquids()
|
||||
end
|
||||
vm:write_to_map()
|
||||
end
|
||||
|
||||
--todo: 6 directions of static slices or dynamic slices if its faster somehow(it wasnt so far)
|
||||
function cozylights:slice_cake(surface,radius)
|
||||
local sliced = {}
|
||||
for k,v in pairs(surface) do
|
||||
-- full sphere except for a cone from center to max -y of 45 degrees or like pi/2 radians or something
|
||||
if v.y > -radius*0.7071 then
|
||||
table.insert(sliced,v)
|
||||
end
|
||||
end
|
||||
return sliced
|
||||
end
|
||||
|
||||
-- radius*radius = x*x + y*y + z*z
|
||||
function cozylights:get_sphere_surface(radius,sliced)
|
||||
if sphere_surfaces[radius] == nil then
|
||||
local sphere_surface = {}
|
||||
local rad_pow2_min, rad_pow2_max = radius * (radius - 1), radius * (radius + 1)
|
||||
for z = -radius, radius do
|
||||
for y = -radius, radius do
|
||||
for x = -radius, radius do
|
||||
local pow2 = x * x + y * y + z * z
|
||||
if pow2 >= rad_pow2_min and pow2 <= rad_pow2_max then
|
||||
-- todo: could arrange these in a more preferable for optimization order
|
||||
sphere_surface[#sphere_surface+1] = {x=x,y=y,z=z}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
local t = {
|
||||
full = sphere_surface
|
||||
}
|
||||
if radius < 30 then
|
||||
t.minusyslice = cozylights:slice_cake(sphere_surface,radius) --typical wielded light
|
||||
sphere_surfaces[radius] = t
|
||||
if sliced == true then
|
||||
return t.minusyslice
|
||||
end
|
||||
end
|
||||
return sphere_surface
|
||||
else
|
||||
if sliced == true and sphere_surfaces[radius].minusyslice ~= nil then
|
||||
return sphere_surfaces[radius].minusyslice
|
||||
end
|
||||
return sphere_surfaces[radius].full
|
||||
end
|
||||
end
|
||||
|
||||
function cozylights:calc_dims(cozy_item)
|
||||
|
||||
local brightness_mod = 0
|
||||
local reach_mod = 0
|
||||
local dim_mod = 0
|
||||
if cozy_item.modifiers ~= nil then
|
||||
brightness_mod = cozylights.coziest_table[cozy_item.modifiers].brightness
|
||||
reach_mod = cozylights.coziest_table[cozy_item.modifiers].reach_factor
|
||||
dim_mod = cozylights.coziest_table[cozy_item.modifiers].dim_factor
|
||||
end
|
||||
local max_light = mf(cozy_item.light_source + cozylights.brightness_factor + brightness_mod)
|
||||
local r = mf(max_light*max_light/10*(cozylights.reach_factor+reach_mod))
|
||||
--print("initial r: "..r)
|
||||
local r_max = 0
|
||||
local dim_levels = {}
|
||||
local dim_factor = cozylights.dim_factor + dim_mod
|
||||
for i = r , 1, -1 do
|
||||
local dim = math.sqrt(math.sqrt(i)) * dim_factor
|
||||
local light_i = max_light + 1 - mf(dim)
|
||||
if light_i < 1 then
|
||||
--light_i = 1
|
||||
r_max = i
|
||||
else
|
||||
if light_i > 14 then
|
||||
light_i = 14
|
||||
end
|
||||
dim_levels[i] = light_i
|
||||
end
|
||||
|
||||
end
|
||||
-- we cut the r only if max_r found is lower than r, so that we keep the ability to have huge radiuses
|
||||
if r_max > 0 and r_max < r then
|
||||
return r_max-1,dim_levels
|
||||
end
|
||||
return r,dim_levels
|
||||
end
|
||||
|
||||
local cozycids_sunlight_propagates = {}
|
||||
-- ensure cozy position in memory
|
||||
-- default amount of lights sources: 194
|
||||
-- in default game with moreblocks mod: 5134
|
||||
--cozylights:prealloc(cozycids_sunlight_propagates, 194, true)
|
||||
--cozycids_sunlight_propagates = {}
|
||||
minetest.after(1, function()
|
||||
cozycids_sunlight_propagates = cozylights.cozycids_sunlight_propagates
|
||||
cozylights:finalize(cozycids_sunlight_propagates)
|
||||
print(#cozycids_sunlight_propagates)
|
||||
cozylights.cozycids_sunlight_propagates = {}
|
||||
local version_welcome = minetest.settings:get("version_welcome")
|
||||
if version_welcome ~= cozylights.version then
|
||||
minetest.settings:set("version_welcome",cozylights.version)
|
||||
minetest.chat_send_all(">.< Running Cozy Lights "..cozylights.version.." alpha. Some features are still missing or might not work properly and might be fixed tomorrow or next week."..
|
||||
"\n>.< To learn more about what it can do check ContentDB page: https://content.minetest.net/packages/SingleDigitIQ/cozylights/"..
|
||||
"\n>.< If you experience problems, appreciate if you report them on ContentDB, Minetest forum, Github or Discord."..
|
||||
"\n>.< If you need more of original ideas and blazingly fast code in open source - leave a positive review on ContentDB or/and add to favorites."..
|
||||
"\n>.< To open mod settings type in chat /cozysettings or /zs, hopefully tooltips are useful."..
|
||||
"\n>.< This message displays only once per new downloaded update for Cozy Lights mod."..
|
||||
"\n>.< Have fun :>"
|
||||
)
|
||||
end
|
||||
end)
|
||||
|
||||
-- adjusting dirfloor might help with some nodes missing. probably the only acceptable way to to eliminate node
|
||||
-- misses and not sacrifice performance too much or at all
|
||||
local dirfloor = 0.5
|
||||
-- raycast but normal
|
||||
-- todo: if radius higher than i think 15, we need to somehow grab more nodes, without it it's not entirely accurate
|
||||
-- i hope a cheaply computed offset based on dir will do
|
||||
-- not to forget: what i mean by that is that + 0.5 in mf has to become a variable
|
||||
|
||||
-- while we have the opportunity to cut the amount of same node reruns in this loop,
|
||||
-- we avoid that because luajit optimization breaks with one more branch and hashtable look up
|
||||
-- at least on my machine, and so it becomes slower to run and at the same time grabs more memory
|
||||
-- todo: actually check for the forth time the above is real
|
||||
function cozylights:lightcast(pos, dir, radius,data,param2data,a,dim_levels)
|
||||
local px, py, pz, dx, dy, dz = pos.x, pos.y, pos.z, dir.x, dir.y, dir.z
|
||||
local light_nerf = 0
|
||||
for i = 1, radius do
|
||||
local x,y,z = mf(dx*i+dirfloor)+px, mf(dy*i+dirfloor)+py, mf(dz*i+dirfloor)+pz
|
||||
local idx = a:index(x,y,z)
|
||||
local cid = data[idx]
|
||||
if cozycids_sunlight_propagates[cid] == true then
|
||||
if cid == c_air or (cid >= c_light1 and cid <= c_light14) then
|
||||
local dim = (dim_levels[i] - light_nerf) >= 1 and (dim_levels[i] - light_nerf) or 1
|
||||
local light = c_lights[dim]
|
||||
if light > cid or param2data[idx] == 0 then
|
||||
data[idx] = light
|
||||
param2data[idx] = dim
|
||||
end
|
||||
else
|
||||
light_nerf = light_nerf + 1
|
||||
end
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function cozylights:lightcast_erase(pos, dir, radius,data,param2data,a,dim_levels)
|
||||
local px, py, pz, dx, dy, dz = pos.x, pos.y, pos.z, dir.x, dir.y, dir.z
|
||||
local light_nerf = 0
|
||||
for i = 1, radius do
|
||||
local x,y,z = mf(dx*i+dirfloor)+px, mf(dy*i+dirfloor)+py, mf(dz*i+dirfloor)+pz
|
||||
local idx = a:index(x,y,z)
|
||||
local cid = data[idx]
|
||||
if cozycids_sunlight_propagates[cid] == true then
|
||||
if cid >= c_light1 and cid <= c_light14 then
|
||||
local dim = (dim_levels[i] - light_nerf) >= 0 and (dim_levels[i] - light_nerf) or 0
|
||||
local light = dim > 0 and c_lights[dim] or c_air
|
||||
if light < cid then
|
||||
data[idx] = light
|
||||
param2data[idx] = dim
|
||||
end
|
||||
elseif cid ~= c_air then
|
||||
light_nerf = light_nerf + 1
|
||||
end
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function cozylights:lightcast_override(pos, dir, radius,data,param2data,a,dim_levels)
|
||||
local px, py, pz, dx, dy, dz = pos.x, pos.y, pos.z, dir.x, dir.y, dir.z
|
||||
local light_nerf = 0
|
||||
for i = 1, radius do
|
||||
local x,y,z = mf(dx*i+dirfloor)+px, mf(dy*i+dirfloor)+py, mf(dz*i+dirfloor)+pz
|
||||
local idx = a:index(x,y,z)
|
||||
local cid = data[idx]
|
||||
if cozycids_sunlight_propagates[cid] == true then
|
||||
if cid == c_air or (cid >= c_light1 and cid <= c_light14) then
|
||||
local dim = (dim_levels[i] - light_nerf) > 0 and (dim_levels[i] - light_nerf) or 1
|
||||
data[idx] = c_lights[dim]
|
||||
param2data[idx] = dim
|
||||
else
|
||||
light_nerf = light_nerf + 1
|
||||
end
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function cozylights:lightcast_lighten(pos, dir, radius,data,param2data,a,dim_levels)
|
||||
local px, py, pz, dx, dy, dz = pos.x, pos.y, pos.z, dir.x, dir.y, dir.z
|
||||
local light_nerf = 0
|
||||
for i = 1, radius do
|
||||
local x,y,z = mf(dx*i+dirfloor)+px, mf(dy*i+dirfloor)+py, mf(dz*i+dirfloor)+pz
|
||||
local idx = a:index(x,y,z)
|
||||
local cid = data[idx]
|
||||
if cozycids_sunlight_propagates[cid] == true then
|
||||
if cid == c_air or (cid >= c_light1 and cid <= c_light14) then
|
||||
local dim = (dim_levels[i] - light_nerf) > 0 and (dim_levels[i] - light_nerf) or 1
|
||||
if c_lights[dim] > cid then
|
||||
local original_light = cid - c_light1
|
||||
dim = mf((dim + original_light)/2+0.5)
|
||||
data[idx] = c_lights[dim]
|
||||
param2data[idx] = dim
|
||||
end
|
||||
else
|
||||
light_nerf = light_nerf + 1
|
||||
end
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function cozylights:lightcast_darken(pos, dir, radius,data,param2data,a,dim_levels)
|
||||
local px, py, pz, dx, dy, dz = pos.x, pos.y, pos.z, dir.x, dir.y, dir.z
|
||||
local light_nerf = 0
|
||||
for i = 1, radius do
|
||||
local x,y,z = mf(dx*i+dirfloor)+px, mf(dy*i+dirfloor)+py, mf(dz*i+dirfloor)+pz
|
||||
local idx = a:index(x,y,z)
|
||||
local cid = data[idx]
|
||||
if cozycids_sunlight_propagates[cid] == true then
|
||||
if cid >= c_light1 and cid <= c_light14 then
|
||||
local dim = (dim_levels[i] - light_nerf) > 0 and (dim_levels[i] - light_nerf) or 1
|
||||
if c_lights[dim] < cid then
|
||||
local original_light = cid - c_light1
|
||||
dim = mf((dim + original_light)/2)
|
||||
data[idx] = c_lights[dim]
|
||||
param2data[idx] = dim
|
||||
end
|
||||
elseif cid ~= c_air then
|
||||
light_nerf = light_nerf + 1
|
||||
end
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function cozylights:lightcast_blend(pos, dir, radius,data,param2data,a,dim_levels)
|
||||
local px, py, pz, dx, dy, dz = pos.x, pos.y, pos.z, dir.x, dir.y, dir.z
|
||||
local light_nerf = 0
|
||||
for i = 1, radius do
|
||||
local x,y,z = mf(dx*i+dirfloor)+px, mf(dy*i+dirfloor)+py, mf(dz*i+dirfloor)+pz
|
||||
local idx = a:index(x,y,z)
|
||||
local cid = data[idx]
|
||||
if cozycids_sunlight_propagates[cid] == true then
|
||||
if cid == c_air or (cid >= c_light1 and cid <= c_light14) then
|
||||
local dim = (dim_levels[i] - light_nerf) > 0 and (dim_levels[i] - light_nerf) or 1
|
||||
local original_light = cid - c_light1 --param2data[idx]
|
||||
dim = mf((dim + original_light)/2+0.5)
|
||||
if dim < 1 then break end
|
||||
data[idx] = c_lights[dim]
|
||||
param2data[idx] = dim
|
||||
else
|
||||
light_nerf = light_nerf + 1
|
||||
end
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- removes some lights that light up the opposite side of an obstacle
|
||||
-- it is weird and inaccurate as of now, i can make it accurate the expensive way,
|
||||
-- still looking for a cheap way
|
||||
function cozylights:lightcast_fix_edges(pos, dir, radius,data,param2data,a,dim_levels,visited_pos)
|
||||
local dirs = { -1*a.ystride, 1*a.ystride,-1,1,-1*a.zstride,1*a.zstride}
|
||||
local px, py, pz, dx, dy, dz = pos.x, pos.y, pos.z, dir.x, dir.y, dir.z
|
||||
local light_nerf = 0
|
||||
local halfrad, braking_brak = radius/2, false
|
||||
local next_x, next_y, next_z = mf(dx+dirfloor) + px, mf(dy+dirfloor) + py, mf(dz+dirfloor) + pz
|
||||
for i = 1, radius,2 do
|
||||
local x,y,z = next_x, next_y, next_z
|
||||
local idx = a:index(x,y,z)
|
||||
for n = 1, 6 do
|
||||
if cozycids_sunlight_propagates[data[idx+dirs[n]]] == nil then
|
||||
braking_brak = true
|
||||
break
|
||||
end
|
||||
end
|
||||
if braking_brak == true then break end
|
||||
x,y,z = nil,nil,nil
|
||||
local cid = data[idx]
|
||||
if cozycids_sunlight_propagates[cid] == true then
|
||||
-- appears that hash lookup in a loop is as bad as math
|
||||
if cid == c_air or (cid >= c_light1 and cid <= c_light14) then
|
||||
if i < halfrad then
|
||||
if not visited_pos[idx] then
|
||||
visited_pos[idx] = true
|
||||
local dim = (dim_levels[i] - light_nerf) > 0 and (dim_levels[i] - light_nerf) or 1
|
||||
local light = c_lights[dim]
|
||||
if light > cid or param2data[idx] == 0 then
|
||||
data[idx] = light
|
||||
param2data[idx] = dim
|
||||
end
|
||||
end
|
||||
else
|
||||
local dim = (dim_levels[i] - light_nerf) > 0 and (dim_levels[i] - light_nerf) or 1
|
||||
local light = c_lights[dim]
|
||||
if light > cid or param2data[idx] == 0 then
|
||||
data[idx] = light
|
||||
param2data[idx] = dim
|
||||
end
|
||||
end
|
||||
else
|
||||
light_nerf = light_nerf + 1
|
||||
end
|
||||
else
|
||||
break
|
||||
end
|
||||
next_x,next_y,next_z = mf(dx*(i+1)+dirfloor)+px, mf(dy*(i+1)+dirfloor)+py, mf(dz*(i+1)+dirfloor)+pz
|
||||
|
||||
--local next_idx = a:index(next_x,next_y,next_z)
|
||||
--for n = 1, 6 do
|
||||
-- if cozycids_sunlight_propagates[data[next_idx+dirs[n]]] == nil then
|
||||
-- braking_brak = true
|
||||
-- break
|
||||
-- end
|
||||
--end
|
||||
--next_x,next_y,next_z = mf(dx*(i+2)+dirfloor)+px, mf(dy*(i+2)+dirfloor)+py, mf(dz*(i+2)+dirfloor)+pz
|
||||
|
||||
--local next_adj_indxs = {
|
||||
-- a:index(next_x,y,z),
|
||||
-- a:index(x,y,next_z),
|
||||
-- a:index(x,next_y,z),
|
||||
-- a:index(next_x,next_y,z),
|
||||
-- a:index(x,next_y,next_z),
|
||||
--}
|
||||
|
||||
--for _, j in pairs(next_adj_indxs) do
|
||||
-- if cozycids_sunlight_propagates[data[j]] ~= true then
|
||||
-- braking_brak = true
|
||||
-- break
|
||||
-- end
|
||||
--end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
function cozylights:lightcast_erase_fix_edges(pos, dir, radius,data,param2data,a,dim_levels,visited_pos)
|
||||
local dirs = { -1*a.ystride, 1*a.ystride,-1,1,-1*a.zstride,1*a.zstride}
|
||||
local px, py, pz, dx, dy, dz = pos.x, pos.y, pos.z, dir.x, dir.y, dir.z
|
||||
local light_nerf = 0
|
||||
local halfrad, braking_brak = radius/2, false
|
||||
local next_x, next_y, next_z = mf(dx+dirfloor) + px, mf(dy+dirfloor) + py, mf(dz+dirfloor) + pz
|
||||
for i = 1, radius do
|
||||
local x,y,z = next_x, next_y, next_z
|
||||
local idx = a:index(x,y,z)
|
||||
for n = 1, 6 do
|
||||
if cozycids_sunlight_propagates[data[idx+dirs[n]]] == nil then
|
||||
braking_brak = true
|
||||
break
|
||||
end
|
||||
end
|
||||
if braking_brak == true then break end
|
||||
x,y,z = nil,nil,nil
|
||||
local cid = data[idx]
|
||||
if cozycids_sunlight_propagates[cid] == true then
|
||||
-- appears that hash lookup in a loop is as bad as math
|
||||
if cid >= c_light1 and cid <= c_light14 then
|
||||
if i < halfrad then
|
||||
if not visited_pos[idx] then
|
||||
visited_pos[idx] = true
|
||||
local dim = (dim_levels[i] - light_nerf) >= 0 and (dim_levels[i] - light_nerf) or 0
|
||||
local light = dim > 0 and c_lights[dim] or c_air
|
||||
if light < cid then
|
||||
data[idx] = light
|
||||
param2data[idx] = dim
|
||||
end
|
||||
end
|
||||
else
|
||||
local dim = (dim_levels[i] - light_nerf) >= 0 and (dim_levels[i] - light_nerf) or 0
|
||||
local light = dim > 0 and c_lights[dim] or c_air
|
||||
if light < cid then
|
||||
data[idx] = light
|
||||
param2data[idx] = dim
|
||||
end
|
||||
end
|
||||
elseif cid ~= c_air then
|
||||
light_nerf = light_nerf + 1
|
||||
end
|
||||
else
|
||||
break
|
||||
end
|
||||
next_x,next_y,next_z = mf(dx*(i+1)+dirfloor)+px, mf(dy*(i+1)+dirfloor)+py, mf(dz*(i+1)+dirfloor)+pz
|
||||
end
|
||||
end
|
||||
|
||||
function cozylights:lightcast_override_fix_edges(pos, dir, radius,data,param2data,a,dim_levels,visited_pos)
|
||||
local dirs = { -1*a.ystride, 1*a.ystride,-1,1,-1*a.zstride,1*a.zstride}
|
||||
local px, py, pz, dx, dy, dz = pos.x, pos.y, pos.z, dir.x, dir.y, dir.z
|
||||
local light_nerf = 0
|
||||
local halfrad, braking_brak = radius/2, false
|
||||
local next_x, next_y, next_z = mf(dx+dirfloor) + px, mf(dy+dirfloor) + py, mf(dz+dirfloor) + pz
|
||||
for i = 1, radius do
|
||||
local x = next_x
|
||||
local y = next_y
|
||||
local z = next_z
|
||||
local idx = a:index(x,y,z)
|
||||
for n = 1, 6 do
|
||||
if cozycids_sunlight_propagates[data[idx+dirs[n]]] == nil then
|
||||
braking_brak = true
|
||||
break
|
||||
end
|
||||
end
|
||||
if braking_brak == true then break end
|
||||
x,y,z = nil,nil,nil -- they are probably still allocated though
|
||||
local cid = data[idx]
|
||||
if cozycids_sunlight_propagates[cid] == true then
|
||||
-- appears that hash lookup in a loop is as bad as math
|
||||
if cid == c_air or (cid >= c_light1 and cid <= c_light14) then
|
||||
if i < halfrad then
|
||||
if not visited_pos[idx] then
|
||||
visited_pos[idx] = true
|
||||
local dim = (dim_levels[i] - light_nerf) > 0 and (dim_levels[i] - light_nerf) or 1
|
||||
data[idx] = c_lights[dim]
|
||||
param2data[idx] = dim
|
||||
end
|
||||
else
|
||||
local dim = (dim_levels[i] - light_nerf) > 0 and (dim_levels[i] - light_nerf) or 1
|
||||
data[idx] = c_lights[dim]
|
||||
param2data[idx] = dim
|
||||
end
|
||||
else
|
||||
light_nerf = light_nerf + 1
|
||||
end
|
||||
else
|
||||
break
|
||||
end
|
||||
next_x,next_y,next_z = mf(dx*(i+1)+dirfloor)+px, mf(dy*(i+1)+dirfloor)+py, mf(dz*(i+1)+dirfloor)+pz
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function cozylights:lightcast_lighten_fix_edges(pos, dir, radius,data,param2data,a,dim_levels,visited_pos)
|
||||
local dirs = { -1*a.ystride, 1*a.ystride,-1,1,-1*a.zstride,1*a.zstride}
|
||||
local px, py, pz, dx, dy, dz = pos.x, pos.y, pos.z, dir.x, dir.y, dir.z
|
||||
local light_nerf = 0
|
||||
local halfrad, braking_brak = radius/2, false
|
||||
local next_x, next_y, next_z = mf(dx+dirfloor) + px, mf(dy+dirfloor) + py, mf(dz+dirfloor) + pz
|
||||
for i = 1, radius do
|
||||
local x = next_x
|
||||
local y = next_y
|
||||
local z = next_z
|
||||
local idx = a:index(x,y,z)
|
||||
for n = 1, 6 do
|
||||
if cozycids_sunlight_propagates[data[idx+dirs[n]]] == nil then
|
||||
braking_brak = true
|
||||
break
|
||||
end
|
||||
end
|
||||
if braking_brak == true then break end
|
||||
x,y,z = nil,nil,nil -- they are probably still allocated though
|
||||
local cid = data[idx]
|
||||
if cozycids_sunlight_propagates[cid] == true then
|
||||
-- appears that hash lookup in a loop is as bad as math
|
||||
if cid == c_air or (cid >= c_light1 and cid <= c_light14) then
|
||||
if i < halfrad then
|
||||
if not visited_pos[idx] then
|
||||
visited_pos[idx] = true
|
||||
local dim = (dim_levels[i] - light_nerf) > 0 and (dim_levels[i] - light_nerf) or 1
|
||||
if c_lights[dim] > cid then
|
||||
local original_light = cid - c_light1
|
||||
dim = mf((dim + original_light)/2+0.5)
|
||||
data[idx] = c_lights[dim]
|
||||
param2data[idx] = dim
|
||||
end
|
||||
end
|
||||
else
|
||||
local dim = (dim_levels[i] - light_nerf) > 0 and (dim_levels[i] - light_nerf) or 1
|
||||
if c_lights[dim] > cid then
|
||||
local original_light = cid - c_light1
|
||||
dim = mf((dim + original_light)/2+0.5)
|
||||
data[idx] = c_lights[dim]
|
||||
param2data[idx] = dim
|
||||
end
|
||||
end
|
||||
else
|
||||
light_nerf = light_nerf + 1
|
||||
end
|
||||
else
|
||||
break
|
||||
end
|
||||
next_x,next_y,next_z = mf(dx*(i+1)+dirfloor)+px, mf(dy*(i+1)+dirfloor)+py, mf(dz*(i+1)+dirfloor)+pz
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function cozylights:lightcast_darken_fix_edges(pos, dir, radius,data,param2data,a,dim_levels,visited_pos)
|
||||
local dirs = { -1*a.ystride, 1*a.ystride,-1,1,-1*a.zstride,1*a.zstride}
|
||||
local px, py, pz, dx, dy, dz = pos.x, pos.y, pos.z, dir.x, dir.y, dir.z
|
||||
local light_nerf = 0
|
||||
local halfrad, braking_brak = radius/2, false
|
||||
local next_x, next_y, next_z = mf(dx+dirfloor) + px, mf(dy+dirfloor) + py, mf(dz+dirfloor) + pz
|
||||
for i = 1, radius do
|
||||
local x = next_x
|
||||
local y = next_y
|
||||
local z = next_z
|
||||
local idx = a:index(x,y,z)
|
||||
for n = 1, 6 do
|
||||
if cozycids_sunlight_propagates[data[idx+dirs[n]]] == nil then
|
||||
braking_brak = true
|
||||
break
|
||||
end
|
||||
end
|
||||
if braking_brak == true then break end
|
||||
x,y,z = nil,nil,nil -- they are probably still allocated though
|
||||
local cid = data[idx]
|
||||
if cozycids_sunlight_propagates[cid] == true then
|
||||
-- appears that hash lookup in a loop is as bad as math
|
||||
if cid == c_air or (cid >= c_light1 and cid <= c_light14) then
|
||||
if i < halfrad then
|
||||
if not visited_pos[idx] then
|
||||
visited_pos[idx] = true
|
||||
local dim = (dim_levels[i] - light_nerf) > 0 and (dim_levels[i] - light_nerf) or 1
|
||||
if c_lights[dim] < cid then
|
||||
local original_light = cid - c_light1
|
||||
dim = mf((dim + original_light)/2)
|
||||
data[idx] = c_lights[dim]
|
||||
param2data[idx] = dim
|
||||
end
|
||||
end
|
||||
else
|
||||
local dim = (dim_levels[i] - light_nerf) > 0 and (dim_levels[i] - light_nerf) or 1
|
||||
if c_lights[dim] < cid then
|
||||
local original_light = cid - c_light1
|
||||
dim = mf((dim + original_light)/2)
|
||||
data[idx] = c_lights[dim]
|
||||
param2data[idx] = dim
|
||||
end
|
||||
end
|
||||
else
|
||||
light_nerf = light_nerf + 1
|
||||
end
|
||||
else
|
||||
break
|
||||
end
|
||||
next_x,next_y,next_z = mf(dx*(i+1)+dirfloor)+px, mf(dy*(i+1)+dirfloor)+py, mf(dz*(i+1)+dirfloor)+pz
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function cozylights:lightcast_blend_fix_edges(pos, dir, radius,data,param2data,a,dim_levels,visited_pos)
|
||||
local dirs = { -1*a.ystride, 1*a.ystride,-1,1,-1*a.zstride,1*a.zstride}
|
||||
local px, py, pz, dx, dy, dz = pos.x, pos.y, pos.z, dir.x, dir.y, dir.z
|
||||
local light_nerf = 0
|
||||
local halfrad, braking_brak = radius/2, false
|
||||
local next_x, next_y, next_z = mf(dx+dirfloor) + px, mf(dy+dirfloor) + py, mf(dz+dirfloor) + pz
|
||||
for i = 1, radius do
|
||||
local x = next_x
|
||||
local y = next_y
|
||||
local z = next_z
|
||||
local idx = a:index(x,y,z)
|
||||
for n = 1, 6 do
|
||||
if cozycids_sunlight_propagates[data[idx+dirs[n]]] == nil then
|
||||
braking_brak = true
|
||||
break
|
||||
end
|
||||
end
|
||||
if braking_brak == true then break end
|
||||
x,y,z = nil,nil,nil -- they are probably still allocated though
|
||||
local cid = data[idx]
|
||||
if cozycids_sunlight_propagates[cid] == true then
|
||||
-- appears that hash lookup in a loop is as bad as math
|
||||
if cid == c_air or (cid >= c_light1 and cid <= c_light14) then
|
||||
if i < halfrad then
|
||||
if not visited_pos[idx] then
|
||||
visited_pos[idx] = true
|
||||
local dim = (dim_levels[i] - light_nerf) > 0 and (dim_levels[i] - light_nerf) or 1
|
||||
local original_light = cid - c_light1
|
||||
dim = mf((dim + original_light)/2+0.5)
|
||||
if dim < 1 then break end
|
||||
data[idx] = c_lights[dim]
|
||||
param2data[idx] = dim
|
||||
end
|
||||
else
|
||||
local dim = (dim_levels[i] - light_nerf) > 0 and (dim_levels[i] - light_nerf) or 1
|
||||
local original_light = cid - c_light1
|
||||
dim = mf((dim + original_light)/2+0.5)
|
||||
if dim < 1 then break end
|
||||
data[idx] = c_lights[dim]
|
||||
param2data[idx] = dim
|
||||
end
|
||||
else
|
||||
light_nerf = light_nerf + 1
|
||||
end
|
||||
else
|
||||
break
|
||||
end
|
||||
next_x,next_y,next_z = mf(dx*(i+1)+dirfloor)+px, mf(dy*(i+1)+dirfloor)+py, mf(dz*(i+1)+dirfloor)+pz
|
||||
|
||||
end
|
||||
end
|
|
@ -1,95 +0,0 @@
|
|||
dofile("../helpers.lua")
|
||||
dofile("../../../builtin/common/vector.lua")
|
||||
|
||||
-- this exists to basically find sweet spot for dirfloor in fastest way i could come up with to spread light.
|
||||
-- dirfloor should change somehow cheaply according to radius maybe or
|
||||
-- according to ray angles, or, dirfloor should be split in x,y,z axis equivalents
|
||||
-- and those should be adjusted.
|
||||
-- some node misses start to appear from radius 6
|
||||
local dirfloor = 0.51
|
||||
|
||||
local mf = math.floor
|
||||
|
||||
-- radius*radius = x*x + y*y + z*z
|
||||
local function get_full_sphere(radius)
|
||||
local sphere = {}
|
||||
local count, offset, rad_pow2, stride_y = 0, 1+radius, radius * (radius + 1), radius+2
|
||||
local stride_z = stride_y * stride_y
|
||||
for z = -radius, radius do
|
||||
for y = -radius, radius do
|
||||
for x = -radius, radius do
|
||||
local pow2 = x * x + y * y + z * z
|
||||
if pow2 <= rad_pow2 then
|
||||
local i = (z + offset) * stride_z + (y + offset) * stride_y + x + offset + 1
|
||||
if sphere[i] ~= true then
|
||||
sphere[i] = true
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return sphere, count
|
||||
end
|
||||
|
||||
local function get_sphere_surface(radius)
|
||||
local sphere_surface = {}
|
||||
local rad_pow2_min, rad_pow2_max = radius * (radius - 1), radius * (radius + 1)
|
||||
for z = -radius, radius do
|
||||
for y = -radius, radius do
|
||||
for x = -radius, radius do
|
||||
local squared = x * x + y * y + z * z
|
||||
if squared >= rad_pow2_min and squared <= rad_pow2_max then
|
||||
sphere_surface[#sphere_surface+1] = {x=x,y=y,z=z}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return sphere_surface
|
||||
end
|
||||
|
||||
local function raycast(dir, radius)
|
||||
local ray = {}
|
||||
local stride_z, stride_y = (radius+2)*radius+2, radius+2
|
||||
local dx, dy, dz = dir.x, dir.y, dir.z
|
||||
for i = 1, radius do
|
||||
local x = mf(dx*i+dirfloor)
|
||||
local y = mf(dy*i+dirfloor)
|
||||
local z = mf(dz*i+dirfloor)
|
||||
local idx = (z+1+radius)*stride_z+1+(y+1+radius)*stride_y+(x+1+radius)
|
||||
if not ray[idx] then
|
||||
ray[idx] = true
|
||||
end
|
||||
end
|
||||
return ray
|
||||
end
|
||||
|
||||
local function reconstruct_sphere(radius)
|
||||
local pos = {x=0,y=0,z=0}
|
||||
local sphere, sphere_len = get_full_sphere(radius)
|
||||
local sphere_surface = get_sphere_surface(radius)
|
||||
local reconstructed_sphere = {}
|
||||
local reconstructed_sphere_len = 0
|
||||
for _,pos2 in ipairs(sphere_surface) do
|
||||
local ray = raycast(vector.direction(pos, pos2),radius)
|
||||
for i,_ in pairs(ray) do
|
||||
if not reconstructed_sphere[i] then
|
||||
reconstructed_sphere[i] = true
|
||||
reconstructed_sphere_len = reconstructed_sphere_len + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
print("#sphere: "..sphere_len)
|
||||
print("#reconstructed_sphere: "..reconstructed_sphere_len)
|
||||
--print(cozylights:dump(sphere))
|
||||
--print(cozylights:dump(reconstructed_sphere))
|
||||
end
|
||||
|
||||
for i=1,1 do
|
||||
dirfloor = dirfloor - 0.01
|
||||
print("running with dirfloor: "..dirfloor)
|
||||
reconstruct_sphere(1)
|
||||
end
|
||||
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
default_glass.png is by Krock (CC0 1.0)
|
||||
|
||||
my debug textures are WTFPL if anything
|
Binary file not shown.
Before Width: | Height: | Size: 270 B |
Binary file not shown.
Before Width: | Height: | Size: 624 B |
|
@ -1,30 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
# This script is naive: does not try to find mod.conf recursevily, so it sometimes can miss something,
|
||||
# and also it can add something unrelated, that is just some logic for light_sources and not a nodedef,
|
||||
# and probably some ancient mod' file extension won't be picked up if it's a thing, aside from gorillions of
|
||||
# other problems. Does enough so far
|
||||
|
||||
match="light_source"
|
||||
|
||||
games_directory="../../../games"
|
||||
mods_directory="../../"
|
||||
game_files=$(grep -l -R --include="*.lua" $match $games_directory)
|
||||
mod_files=$(grep -l -R --include="*.lua" $match $mods_directory)
|
||||
files=("${game_files[@]}""${mod_files[@]}")
|
||||
mod_names=""
|
||||
i=0
|
||||
for file in $files
|
||||
do
|
||||
directory=$(dirname $file)
|
||||
mod_conf=$(find $directory -name "*.conf")
|
||||
if [[ $mod_conf != "" ]]; then
|
||||
dir_name_comma="$(basename $directory),"
|
||||
if [[ $mod_names != *$dir_name_comma* ]]; then
|
||||
let i++;
|
||||
mod_names="${mod_names} $dir_name_comma"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
echo "mod_names array:" $mod_names
|
||||
echo "length:" $i
|
|
@ -1,262 +0,0 @@
|
|||
local c_air = minetest.get_content_id("air")
|
||||
local c_light1 = minetest.get_content_id("cozylights:light1")
|
||||
|
||||
local c_lights = { c_light1, c_light1 + 1, c_light1 + 2, c_light1 + 3, c_light1 + 4, c_light1 + 5, c_light1 + 6,
|
||||
c_light1 + 7, c_light1 + 8, c_light1 + 9, c_light1 + 10, c_light1 + 11, c_light1 + 12, c_light1 + 13 }
|
||||
|
||||
local gent_total = 0
|
||||
local gent_count = 0
|
||||
local mf = math.floor
|
||||
--local cozycids_sunlight_propagates = cozylights.cozycids_sunlight_propagates
|
||||
|
||||
local function destroy_stale_wielded_light(data,param2data,a,cozyplayer)
|
||||
local c_light1 = c_lights[1]
|
||||
local c_light14 = c_lights[14]
|
||||
for j,p in ipairs(cozyplayer.prev_wielded_lights) do
|
||||
if a and a:containsp(p) then
|
||||
local idx = a:indexp(p)
|
||||
local cid = data[idx]
|
||||
if cid >= c_light1 and cid <= c_light14 then
|
||||
if param2data[idx] > 0 and param2data[idx] <= 14 then
|
||||
data[idx] = c_light1 + param2data[idx] - 1
|
||||
else
|
||||
data[idx] = c_air
|
||||
end
|
||||
end
|
||||
else
|
||||
local node = minetest.get_node(p)
|
||||
if string.find(node.name, "cozylights:light") then
|
||||
if node.param2 == 0 then
|
||||
minetest.set_node(p,{name="air"})
|
||||
else
|
||||
minetest.set_node(p,{name="cozylights:light"..node.param2})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
cozyplayer.prev_wielded_lights = {}
|
||||
end
|
||||
|
||||
--- Like normal raycast but only covers surfaces, faster for large distances, somewhat less accurate
|
||||
local function lightcast_lite(pos, dir, dirs, radius,data, param2data, a,dim_levels,cozyplayer)
|
||||
local px, py, pz, dx, dy, dz = pos.x, pos.y, pos.z, dir.x, dir.y, dir.z
|
||||
local c_light14 = c_lights[14]
|
||||
local light_nerf = 0
|
||||
for i = 1, radius do
|
||||
local x = mf(dx*i+0.5) + px
|
||||
local y = mf(dy*i+0.5) + py
|
||||
local z = mf(dz*i+0.5) + pz
|
||||
local idx = a:index(x,y,z)
|
||||
local cid = data[idx]
|
||||
if cid and (cid == c_air or (cid >= c_light1 and cid <= c_light14)) then
|
||||
for n = 1, 6 do
|
||||
local adj_idx = idx+dirs[n]
|
||||
local adj_cid = data[adj_idx]
|
||||
if adj_cid and ((adj_cid < c_light1 and adj_cid ~= c_air)or adj_cid > c_light14) then
|
||||
local dim = (dim_levels[i] - light_nerf) > 0 and (dim_levels[i] - light_nerf) or 1
|
||||
local light = c_lights[dim]
|
||||
if light > cid then
|
||||
data[idx] = light
|
||||
table.insert(cozyplayer.prev_wielded_lights, {x=x,y=y,z=z})
|
||||
if cid == c_air and param2data[idx] > 0 then
|
||||
param2data[idx] = 0
|
||||
end
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function cozylights:wielded_light_cleanup(player,cozyplayer,radius)
|
||||
local pos = vector.round(player:getpos())
|
||||
local vm = minetest.get_voxel_manip()
|
||||
local emin, emax
|
||||
local last_pos = cozyplayer.last_pos
|
||||
local distance = vector.distance(pos,last_pos)
|
||||
if distance < 20 then
|
||||
local pos1 = {
|
||||
x=pos.x < last_pos.x and pos.x or last_pos.x,
|
||||
y=pos.y < last_pos.y and pos.y or last_pos.y,
|
||||
z=pos.z < last_pos.z and pos.z or last_pos.z,
|
||||
}
|
||||
local pos2 = {
|
||||
x=pos.x > last_pos.x and pos.x or last_pos.x,
|
||||
y=pos.y > last_pos.y and pos.y or last_pos.y,
|
||||
z=pos.z > last_pos.z and pos.z or last_pos.z,
|
||||
}
|
||||
emin, emax = vm:read_from_map(vector.subtract(pos1, radius+1), vector.add(pos2, radius+1))
|
||||
else
|
||||
emin, emax = vm:read_from_map(vector.subtract(pos, radius+1), vector.add(pos, radius+1))
|
||||
end
|
||||
local data = vm:get_data()
|
||||
local a = VoxelArea:new{
|
||||
MinEdge = emin,
|
||||
MaxEdge = emax
|
||||
}
|
||||
local param2data = vm:get_param2_data()
|
||||
destroy_stale_wielded_light(data,param2data,a,cozyplayer)
|
||||
|
||||
cozylights:setVoxelManipData(vm,data,nil,true)
|
||||
end
|
||||
|
||||
local max_wield_light_radius = cozylights.max_wield_light_radius
|
||||
|
||||
function cozylights:set_wielded_light_radius(_radius)
|
||||
max_wield_light_radius = _radius
|
||||
minetest.settings:set("cozylights_wielded_light_radius",_radius)
|
||||
cozylights.max_wield_light_radius = _radius
|
||||
end
|
||||
|
||||
--ffi.cdef([[
|
||||
--typedef struct {float x, y, z;} v3float;
|
||||
--typedef struct {int16_t x, y, z;} v3;
|
||||
--typedef struct {uint16_t* data; uint8_t* param2data;} vm_data;
|
||||
--vm_data l_ttt(
|
||||
-- v3* sphere_surface, int sphere_surface_length, v3 pos, v3 minp, v3 maxp, uint16_t radius, uint16_t* data, uint8_t* param2data,
|
||||
-- uint8_t* dim_levels, bool* cozycids_sunlight, int c_air, uint16_t* c_lights
|
||||
--);
|
||||
--]])
|
||||
--local ctest = ffi.load(cozylights.modpath.."/liblight.so")
|
||||
|
||||
function cozylights:draw_wielded_light(pos, last_pos, cozy_item,vel,cozyplayer,vm,a,data,param2data,emin,emax)
|
||||
local t = os.clock()
|
||||
local update_needed = 0
|
||||
local radius, dim_levels = cozylights:calc_dims(cozy_item)
|
||||
radius = radius > max_wield_light_radius and max_wield_light_radius or radius
|
||||
if radius == 0 then
|
||||
destroy_stale_wielded_light(data,param2data,a,cozyplayer)
|
||||
local node = minetest.get_node(pos)
|
||||
if node.name == "air" or string.match(node.name,"cozylights:") then
|
||||
local brightness_mod = cozy_item.modifiers ~= nil and cozylights.coziest_table[cozy_item.modifiers].brightness or 0
|
||||
local max_light = mf(cozy_item.light_source + cozylights.brightness_factor + brightness_mod) > 0 and mf(cozy_item.light_source + cozylights.brightness_factor + brightness_mod) or 0
|
||||
max_light = max_light > 14 and 14 or max_light
|
||||
local cid = minetest.get_content_id("cozylights:light"..max_light)
|
||||
if cid > minetest.get_content_id(node.name) then
|
||||
minetest.set_node(pos,{name="cozylights:light"..max_light,param2=node.param2})
|
||||
cozyplayer.prev_wielded_lights[#cozyplayer.prev_wielded_lights+1] = pos
|
||||
end
|
||||
else
|
||||
pos.y = pos.y - 1
|
||||
local n_name = minetest.get_node(pos).name
|
||||
if n_name == "air" or string.match(n_name,"cozylights:") then
|
||||
local brightness_mod = cozy_item.modifiers ~= nil and cozylights.coziest_table[cozy_item.modifiers].brightness or 0
|
||||
local max_light = mf(cozy_item.light_source + cozylights.brightness_factor + brightness_mod) > 0 and mf(cozy_item.light_source + cozylights.brightness_factor + brightness_mod) or 0
|
||||
max_light = max_light > 14 and 14 or max_light
|
||||
local cid = minetest.get_content_id("cozylights:light"..max_light)
|
||||
if cid > minetest.get_content_id(node.name) then
|
||||
minetest.set_node(pos,{name="cozylights:light"..max_light,param2=node.param2})
|
||||
cozyplayer.prev_wielded_lights[#cozyplayer.prev_wielded_lights+1] = pos
|
||||
end
|
||||
end
|
||||
end
|
||||
return
|
||||
end
|
||||
local possible_pos = vector.add(pos,vel)
|
||||
local node = minetest.get_node(possible_pos)
|
||||
if node.name == "air" or string.match(node.name, "cozylights:light") then
|
||||
pos = possible_pos
|
||||
end
|
||||
|
||||
if vm == nil then
|
||||
vm = minetest.get_voxel_manip()
|
||||
local distance = vector.distance(pos,last_pos)
|
||||
if distance < 20 then
|
||||
local pos1 = {
|
||||
x=pos.x < last_pos.x and pos.x or last_pos.x,
|
||||
y=pos.y < last_pos.y and pos.y or last_pos.y,
|
||||
z=pos.z < last_pos.z and pos.z or last_pos.z,
|
||||
}
|
||||
local pos2 = {
|
||||
x=pos.x > last_pos.x and pos.x or last_pos.x,
|
||||
y=pos.y > last_pos.y and pos.y or last_pos.y,
|
||||
z=pos.z > last_pos.z and pos.z or last_pos.z,
|
||||
}
|
||||
emin, emax = vm:read_from_map(vector.subtract(pos1, radius+1), vector.add(pos2, radius+1))
|
||||
else
|
||||
emin, emax = vm:read_from_map(vector.subtract(pos, radius+1), vector.add(pos, radius+1))
|
||||
end
|
||||
data = vm:get_data()
|
||||
param2data = vm:get_param2_data()
|
||||
a = VoxelArea:new{
|
||||
MinEdge = emin,
|
||||
MaxEdge = emax
|
||||
}
|
||||
update_needed = 1
|
||||
end
|
||||
destroy_stale_wielded_light(data,param2data,a,cozyplayer)
|
||||
|
||||
local c_light14 = c_lights[14]
|
||||
local sphere_surface = cozylights:get_sphere_surface(radius)
|
||||
local px = pos.x
|
||||
local py = pos.y
|
||||
local pz = pos.z
|
||||
local y_below = py - 1
|
||||
local y_above = py + 1
|
||||
local cidb = data[a:index(px,y_below,pz)]
|
||||
local cida = data[a:index(px,y_above,pz)]
|
||||
if cidb and cida then
|
||||
if (cidb == c_air or (cidb >= c_light1 and cidb <= c_light14))
|
||||
and cida ~= c_air and (cida < c_light1 or cida > c_light14)
|
||||
then
|
||||
py = py - 1
|
||||
end
|
||||
else
|
||||
return
|
||||
end
|
||||
local zstride, ystride = a.zstride, a.ystride
|
||||
local dirs = { -1*ystride, 1*ystride,-1,1,-1*zstride,1*zstride}
|
||||
--[[--cdata experiments, so if we offload heavy lifting on c, it will actually be slower by 20%
|
||||
--not even a bit faster, so i d rather not continue on this
|
||||
--because vm:set_data works with lua state and expects lua table,
|
||||
--and interpreting c types back to lua table seems to be ridiculously expensive to bother
|
||||
--basically lua is useless and helpless without lua state
|
||||
minetest.chat_send_all("jit.status() "..cozylights:dump(jit.status()))
|
||||
local csphere_surface = ffi.new("v3struct["..(#sphere_surface+1).."]", sphere_surface)
|
||||
local cpos = ffi.new("v3struct", pos)
|
||||
local cemin = ffi.new("v3struct",emin)
|
||||
local cemax = ffi.new("v3struct",emax)
|
||||
local cradius = ffi.new("int",radius)
|
||||
local testcdata = ffi.new("uint16_t["..(#data).."]")
|
||||
local cdim_levels = ffi.new("uint16_t["..(#dim_levels+1).."]", dim_levels)
|
||||
local cc_air = ffi.new("int",c_air)
|
||||
local cc_lights = ffi.new("uint16_t["..(#c_lights+1).."]", c_lights)
|
||||
for i = 1, #data do
|
||||
testcdata[i-1] = ffi.new("uint16_t",data[i])
|
||||
end
|
||||
local cparam2data = ffi.new("uint16_t["..#param2data.."]")
|
||||
for i = 1, #param2data do
|
||||
cparam2data[i-1] = ffi.new("uint16_t",param2data[i])
|
||||
end
|
||||
local ccozycids = ffi.new("bool["..#cozycids_sunlight_propagates.."]",cozycids_sunlight_propagates)
|
||||
local length = ffi.new("int",#sphere_surface)
|
||||
local idk = (ctest.l_ttt(csphere_surface,length, cpos,cemin,cemax,cradius,testcdata,cparam2data,cdim_levels,ccozycids,cc_air,cc_lights))
|
||||
idk = idk.data
|
||||
if idk ~= nil then
|
||||
for i=0,#data do
|
||||
local incoming = tonumber(idk[i])
|
||||
if data[i+1] ~= incoming then
|
||||
data[i+1] = incoming
|
||||
table.insert(cozyplayer.prev_wielded_lights, a:position(i+1))
|
||||
end
|
||||
end
|
||||
end
|
||||
for i = 1, #param2data do
|
||||
param2data[i] = tonumber(cparam2data[i-1])
|
||||
end]]
|
||||
|
||||
for i,pos2 in ipairs(sphere_surface) do
|
||||
lightcast_lite(pos, vector.direction(pos,{x=px+pos2.x,y=py+pos2.y,z=pz+pos2.z}),dirs,radius,data,param2data,a,dim_levels,cozyplayer)
|
||||
end
|
||||
if update_needed == 1 then
|
||||
cozylights:setVoxelManipData(vm,data,param2data,true)
|
||||
end
|
||||
cozyplayer.last_wield_radius = radius
|
||||
gent_total = gent_total + mf((os.clock() - t) * 1000)
|
||||
gent_count = gent_count + 1
|
||||
--print("Av wield illum time " .. mf(gent_total/gent_count) .. " ms. Sample of: "..gent_count)
|
||||
end
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue