Who doesn't love hopper minecarts?

This commit is contained in:
ancientmarinerdev 2022-11-12 17:47:20 +00:00 committed by cora
parent c21527d207
commit ce457eb351
4 changed files with 223 additions and 30 deletions

View file

@ -2,6 +2,15 @@ mcl_entity_invs = {}
local open_invs = {} local open_invs = {}
local LOGGING_ON = minetest.settings:get_bool("mcl_logging_default",false)
local LOG_MODULE = "[Entity Invs]"
local function mcl_log (message)
if LOGGING_ON and message then
minetest.log(LOG_MODULE .. " " .. message)
end
end
local function check_distance(inv,player,count) local function check_distance(inv,player,count)
for _,o in pairs(minetest.get_objects_inside_radius(player:get_pos(),5)) do for _,o in pairs(minetest.get_objects_inside_radius(player:get_pos(),5)) do
local l = o:get_luaentity() local l = o:get_luaentity()
@ -22,20 +31,25 @@ local inv_callbacks = {
end, end,
} }
local function load_inv(ent,size) function mcl_entity_invs.load_inv(ent,size)
mcl_log("load_inv")
if not ent._inv_id then return end if not ent._inv_id then return end
mcl_log("load_inv 2")
local inv = minetest.get_inventory({type="detached", name=ent._inv_id}) local inv = minetest.get_inventory({type="detached", name=ent._inv_id})
if not inv then if not inv then
mcl_log("load_inv 3")
inv = minetest.create_detached_inventory(ent._inv_id, inv_callbacks) inv = minetest.create_detached_inventory(ent._inv_id, inv_callbacks)
inv:set_size("main", size) inv:set_size("main", size)
if ent._items then if ent._items then
inv:set_list("main",ent._items) inv:set_list("main",ent._items)
end end
else
mcl_log("load_inv 4")
end end
return inv return inv
end end
local function save_inv(ent) function mcl_entity_invs.save_inv(ent)
if ent._inv then if ent._inv then
ent._items = {} ent._items = {}
for i,it in ipairs(ent._inv:get_list("main")) do for i,it in ipairs(ent._inv:get_list("main")) do
@ -46,32 +60,60 @@ local function save_inv(ent)
end end
end end
local function load_default_formspec (ent, text)
text = text or ""
local invent_size = ent._inv_size
local div_by_two = invent_size % 2 == 0
local div_by_three = invent_size % 3 == 0
--mcl_log("Div by 3: ".. tostring(div_by_three))
--mcl_log("Div by 2: ".. tostring(div_by_two))
--mcl_log("invent_size: ".. tostring(invent_size))
local rows = 3
if invent_size > 18 or (div_by_three == true and invent_size > 8) then
--mcl_log("Div by 3")
rows = 3
elseif (div_by_two == true and invent_size > 3) or invent_size > 9 then
--mcl_log("Div by 2")
rows = 2
else
--mcl_log("Not div by 2 or 3")
rows = 1
end
--local rows = 3
local cols = (math.ceil(ent._inv_size/rows))
local spacing = (9 - cols) / 2
local formspec = "size[9,8.75]"
.. "label[0,0;" .. minetest.formspec_escape(
minetest.colorize("#313131", ent._inv_title .. " ".. text)) .. "]"
.. "list[detached:"..ent._inv_id..";main;"..spacing..",0.5;"..cols..","..rows..";]"
.. mcl_formspec.get_itemslot_bg(spacing,0.5,cols,rows)
.. "label[0,4.0;" .. minetest.formspec_escape(
minetest.colorize("#313131", "Inventory")) .. "]"
.. "list[current_player;main;0,4.5;9,3;9]"
.. mcl_formspec.get_itemslot_bg(0,4.5,9,3)
.. "list[current_player;main;0,7.74;9,1;]"
.. mcl_formspec.get_itemslot_bg(0,7.74,9,1)
.. "listring[detached:"..ent._inv_id..";main]"
.. "listring[current_player;main]"
return formspec
end
function mcl_entity_invs.show_inv_form(ent,player,text) function mcl_entity_invs.show_inv_form(ent,player,text)
if not ent._inv_id then return end if not ent._inv_id then return end
if not open_invs[ent] then if not open_invs[ent] then
open_invs[ent] = 0 open_invs[ent] = 0
end end
text = text or "" ent._inv = mcl_entity_invs.load_inv(ent,ent._inv_size)
ent._inv = load_inv(ent,ent._inv_size)
open_invs[ent] = open_invs[ent] + 1 open_invs[ent] = open_invs[ent] + 1
local playername = player:get_player_name() local playername = player:get_player_name()
local rows = 3
local cols = (math.ceil(ent._inv_size/rows)) minetest.show_formspec(playername, ent._inv_id, load_default_formspec (ent, text))
local spacing = (9 - cols) / 2
local formspec = "size[9,8.75]"
.. "label[0,0;" .. minetest.formspec_escape(
minetest.colorize("#313131", ent._inv_title .. " ".. text)) .. "]"
.. "list[detached:"..ent._inv_id..";main;"..spacing..",0.5;"..cols..","..rows..";]"
.. mcl_formspec.get_itemslot_bg(spacing,0.5,cols,rows)
.. "label[0,4.0;" .. minetest.formspec_escape(
minetest.colorize("#313131", "Inventory")) .. "]"
.. "list[current_player;main;0,4.5;9,3;9]"
.. mcl_formspec.get_itemslot_bg(0,4.5,9,3)
.. "list[current_player;main;0,7.74;9,1;]"
.. mcl_formspec.get_itemslot_bg(0,7.74,9,1)
.. "listring[detached:"..ent._inv_id..";main]"
.. "listring[current_player;main]"
minetest.show_formspec(playername,ent._inv_id,formspec)
end end
local function drop_inv(ent) local function drop_inv(ent)
@ -85,9 +127,9 @@ local function drop_inv(ent)
end end
local function on_remove(self,killer,oldf) local function on_remove(self,killer,oldf)
save_inv(self) mcl_entity_invs.save_inv(self)
drop_inv(self) drop_inv(self)
if oldf then return oldf(self,killer) end if oldf then return oldf(self,killer) end
end end
minetest.register_on_player_receive_fields(function(player, formname, fields) minetest.register_on_player_receive_fields(function(player, formname, fields)
@ -95,7 +137,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname == k._inv_id then if formname == k._inv_id then
open_invs[k] = open_invs[k] - 1 open_invs[k] = open_invs[k] - 1
if open_invs[k] < 1 then if open_invs[k] < 1 then
save_inv(k) mcl_entity_invs.save_inv(k)
open_invs[k] = nil open_invs[k] = nil
end end
end end
@ -151,7 +193,7 @@ function mcl_entity_invs.register_inv(entity_name,show_name,size,no_on_righclick
local old_ode = minetest.registered_entities[entity_name].on_deactivate local old_ode = minetest.registered_entities[entity_name].on_deactivate
minetest.registered_entities[entity_name].on_deactivate = function(self,removal) minetest.registered_entities[entity_name].on_deactivate = function(self,removal)
save_inv(self) mcl_entity_invs.save_inv(self)
if removal then if removal then
on_remove(self) on_remove(self)
end end

View file

@ -25,4 +25,10 @@ http://minetest.net/
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO. 0. You just DO WHAT THE FUCK YOU WANT TO.
---------
Alterations and contributions are released under GNU GPLv3 after 11/11/2022 and for contributors:
AncientMariner/ancientmarinerdev

View file

@ -6,6 +6,17 @@ local pool = {}
local tick = false local tick = false
local LOGGING_ON = minetest.settings:get_bool("mcl_logging_default",false)
local LOG_MODULE = "[Item entities]"
local function mcl_log (message)
if LOGGING_ON and message then
minetest.log(LOG_MODULE .. " " .. message)
end
end
minetest.register_on_joinplayer(function(player) minetest.register_on_joinplayer(function(player)
local name local name
name = player:get_player_name() name = player:get_player_name()
@ -375,6 +386,133 @@ local function cxcz(o, cw, one, zero)
return o return o
end end
local function hopper_take_item (self, pos)
--mcl_log("self.itemstring: ".. self.itemstring)
--local current_itemstack = nil
--if self.itemstring then
-- mcl_log("there is an itemstring")
-- current_itemstack = ItemStack(self.itemstring)
--else
-- mcl_log("no item string")
--end
--mcl_log("self.itemstring: ".. minetest.pos_to_string(pos))
--minetest.get_node(pos).name
local objs = minetest.get_objects_inside_radius(pos, 2)
if objs and self.itemstring then
--mcl_log("there is an itemstring. Number of objs: ".. #objs)
for k,v in pairs(objs) do
local ent = v:get_luaentity()
-- Don't forget actual hoppers
if ent and ent.name == "mcl_minecarts:hopper_minecart" then
local taken_items = false
-- Do we still need this def stuff
local node_def = minetest.registered_nodes[ent.name]
if node_def then
mcl_log("stack max: ".. tostring(node_def.get_stack_max()))
end
mcl_log("ent.name: ".. tostring(ent.name))
mcl_log("ent pos: ".. tostring(ent.object:get_pos()))
mcl_log("Inv id: " .. ent._inv_id)
local inv = mcl_entity_invs.load_inv(ent,5)
if not inv then
mcl_log("No inv")
return false
end
local current_itemstack = ItemStack(self.itemstring)
mcl_log("inv. size: " .. ent._inv_size)
if inv:room_for_item("main", current_itemstack) then
mcl_log("Room")
inv:add_item("main", current_itemstack)
self.object:get_luaentity().itemstring = ""
self.object:remove()
taken_items = true
else
mcl_log("no Room")
end
if not taken_items then
local items_remaining = current_itemstack:get_count()
-- This will take pat of a floating item stack
for i = 1, ent._inv_size,1 do
local stack1 = inv:get_stack("main", i)
mcl_log("i: " .. tostring(i))
mcl_log("Items remaining: " .. items_remaining)
mcl_log("Name: " .. tostring(stack1:get_name()))
if current_itemstack:get_name() == stack1:get_name() then
mcl_log("We have a match. Name: " .. tostring(stack1:get_name()))
local room_for = stack1:get_stack_max() - stack1:get_count()
mcl_log("Room for: " .. tostring(room_for))
if room_for == 0 then
-- Do nothing
mcl_log("No room")
elseif room_for < items_remaining then
mcl_log("We have more items remaining than space")
items_remaining = items_remaining - room_for
-- Set full stack
stack1:set_count(stack1:get_stack_max())
inv:set_stack("main", i, stack1)
taken_items = true
else
local new_stack_size = stack1:get_count() + items_remaining
mcl_log("We have more than enough space. Now holds: " .. new_stack_size)
stack1:set_count(new_stack_size)
inv:set_stack("main", i, stack1)
items_remaining = 0
-- Delete as no longer needed
self.object:get_luaentity().itemstring = ""
self.object:remove()
taken_items = true
break
end
mcl_log("Count: " .. tostring(stack1:get_count()))
mcl_log("stack max: " .. tostring(stack1:get_stack_max()))
--mcl_log("Is it empty: " .. stack1:to_string())
end
if i == ent._inv_size and taken_items then
mcl_log("We are on last item and still have items left. Set final stack size: " .. items_remaining)
current_itemstack:set_count(items_remaining)
--mcl_log("Itemstack2: " .. current_itemstack:to_string())
self.itemstring = current_itemstack:to_string()
end
end
end
--Add in, and delete
if taken_items then
mcl_log("Saving")
mcl_entity_invs.save_inv(ent)
return taken_items
else
mcl_log("No need to save")
end
end
end
end
return false
end
minetest.register_entity(":__builtin:item", { minetest.register_entity(":__builtin:item", {
initial_properties = { initial_properties = {
hp_max = 1, hp_max = 1,
@ -648,6 +786,12 @@ minetest.register_entity(":__builtin:item", {
end end
local p = self.object:get_pos() local p = self.object:get_pos()
-- If hopper has taken item, it has gone, and no operations should be conducted on this item
if hopper_take_item(self, p) then
return
end
local node = minetest.get_node_or_nil(p) local node = minetest.get_node_or_nil(p)
local in_unloaded = (node == nil) local in_unloaded = (node == nil)

View file

@ -770,8 +770,9 @@ register_minecart(
}, },
"mcl_minecarts_minecart_hopper.png", "mcl_minecarts_minecart_hopper.png",
{"mcl_minecarts:minecart", "mcl_hoppers:hopper"}, {"mcl_minecarts:minecart", "mcl_hoppers:hopper"},
nil, nil, false nil, nil, true
) )
mcl_entity_invs.register_inv("mcl_minecarts:hopper_minecart", "Hopper Minecart", 5, false, true)
-- Minecart with TNT -- Minecart with TNT
register_minecart( register_minecart(
@ -841,14 +842,14 @@ minetest.register_craft({
-- TODO: Re-enable crafting of special minecarts when they have been implemented -- TODO: Re-enable crafting of special minecarts when they have been implemented
--[[minetest.register_craft({ minetest.register_craft({
output = "mcl_minecarts:hopper_minecart", output = "mcl_minecarts:hopper_minecart",
recipe = { recipe = {
{"mcl_hoppers:hopper"}, {"mcl_hoppers:hopper"},
{"mcl_minecarts:minecart"}, {"mcl_minecarts:minecart"},
}, },
}) })
--]]
minetest.register_craft({ minetest.register_craft({
output = "mcl_minecarts:chest_minecart", output = "mcl_minecarts:chest_minecart",