Battery and Server added

Further improvements
This commit is contained in:
Joachim Stolberg 2018-06-26 23:04:25 +02:00
parent 7babb6c89f
commit 7d22092657
12 changed files with 298 additions and 68 deletions

@ -12,7 +12,7 @@
]]-- ]]--
safer_lua.MaxCodeSize = 1000 -- size in length of byte code safer_lua.MaxCodeSize = 2000 -- size in length of byte code
safer_lua.MaxTableSize = 1000 -- number of table entries considering string lenghts safer_lua.MaxTableSize = 1000 -- number of table entries considering string lenghts

@ -35,6 +35,7 @@ safer_lua.StoreHelp = [[
tbl.set(key, value) --> add/set a value tbl.set(key, value) --> add/set a value
tbl.get(key) --> read a value tbl.get(key) --> read a value
tbl.size() --> return the table size tbl.size() --> return the table size
tbl.capa() --> return the max. capacity
tbl.insert(pos, value) --> insert into list tbl.insert(pos, value) --> insert into list
tbl.remove(pos) --> return and remove from list tbl.remove(pos) --> return and remove from list
tbl.sort() -- sort list tbl.sort() -- sort list
@ -79,14 +80,27 @@ function safer_lua.Store(...)
end end
new_t.set = function(k,v) new_t.set = function(k,v)
if type(k) == "string" or type(k) == "number" then if type(k) == "number" then
Count = Count - mt.count(rawget(new_t.__data__, k))
local cnt = mt.count(v) local cnt = mt.count(v)
if cnt then cnt = cnt - mt.count(rawget(new_t.__data__, k))
Count = Count + cnt if Count + cnt < safer_lua.MaxTableSize then
if Count < safer_lua.MaxTableSize then
rawset(new_t.__data__,k,v) rawset(new_t.__data__,k,v)
Count = Count + cnt
end end
elseif type(k) == "string" then
local cnt = mt.count(rawget(new_t.__data__, k))
if cnt == 0 then -- new entry?
cnt = mt.count(v)
cnt = cnt + mt.count(k)
elseif v == nil then -- delete entry?
cnt = - cnt - mt.count(k)
else -- overwrite
cnt = mt.count(v) - cnt
end
if Count + cnt < safer_lua.MaxTableSize then
rawset(new_t.__data__,k,v)
Count = Count + cnt
end end
end end
end end
@ -99,14 +113,16 @@ function safer_lua.Store(...)
return Count return Count
end end
new_t.capa = function(t)
return safer_lua.MaxTableSize
end
new_t.insert = function(v, i) new_t.insert = function(v, i)
local cnt = mt.count(v) local cnt = mt.count(v)
if cnt then
Count = Count + cnt
if i == nil then i = #new_t.__data__ + 1 end if i == nil then i = #new_t.__data__ + 1 end
if Count < safer_lua.MaxTableSize then if Count + cnt < safer_lua.MaxTableSize then
table.insert(new_t.__data__,i,v) table.insert(new_t.__data__,i,v)
end Count = Count + cnt
end end
end end

@ -12,10 +12,15 @@
]]-- ]]--
local function calc_percent(content)
local val = (sl_controller.battery_capacity -
math.min(content or 0, sl_controller.battery_capacity))
return 100 - math.floor((val * 100.0 / sl_controller.battery_capacity))
end
local function on_timer(pos, elapsed) local function on_timer(pos, elapsed)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
local percent = (sl_controller.battery_capacity - meta:get_int("content")) local percent = calc_percent(meta:get_int("content"))
percent = 100 - math.floor((percent * 100.0 / sl_controller.battery_capacity))
meta:set_string("infotext", "Battery ("..percent.."%)") meta:set_string("infotext", "Battery ("..percent.."%)")
if percent == 0 then if percent == 0 then
local node = minetest.get_node(pos) local node = minetest.get_node(pos)
@ -26,7 +31,8 @@ local function on_timer(pos, elapsed)
return true return true
end end
minetest.register_node("sl_controller:battery", { local function register_battery(ext, percent)
minetest.register_node("sl_controller:battery"..ext, {
description = "Battery", description = "Battery",
inventory_image = 'sl_controller_battery_inventory.png', inventory_image = 'sl_controller_battery_inventory.png',
wield_image = 'sl_controller_battery_inventory.png', wield_image = 'sl_controller_battery_inventory.png',
@ -50,13 +56,37 @@ minetest.register_node("sl_controller:battery", {
after_place_node = function(pos, placer) after_place_node = function(pos, placer)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
meta:set_int("content", sl_controller.battery_capacity) meta:set_int("content", sl_controller.battery_capacity * percent)
local node = minetest.get_node(pos)
node.name = "sl_controller:battery"
minetest.swap_node(pos, node)
on_timer(pos, 1) on_timer(pos, 1)
minetest.get_node_timer(pos):start(30) minetest.get_node_timer(pos):start(30)
end, end,
on_timer = on_timer, on_timer = on_timer,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
local percent = calc_percent(tonumber(oldmetadata.fields.content))
print("percent", percent)
local stack
if percent > 95 then
stack = ItemStack("sl_controller:battery")
elseif percent > 75 then
stack = ItemStack("sl_controller:battery75")
elseif percent > 50 then
stack = ItemStack("sl_controller:battery50")
elseif percent > 25 then
stack = ItemStack("sl_controller:battery25")
else
return
end
print("percent", percent)
local inv = minetest.get_inventory({type="player", name=digger:get_player_name()})
inv:add_item("main", stack)
end,
paramtype = "light", paramtype = "light",
sunlight_propagates = true, sunlight_propagates = true,
paramtype2 = "facedir", paramtype2 = "facedir",
@ -65,6 +95,12 @@ minetest.register_node("sl_controller:battery", {
is_ground_content = false, is_ground_content = false,
sounds = default.node_sound_stone_defaults(), sounds = default.node_sound_stone_defaults(),
}) })
end
register_battery("", 1.0)
register_battery("75", 0.75)
register_battery("50", 0.5)
register_battery("25", 0.25)
minetest.register_node("sl_controller:battery_empty", { minetest.register_node("sl_controller:battery_empty", {
description = "Battery", description = "Battery",

@ -1,2 +1,2 @@
-- Battery capacity in usec CPU time -- Battery capacity in usec CPU time
sl_controller.battery_capacity = tonumber(minetest.setting_get("battery_capacity")) or 10000000 sl_controller.battery_capacity = tonumber(minetest.setting_get("battery_capacity")) or 5000000

@ -21,7 +21,12 @@ SaferLua is a subset of Lua with the following restrictions:
- Store() as alternative to Lua tables - Store() as alternative to Lua tables
The controller needs a battery nearby. The controller needs a battery nearby.
Don't remove the battery, it will be destroyed!
The controller will be restarted with every
server start. That means, init() will be
called again and all variables are reset.
To store the data non-volatile, use a Server.
commands: $server_read(), $server_write().
See: goo.gl/WRWZgt See: goo.gl/WRWZgt
]] ]]
@ -189,7 +194,7 @@ local function compile(pos, meta, number)
local loop = meta:get_string("loop") local loop = meta:get_string("loop")
local owner = meta:get_string("owner") local owner = meta:get_string("owner")
local env = table.copy(tCommands) local env = table.copy(tCommands)
env.meta = {pos=pos, owner=owner, number=number} env.meta = {pos=pos, owner=owner, number=number, error=error}
local code = safer_lua.init(pos, init, loop, env, error) local code = safer_lua.init(pos, init, loop, env, error)
if code then if code then
@ -282,12 +287,8 @@ local function on_timer(pos, elapsed)
no_battery(pos) no_battery(pos)
return false return false
end end
else
stop_controller(pos)
end end
return res return res
else
stop_controller(pos)
end end
return false return false
end end
@ -329,6 +330,8 @@ local function on_receive_fields(pos, formname, fields, player)
meta:set_string("formspec", formspec5(sFunctionList, 1, sHELP)) meta:set_string("formspec", formspec5(sFunctionList, 1, sHELP))
elseif fields.start == "Start" then elseif fields.start == "Start" then
start_controller(pos) start_controller(pos)
minetest.log("action", player:get_player_name() ..
" starts the sl_controller at ".. minetest.pos_to_string(pos))
elseif fields.stop == "Stop" then elseif fields.stop == "Stop" then
stop_controller(pos) stop_controller(pos)
elseif fields.functions then elseif fields.functions then

@ -16,3 +16,4 @@ dofile(minetest.get_modpath("sl_controller") .. "/config.lua")
dofile(minetest.get_modpath("sl_controller") .. "/controller.lua") dofile(minetest.get_modpath("sl_controller") .. "/controller.lua")
dofile(minetest.get_modpath("sl_controller") .. "/commands.lua") dofile(minetest.get_modpath("sl_controller") .. "/commands.lua")
dofile(minetest.get_modpath("sl_controller") .. "/battery.lua") dofile(minetest.get_modpath("sl_controller") .. "/battery.lua")
dofile(minetest.get_modpath("sl_controller") .. "/server.lua")

@ -1,4 +1,4 @@
SaferLua Controller [sl_controller] v0.01 SaferLua Controller [sl_controller] v0.02
========================================= =========================================
@ -17,3 +17,4 @@ tubelib, safer_lua
### History ### History
- 2018-06-24 v0.01 * first draft - 2018-06-24 v0.01 * first draft
- 2018-06-26 v0.02 * Battery and Server added

173
sl_controller/server.lua Normal file

@ -0,0 +1,173 @@
--[[
sl_controller
=============
Copyright (C) 2018 Joachim Stolberg
LGPLv2.1+
See LICENSE.txt for more information
server.lua:
]]--
local SERVER_CAPA = 5000
local DEFAULT_MEM = {
size=0,
data={
version = 1,
info = "SaferLua key/value Server",
}
}
local function on_time(pos, elasped)
local meta = minetest.get_meta(pos)
local number = meta:get_string("number")
local mem = tubelib.get_data(number, "memory") or DEFAULT_MEM
meta:set_string("infotext", "Server "..number..": ("..(mem.size or 0).."/"..SERVER_CAPA..")")
return true
end
minetest.register_node("sl_controller:server", {
description = "Central Server",
tiles = {
-- up, down, right, left, back, front
"sl_controller_server_top.png",
"sl_controller_server_top.png",
"sl_controller_server_side.png",
"sl_controller_server_side.png^[transformFX",
"sl_controller_server_back.png",
{
image = "sl_controller_server_front.png",
backface_culling = false,
animation = {
type = "vertical_frames",
aspect_w = 32,
aspect_h = 32,
length = 1,
},
},
},
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {
{ -3/16, -8/16, -7/16, 3/16, 6/16, 7/16},
},
},
after_place_node = function(pos, placer)
local meta = minetest.get_meta(pos)
local number = tubelib.add_node(pos, "sl_controller:server")
meta:set_string("owner", placer:get_player_name())
meta:set_string("number", number)
tubelib.set_data(number, "memory", DEFAULT_MEM)
on_time(pos, 0)
minetest.get_node_timer(pos):start(20)
end,
on_dig = function(pos, node, puncher, pointed_thing)
if minetest.is_protected(pos, puncher:get_player_name()) then
return
end
minetest.node_dig(pos, node, puncher, pointed_thing)
tubelib.remove_node(pos)
end,
on_timer = on_time,
paramtype = "light",
sunlight_propagates = true,
paramtype2 = "facedir",
groups = {choppy=1, cracky=1, crumbly=1},
drop = "",
is_ground_content = false,
sounds = default.node_sound_stone_defaults(),
})
minetest.register_craft({
output = "sl_controller:server",
recipe = {
{"", "", ""},
{"default:mese_crystal_fragment", "tubelib:wlanchip", "default:mese_crystal_fragment"},
{"", "default:copper_ingot", ""},
},
})
local function calc_size(v)
if type(v) == "number" then
return 1
elseif v == nil then
return 0
elseif type(v) == "string" then
return #v
else
return nil
end
end
local function write_value(mem, key, value)
if mem and mem.size < SERVER_CAPA then
if value == nil then
mem.size = mem.size - calc_size(mem.data[key])
else
mem.size = mem.size - calc_size(mem.data[key])
mem.size = mem.size + calc_size(value)
end
mem.data[key] = value
end
end
tubelib.register_node("sl_controller:server", {}, {
on_recv_message = function(pos, topic, payload)
local meta = minetest.get_meta(pos)
if meta then
local number = meta:get_string("number")
local mem = tubelib.get_data(number, "memory") or DEFAULT_MEM
if topic == "read" then
return mem.data[payload]
elseif topic == "write" then
write_value(mem, payload.key, payload.value)
tubelib.set_data(number, "memory", mem)
else
return "unsupported"
end
end
end,
})
sl_controller.register_function("server_read", {
cmnd = function(self, num, key)
if type(key) == "string" then
return tubelib.send_request(num, "read", key)
else
self.error("Invalid server_read parameter")
end
end,
help = " $server_read(num, key)\n"..
" Read a value from the server.\n"..
" 'key' must be a string.\n"..
' example: state = $server_read("0123", "state")'
})
sl_controller.register_action("server_write", {
cmnd = function(self, num, key, value)
if type(key) == "string" and type(value) == "string" or type(value) == "number" then
tubelib.send_message(num, self.meta.owner, nil, "write", {key=key, value=value})
else
self.error("Invalid server_write parameter")
end
end,
help = " $server_write(num, key, value)\n"..
" Store a value on the server under the key 'key'.\n"..
" 'key' must be a string. 'value' can be\n"..
" either a number or a string.\n"..
' example: $server_write("0123", "state", state)'
})

Binary file not shown.

After

Width:  |  Height:  |  Size: 351 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 265 B