summaryrefslogtreecommitdiff
path: root/init.lua
diff options
context:
space:
mode:
authorLNJ <git@lnj.li>2017-03-26 16:17:48 +0200
committerLNJ <git@lnj.li>2017-03-26 16:17:48 +0200
commit4c3dd28fcd8c9cf89b8d58df53766c4d5a10cea9 (patch)
treef8aaae894617d2ef7a8f83b4eae3949fde87145b /init.lua
Inital Commit
Diffstat (limited to 'init.lua')
-rw-r--r--init.lua341
1 files changed, 341 insertions, 0 deletions
diff --git a/init.lua b/init.lua
new file mode 100644
index 0000000..5ae8718
--- /dev/null
+++ b/init.lua
@@ -0,0 +1,341 @@
+--[[
+Minetest Mod Drawers - A Mod adding storage drawers
+
+Copyright (C) 2017 LNJ <git@lnj.li>
+Copyright (C) 2016 Mango Tango <mtango688@gmail.com>
+
+MIT License
+
+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.
+]]
+
+drawers = {}
+
+drawers.node_box_simple = {
+ {-0.5, -0.5, -0.4375, 0.5, 0.5, 0.5},
+ {-0.5, -0.5, -0.5, -0.4375, 0.5, -0.4375},
+ {0.4375, -0.5, -0.5, 0.5, 0.5, -0.4375},
+ {-0.4375, 0.4375, -0.5, 0.4375, 0.5, -0.4375},
+ {-0.4375, -0.5, -0.5, 0.4375, -0.4375, -0.4375},
+}
+
+local function gen_info_text(basename, count, factor, stack_max)
+ -- in the end it should look like:
+ -- Sand [4x99+43 / 24x99]
+ -- bot NOT so:
+ -- Dirt [2x99 + 0 / 24x99]
+ local countstr = tostring(math.floor(count / stack_max)) .. "x" ..
+ stack_max
+ if count % stack_max ~= 0 then
+ countstr = countstr .. " + " .. count % stack_max
+ end
+ return basename .. " [" .. countstr .. " / " .. factor .. "x" .. stack_max .. "]"
+end
+
+local function get_inv_image(name)
+ local texture = default_texture
+ local def = minetest.registered_items[name]
+ if name ~= "air" and def then
+ if def.inventory_image and #def.inventory_image > 0 then
+ texture = def.inventory_image
+ else
+ local c = #def.tiles
+ local x = {}
+ for i, v in ipairs(def.tiles) do
+ if type(v) == "table" then
+ x[i] = v.name
+ else
+ x[i] = v
+ end
+ i = i + 1
+ end
+ if not x[3] then x[3] = x[1] end
+ if not x[4] then x[4] = x[3] end
+ texture = core.inventorycube(x[1], x[3], x[4])
+ end
+ end
+ return texture
+end
+
+core.register_entity("drawers:visual", {
+ initial_properties = {
+ hp_max = 1,
+ physical = false,
+ collide_with_objects = false,
+ collisionbox = {-0.4374, -0.4374, 0, 0.4374, 0.4374, 0}, -- for param2 0, 2
+ visual = "upright_sprite", -- "wielditem" for items without inv img?
+ visual_size = {x = 0.6, y = 0.6},
+ textures = {"drawers_empty.png"},
+ spritediv = {x = 1, y = 1},
+ initial_sprite_basepos = {x = 0, y = 0},
+ is_visible = true,
+ },
+
+ get_staticdata = function(self)
+ return core.serialize({
+ drawer_posx = self.drawer_pos.x,
+ drawer_posy = self.drawer_pos.y,
+ drawer_posz = self.drawer_pos.z,
+ texture = self.texture
+ })
+ end,
+
+ on_activate = function(self, staticdata, dtime_s)
+ -- Restore data
+ data = core.deserialize(staticdata)
+ if data then
+ self.drawer_pos = {
+ x = data.drawer_posx,
+ y = data.drawer_posy,
+ z = data.drawer_posz,
+ }
+ self.texture = data.texture
+ else
+ self.drawer_pos = drawers.last_drawer_pos
+ self.texture = "drawers_empty.png"
+ end
+
+
+ local node = core.get_node(self.drawer_pos)
+
+ -- collisionbox
+ local colbox = {-0.4374, -0.4374, 0, 0.4374, 0.4374, 0} -- for param2 = 0 or 2
+ if node.param2 == 1 or node.param2 == 3 then
+ colbox = {0, -0.4374, -0.4374, 0, 0.4374, 0.4374}
+ end
+
+
+ -- infotext
+ local meta = core.get_meta(self.drawer_pos)
+ local infotext = meta:get_string("entity_infotext") .. "\n\n\n\n\n"
+
+ self.object:set_properties({
+ collisionbox = colbox,
+ infotext = infotext,
+ textures = {self.texture}
+ })
+
+ -- make entity undestroyable
+ self.object:set_armor_groups({immortal = 1})
+ end,
+
+ on_rightclick = function(self, clicker)
+ local node = core.get_node(self.drawer_pos)
+ local itemstack = clicker:get_wielded_item()
+ local add_count = itemstack:get_count()
+ local add_name = itemstack:get_name()
+
+ local meta = core.get_meta(self.drawer_pos)
+ local name = meta:get_string("name")
+ local count = meta:get_int("count")
+ local max_count = meta:get_int("max_count")
+
+ local base_stack_max = meta:get_int("base_stack_max")
+ local stack_max_factor = meta:get_int("stack_max_factor")
+
+ -- if nothing to be added, return
+ if add_count <= 0 then return end
+ -- if no itemstring, return
+ if item_name == "" then return end
+
+ -- only add one, if player holding sneak key
+ if clicker:get_player_control().sneak then
+ add_count = 1
+ end
+
+ -- if current itemstring is not empty
+ if name ~= "" then
+ -- check if same item
+ if add_name ~= name then return end
+ else -- is empty
+ name = add_name
+ meta:set_string("name", name)
+ count = 0
+
+ -- get new stack max
+ base_stack_max = ItemStack(name):get_stack_max()
+ meta:set_int("base_stack_max", base_stack_max)
+ max_count = base_stack_max * stack_max_factor
+ meta:set_int("max_count", max_count)
+ end
+
+ -- set new counts:
+ -- if new count is more than max_count
+ if (count + add_count) > max_count then
+ count = max_count
+ itemstack:set_count((count + add_count) - max_count)
+ else -- new count fits
+ count = count + add_count
+ itemstack:set_count(itemstack:get_count() - add_count)
+ end
+ -- set new drawer count
+ meta:set_int("count", count)
+
+ -- update infotext
+ local infotext = gen_info_text(core.registered_items[name].description,
+ count, stack_max_factor, base_stack_max)
+ meta:set_string("entity_infotext", infotext)
+
+ -- texture
+ self.texture = get_inv_image(name)
+
+ self.object:set_properties({
+ infotext = infotext .. "\n\n\n\n\n",
+ textures = {self.texture}
+ })
+
+ clicker:set_wielded_item(itemstack)
+ end,
+
+ on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir)
+ local meta = minetest.get_meta(self.drawer_pos)
+ local count = meta:get_int("count")
+
+ if count <= 0 then
+ return
+ end
+ local name = meta:get_string("name")
+
+ local remove_count = 1
+ if not puncher:get_player_control().sneak then
+ remove_count = ItemStack(name):get_stack_max()
+ end
+ if remove_count > count then remove_count = count end
+
+ local stack = ItemStack(name)
+ stack:set_count(remove_count)
+
+ local inv = puncher:get_inventory()
+ if not inv:room_for_item("main", stack) then
+ return
+ end
+
+ inv:add_item("main", stack)
+ count = count - remove_count
+ meta:set_int("count", count)
+
+ -- update infotext
+ local stack_max_factor = meta:get_int("stack_max_factor")
+ local base_stack_max = meta:get_int("base_stack_max")
+ local item_description = ""
+ if core.registered_items[name] then
+ item_description = core.registered_items[name].description
+ end
+
+ if count <= 0 then
+ meta:set_string("name", "")
+ self.texture = "drawers_empty.png"
+ item_description = "Empty"
+ end
+
+ local infotext = gen_info_text(item_description,
+ count, stack_max_factor, base_stack_max)
+ meta:set_string("entity_infotext", infotext)
+
+ self.object:set_properties({
+ infotext = infotext .. "\n\n\n\n\n",
+ textures = {self.texture}
+ })
+ end
+})
+
+-- construct drawer
+local function drawer_on_construct(pos)
+ local node = core.get_node(pos)
+ local ndef = core.registered_nodes[node.name]
+
+ local base_stack_max = core.nodedef_default.stack_max or 99
+ local stack_max_factor = ndef.drawer_stack_max_factor or 24 -- 3x8
+
+ -- meta
+ local meta = core.get_meta(pos)
+ meta:set_string("name", "")
+ meta:set_int("count", 0)
+ meta:set_int("max_count", base_stack_max * stack_max_factor)
+ meta:set_int("stack_max_factor", stack_max_factor)
+ meta:set_int("base_stack_max", base_stack_max)
+ meta:set_string("ntt_infotext", gen_info_text("Empty", 0,
+ stack_max_factor, base_stack_max))
+
+
+ -- data for the new visual
+ drawers.last_drawer_pos = pos
+
+ local bdir = core.facedir_to_dir(node.param2)
+ local fdir = vector.new(-bdir.x, 0, -bdir.z)
+ local pos2 = vector.add(pos, vector.multiply(fdir, 0.438))
+
+ obj = core.add_entity(pos2, "drawers:visual")
+
+ if bdir.x < 0 then obj:setyaw(0.5 * math.pi) end
+ if bdir.z < 0 then obj:setyaw(math.pi) end
+ if bdir.x > 0 then obj:setyaw(1.5 * math.pi) end
+end
+
+-- destruct drawer
+local function drawer_on_destruct(pos)
+ local objs = core.get_objects_inside_radius(pos, 0.5)
+ if objs then
+ for _, obj in pairs(objs) do
+ if obj and obj:get_luaentity() and
+ obj:get_luaentity().name == "drawers:visual" then
+ obj:remove()
+ return
+ end
+ end
+ end
+end
+
+-- drop all items
+local function drawer_on_dig(pos, node, player)
+ core.node_dig(pos, node, player)
+ return
+end
+
+function drawers.register_drawer(name, def)
+ def.description = def.description or "Drawer"
+ def.drawtype = "nodebox"
+ def.node_box = {type = "fixed", fixed = drawers.node_box_simple}
+ def.collision_box = {type = "regular"}
+ def.selection_box = {type = "regular"}
+ def.tiles = def.tiles or {"default_wood.png"}
+ def.paramtype = "light"
+ def.paramtype2 = "facedir"
+ def.legacy_facedir_simple = true
+ def.groups = def.groups or {}
+ def.groups.drawer = def.groups.drawer or 1
+ def.drawer_stack_max_factor = def.drawer_stack_max_factor or 24
+
+ -- events
+ def.on_construct = drawer_on_construct
+ def.on_destruct = drawer_on_destruct
+ def.on_dig = drawer_on_dig
+
+ if screwdriver then
+ def.on_rotate = def.on_rotate or screwdriver.disallow
+ end
+
+ core.register_node(name, def)
+end
+
+drawers.register_drawer("drawers:wood", {
+ description = "Wooden Drawer",
+ groups = {choppy = 3},
+ drawer_stack_max_factor = 3 * 8 -- normal chest size
+})