Broken "for" loops
#1
Hello,
I was making a plugin that had to run something ten times and came across what seems to be a bug:

Code:
    for i = 1, 10, 1 do         Player:SendMessage("Pass " .. i)     end

This should return
Pass 1
Pass 2
Pass 3
Pass 4
Pass 5
Pass 6
Pass 7
Pass 8
Pass 9
Pass 10
in chat.
But instead, i get this error:
'=' expected near 'for'
Reply
Thanks given by:
#2
Could you post the code around the for loop?
Reply
Thanks given by:
#3
(02-19-2021, 06:47 PM)NiLSPACE Wrote: Could you post the code around the for loop?

Warning: this code is a mess. Im planning on making a /fill command and it has to run setBlock for every block inside an area the player provides using a command. For testing, i made the area 10 blocks on the x axis. If that would have worked, I would have run x, increment z by one, x, increment z, and so on until it has to increment y and then loop again.
Here it goes but be warned: It may cause eye cancer because im really bad at lua (this is the second time i made something in lua)

Code:
PLUGIN = nil function Initialize(Plugin) Plugin:SetName("VanillaFill") Plugin:SetVersion(1) -- Hooks PLUGIN = Plugin -- NOTE: only needed if you want OnDisable() to use GetName() or something like that -- Command Bindings cPluginManager.BindCommand("/setblock", "vanillafill.setblock", setblock, " ~ Changes a block at X Y Z."); cPluginManager.BindCommand("/fill", "vanillafill.fill", fill, " ~ Fills an area from X Y Z to X2 Y2 Z2."); LOG("Initialised " .. Plugin:GetName() .. " v." .. Plugin:GetVersion()) return true end function OnDisable() LOG(PLUGIN:GetName() .. " is shutting down...") end -- This segment is a bit of stripped-down code from the WorldEdit Plugin (github.com/cuberite/WorldEdit) -- Returns the block type (and block meta) from a string. This can be something like "1", "1:0", "stone" and "stone:0". -- If a string with a percentage sign is given it will take the second half of the string (With "40%1:0" it uses only "1:0") function GetBlockTypeMeta(a_BlockString) g_DefaultMetas = { [E_BLOCK_CHEST]              = 2, [E_BLOCK_ENDER_CHEST]        = 2, [E_BLOCK_FURNACE]            = 2, [E_BLOCK_LADDER]            = 2, [E_BLOCK_LIT_FURNACE]        = 2, [E_BLOCK_NETHER_PORTAL]      = 1, [E_BLOCK_TORCH]              = 1, [E_BLOCK_TRAPPED_CHEST]      = 2, [E_BLOCK_REDSTONE_TORCH_ON]  = 1, [E_BLOCK_REDSTONE_TORCH_OFF] = 1, [E_BLOCK_WALLSIGN]          = 2, [E_BLOCK_WALL_BANNER]        = 2 } if (a_BlockString:find("%%")) then local ItemInfo = StringSplit(a_BlockString, "%") if (#ItemInfo ~= 2) then return false end a_BlockString = ItemInfo[2] end local BlockID = tonumber(a_BlockString) -- Check if it was a normal number if (BlockID) then return BlockID, g_DefaultMetas[BlockID] or 0, true end -- Check for block meta local HasMeta = string.find(a_BlockString, ":") -- Check if it was a name. local Item = cItem() if (not StringToItem(a_BlockString, Item)) then return false else if (HasMeta or (Item.m_ItemDamage ~= 0)) then return Item.m_ItemType, Item.m_ItemDamage else return Item.m_ItemType, g_DefaultMetas[Item.m_ItemType] or 0, true end end end function setblock(Split, Player) if (#Split ~= 5) then -- There was more or less than four arguments (excluding the "/" bit) -- Send the proper usage to the player and exit Player:SendMessage("Usage: /setblock X Y Z [blocktype]") return true end     outVector3 = Vector3i(tonumber(Split[2]), tonumber(Split[3]), tonumber(Split[4]))     Player:SendMessage("Setting block " .. Split[2] .. " "  .. Split[3] .. " " .. Split[4] .. " to type " .. Split[5])     local type, meta = GetBlockTypeMeta(Split[5])     Player:GetWorld():SetBlock(outVector3, type, meta)     return true end function fill(Split, Player) if (#Split ~= 8) then -- There was more or less than seven arguments (excluding the "/" bit) -- Send the proper usage to the player and exit Player:SendMessage("Usage: /fill X1 Y1 Z1 X2 Y2 Z2 [blocktype]") return true end     offsetx = tonumber("0")     x1 = tonumber(Split[2])     y1 = tonumber(Split[3])     z1 = tonumber(Split[4])     x2 = tonumber(Split[5])     y2 = tonumber(Split[6])     z2 = tonumber(Split[7])     countx = tonumber("0")     county = tonumber("0")     countz = tonumber("0")     posx = tonumber("0")     posy = tonumber("0")     posz = tonumber("0") -- Calculate the numbers for the couter:     offsetx = offsetx(x1, x2, offsetx)     countx = tonumber(offsetx(x1, x2, offsetx).replace("-", ""))     countx -- Doesnt work because of broken if statement???        for i=10,0,-1     do --      Placeholder. Will put filling function in here later         Player:SendMessage("offsetX=" .. offsetx)     end         --    for i=countx+county+countz,0,-1 --    do     --    end --    setblockforplugins(Player, posx, posy, posz, Split[8])     outVector3 = Vector3i(tonumber(Split[2]), tonumber(Split[3]), tonumber(Split[4]))     Player:SendMessage("Setting block " .. Split[2] .. " "  .. Split[3] .. " " .. Split[4] .. " to type " .. Split[5])     local type, meta = GetBlockTypeMeta(Split[5])     Player:GetWorld():SetBlock(outVector3, type, meta)     return true end function setblockforplugins(Player, Split)     outVector3 = Vector3i(tonumber(Split[2]), tonumber(Split[3]), tonumber(Split[4]))     Player:SendMessage("Setting block " .. Split[2] .. " "  .. Split[3] .. " " .. Split[4] .. " to type " .. Split[5])     local type, meta = GetBlockTypeMeta(Split[5])     Player:GetWorld():SetBlock(outVector3, type, meta)     return true end -- Will use this later to find the vertical offset and size: function countY(y1, y2)     if tonumber(y1) < tonumber(y2) then for i=y1,y2,-1 do   -- put function here end     else for i=y1,y2,-1 do   -- put function here end         end     return y1, y2 end -- Make offset and size and find out which values are negative. function offsetX(x1, x2, xoffset)     if tonumber(x1) < 0 then         if tonumber(x2) < 0 then     if tonumber(x1) < tonumber(x2) then for i=x1,x2,1 do                     xoffset = xoffset - 1 end     else for i=x1,x2,-1 do                     xoffset = xoffset + 1 end     end else     if tonumber(x1) < tonumber(x2) then for i=tonumber(x1.replace("-", "")),x2,1 do                     xoffset = xoffset + 1 end     else     if tonumber(x1) < tonumber(x2) then for i=x1,tonumber(x2.replace("-", "")),1 do                     xoffset = xoffset + 1 end     end         end     end     if tonumber(x1) > 0 then         if tonumber(x2) < 0 then     if tonumber(x1) < tonumber(x2) then for i=x1,tonumber(x2.replace("-", "")),1 do                     xoffset = xoffset + 1 end     else for i=tonumber(x1.replace("-", "")),x2,1 do                     xoffset = xoffset + 1 end     end else     if tonumber(x1) < tonumber(x2) then for i=x2,x1,1 do                     xoffset = xoffset + 1 end     else for i=x1,x2,1 do                     xoffset = xoffset + 1 end     end         end     end     return xoffset end
Reply
Thanks given by:
#4
If there is a more elegant way to fill an area from a plugin, please tell me. Would make my life way easyer here.
Reply
Thanks given by:
#5
The reason why the for loop doesn't work is because the statement above it is incorrect. You just have 'countx' which isn't a valid statement. Once you remove that or comment it out the for loop should work.
Reply
Thanks given by:
#6
(02-19-2021, 07:32 PM)mueller_minki Wrote: If there is a more elegant way to fill an area from a plugin, please tell me. Would make my life way easyer here.

What is the fill command supposed to do? Is it just take two sets of coordinates and fill it with the specified block?
Reply
Thanks given by:
#7
(02-19-2021, 07:32 PM)NiLSPACE Wrote: The reason why the for loop doesn't work is because the statement above it  is incorrect. You just have 'countx' which isn't a valid statement. Once you remove that or comment it out the for loop should work.

Ok, changed my code:

Code:
PLUGIN = nil function Initialize(Plugin) Plugin:SetName("VanillaFill") Plugin:SetVersion(1) -- Hooks PLUGIN = Plugin -- NOTE: only needed if you want OnDisable() to use GetName() or something like that -- Command Bindings cPluginManager.BindCommand("/setblock", "vanillafill.setblock", setblock, " ~ Changes a block at X Y Z."); cPluginManager.BindCommand("/fill", "vanillafill.fill", fill, " ~ Fills an area from X Y Z to X2 Y2 Z2."); LOG("Initialised " .. Plugin:GetName() .. " v." .. Plugin:GetVersion()) return true end function OnDisable() LOG(PLUGIN:GetName() .. " is shutting down...") end -- This segment is a bit of stripped-down code from the WorldEdit Plugin (github.com/cuberite/WorldEdit) -- Returns the block type (and block meta) from a string. This can be something like "1", "1:0", "stone" and "stone:0". -- If a string with a percentage sign is given it will take the second half of the string (With "40%1:0" it uses only "1:0") function GetBlockTypeMeta(a_BlockString) g_DefaultMetas = { [E_BLOCK_CHEST]              = 2, [E_BLOCK_ENDER_CHEST]        = 2, [E_BLOCK_FURNACE]            = 2, [E_BLOCK_LADDER]            = 2, [E_BLOCK_LIT_FURNACE]        = 2, [E_BLOCK_NETHER_PORTAL]      = 1, [E_BLOCK_TORCH]              = 1, [E_BLOCK_TRAPPED_CHEST]      = 2, [E_BLOCK_REDSTONE_TORCH_ON]  = 1, [E_BLOCK_REDSTONE_TORCH_OFF] = 1, [E_BLOCK_WALLSIGN]          = 2, [E_BLOCK_WALL_BANNER]        = 2 } if (a_BlockString:find("%%")) then local ItemInfo = StringSplit(a_BlockString, "%") if (#ItemInfo ~= 2) then return false end a_BlockString = ItemInfo[2] end local BlockID = tonumber(a_BlockString) -- Check if it was a normal number if (BlockID) then return BlockID, g_DefaultMetas[BlockID] or 0, true end -- Check for block meta local HasMeta = string.find(a_BlockString, ":") -- Check if it was a name. local Item = cItem() if (not StringToItem(a_BlockString, Item)) then return false else if (HasMeta or (Item.m_ItemDamage ~= 0)) then return Item.m_ItemType, Item.m_ItemDamage else return Item.m_ItemType, g_DefaultMetas[Item.m_ItemType] or 0, true end end end function setblock(Split, Player) if (#Split ~= 5) then -- There was more or less than four arguments (excluding the "/" bit) -- Send the proper usage to the player and exit Player:SendMessage("Usage: /setblock X Y Z [blocktype]") return true end     outVector3 = Vector3i(tonumber(Split[2]), tonumber(Split[3]), tonumber(Split[4]))     Player:SendMessage("Setting block " .. Split[2] .. " "  .. Split[3] .. " " .. Split[4] .. " to type " .. Split[5])     local type, meta = GetBlockTypeMeta(Split[5])     Player:GetWorld():SetBlock(outVector3, type, meta)     return true end function fill(Split, Player) if (#Split ~= 8) then -- There was more or less than seven arguments (excluding the "/" bit) -- Send the proper usage to the player and exit Player:SendMessage("Usage: /fill X1 Y1 Z1 X2 Y2 Z2 [blocktype]") return true end     offsetx = tonumber("0")     x1 = tonumber(Split[2])     y1 = tonumber(Split[3])     z1 = tonumber(Split[4])     x2 = tonumber(Split[5])     y2 = tonumber(Split[6])     z2 = tonumber(Split[7])     countx = tonumber("0")     county = tonumber("0")     countz = tonumber("0")     posx = tonumber("0")     posy = tonumber("0")     posz = tonumber("0") -- Calculate the numbers for the couter:     offsetx = offsetx(x1, x2, offsetx)     countx = tonumber(offsetx(x1, x2, offsetx).replace("-", "")) -- Doesnt work because of broken if statement???        for i=10,0,-1     do --      Placeholder. Will put filling function in here later         Player:SendMessage("offsetX=" .. offsetx)     end         --    for i=countx+county+countz,0,-1 --    do     --    end --    setblockforplugins(Player, posx, posy, posz, Split[8])     outVector3 = Vector3i(tonumber(Split[2]), tonumber(Split[3]), tonumber(Split[4]))     Player:SendMessage("Setting block " .. Split[2] .. " "  .. Split[3] .. " " .. Split[4] .. " to type " .. Split[5])     local type, meta = GetBlockTypeMeta(Split[5])     Player:GetWorld():SetBlock(outVector3, type, meta)     return true end function setblockforplugins(Player, Split)     outVector3 = Vector3i(tonumber(Split[2]), tonumber(Split[3]), tonumber(Split[4]))     Player:SendMessage("Setting block " .. Split[2] .. " "  .. Split[3] .. " " .. Split[4] .. " to type " .. Split[5])     local type, meta = GetBlockTypeMeta(Split[5])     Player:GetWorld():SetBlock(outVector3, type, meta)     return true end -- Will use this later to find the vertical offset and size: function countY(y1, y2)     if tonumber(y1) < tonumber(y2) then for i=y1,y2,-1 do   -- put function here end     else for i=y1,y2,-1 do   -- put function here end         end     return y1, y2 end -- Make offset and size and find out which values are negative. function offsetX(x1, x2, xoffset)     if tonumber(x1) < 0 then         if tonumber(x2) < 0 then     if tonumber(x1) < tonumber(x2) then for i=x1,x2,1 do                     xoffset = xoffset - 1 end     else for i=x1,x2,-1 do                     xoffset = xoffset + 1 end     end else     if tonumber(x1) < tonumber(x2) then for i=tonumber(x1.replace("-", "")),x2,1 do                     xoffset = xoffset + 1 end     else     if tonumber(x1) < tonumber(x2) then for i=x1,tonumber(x2.replace("-", "")),1 do                     xoffset = xoffset + 1 end     end         end     end     if tonumber(x1) > 0 then         if tonumber(x2) < 0 then     if tonumber(x1) < tonumber(x2) then for i=x1,tonumber(x2.replace("-", "")),1 do                     xoffset = xoffset + 1 end     else for i=tonumber(x1.replace("-", "")),x2,1 do                     xoffset = xoffset + 1 end     end else     if tonumber(x1) < tonumber(x2) then for i=x2,x1,1 do                     xoffset = xoffset + 1 end     else for i=x1,x2,1 do                     xoffset = xoffset + 1 end     end         end     end     return xoffset end end

Now it at least loads. But I get this error now:
[10:41:40] LUA: Plugins/VanillaFill/main.lua:115: attempt to call global 'offsetx' (a number value)
[10:41:40] Stack trace:
[10:41:40]  Plugins/VanillaFill/main.lua(115): (no name)
[10:41:40] Stack trace end
[10:41:40] Error in <attached> calling function <callback>()
Reply
Thanks given by:
#8
That's because you're trying to use the variable 'offsetx' as a function. You probably want to use your 'offsetX' function with a capital X.
Reply
Thanks given by:
#9
(02-19-2021, 07:45 PM)NiLSPACE Wrote: That's because you're trying to use the variable 'offsetx' as a function. You probably want to use your 'offsetX' function with a capital X.

You were right. It was a simple typo. Thank you so much.
Reply
Thanks given by:




Users browsing this thread: 1 Guest(s)