Noch mehr mods
This commit is contained in:
parent
a063db5d3b
commit
cf017b2ca1
527 changed files with 21113 additions and 181 deletions
21
mods/i_have_hands/LICENSE
Normal file
21
mods/i_have_hands/LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2024 KingTheGuy
|
||||
|
||||
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.
|
68
mods/i_have_hands/README.md
Normal file
68
mods/i_have_hands/README.md
Normal file
|
@ -0,0 +1,68 @@
|
|||

|
||||
|
||||
---
|
||||
|
||||
Carry a storage block/node without breaking it.
|
||||
you can carry a chest, a barrel.. just about anything that has an inventory.
|
||||
|
||||
**how?**
|
||||
|
||||
_Hold `sneak` then `right_click(place button)` with an `empty_hand` to pickup/place down the storage containers_
|
||||
|
||||
[view the roadmap](/ROADMAP.md)
|
||||
|
||||
---
|
||||
|
||||
_1.0.9 CHANGELOG:_
|
||||
|
||||
bugfix:
|
||||
|
||||
- crash when dropping a chest with pipeworks installed
|
||||
|
||||
_1.0.8 CHANGELOG:_
|
||||
|
||||
bugfix:
|
||||
|
||||
- VoxeLibre players could not open door with an empty hand
|
||||
|
||||
_1.0.7 CHANGELOG:_
|
||||
|
||||
- \*\*add support for _mineclonia_
|
||||
- add a short delay to the hud popup
|
||||
- don't show the hud when the player is already holding a "chest/inventory"
|
||||
|
||||
_1.0.6 CHANGELOG:_
|
||||
|
||||
- updated gif
|
||||
- hud over
|
||||
- bug fixes
|
||||
|
||||
_1.0.5 CHANGELOG:_
|
||||
|
||||
- added support for pipeworks [link](https://content.minetest.net/packages/mt-mods/pipeworks/)
|
||||
- on storage containers pickup/drop tubes will update
|
||||
|
||||
_1.0.4 CHANGELOG:_
|
||||
|
||||
- held storage containers can now be placed in water
|
||||
- voxelibre chests once again render in hand
|
||||
|
||||
_1.0.3 CHANGELOG:_
|
||||
|
||||
- added support for the drawers mod (Storage Drawers) [link](https://content.minetest.net/packages/LNJ/drawers/)
|
||||
- faster animation
|
||||
|
||||
- removed usage of keyword `goto`
|
||||
|
||||
_1.0.2 CHANGELOG:_
|
||||
|
||||
- first person visual indicator
|
||||
- block animation for placing down.
|
||||
- added mcl double chest support
|
||||
- can now view mcl chests in \*hand (not happy with how ive had to implement this)
|
||||
- mcl disabled picking up shulkers
|
||||
- bug fixes
|
||||
|
||||
_1.0.1 CHANGELOG:_
|
||||
|
||||
- should take into account protected areas/blocks
|
552
mods/i_have_hands/init.lua
Normal file
552
mods/i_have_hands/init.lua
Normal file
|
@ -0,0 +1,552 @@
|
|||
dofile(minetest.get_modpath("i_have_hands") .. "/utils.lua")
|
||||
|
||||
--moving a hot furnace with just your hands.. i don't this so buddy
|
||||
local RayDistance = 4; --this should be changed to the players reach
|
||||
--invs to block
|
||||
local blacklist = { "furnace", "shulker" } --if the name contains any of
|
||||
|
||||
local data_storage = core.get_mod_storage()
|
||||
|
||||
---@class Animate
|
||||
---@field player table The damn player
|
||||
---@field rotation integer Not sure if this is vector
|
||||
---@field object table Is this a table?
|
||||
---@field frame integer Not sure if frame is the correct term here
|
||||
---@field item_name string This is probabliy the only thing that is correct
|
||||
local to_animate = {}
|
||||
|
||||
---@param this_string string the string
|
||||
---@param split string sub to split at
|
||||
function Split(this_string, split)
|
||||
local new_word = {}
|
||||
local index = string.find(this_string, split)
|
||||
if index == nil then
|
||||
return nil
|
||||
end
|
||||
local split_index = index
|
||||
local split_start = ""
|
||||
for x = 0, split_index - 1, 1 do
|
||||
split_start = split_start .. string.sub(this_string, x, x)
|
||||
end
|
||||
new_word[1] = split_start
|
||||
|
||||
local split_end = ""
|
||||
for x = split_index + #split, #this_string, 1 do
|
||||
split_end = split_end .. string.sub(this_string, x, x)
|
||||
end
|
||||
new_word[2] = split_end
|
||||
return new_word
|
||||
end
|
||||
|
||||
local function placeDown(placer, rot, obj, above, frame, held_item_name)
|
||||
table.insert(to_animate,
|
||||
{ player = placer, rot = rot, obj = obj, pos = above, frame = frame, item = held_item_name })
|
||||
end
|
||||
|
||||
local function quantize_direction(yaw)
|
||||
local angle = math.deg(yaw) % 360 -- Convert yaw to degrees and get its modulo 360
|
||||
if angle < 45 or angle >= 315 then
|
||||
return math.rad(0) -- Facing North
|
||||
elseif angle >= 45 and angle < 135 then
|
||||
return math.rad(90) -- Facing East
|
||||
elseif angle >= 135 and angle < 225 then
|
||||
return math.rad(180) -- Facing South
|
||||
else
|
||||
return math.rad(270) -- Facing West
|
||||
end
|
||||
end
|
||||
|
||||
--object, pos, frame
|
||||
--not in use atm
|
||||
local function animatePlace()
|
||||
for i, v in pairs(to_animate) do
|
||||
if v.frame == 0 then
|
||||
v.obj:set_detach()
|
||||
v.obj:set_yaw(v.rot)
|
||||
local obj_rot = v.obj:get_rotation()
|
||||
v.obj:set_rotation({ x = math.rad(-20), y = obj_rot.y, z = obj_rot.z })
|
||||
v.obj:set_properties({ visual_size = { x = 0.5, y = 0.5, z = 0.5 } })
|
||||
v.obj:set_pos(v.pos)
|
||||
v.obj:set_properties({ pointable = true })
|
||||
core.sound_play({ name = "i_have_hands_pickup_node" }, { pos = v.pos, pitch = 0.7 }, true)
|
||||
end
|
||||
if v.frame == 1 then
|
||||
local obj_rot = v.obj:get_rotation()
|
||||
v.obj:set_rotation({ x = math.rad(0), y = obj_rot.y, z = obj_rot.z })
|
||||
v.obj:set_properties({ visual_size = { x = 0.6, y = 0.6, z = 0.6 } })
|
||||
end
|
||||
if v.frame == 2 then
|
||||
v.obj:set_properties({ visual_size = { x = 0.65, y = 0.65, z = 0.65 } })
|
||||
end
|
||||
if v.frame == 1 then
|
||||
local found_meta = data_storage:get_string(v.obj:get_luaentity().initial_pos)
|
||||
data_storage:set_string(v.obj:get_luaentity().initial_pos, "") --clear it
|
||||
core.set_node(v.pos, { name = v.item, param2 = core.dir_to_fourdir(core.yaw_to_dir(v.rot)) })
|
||||
core.sound_play({ name = "i_have_hands_place_down_node" }, { pos = v.pos }, true)
|
||||
local meta = core.get_meta(v.pos)
|
||||
|
||||
local node_containers = {}
|
||||
for i, v in pairs(core.deserialize(found_meta)["data"]) do
|
||||
local found_container = {}
|
||||
for container, container_items in pairs(v) do
|
||||
local found_inv = {}
|
||||
if type(container_items) == "string" then
|
||||
found_container[container] = container_items
|
||||
else
|
||||
for slot, item in pairs(container_items) do
|
||||
found_inv[slot] = item
|
||||
end
|
||||
found_container[container] = found_inv
|
||||
end
|
||||
end
|
||||
node_containers[i] = found_container
|
||||
end
|
||||
meta:from_table(node_containers)
|
||||
|
||||
--NOTE(COMPAT): this adds support for the storage_drawers mod
|
||||
if core.get_modpath("drawers") and drawers then
|
||||
drawers.spawn_visuals(v.pos)
|
||||
end
|
||||
--NOTE(COMPAT): pipeworks update pipe, on place down
|
||||
if core.get_modpath("pipeworks") and pipeworks then
|
||||
pipeworks.after_place(v.pos)
|
||||
end
|
||||
end
|
||||
v.frame = v.frame + 1
|
||||
if v.frame >= 6 then
|
||||
v.obj:remove()
|
||||
v.obj = nil
|
||||
table.remove(to_animate, i)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---@param pos table
|
||||
---@param user table
|
||||
---@return boolean
|
||||
local function checkProtection(pos, user)
|
||||
local protected = core.is_protected(pos, user:get_player_name())
|
||||
local owner = core.get_meta(pos):get_string("owner")
|
||||
local player_name = user:get_player_name()
|
||||
if owner ~= "" then
|
||||
if owner ~= player_name then
|
||||
core.chat_send_player(player_name, core.colorize("pink", "You are not the owner."))
|
||||
return true
|
||||
end
|
||||
end
|
||||
if protected then
|
||||
core.chat_send_player(player_name, core.colorize("pink", "This is protected"))
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function isInventory(meta)
|
||||
local count = 0
|
||||
for _ in pairs(meta:to_table()["inventory"]) do count = count + 1 end
|
||||
if count < 1 then --inve have a value of 1 or greater
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local function isBlacklisted(pos)
|
||||
for _, v in ipairs(blacklist) do
|
||||
if utils.StringContains(core.get_node(pos).name, v) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function find_empty_position(pos, radius)
|
||||
local x, y, z = pos.x, pos.y, pos.z
|
||||
local found = false
|
||||
local empty_pos = nil
|
||||
|
||||
for r = 0, radius do
|
||||
for a = 0, 360, 10 do
|
||||
local dx = math.floor(r * math.cos(math.rad(a)))
|
||||
local dz = math.floor(r * math.sin(math.rad(a)))
|
||||
local nx, nz = x + dx, z + dz
|
||||
local ny = y
|
||||
|
||||
while ny < 100 and not found do
|
||||
local node = minetest.get_node({ x = nx, y = ny, z = nz })
|
||||
if node.name == "air" then
|
||||
empty_pos = { x = nx, y = ny, z = nz }
|
||||
found = true
|
||||
end
|
||||
ny = ny + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return empty_pos
|
||||
end
|
||||
|
||||
local handdef = core.registered_items[""]
|
||||
local on_place = handdef and handdef.on_place
|
||||
|
||||
local function hands(itemstack, placer, pointed_thing)
|
||||
local contains = false
|
||||
if placer:get_player_control()["sneak"] == true then
|
||||
-- core.debug("what is this?",core.get_node(pointed_thing.under).name)
|
||||
-- core.debug(string.format("location: %s", dump(core.get_modpath("drawers"))))
|
||||
-- core.debug(core.colorize("yellow", "howdy mate, ive got the shits"))
|
||||
if #placer:get_children() > 0 then --this is getting all connect objects
|
||||
for index, obj in pairs(placer:get_children()) do
|
||||
-- core.debug(dump(obj:get_luaentity().name))
|
||||
-- core.debug("got something: "..obj.name)
|
||||
-- end
|
||||
-- for index, value in pairs(placer:get_children()) do
|
||||
local above = pointed_thing.above
|
||||
-- core.debug("node: "..core.get_node(above).name)
|
||||
if checkProtection(above, placer) == false then
|
||||
if obj:get_luaentity().name == "i_have_hands:held" then
|
||||
contains = true
|
||||
-- core.debug("ok: "..type(held).."-"..held.."-")
|
||||
local try_inside = core.registered_nodes[core.get_node(pointed_thing.under).name]
|
||||
-- core.debug("buildabled? ",try_inside.buildable_to)
|
||||
if core.get_node(above).name ~= "air" then
|
||||
-- if core.get_node(above).name == "water" then
|
||||
if utils.StringContains(core.get_node(above).name, "water") then
|
||||
--do nothing
|
||||
else
|
||||
return itemstack
|
||||
end
|
||||
end
|
||||
if #core.get_objects_inside_radius(above, 0.5) > 0 then
|
||||
return itemstack
|
||||
end
|
||||
if try_inside.buildable_to == true then
|
||||
above = pointed_thing.under
|
||||
end
|
||||
|
||||
|
||||
local held_item_name = core.registered_nodes[obj:get_properties().wield_item].name
|
||||
-- local player_p = core.dir_to_fourdir(placer:get_look_dir())
|
||||
-- obj:set_pos(above)
|
||||
-- animatePlace(obj,above)
|
||||
|
||||
-- table.insert(to_animate,
|
||||
-- { player = placer, rot = rot, obj = obj, pos = above, frame = 0, item = held_item_name })
|
||||
local rot = quantize_direction(placer:get_look_horizontal())
|
||||
placeDown(placer, rot, obj, above, 0, held_item_name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if contains == false then
|
||||
local is_blacklisted = false
|
||||
|
||||
if isBlacklisted(pointed_thing.under) then
|
||||
is_blacklisted = true
|
||||
end
|
||||
if is_blacklisted == false then
|
||||
if checkProtection(pointed_thing.under, placer) then
|
||||
return itemstack
|
||||
end
|
||||
local meta = core.get_meta(pointed_thing.under)
|
||||
if isInventory(meta) == false then
|
||||
return itemstack
|
||||
end
|
||||
local obj = core.add_entity(placer:get_pos(), "i_have_hands:held")
|
||||
obj:set_attach(placer, "", { x = 0, y = 9, z = 3.2 }, { x = 0, y = math.rad(90), z = 0 }, true)
|
||||
--NOTE: attaching to the head just does not look very good, so lets not do that.
|
||||
-- obj:set_attach(placer, "Head", { x = 0, y = -2, z = -3.2 }, { x = 0, y = math.rad(90), z = 0 }, true)
|
||||
obj:set_properties({
|
||||
wield_item = core.registered_nodes[core.get_node(pointed_thing.under).name]
|
||||
.name
|
||||
})
|
||||
obj:get_luaentity().initial_pos = vector.to_string(obj:get_pos())
|
||||
|
||||
--NOTE(COMPAT): this takes care of voxelibre chests
|
||||
if utils.StringContains(core.registered_nodes[core.get_node(pointed_thing.under).name].name, "mcl_chests") then
|
||||
obj:set_properties({ wield_item = "mcl_chests:chest" })
|
||||
end
|
||||
|
||||
-- core.debug(core.colorize("yellow",dump(core.registered_nodes[core.get_node(pointed_thing.under).name])))
|
||||
-- core.debug(core.colorize("blue", "all: \n" .. dump(meta:to_table())))
|
||||
local node_containers = {}
|
||||
for i, v in pairs(meta:to_table()) do
|
||||
local found_container = {}
|
||||
for container, container_items in pairs(v) do
|
||||
local found_inv = {}
|
||||
if type(container_items) == "table" then
|
||||
for slot, item in pairs(container_items) do
|
||||
table.insert(found_inv, slot, item:to_string())
|
||||
end
|
||||
found_container[container] = found_inv
|
||||
else
|
||||
found_container[container] = container_items
|
||||
end
|
||||
end
|
||||
node_containers[i] = found_container
|
||||
end
|
||||
local full_data = { node = core.get_node(pointed_thing.under), data = node_containers }
|
||||
-- core.debug("full_data: ".. dump(full_data.data))
|
||||
|
||||
local pos = vector.to_string(obj:get_pos())
|
||||
data_storage:set_string(pos, core.serialize(full_data))
|
||||
obj:get_luaentity().initial_pos = pos
|
||||
-- placer:get_meta():set_string("obj_obj",core.write_json(obj))
|
||||
core.remove_node(pointed_thing.under)
|
||||
core.sound_play({ name = "i_have_hands_pickup_node" }, { pos = pointed_thing.under }, true)
|
||||
|
||||
--NOTE(COMPAT): pipeworks update pipe, on pickup
|
||||
if core.get_modpath("pipeworks") and pipeworks then
|
||||
pipeworks.after_place(pointed_thing.under)
|
||||
end
|
||||
|
||||
-- core.sound_play({ name = "i_have_hands_pickup" }, { pos = pointed_thing.under,gain = 0.1}, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
--you know, return itemstack
|
||||
end
|
||||
|
||||
-- local original_on_place = minetest.registered_items[""].on_place
|
||||
|
||||
core.override_item("", {
|
||||
on_place = function(itemstack, placer, pointed_thing)
|
||||
itemstack = on_place(itemstack, placer, pointed_thing)
|
||||
hands(itemstack, placer, pointed_thing)
|
||||
|
||||
-- Call the original on_place function if it exists
|
||||
-- if original_on_place then
|
||||
-- return original_on_place(itemstack, placer, pointed_thing)
|
||||
-- end
|
||||
return itemstack
|
||||
end,
|
||||
-- on_secondary_use = function(itemstack, placer, pointed_thing)
|
||||
-- hands(itemstack, placer, pointed_thing)
|
||||
-- end
|
||||
})
|
||||
|
||||
--check if the player is holding an inventory
|
||||
local function isHolding(player)
|
||||
if #player:get_children() > 0 then --this is getting all connect objects
|
||||
for index, obj in pairs(player:get_children()) do
|
||||
if obj:get_luaentity().name == "i_have_hands:held" then
|
||||
-- core.debug("this dude is holding")
|
||||
return true
|
||||
end
|
||||
-- core.debug("nope not holding")
|
||||
return false
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
core.register_entity("i_have_hands:held", {
|
||||
selectionbox = { -0.0, -0.0, -0.0, 0.0, 0.0, 0.0, rotate = false },
|
||||
pointable = false,
|
||||
physical = false,
|
||||
collide_with_objects = false,
|
||||
visual = "item",
|
||||
wield_item = "",
|
||||
visual_size = { x = 0.35, y = 0.35, z = 0.35 },
|
||||
_initial_pos = "",
|
||||
on_step = function(self, dtime, moveresult)
|
||||
-- core.debug(core.colorize("cyan", "dropping: \n" .. dump(data_storage:get_keys())))
|
||||
|
||||
if self.object:get_attach() == nil then
|
||||
local contains = false
|
||||
for i, v in pairs(to_animate) do
|
||||
if v.obj == self.object then
|
||||
-- core.debug("should not delete this yet")
|
||||
contains = true
|
||||
end
|
||||
end
|
||||
if contains == false then
|
||||
local pos = self.object:get_luaentity().initial_pos
|
||||
for i, v in pairs(data_storage:get_keys()) do
|
||||
if v == pos then
|
||||
core.set_node(vector.from_string(pos), core.deserialize(data_storage:get_string(v))["node"])
|
||||
local meta = core.get_meta(vector.from_string(pos))
|
||||
meta:from_table(utils.DeserializeMetaData(core.deserialize(data_storage:get_string(v))["data"]))
|
||||
data_storage:set_string(v, "")
|
||||
end
|
||||
end
|
||||
self.object:remove()
|
||||
end
|
||||
end
|
||||
|
||||
--updute pos and data
|
||||
if self.object:get_luaentity() then
|
||||
if self.object:get_luaentity().initial_pos ~= nil then
|
||||
local pos = self.object:get_luaentity().initial_pos
|
||||
local data = data_storage:get_string(pos)
|
||||
data_storage:set_string(pos)
|
||||
self.object:get_luaentity().initial_pos = vector.to_string(self.object:get_pos())
|
||||
data_storage:set_string(vector.to_string(self.object:get_pos()), data)
|
||||
end
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
local player_hud_id = {}
|
||||
|
||||
local function getPlayerFromPlayerHuds(player_name)
|
||||
for _, ph in ipairs(player_hud_id) do
|
||||
if ph.player_name == player_name then
|
||||
return ph
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
local function getPlayerHud(player_name)
|
||||
-- core.debug("player_huds are " .. #player_hud_id .. " in length.")
|
||||
for _, ph in ipairs(player_hud_id) do
|
||||
if ph.player_name == player_name then
|
||||
if ph.player_hud == nil then return nil end
|
||||
return ph.player_hud
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function removePlayerHud(player)
|
||||
local hud_id = getPlayerHud(player:get_player_name())
|
||||
if hud_id ~= nil then
|
||||
player:hud_remove(hud_id)
|
||||
for index, ph in ipairs(player_hud_id) do
|
||||
if ph.player_name == player:get_player_name() then
|
||||
table.remove(player_hud_id, index)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--FIXME: only raycast if the player's "hand" is empty (no need to cast when the player cant event pick it up to start with)
|
||||
local function raycast()
|
||||
local player = core.get_connected_players()
|
||||
if #player > 0 then
|
||||
for _, p in ipairs(player) do
|
||||
local eye_height = p:get_properties().eye_height
|
||||
local player_look_dir = p:get_look_dir()
|
||||
local pos = p:get_pos():add(player_look_dir)
|
||||
local player_pos = { x = pos.x, y = pos.y + eye_height, z = pos.z }
|
||||
local new_pos = p:get_look_dir():multiply(RayDistance):add(player_pos)
|
||||
local raycast_result = core.raycast(player_pos, new_pos, false, false):next()
|
||||
if isHolding(p) then
|
||||
removePlayerHud(p)
|
||||
return
|
||||
end
|
||||
|
||||
local hud_id = nil; --FIXME this need to be added to list of all player HUDS
|
||||
if raycast_result then
|
||||
local pointed_node = core.get_node(raycast_result.under)
|
||||
if isBlacklisted(raycast_result.under) then
|
||||
removePlayerHud(p)
|
||||
return
|
||||
end
|
||||
if p:get_wielded_item():get_name() ~= "" then
|
||||
removePlayerHud(p)
|
||||
return
|
||||
end
|
||||
if isInventory(core.get_meta(raycast_result.under)) then
|
||||
hud_id = getPlayerHud(p:get_player_name())
|
||||
local player_with_hud = getPlayerFromPlayerHuds(p:get_player_name())
|
||||
if player_with_hud == nil then
|
||||
local this_players_hud = { player_name = p:get_player_name(), player_hud = hud_id , hud_delay = 6, chest_location = raycast_result.under}
|
||||
table.insert(player_hud_id, this_players_hud)
|
||||
else
|
||||
-- core.debug("what do we have here? "..player_with_hud.hud_delay)
|
||||
if player_with_hud.hud_delay == 0 then
|
||||
if hud_id == nil then
|
||||
hud_id = p:hud_add({
|
||||
hud_elem_type = "text",
|
||||
position = { x = 0.5, y = 0.6 },
|
||||
direction = 0,
|
||||
name = "ihh",
|
||||
scale = { x = 1, y = 1 },
|
||||
-- text = "crouch & interact to lift this",
|
||||
text = "Carry: crouch & interact",
|
||||
number = "0xFFFFFF",
|
||||
z_index = 0,
|
||||
})
|
||||
end
|
||||
player_with_hud.player_hud = hud_id
|
||||
end
|
||||
if player_with_hud.chest_location ~= raycast_result.under then
|
||||
removePlayerHud(p)
|
||||
end
|
||||
end
|
||||
-- core.debug("so wtf is this then? " .. tostring(hud_id))
|
||||
else
|
||||
removePlayerHud(p)
|
||||
end
|
||||
-- core.debug(string.format("what is this?",core.registered_nodes[pointed_node].name))
|
||||
else
|
||||
removePlayerHud(p)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function hotbarSlotNotEmpty()
|
||||
local player = core.get_connected_players()
|
||||
if #player > 0 then
|
||||
for _, p in ipairs(player) do
|
||||
if p:get_wielded_item():get_name() ~= "" then
|
||||
if #p:get_children() > 0 then --this is getting all connect objects
|
||||
for index, obj in pairs(p:get_children()) do
|
||||
if obj:get_luaentity().name == "i_have_hands:held" then
|
||||
local held_item_name = core.registered_nodes[obj:get_properties().wield_item].name
|
||||
placeDown(p, 0, obj, find_empty_position(p:get_pos(), 10), 0, held_item_name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function tickHudDelay()
|
||||
for _,h in pairs(player_hud_id) do
|
||||
if h.hud_delay > 0 then
|
||||
h.hud_delay = h.hud_delay - 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local ran_once = false
|
||||
local tick = 0
|
||||
core.register_globalstep(function(dtime)
|
||||
-- raycast()
|
||||
tick = tick + 0.5
|
||||
if tick > 2 then
|
||||
animatePlace()
|
||||
raycast()
|
||||
hotbarSlotNotEmpty()
|
||||
tickHudDelay()
|
||||
tick = 0
|
||||
end
|
||||
if ran_once == false then
|
||||
ran_once = true
|
||||
for i, v in pairs(data_storage:get_keys()) do
|
||||
local pos = vector.from_string(v)
|
||||
core.set_node(pos, core.deserialize(data_storage:get_string(v))["node"])
|
||||
local meta = core.get_meta(pos)
|
||||
meta:from_table(utils.DeserializeMetaData(core.deserialize(data_storage:get_string(v))["data"]))
|
||||
data_storage:set_string(v, "")
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
core.register_on_dieplayer(function(ObjectRef, reason)
|
||||
if #ObjectRef:get_children() > 0 then --this is getting all connect objects
|
||||
for index, obj in pairs(ObjectRef:get_children()) do
|
||||
if obj:get_luaentity().name == "i_have_hands:held" then
|
||||
local held_item_name = core.registered_nodes[obj:get_properties().wield_item].name
|
||||
placeDown(ObjectRef, 0, obj, find_empty_position(ObjectRef:get_pos(), 10), 0, held_item_name)
|
||||
end
|
||||
end
|
||||
end
|
||||
-- core.debug("what death? " .. ObjectRef:get_player_name())
|
||||
end)
|
6
mods/i_have_hands/mod.conf
Normal file
6
mods/i_have_hands/mod.conf
Normal file
|
@ -0,0 +1,6 @@
|
|||
name = i_have_hands
|
||||
description = Carry nodes/blocks with inventories without breaking them.
|
||||
author = SURV
|
||||
title = I Have Hands
|
||||
optional_depends = drawers, pipeworks, mcl_meshhand
|
||||
release = 30818
|
BIN
mods/i_have_hands/sounds/i_have_hands_pickup_node.ogg
Normal file
BIN
mods/i_have_hands/sounds/i_have_hands_pickup_node.ogg
Normal file
Binary file not shown.
BIN
mods/i_have_hands/sounds/i_have_hands_place_down_node.ogg
Normal file
BIN
mods/i_have_hands/sounds/i_have_hands_place_down_node.ogg
Normal file
Binary file not shown.
56
mods/i_have_hands/utils.lua
Normal file
56
mods/i_have_hands/utils.lua
Normal file
|
@ -0,0 +1,56 @@
|
|||
utils = {}
|
||||
|
||||
function utils.Distance(x1, y1, z1, x2, y2, z2)
|
||||
local dx = x2 - x1
|
||||
local dy = y2 - y1
|
||||
local dz = z2 - z1
|
||||
return math.sqrt(dx * dx + dy * dy + dz * dz)
|
||||
end
|
||||
|
||||
function utils.StringContains(str, find)
|
||||
str = string.upper(str)
|
||||
find = string.upper(find)
|
||||
local i, _ = string.find(str, find)
|
||||
return i
|
||||
end
|
||||
|
||||
function utils.SerializeMetaData(data)
|
||||
local node_containers = {}
|
||||
for i, v in pairs(data:to_table()) do
|
||||
local found_container = {}
|
||||
for container, container_items in pairs(v) do
|
||||
local found_inv = {}
|
||||
if type(container_items) == "table" then
|
||||
for slot, item in pairs(container_items) do
|
||||
table.insert(found_inv, slot, item:to_string())
|
||||
end
|
||||
found_container[container] = found_inv
|
||||
else
|
||||
found_container[container] = container_items
|
||||
end
|
||||
end
|
||||
node_containers[i] = found_container
|
||||
end
|
||||
return core.serialize(node_containers)
|
||||
end
|
||||
|
||||
function utils.DeserializeMetaData(data)
|
||||
local node_containers = {}
|
||||
for i, v in pairs(data) do
|
||||
local found_container = {}
|
||||
for container, container_items in pairs(v) do
|
||||
local found_inv = {}
|
||||
if type(container_items) == "string" then
|
||||
found_container[container] = container_items
|
||||
else
|
||||
for slot, item in pairs(container_items) do
|
||||
found_inv[slot] = item
|
||||
end
|
||||
found_container[container] = found_inv
|
||||
end
|
||||
end
|
||||
node_containers[i] = found_container
|
||||
end
|
||||
return node_containers
|
||||
end
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue