Posts: 14
Threads: 5
Joined: Feb 2021
Thanks: 1
Given 1 thank(s) in 1 post(s)
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'
Posts: 4,628
Threads: 115
Joined: Dec 2011
Thanks: 693
Given 494 thank(s) in 423 post(s)
Could you post the code around the for loop?
Posts: 14
Threads: 5
Joined: Feb 2021
Thanks: 1
Given 1 thank(s) in 1 post(s)
(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
Posts: 14
Threads: 5
Joined: Feb 2021
Thanks: 1
Given 1 thank(s) in 1 post(s)
If there is a more elegant way to fill an area from a plugin, please tell me. Would make my life way easyer here.
Posts: 4,628
Threads: 115
Joined: Dec 2011
Thanks: 693
Given 494 thank(s) in 423 post(s)
02-19-2021, 07:32 PM
(This post was last modified: 02-19-2021, 07:33 PM by NiLSPACE.)
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.
Posts: 4,628
Threads: 115
Joined: Dec 2011
Thanks: 693
Given 494 thank(s) in 423 post(s)
(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?
Posts: 14
Threads: 5
Joined: Feb 2021
Thanks: 1
Given 1 thank(s) in 1 post(s)
(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>()
Posts: 4,628
Threads: 115
Joined: Dec 2011
Thanks: 693
Given 494 thank(s) in 423 post(s)
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.
Posts: 14
Threads: 5
Joined: Feb 2021
Thanks: 1
Given 1 thank(s) in 1 post(s)
(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.
|