techage/basic_machines/forceload.lua

215 lines
6.2 KiB
Lua
Raw Normal View History

2019-04-28 22:34:21 +03:00
--[[
2019-04-28 22:51:26 +03:00
TechAge
=======
2019-04-28 22:34:21 +03:00
2019-04-28 22:51:26 +03:00
Copyright (C) 2019 Joachim Stolberg
2019-04-28 22:34:21 +03:00
GPL v3
2019-04-28 22:34:21 +03:00
See LICENSE.txt for more information
2019-04-28 22:51:26 +03:00
Forceload block
2019-04-28 22:34:21 +03:00
]]--
-- for lazy programmers
local M = minetest.get_meta
local P2S = function(pos) if pos then return minetest.pos_to_string(pos) end end
local S = techage.S
2019-04-28 22:34:21 +03:00
local function calc_area(pos)
local xpos = (math.floor(pos.x / 16) * 16)
local ypos = (math.floor(pos.y / 16) * 16)
local zpos = (math.floor(pos.z / 16) * 16)
local pos1 = {x=xpos, y=ypos, z=zpos}
local pos2 = {x=xpos+15, y=ypos+15, z=zpos+15}
return pos1, pos2
end
local function in_list(list, x)
local pos1 = calc_area(x)
for _,v in ipairs(list) do
local pos2 = calc_area(v)
if vector.equals(pos1, pos2) then return true end
end
return false
end
local function remove_list_elem(list, x)
local n = nil
for idx, v in ipairs(list) do
if vector.equals(v, x) then
n = idx
break
end
end
if n then
table.remove(list, n)
end
return list
end
local function chat(player, text)
2019-04-28 22:51:26 +03:00
minetest.chat_send_player(player:get_player_name(), "[Techage] "..text)
2019-04-28 22:34:21 +03:00
end
local function add_pos(pos, player)
2019-04-28 22:51:26 +03:00
local lPos = minetest.deserialize(player:get_attribute("techage_forceload_blocks")) or {}
2019-06-09 18:20:40 +03:00
if not in_list(lPos, pos) and (#lPos < techage.max_num_forceload_blocks or
creative and creative.is_enabled_for and
creative.is_enabled_for(player:get_player_name())) then
2019-04-28 22:34:21 +03:00
lPos[#lPos+1] = pos
2019-04-28 22:51:26 +03:00
player:set_attribute("techage_forceload_blocks", minetest.serialize(lPos))
2019-04-28 22:34:21 +03:00
return true
end
return false
end
local function del_pos(pos, player)
2019-04-28 22:51:26 +03:00
local lPos = minetest.deserialize(player:get_attribute("techage_forceload_blocks")) or {}
2019-04-28 22:34:21 +03:00
lPos = remove_list_elem(lPos, pos)
2019-04-28 22:51:26 +03:00
player:set_attribute("techage_forceload_blocks", minetest.serialize(lPos))
2019-04-28 22:34:21 +03:00
end
local function get_pos_list(player)
2019-04-28 22:51:26 +03:00
return minetest.deserialize(player:get_attribute("techage_forceload_blocks")) or {}
2019-04-28 22:34:21 +03:00
end
local function set_pos_list(player, lPos)
2019-04-28 22:51:26 +03:00
player:set_attribute("techage_forceload_blocks", minetest.serialize(lPos))
2019-04-28 22:34:21 +03:00
end
local function get_data(pos, player)
local pos1, pos2 = calc_area(pos)
2019-04-28 22:51:26 +03:00
local num = #minetest.deserialize(player:get_attribute("techage_forceload_blocks")) or 0
local max = techage.max_num_forceload_blocks
2019-04-28 22:34:21 +03:00
return pos1, pos2, num, max
end
local function formspec(player)
local lPos = get_pos_list(player)
local tRes = {}
tRes[1] = "size[7,9]"..
default.gui_bg..
default.gui_bg_img..
default.gui_slots..
"label[0,0;List of your Forceload Blocks:]"
for idx,pos in ipairs(lPos) do
local pos1, pos2 = calc_area(pos)
local ypos = 0.2 + idx * 0.4
tRes[#tRes+1] = "label[0,"..ypos..";"..idx.."]"
tRes[#tRes+1] = "label[0.8,"..ypos..";"..P2S(pos1).."]"
2019-04-28 22:34:21 +03:00
tRes[#tRes+1] = "label[3.2,"..ypos..";to]"
tRes[#tRes+1] = "label[4,"..ypos..";"..P2S(pos2).."]"
2019-04-28 22:34:21 +03:00
end
return table.concat(tRes)
end
2019-04-28 22:51:26 +03:00
minetest.register_node("techage:forceload", {
description = "Techage Forceload Block",
2019-04-28 22:34:21 +03:00
tiles = {
-- up, down, right, left, back, front
2019-04-28 22:51:26 +03:00
'techage_filling_ta2.png^techage_frame_ta2_top.png',
'techage_filling_ta2.png^techage_frame_ta2_top.png',
2019-04-28 22:34:21 +03:00
{
2019-04-28 22:51:26 +03:00
image = "techage_filling_ta2.png^techage_frame_ta2_top.png^techage_appl_forceload.png",
2019-04-28 22:34:21 +03:00
backface_culling = false,
animation = {
type = "vertical_frames",
aspect_w = 32,
aspect_h = 32,
length = 0.5,
},
},
},
after_place_node = function(pos, placer, itemstack)
if add_pos(pos, placer) then
minetest.forceload_block(pos, true)
local pos1, pos2, num, max = get_data(pos, placer)
M(pos):set_string("infotext", "Area "..P2S(pos1).." to "..P2S(pos2).." loaded!\n"..
2019-04-28 22:34:21 +03:00
"Punch the block to make the area visible.")
chat(placer, "Area ("..num.."/"..max..") "..P2S(pos1).." to "..P2S(pos2).." loaded!")
2019-04-28 22:51:26 +03:00
techage.mark_region(placer:get_player_name(), pos1, pos2)
2019-04-28 22:34:21 +03:00
M(pos):set_string("owner", placer:get_player_name())
else
chat(placer, "Area already loaded or max. number of Forceload Blocks reached!")
minetest.remove_node(pos)
return itemstack
end
end,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
local player = minetest.get_player_by_name(oldmetadata.fields.owner)
if player then
del_pos(pos, player)
end
minetest.forceload_free_block(pos, true)
2019-04-28 22:51:26 +03:00
techage.unmark_region(oldmetadata.fields.owner)
2019-04-28 22:34:21 +03:00
end,
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
if M(pos):get_string("owner") == clicker:get_player_name() or
minetest.check_player_privs(clicker:get_player_name(), "server") then
local s = formspec(clicker)
2019-04-28 22:51:26 +03:00
minetest.show_formspec(clicker:get_player_name(), "techage:forceload", s)
2019-04-28 22:34:21 +03:00
end
end,
on_punch = function(pos, node, puncher, pointed_thing)
local pos1, pos2 = calc_area(pos)
2019-04-28 22:51:26 +03:00
techage.switch_region(puncher:get_player_name(), pos1, pos2)
2019-04-28 22:34:21 +03:00
end,
paramtype = "light",
sunlight_propagates = true,
groups = {choppy=2, cracky=2, crumbly=2,
2019-04-28 22:51:26 +03:00
not_in_creative_inventory = techage.max_num_forceload_blocks == 0 and 1 or 0},
2019-04-28 22:34:21 +03:00
is_ground_content = false,
sounds = default.node_sound_wood_defaults(),
})
2019-04-28 22:51:26 +03:00
if techage.max_num_forceload_blocks > 0 then
2019-04-28 22:34:21 +03:00
minetest.register_craft({
2019-04-28 22:51:26 +03:00
output = "techage:forceload",
2019-04-28 22:34:21 +03:00
recipe = {
{"group:wood", "", "group:wood"},
2019-06-17 22:24:48 +03:00
{"default:mese_crystal_fragment", "techage:usmium_nuggets", "default:mese_crystal_fragment"},
2019-04-28 22:51:26 +03:00
{"group:wood", "techage:iron_ingot", "group:wood"},
2019-04-28 22:34:21 +03:00
},
})
end
minetest.register_on_joinplayer(function(player)
local lPos = {}
for _,pos in ipairs(get_pos_list(player)) do
2019-06-09 01:25:25 +03:00
local node = techage.get_node_lvm(pos)
2019-04-28 22:51:26 +03:00
if node.name == "techage:forceload" then
2019-04-28 22:34:21 +03:00
minetest.forceload_block(pos, true)
lPos[#lPos+1] = pos
end
end
set_pos_list(player, lPos)
end)
minetest.register_on_leaveplayer(function(player)
for _,pos in ipairs(get_pos_list(player)) do
minetest.forceload_free_block(pos, true)
end
end)
techage.register_entry_page("ta", "forceload",
S("Techage Forceload Block"),
S("The Forceload Block keeps the corresponding area loaded and the machines operational "..
"as far as the player is logged in. If the player leaves the game, all areas will be unloaded.@n"..
"The maximum number of Forceload Blocks per player is configurable (default 16).@n"..
"The loaded area per block is a cube with 16 m side length (according to a Minetest area block). "..
"Punching the block makes the area visible and invisible again."),
"techage:forceload")