cBlockArea
#1
I've finished the rudimentary cBlockArea support - now the object can be read and written and somewhat manipulated. It should become one of the most important parts of plugin API - whenever a plugin needs to read or write multiple blocks at once, it should do so using a cBlockArea.

I've also implemented a tiny example plugin that uses the cBlockArea: DiamondMover. When a player right-clicks a block while holding a diamond, an area around that block is shifted in the direction the player is looking.
Reply
Thanks given by:
#2
Sounds very usefulBig Grin
Reply
Thanks given by:
#3
Check out the DiamondMover plugin, it's so simple yet so hilarious Wink
Reply
Thanks given by:
#4
I don't realy know how cBlockArea works but it seems realy good. i want to use it in my PreciousBlocks plugin but i don't realy know how to work with it. i now use World:SetBlock to set a blocktype but how can i use cBlockArea with that?
Reply
Thanks given by:
#5
cBlockArea is somewhat like the Clipboard in Windows - you press Ctrl+C, it remembers. You press Ctrl+V, it writes whatever is stored within. But cBlockArea is even better, because you can modify its contents between the copy and paste operations.

So, the usual workflow is:
1, Create a new empty cBlockArea object: local Area = cBlockArea();
2, Read an area from cWorld (Ctrl+C): Area:Read(World, MinX, MaxX, MinY, MaxY, MinZ, MaxZ);
3, Query or modify the contents: Area:SetRelBlockTypeMeta(RelX, RelY, RelZ, E_BLOCK_AIR, 0); etc.
4, Write the area to cWorld (Ctrl+V): Area:Write(World, MinX, MinY, MinZ);

For example, the following code reads an area around a player and replaces all air with cobwebs (off the top of my head, not checked, may need tweaking / fixing):
Code:
local Area = cBlockArea();
local BlockX = Player:GetPosX();
local BlockY = Player:GetPosY();
local BlockZ = Player:GetPosZ();
Area:Read(Player:GetWorld(),
    BlockX - 8, BlockX + 8,  -- 17 blocks across the X coord
    BlockY - 8, BlockY + 8,  -- 17 blocks across the Y coord
    BlockZ - 8, BlockZ + 8   -- 17 blocks across the Z coord
);
for y = 0, 17 do
    for z = 0, 17 do
        for x = 0, 17 do
            if (Area:GetRelBlockType(x, y, z) == E_BLOCK_AIR) then
                Area:SetRelBlockTypeMeta(x, y, z, E_BLOCK_COBWEB, 0);
            end
        end
    end
end
Area:Write(Player:GetWorld, BlockX - 8, BlockY - 8, BlockZ - 8);

Alternatively, instead of reading a block area from cWorld, you can either create an empty one from scratch (cBlockArea:Create() ) or load from disk (cBlockArea:LoadFromSchematicFile() )

The benefit of using cBlockArea over cWorld:GetBlock() is really seen when it comes to multiple blocks being manipulated.
cWorld:GetBlock has to do all this each time it is called:
1, Lock the chunkmap (so that no other thread can modify or unload chunks)
2, Find the chunk corresponding to the coords
3, Retrieve (or set) the block type in the found chunk
4, Unlock the chunkmap
If you do this for many blocks, soon you will find out that the locking and searching (steps 1 & 2) are really eating away your performance.

For example, if you wanted to do the same thing as my previous example did (replace air blocks around the player with cobwebs) using cWorld:GetBlock() and cWorld:SetBlock(), it would make 17x17x17 locks and searches for the GetBlock() and up to 17x17x17 locks and searches for SetBlock(). That's a whopping 9826 locks and searches. Compare that to a single lock and search for cBlockArea:Read() and another single lock and search for cBlockArea:Write().
Reply
Thanks given by:
#6
cBlockArea can't copy/paste chest's. you can't even open them.
Reply
Thanks given by:
#7
yeah, it doesn't have support for block entities yet.
Reply
Thanks given by:
#8
how does BlockArea:GetBlockMeta and BlockArea:GetBlockType work? i am now trying to make //replace work with BlockArea but GetBlockType gives or 0 or a high number like 178. I used this code:
BlockArea:Read( World, OneX, TwoX, OneY, TwoY, OneZ, TwoZ )

for X=1, BlockArea:GetSizeX() do
	for Y=1, BlockArea:GetSizeY() do
		for Z=1, BlockArea:GetSizeZ() do
			if BlockArea:GetBlockType( X, Y, Z )== ChangeBlock[1] then
				if BlockArea:GetBlockMeta( X, Y, Z )== ChangeBlock[2] then
					BlockArea:SetBlockType( X, Y, Z, ToChangeBlock[1] )
					BlockArea:SetBlockMeta( X, Y, Z, ToChangeBlock[2] )
					Blocks[Player:GetName()] = Blocks[Player:GetName()] + 1					
                end
			end
		end
	end
end
Reply
Thanks given by:
#9
It should work normally, but the coords are 0-based, so your for-loops should be a bit different:
for X = 0, BlockArea:GetSizeX() - 1 do
    for Y = 0, BlockArea:GetSizeY() - 1 do
        for Z = 0, BlockArea:GetSizeZ() - 1 do
You were probably reading out of range, that's why you got 178.
Reply
Thanks given by:
#10
It works Smile thanksBig Grin

... it doesn't work. :S i just forgot to disable the old slower code. i still get weird numbers. i used
 print( "Type: " .. BlockArea:GetBlockType( X, Y, Z ) )
print( "Meta: " .. BlockArea:GetBlockMeta( X, Y, Z ) ) 
in the for-loop and i got this in a 1x4 selection:
Code:
Type: 0
Meta: 0
Type: 75
Meta: 25
Type: 139
Meta: 139
Type: 178
Meta: 178

wait i got it workingBig Grin i had to use BlockArea:GetRelBlockType.
Reply
Thanks given by:




Users browsing this thread: 5 Guest(s)