master
BuckarooBanzay 2020-05-25 11:24:25 +02:00
commit 8a28882fb0
13 changed files with 289 additions and 0 deletions

17
.github/workflows/luacheck.yml vendored Normal file
View File

@ -0,0 +1,17 @@
name: luacheck
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: apt
run: sudo apt-get install -y luarocks
- name: luacheck install
run: luarocks install --local luacheck
- name: luacheck run
run: $HOME/.luarocks/bin/luacheck ./

19
.luacheckrc Normal file
View File

@ -0,0 +1,19 @@
globals = {
"area_effects"
}
read_globals = {
-- Stdlib
string = {fields = {"split"}},
table = {fields = {"copy", "getn"}},
-- Minetest
"minetest",
"vector", "ItemStack",
"dump", "VoxelArea",
-- deps
"epic", "epic_skybox",
"screwdriver", "areas"
}

18
accessors.lua Normal file
View File

@ -0,0 +1,18 @@
-- setter / getter / lookup
function area_effects.set(id, value)
area_effects.area_data[id] = value
area_effects.save()
end
-- returns "xy" (the data) or nil
function area_effects.get(id)
return area_effects.area_data[id]
end
areas:registerOnRemove(function(id)
area_effects.area_data[id] = nil
area_effects.save()
end)

57
chatcommands.lua Normal file
View File

@ -0,0 +1,57 @@
local function format_data(data)
local str = ""
for k, v in pairs(data) do
str = str .. "+ " .. k .. " = '" .. v .. "'\n"
end
return str
end
minetest.register_chatcommand("area_effect_set", {
params = "<ID> <key> <value>",
description = "Sets an area attribute",
func = function(playername, param)
local _, _, id_str, key, value = string.find(param, "^([^%s]+)%s+([^%s])%s+(.*)$")
if id_str == nil or not key then
return true, "Invalid syntax!"
end
local id = tonumber(id_str)
if not id then
return true, "area-id is not numeric: " .. id_str
end
if not areas:isAreaOwner(id, playername) and
not minetest.check_player_privs(playername, { protection_bypas=true }) then
return true, "you are not the owner of area: " .. id
end
if value == "nil" or value == "false" then
value = nil
end
local data = area_effects.get(id) or {}
data[key] = value
area_effects.set(id, data)
return true, "Area " .. id .. "\n" .. format_data(data)
end,
})
minetest.register_chatcommand("area_effect_get", {
params = "<ID>",
description = "Returns the area attributes",
func = function(_, param)
if param == nil then
return true, "Invalid syntax!"
end
local id = tonumber(param)
if not id then
return true, "area-id is not numeric: " .. param
end
local data = epic.data_area.get(id)
return true, "Area " .. id .. "\n" .. format_data(data)
end
})

4
effects.lua Normal file
View File

@ -0,0 +1,4 @@
function area_effects.register_effect(key, description)
area_effects.effects[key] = description
end

16
hooks.lua Normal file
View File

@ -0,0 +1,16 @@
local hooks = {}
area_effects.register_hook = function(hook)
table.insert(hooks, hook)
end
area_effects.run_hook = function(name, params)
for _, hook in ipairs(hooks) do
local fn = hook[name]
if fn and type(fn) == "function" then
fn( unpack(params) )
end
end
end

22
init.lua Normal file
View File

@ -0,0 +1,22 @@
area_effects = {
-- local data
-- id -> {}
area_data = {},
-- key => description
effects = {}
}
local MP = minetest.get_modpath("area_effects")
dofile(MP.."/effects.lua")
dofile(MP.."/storage.lua")
dofile(MP.."/accessors.lua")
dofile(MP.."/transition.lua")
dofile(MP.."/hooks.lua")
dofile(MP.."/log.lua")
if minetest.get_modpath("epic_skybox") then
dofile(MP.."/integrations/epic_skybox.lua")
end

View File

@ -0,0 +1,23 @@
area_effects.register_effect("skybox", "names from /skybox_list")
area_effects.register_hook({
enter = function(player, id)
local data = area_effects.get(id)
if data.skybox then
for _, skyboxdef in ipairs(epic_skybox.list) do
if skyboxdef == data.skybox then
epic_skybox.set_skybox(player, skyboxdef)
break
end
end
end
end,
leave = function(player, id)
local data = area_effects.get(id)
if data.skybox then
epic_skybox.set_skybox(player)
end
end
})

18
log.lua Normal file
View File

@ -0,0 +1,18 @@
area_effects.register_hook({
enter = function(player, id)
local playername = player:get_player_name()
minetest.log("action",
"[area_effects] player '" .. playername .. "' " ..
"entered area " .. id
)
end,
leave = function(player, id)
local playername = player:get_player_name()
minetest.log("action",
"[area_effects] player '" .. playername .. "' " ..
"left area " .. id
)
end
})

4
mod.conf Normal file
View File

@ -0,0 +1,4 @@
name = area_effects
description = area based effects
depends = areas
optional_depends = epic_skybox

11
readme.md Normal file
View File

@ -0,0 +1,11 @@
Area based effects
# Chatcommands
## Skybox (epic_skybox)
* **/skybox_list** List available skyboxes
* **/area_effect_set skybox Plain Black** Set
* **/area_effect_get skybox** Get
* **/area_effect_set skybox false** Clear

33
storage.lua Normal file
View File

@ -0,0 +1,33 @@
-- area-based data service
-- stores data related to area-id's
-- use-case: area-based weather or effects
-- File writing / reading utilities
local wpath = minetest.get_worldpath()
local filename = wpath.."/area_effects.dat"
-- load data from disk
function area_effects.load()
local f = io.open(filename, "r")
if f == nil then return {} end
local t = f:read("*all")
f:close()
if t ~= "" and t ~= nil then
-- existing data found
area_effects.area_data = minetest.deserialize(t)
else
-- no saved data yet
area_effects.area_data = {}
end
end
-- save data to disk
function area_effects.save()
local f = io.open(filename, "w")
f:write(minetest.serialize(area_effects.area_data))
f:close()
end
area_effects.load()

47
transition.lua Normal file
View File

@ -0,0 +1,47 @@
-- playername -> { id = true }
local active = {}
-- cleanup
minetest.register_on_leaveplayer(function(player)
local playername = player:get_player_name()
active[playername] = nil
end)
local function check()
for _, player in ipairs(minetest.get_connected_players()) do
local ppos = player:get_pos()
local playername = player:get_player_name()
local active_entry = active[playername]
if not active_entry then
active_entry = {}
active[playername] = active_entry
end
local area_list = areas:getAreasAtPos(ppos)
local current_ids = {}
-- check areas
for id in pairs(area_list) do
current_ids[id] = true
if not active_entry[id] then
-- player entered
area_effects.run_hook("enter", { player, id })
end
end
-- check previous area-ids
for id in pairs(active_entry) do
if not current_ids[id] then
-- player left
area_effects.run_hook("leave", { player, id })
end
end
end
minetest.after(1, check)
end
minetest.after(1, check)