This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
KingofGamesYami's profile picture

Formatting getBlockInfos results

Started by KingofGamesYami, 03 June 2016 - 09:26 PM
KingofGamesYami #1
Posted 03 June 2016 - 11:26 PM
Spoiler
function getFormattedBlockInfos( x, y, z, x2, y2, z2 )
  local tBlockInfos = commands.getBlockInfos( x, y, z, x2, y2, z2 )
  local tFormattedBlockInfos = {}
  local iTablePosition = 1
  --find the minimum and maximum verticies
  local minx, miny, minz = math.min( x, x2 ), math.min( y, y2 ), math.min( z, z2 )
  local maxx, maxy, maxz = math.max( x, x2 ), math.max( y, y2 ), math.max( z, z2 )

  for iy = miny, maxy do
    for iz = minz, maxz do
      for ix = minx, maxx do
        tFormattedBlockInfos[ ix ] = tFormattedBlockInfos[ ix ] or {}
        tFormattedBlockInfos[ ix ][ iy ] = tFormattedBlockInfos[ ix ][ iy ] or {}
        tFormattedBlockInfos[ ix ][ iy ][ iz ] = tBlockInfos[ iTablePosition ]
        iTablePosition = iTablePosition + 1
      end
    end
  end
  print( #tBlockInfos )
  print( iTablePosition )
  print( #tFormattedBlockInfos )
  return tFormattedBlockInfos
end

This amazing code, designed to convert the data from getBlockInfos into a table indexed by the coordinates, is not working. tBlockInfos is bigger than iTablePosition when printed, meaning it is not scanning the entire table. In addition, the size of tFormattedBlockInfos is 0, which I find very weird, since iTablePosition is a very high number.
Emma #2
Posted 04 June 2016 - 12:05 AM
This doesn't necessarily fix the code, but a possible reason that #tFormattedBlockInfos returns 0 would be that using the # operator is essentially this:

local i=0
for k,v in ipairs(tbl)
  i = i + 1
end
It only counts the elements that count sequentially by whole numbers from 1.
If you want all of the elements in the table, use the code above, but with pairs instead of ipairs.
Edited on 03 June 2016 - 10:08 PM
KingofGamesYami #3
Posted 04 June 2016 - 12:43 AM
Thanks, I think I've discovered the problem. It was not in my function, it was in the coordinates I was supplying (they were decimals).
KingofGamesYami #4
Posted 04 June 2016 - 12:57 AM
The function is now messing up the y values, for some reason.


local function integerAwayFromZero( n )
  return n < 0 and math.floor( n ) or math.ceil( n )
end

function getFormattedBlockInfos( x, y, z, x2, y2, z2 )
  local tBlockInfos = commands.getBlockInfos( x, y, z, x2, y2, z2 )
  local tFormattedBlockInfos = {}
  local iTablePosition = 1
  --find the minimum and maximum verticies
  local minx, miny, minz = integerAwayFromZero( math.min( x, x2 ) ), integerAwayFromZero( math.min( y, y2 ) ), integerAwayFromZero( math.min( z, z2 ) )
  local maxx, maxy, maxz = integerAwayFromZero( math.max( x, x2 ) ), integerAwayFromZero( math.max( y, y2 ) ), integerAwayFromZero( math.max( z, z2 ) )

  for iy = miny, maxy do
    for iz = minz, maxz do
      for ix = minx, maxx do
        tFormattedBlockInfos[ ix ] = tFormattedBlockInfos[ ix ] or {}
        tFormattedBlockInfos[ ix ][ iy ] = tFormattedBlockInfos[ ix ][ iy ] or {}
        tFormattedBlockInfos[ ix ][ iy ][ iz ] = tBlockInfos[ iTablePosition ]
        iTablePosition = iTablePosition + 1
      end
    end
  end
  return tFormattedBlockInfos
end

SpoilerThis code is seriously annoying me, it returns 3 coordinates, but almost always 1 y value above. I can tell because the code that's calling it prints the returned values, then the name of the block (using .getBlockInfo)


local f = math.floor

function getObservedBlock( playerName ) --Selects the block the player is looking at.
  local rotationx, rotationy = getPlayerRotation( playerName )
  local px, py, pz = getPlayerPosition( playerName, true )
  py = py + 1.62 --#The player's eyes are 1.62 blocks from the ground
  --Convert pitch/yaw into Vec3 from http://stackoverflow.com/questions/10569659/camera-pitch-yaw-to-direction-vector
  local xzLen=-math.cos(math.rad(rotationy))
  local x, y, z = xzLen * math.sin( -math.rad( rotationx+180 ) ), math.sin( math.rad( -rotationy ) ), xzLen * math.cos( math.rad( rotationx + 180 ) )

  local maxProjectedLength = 5

  local tBlockInfos = getFormattedBlockInfos( px, py, pz, x * maxProjectedLength + px, y * maxProjectedLength + py, z * maxProjectedLength + py )

  local lastX, lastY, lastZ, skip
  for mult = 0, maxProjectedLength, 0.05 do  --Extend the vector linearly
    local currX,currY,currZ= x*mult+px,y*mult+py,z*mult+pz
    skip = lastX and f( currX ) == f( lastX ) and f( currY ) == f( lastY ) and f( currZ ) == f( lastZ )
    if not skip and not tIgnoredBlocks[ tBlockInfos[ f( currX ) ][ f( currY ) ][ f( currZ ) ].name ] then
      return f( currX ), f( currY ), f( currZ )
    end
    lastX,lastY,lastZ=currX,currY,currZ
  end
end
Bomb Bloke #5
Posted 04 June 2016 - 02:27 AM
integerAwayFromZero() is a problem. Why would you want different behaviour just because values have gone negative / positive? Minecraft never ceils co-ords, and neither should you.

In getObservedBlock(), you're flooring too often. Just do it here:

local currX, currY, currZ= f(x*mult+px), f(y*mult+py), f(z*mult+pz)

… and that's it, you don't need to do it again.

I rather suspect that function will step into line once you ditch getFormattedBlockInfos()' use of integerAwayFromZero().
Wergat #6
Posted 04 June 2016 - 02:36 AM
Not sure what you actually want with the code, but this is a parser i used to convert getBlockInfos to a 3D array. This array starts from1/1/1 and goes up to the size of the selected area. Its solving the problem on another way, and it works this way. But it might help you by showing how to parse the X/Y/Z values from any position within the block array.


function(x1,y1,z1,x2,y2,z2)
  -- Calculating size and base position
  local basex = math.min(x1, x2)
  local basey = math.min(y1, y2)
  local basez = math.min(z1, z2)
  local sidex = math.max(x1, x2) - basex + 1
  local sidey = math.max(y1, y2) - basey + 1
  local sidez = math.max(z1, z2) - basez + 1

  size = {sidex,sidey,sidez}

  -- Scanning the blocks and sending the data to another function
  local s,e = commands.getBlockInfos(x1,y1,z1,x2,y2,z2)
  for k,v in pairs(s) do
   local x = ((k+(sidex-1))%sidex)
   local y = (math.floor((k-1)/(sidex*sidez)))
   local z = math.floor(((k-1)%(sidex*sidez))/sidex)
   --setBlock(x,y,z,v)
  end
  -- For testing a specific block:
  --print(self.areaData[14][8][14].id)
end

Hope i could help.
KingofGamesYami #7
Posted 04 June 2016 - 02:47 PM
Changed some stuff,
Spoiler

local f = math.floor
function getFormattedBlockInfos( x, y, z, x2, y2, z2 )
local tBlockInfos = commands.getBlockInfos( x, y, z, x2, y2, z2 )
local tFormattedBlockInfos = {}
local iTablePosition = 1
--find the minimum and maximum verticies
local minx, miny, minz = f( math.min( x, x2 ) ), f( math.min( y, y2 ) ), f( math.min( z, z2 ) )
local maxx, maxy, maxz = f( math.max( x, x2 ) ), f( math.max( y, y2 ) ), f( math.max( z, z2 ) )
for iy = miny, maxy do
for iz = minz, maxz do
for ix = minx, maxx do
tFormattedBlockInfos[ ix ] = tFormattedBlockInfos[ ix ] or {}
tFormattedBlockInfos[ ix ][ iy ] = tFormattedBlockInfos[ ix ][ iy ] or {}
tFormattedBlockInfos[ ix ][ iy ][ iz ] = tBlockInfos[ iTablePosition ]
iTablePosition = iTablePosition + 1
end
end
end
return tFormattedBlockInfos
end
local tIgnoredBlocks = {
["minecraft:air"] = true,
["minecraft:water"] = true,
["minecraft:flowing_water"] = true,
["minecraft:lava"] = true,
["minecraft:flowing_lava"] = true,
}
function getObservedBlock( playerName ) --Selects the block the player is looking at.
local rotationx, rotationy = getPlayerRotation( playerName )
local px, py, pz = getPlayerPosition( playerName, true )
py = py + 1.62 --#The player's eyes are 1.62 blocks from the ground
--Convert pitch/yaw into Vec3 from http://stackoverflow.com/questions/10569659/camera-pitch-yaw-to-direction-vector
local xzLen=-math.cos(math.rad(rotationy))
local x, y, z = xzLen * math.sin( -math.rad( rotationx+180 ) ), math.sin( math.rad( -rotationy ) ), xzLen * math.cos( math.rad( rotationx + 180 ) )
local maxProjectedLength = 5
local tBlockInfos = getFormattedBlockInfos( px, py, pz, x * maxProjectedLength + px, y * maxProjectedLength + py, z * maxProjectedLength + py )
local lastX, lastY, lastZ, skip
for mult = 0, maxProjectedLength, 0.05 do --Extend the vector linearly
local currX,currY,currZ= f( x*mult+px ), f( y*mult+py ), f( z*mult+pz )
skip = lastX and currX == lastX and currY== lastY and currZ == lastZ
if not skip and not tIgnoredBlocks[ tBlockInfos[ currX ][ currY ][ currZ ].name ] then
return currX, currY, currZ
end
lastX,lastY,lastZ=currX,currY,currZ
end
end
…but now it returns the coordinates of the block below the block I'm looking at. I can compensate (by adding 1), but I would rather figure out where the error came from.

Edit: It turns out that if I use the calculated minimum and maximum values for the getBlockInfos call it works fine, but if I don't I get off-by-one errors. For now I'm using those values, but it makes me wonder if I shouldn't be flooring them.
Edited on 04 June 2016 - 04:22 PM
KingofGamesYami #8
Posted 04 June 2016 - 06:37 PM
Spoiler
function getFormattedBlockInfos( x, y, z, x2, y2, z2 )
  --find the minimum and maximum verticies
  local minx, miny, minz = f( math.min( x, x2 ) ), f( math.min( y, y2 ) ), f( math.min( z, z2 ) )
  local maxx, maxy, maxz = f( math.max( x, x2 ) ), f( math.max( y, y2 ) ), f( math.max( z, z2 ) )

  local tBlockInfos = commands.getBlockInfos( minx, miny, minz, maxx, maxy, maxz )
  local tFormattedBlockInfos = {}
  local iTablePosition = 1

  for iy = miny, maxy do
    for iz = minz, maxz do
      for ix = minx, maxx do
        tFormattedBlockInfos[ ix ] = tFormattedBlockInfos[ ix ] or {}
        tFormattedBlockInfos[ ix ][ iy ] = tFormattedBlockInfos[ ix ][ iy ] or {}
        tFormattedBlockInfos[ ix ][ iy ][ iz ] = tBlockInfos[ iTablePosition ]
        iTablePosition = iTablePosition + 1
      end
    end
  end
  return tFormattedBlockInfos
end

local tIgnoredBlocks = {
  ["minecraft:air"] = true,
  ["minecraft:water"] = true,
  ["minecraft:flowing_water"] = true,
  ["minecraft:lava"] = true,
  ["minecraft:flowing_lava"] = true,
}

function getObservedBlock( playerName ) --Selects the block the player is looking at.
  local rotationx, rotationy = getPlayerRotation( playerName )
  local px, py, pz = getPlayerPosition( playerName, true )
  py = py + 1.62 --#The player's eyes are 1.62 blocks from the ground
  --Convert pitch/yaw into Vec3 from http://stackoverflow.com/questions/10569659/camera-pitch-yaw-to-direction-vector
  local xzLen=-math.cos(math.rad(rotationy))
  local x, y, z = xzLen * math.sin( -math.rad( rotationx+180 ) ), math.sin( math.rad( -rotationy ) ), xzLen * math.cos( math.rad( rotationx + 180 ) )

  local maxProjectedLength = 10
  local change_in_x, change_in_y, change_in_z = x*maxProjectedLength, y*maxProjectedLength, z*maxProjectedLength
  print( change_in_x * change_in_y * change_in_z )

  local tBlockInfos = getFormattedBlockInfos( px, py, pz, (x * maxProjectedLength) + px, (y * maxProjectedLength) + py, (z * maxProjectedLength) + py )

  local lastX, lastY, lastZ, skip
  for mult = 0, maxProjectedLength - 1, 0.05 do  --Extend the vector linearly
    local currX,currY,currZ= f( (x*mult )+px ), f( (y*mult)+py ), f( (z*mult)+pz )
    skip = lastX and currX == lastX and currY== lastY and currZ == lastZ
    if not skip and not tIgnoredBlocks[ tBlockInfos[ currX ][ currY ][ currZ ].name ] then
      return currX, currY, currZ
    end
    lastX,lastY,lastZ=currX,currY,currZ
  end
end

It's now erroring with 'too many blocks', even though the changes multiplied together are under 200 blocks, and it's supposedly able to handle over 4000.
Emma #9
Posted 04 June 2016 - 08:20 PM
Spoiler
function getFormattedBlockInfos( x, y, z, x2, y2, z2 )
  --find the minimum and maximum verticies
  local minx, miny, minz = f( math.min( x, x2 ) ), f( math.min( y, y2 ) ), f( math.min( z, z2 ) )
  local maxx, maxy, maxz = f( math.max( x, x2 ) ), f( math.max( y, y2 ) ), f( math.max( z, z2 ) )

  local tBlockInfos = commands.getBlockInfos( minx, miny, minz, maxx, maxy, maxz )
  local tFormattedBlockInfos = {}
  local iTablePosition = 1

  for iy = miny, maxy do
	for iz = minz, maxz do
	  for ix = minx, maxx do
		tFormattedBlockInfos[ ix ] = tFormattedBlockInfos[ ix ] or {}
		tFormattedBlockInfos[ ix ][ iy ] = tFormattedBlockInfos[ ix ][ iy ] or {}
		tFormattedBlockInfos[ ix ][ iy ][ iz ] = tBlockInfos[ iTablePosition ]
		iTablePosition = iTablePosition + 1
	  end
	end
  end
  return tFormattedBlockInfos
end

local tIgnoredBlocks = {
  ["minecraft:air"] = true,
  ["minecraft:water"] = true,
  ["minecraft:flowing_water"] = true,
  ["minecraft:lava"] = true,
  ["minecraft:flowing_lava"] = true,
}

function getObservedBlock( playerName ) --Selects the block the player is looking at.
  local rotationx, rotationy = getPlayerRotation( playerName )
  local px, py, pz = getPlayerPosition( playerName, true )
  py = py + 1.62 --#The player's eyes are 1.62 blocks from the ground
  --Convert pitch/yaw into Vec3 from http://stackoverflow.com/questions/10569659/camera-pitch-yaw-to-direction-vector
  local xzLen=-math.cos(math.rad(rotationy))
  local x, y, z = xzLen * math.sin( -math.rad( rotationx+180 ) ), math.sin( math.rad( -rotationy ) ), xzLen * math.cos( math.rad( rotationx + 180 ) )

  local maxProjectedLength = 10
  local change_in_x, change_in_y, change_in_z = x*maxProjectedLength, y*maxProjectedLength, z*maxProjectedLength
  print( change_in_x * change_in_y * change_in_z )

  local tBlockInfos = getFormattedBlockInfos( px, py, pz, (x * maxProjectedLength) + px, (y * maxProjectedLength) + py, (z * maxProjectedLength) + py )

  local lastX, lastY, lastZ, skip
  for mult = 0, maxProjectedLength - 1, 0.05 do  --Extend the vector linearly
	local currX,currY,currZ= f( (x*mult )+px ), f( (y*mult)+py ), f( (z*mult)+pz )
	skip = lastX and currX == lastX and currY== lastY and currZ == lastZ
	if not skip and not tIgnoredBlocks[ tBlockInfos[ currX ][ currY ][ currZ ].name ] then
	  return currX, currY, currZ
	end
	lastX,lastY,lastZ=currX,currY,currZ
  end
end

It's now erroring with 'too many blocks', even though the changes multiplied together are under 200 blocks, and it's supposedly able to handle over 4000.
local tBlockInfos = getFormattedBlockInfos( px, py, pz, (x * maxProjectedLength) + px, (y * maxProjectedLength) + py, (z * maxProjectedLength) + py )
You wrote +py and then +py again instead of +pz
Edited on 04 June 2016 - 06:21 PM
KingofGamesYami #10
Posted 04 June 2016 - 08:46 PM
I seriously cannot find simple mistakes like this in my own code, yet I'll spot them easily if I didn't write the program. So weird.

Thanks! It works now :)/>