Page 1 of 1

Forcefield mod help

PostPosted: Thu Apr 04, 2013 00:30
by ch98
I am going to make a forcefield mod where undigable block (forcefield block) is placed around about 6 blocks from forcefield generator block when it has coal in it and takes a coal away every 10 times forcefield block is hit, every 10 seconds, or if any block is missing, and destroys all forcefield block when there is no more coal. I am stuck on part detecting if coal is in the forcefield generator and there will be way more help needed afterwards.

init.lua:
Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
minetest.register_node("forcefield:forcefield", {
    tiles = {"forcefield_forcefield.png"},
    drawtype = glasslike,
    sunlight_propagates = true,
    walkable = true,
    diggable = false,
    on_punch = function(pos, node, puncher)
        pos = position
        a = "a" + "1"
    end,
})




default.forcefield_formspec =
    "size[8,9]"..
    "list[current_name;coal;1,1;6,3;]"..
    "list[current_player;main;0,5;8,4;]"



minetest.register_node("forcefield:fmaker", {
    description = "Forcefield Generator",
    tiles = {"forcefield_sides.png","forcefield_sides.png","forcefield_front.png","forcefield_sides.png","forcefield_sides.png","forcefield_sides.png"},
    groups = {snappy=2, choppy=2},
    on_construct = function(pos)
        local meta = minetest.env:get_meta(pos)
        meta:set_string("formspec", default.forcefield_formspec)
        meta:set_string("infotext", "forcefield generator")
        local inv = meta:get_inventory()
        inv:set_size("coal", 18)
    end,
    can_dig = function(pos,player)
        local meta = minetest.env:get_meta(pos);
        local inv = meta:get_inventory()
        if not inv:is_empty("coal", 18) then
            return false
        end
        return true
    end,
 
})



minetest.register_abm({
    nodenames = {"forcefield:fmaker"},
    interval = 1.0,
    chance = 1,
    action = function(pos, node, active_object_count, active_object_count_wider)
        local meta = minetest.env:get_meta(pos)
        local inv = meta:get_inventory()
        local fuel = inv:get_list("coal")
            if fuel == "default:coal_lump" then
            srcstack = inv:get_stack("coal", 1)
                    srcstack:take_item("default:coal_lump")
                    inv:set_stack("coal", 1, srcstack)
                else
                    print("there was no coal")
        end
    end,
})


minetest.register_craft({
    output = 'forcefield:fmaker',
    recipe = {
        {'default:mese', 'default:mese', 'default:mese'},
        {'default:mese', 'default:furnace', 'default:mese'},
        {'default:mese', 'default:mese', 'default:mese'},
    }
})


PostPosted: Thu Apr 04, 2013 00:32
by 12Me21
I think that has been made before, in the technic mod i think

PostPosted: Thu Apr 04, 2013 00:34
by ch98
I don't think there was any forcefield related mod.

EDIT: in minetest. there is one in minecraft.

PostPosted: Fri Apr 05, 2013 01:08
by ch98
place i need help on is

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
minetest.register_abm({
    nodenames = {"forcefield:fmaker"},
    interval = 1.0,
    chance = 1,
    action = function(pos, node, active_object_count, active_object_count_wider)
        local meta = minetest.env:get_meta(pos)
        local inv = meta:get_inventory()
        local fuel = inv:get_list("coal")
            if fuel == "default:coal_lump" then
            srcstack = inv:get_stack("coal", 1)
                    srcstack:take_item("default:coal_lump")
                    inv:set_stack("coal", 1, srcstack)
                else
                    print("there was no coal")
        end
    end,
})


when I remove "if else" part it works. How can I fix it to detect if coal is in this node or not?

PostPosted: Fri Apr 05, 2013 10:58
by Topywo
ch98 wrote:place i need help on is


when I remove "if else" part it works. How can I fix it to detect if coal is in this node or not?


I didn't try, but maybe you need a return before or after the print.

PostPosted: Fri Apr 05, 2013 22:21
by ch98
Topywo wrote:
ch98 wrote:place i need help on is


when I remove "if else" part it works. How can I fix it to detect if coal is in this node or not?


I didn't try, but maybe you need a return before or after the print.

ok, I will try that.

Edit: didn't work but thank you.

PostPosted: Fri Apr 05, 2013 23:08
by RealBadAngel
ch98 wrote:I don't think there was any forcefield related mod.

EDIT: in minetest. there is one in minecraft.


Theres one made by ShadowNinja:
Image
https://github.com/RealBadAngel/technic/blob/master/technic/forcefield.lua

PostPosted: Fri Apr 05, 2013 23:31
by ch98
RealBadAngel wrote:
ch98 wrote:I don't think there was any forcefield related mod.

EDIT: in minetest. there is one in minecraft.


Theres one made by ShadowNinja:
Image
https://github.com/RealBadAngel/technic/blob/master/technic/forcefield.lua

I didn't find anything in forum search and google search. Also, I want to make it coal driven without extra mods. Can you help me?

PostPosted: Sat Apr 06, 2013 02:43
by ch98
Is it legal to modify code from minetest default (furnace) for my mod?

PostPosted: Sat Apr 06, 2013 03:07
by hdastwb
ch98 wrote:Is it legal to modify code from minetest default (furnace) for my mod?


I do believe it was fair game for desert_uses
http://forum.minetest.net/viewtopic.php?id=3761

Perhaps there should be some sort of generic way of making stuff that burns stuff, rather than duplicating the furnace code from default?

PostPosted: Sat Apr 06, 2013 04:22
by ch98
hdastwb wrote:
ch98 wrote:Is it legal to modify code from minetest default (furnace) for my mod?


I do believe it was fair game for desert_uses
http://forum.minetest.net/viewtopic.php?id=3761

Perhaps there should be some sort of generic way of making stuff that burns stuff, rather than duplicating the furnace code from default?

I'm trying to but I can't get any good help so just in case I never get help.

PostPosted: Sat Apr 06, 2013 05:13
by VanessaE
All of the code in Minetest is under the Lesser GNU Public License v2.1 or later, while the textures are CC-By-SA 3.0. So yeah, it's legal to use the code/textures as long as you comply with those licenses.

PostPosted: Sat Apr 06, 2013 07:17
by prestidigitator
InvRef:get_list(...) is, I believe, going to return you an array of ItemStacks. You probably want to either get a single item stack and test the type of item instead:

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
if inv:get_stack("coal", 1):get_name() == "coal" then ...


or ask the inventory whether there is any of a type of item in the whole list:

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
if inv:contains_item("coal", ItemStack("coal")) then ...


The inventory list being named "coal" is a little confusing in those examples. If you pretend instead that the inventory list were named "fuel", then they would look like:

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
if inv:get_stack("fuel", 1):get_name() == "coal" then ...

if inv:contains_item("fuel", ItemStack("coal")) then ...


Another possibility would be to use inventory callbacks (specifically allow_metadata_inventory_put and—if the node has multiple lists in its inventory—also allow_metadata_inventory_move) to ensure that ONLY coal can be stored in the inventory list. In that case you could be reasonably certain that if there is ANYTHING in the inventory list, then it must be coal:

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
if not inv:is_empty("fuel") then ...

PostPosted: Sun Apr 07, 2013 00:20
by ch98
prestidigitator wrote:InvRef:get_list(...) is, I believe, going to return you an array of ItemStacks. You probably want to either get a single item stack and test the type of item instead:

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
if inv:get_stack("coal", 1):get_name() == "coal" then ...


or ask the inventory whether there is any of a type of item in the whole list:

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
if inv:contains_item("coal", ItemStack("coal")) then ...


The inventory list being named "coal" is a little confusing in those examples. If you pretend instead that the inventory list were named "fuel", then they would look like:

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
if inv:get_stack("fuel", 1):get_name() == "coal" then ...

if inv:contains_item("fuel", ItemStack("coal")) then ...


Another possibility would be to use inventory callbacks (specifically allow_metadata_inventory_put and—if the node has multiple lists in its inventory—also allow_metadata_inventory_move) to ensure that ONLY coal can be stored in the inventory list. In that case you could be reasonably certain that if there is ANYTHING in the inventory list, then it must be coal:

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
if not inv:is_empty("fuel") then ...


Thank you. That way worked great. (Unfortunately, I found similar code in instruction manual yesterday taking 3 hours but this works way better. Thank You.)
Do you know how to take a coal from any of the 18 boxes?

PostPosted: Sun Apr 07, 2013 01:59
by ch98
I also need to make it suck only coal and place item in big hollow cube with set diameter (hollow sphere is good too) without erasing solid objects.

PostPosted: Mon Apr 08, 2013 08:07
by prestidigitator
ch98 wrote:Do you know how to take a coal from any of the 18 boxes?

If the boxes are all in one inventory list, you should be able to just do:

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
local stackOfRemovedItems = inv:remove_item(ItemStack("coal"))


or, if you want to remove more than one all at once:

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
local stackOfRemovedItems = inv:remove_item(ItemStack("coal "..n))


I'm not sure if that one will return a partial list if not all n items were available, if it will return nil/empty. You'll probably just have to try it.

PostPosted: Mon Apr 08, 2013 08:28
by prestidigitator
ch98 wrote:I also need to make it suck only coal and place item in big hollow cube with set diameter (hollow sphere is good too) without erasing solid objects.

You'll need to think about how you really want to define "solid". If you mean nodes that a player couldn't normally walk through, you should be able to test the existing node's "walkable" flag. If you mean nodes you couldn't normally build over, you can test the node's "buildable_to" flag. If you really don't want to replace anything that might be interesting, you could do something very explicit like test for just "air", "default:water_source" and "default:water_flowing". In terms of the geometry, you could place a cubic or spherical shell using something like:

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
local function placeNode(pos)
   ...
end

local function placeCubicShell(pos, sideLen)
   local s = math.floor(sideLen/2)
   for dx = -s, s do
      for dy = -s, s do
         placeNode({ x = pos.x + dx, y = pos.y + dy, z = pos.z - s })
         placeNode({ x = pos.x + dx, y = pos.y + dy, z = pos.z + s })
      end
   end
   for dy = -s, s do
      for dz = -s, s do
         placeNode({ x = pos.x - s, y = pos.y + dy, z = pos.z + dz })
         placeNode({ x = pos.x + s, y = pos.y + dy, z = pos.z + dz })
      end
   end
   for dz = -s, s do
      for dx = -s, s do
         placeNode({ x = pos.x + dx, y = pos.y - s, z = pos.z + dz })
         placeNode({ x = pos.x + dx, y = pos.y + s, z = pos.z + dz })
      end
   end
end

local function placeSphericalShell(pos, radius)
   local rSq = radius^2
   local rx = math.floor(radius)
   if rx > 0 then
      for dx = -rx, rx do
         local rz = math.floor(math.sqrt(rSq - dx^2))
         if rz > 0 then
            for dz = -rz, rz do
               local ry = math.floor(math.sqrt(rSq - dx^2 - dz^2))
               if ry > 0 then
                  placeNode({ x = pos.x + dx, y = pos.y - ry, z = pos.z + dz })
                  placeNode({ x = pos.x + dx, y = pos.y + ry, z = pos.z + dz })
               end
            end
         end
      end
   end
end


That's untested, but it should give you the idea. The placeNode(pos) function would be where you test each position to see if you should put a node there, and do so if the node matches your conception of "not solid". The one for the cubic shell could also be improved by removing redundancy, but this logic is probably a bit easier to understand and should be a good starting point.

PostPosted: Mon Apr 08, 2013 22:28
by ch98
prestidigitator wrote:
ch98 wrote:I also need to make it suck only coal and place item in big hollow cube with set diameter (hollow sphere is good too) without erasing solid objects.

You'll need to think about how you really want to define "solid". If you mean nodes that a player couldn't normally walk through, you should be able to test the existing node's "walkable" flag. If you mean nodes you couldn't normally build over, you can test the node's "buildable_to" flag. If you really don't want to replace anything that might be interesting, you could do something very explicit like test for just "air", "default:water_source" and "default:water_flowing". In terms of the geometry, you could place a cubic or spherical shell using something like:

Your phone or window isn't wide enough to display the code box. If it's a phone, try rotating it to landscape mode.
Code: Select all
local function placeNode(pos)
   ...
end

local function placeCubicShell(pos, sideLen)
   local s = math.floor(sideLen/2)
   for dx = -s, s do
      for dy = -s, s do
         placeNode({ x = pos.x + dx, y = pos.y + dy, z = pos.z - s })
         placeNode({ x = pos.x + dx, y = pos.y + dy, z = pos.z + s })
      end
   end
   for dy = -s, s do
      for dz = -s, s do
         placeNode({ x = pos.x - s, y = pos.y + dy, z = pos.z + dz })
         placeNode({ x = pos.x + s, y = pos.y + dy, z = pos.z + dz })
      end
   end
   for dz = -s, s do
      for dx = -s, s do
         placeNode({ x = pos.x + dx, y = pos.y - s, z = pos.z + dz })
         placeNode({ x = pos.x + dx, y = pos.y + s, z = pos.z + dz })
      end
   end
end

local function placeSphericalShell(pos, radius)
   local rSq = radius^2
   local rx = math.floor(radius)
   if rx > 0 then
      for dx = -rx, rx do
         local rz = math.floor(math.sqrt(rSq - dx^2))
         if rz > 0 then
            for dz = -rz, rz do
               local ry = math.floor(math.sqrt(rSq - dx^2 - dz^2))
               if ry > 0 then
                  placeNode({ x = pos.x + dx, y = pos.y - ry, z = pos.z + dz })
                  placeNode({ x = pos.x + dx, y = pos.y + ry, z = pos.z + dz })
               end
            end
         end
      end
   end
end


That's untested, but it should give you the idea. The placeNode(pos) function would be where you test each position to see if you should put a node there, and do so if the node matches your conception of "not solid". The one for the cubic shell could also be improved by removing redundancy, but this logic is probably a bit easier to understand and should be a good starting point.


Wow. exactly what I needed. (I also need a way to take coal from any of the 18 spaces to put coal)

PostPosted: Sat Apr 20, 2013 03:30
by ch98
All questions here are solved.
More help may be needed at http://forum.minetest.net/viewtopic.php?pid=85204#p85204