Cuberite Forum
ReGen Chunk in selfmade World - Printable Version

+- Cuberite Forum (https://forum.cuberite.org)
+-- Forum: Plugins (https://forum.cuberite.org/forum-1.html)
+--- Forum: Plugin Discussion (https://forum.cuberite.org/forum-8.html)
+--- Thread: ReGen Chunk in selfmade World (/thread-2697.html)



ReGen Chunk in selfmade World - moiko89 - 12-17-2016

Hi there,
i have make my own map with WorldPainter. Now i would write a plugin for regenerate chunks when there are modify by a player.
How i can make this? I cant regenerate with seed. Must i copy the chunks from a copy of my map?

moiko89


RE: ReGen Chunk in selfmade World - NiLSPACE - 12-17-2016

If you want to prevent a player from changing chunks you can use the HOOK_PLAYER_RIGHT_CLICK and HOOK_PLAYER_LEFT_CLICK hooks.


RE: ReGen Chunk in selfmade World - xoft - 12-17-2016

There are basically four options:
- don't let the players modify the world at all
- keep a copy of the world and copy from there
- keep track of all changes made by the players and undo those
- use the Forgetful world storage schema

The first one is what NiLSPACE was hinting at.

The second is a perfect example of using multiworld as an advantage - make Cuberite load both worlds, but don't let players into the "backup" world. Then simply copy any area from the backup to the main world.

Third option is the most versatile, but perhaps the most difficult to implement. An extra advantage would be the ability to selectively undo only a part of the changes.

If I were to do this, I would first try to use the fourth approach; if that wouldn't satisfy my needs, then approach number two.


RE: ReGen Chunk in selfmade World - moiko89 - 05-14-2017

(12-17-2016, 10:42 PM)xoft Wrote: - keep a copy of the world and copy from there

The second is a perfect example of using multiworld as an advantage - make Cuberite load both worlds, but don't let players into the "backup" world. Then simply copy any area from the backup to the main world.

At first i think the second option is the best.
How i can log if a entity has modify a chunk?

How i can copy the chunk from backup world to main world?
Okay, i looked in the WorldEdit Plugin, is this the best way?

PHP Code:
function copy(World,chX,chZ)
    print(
"Start Copy for:",chX,chZ)

    
local startX math.floor(chX 16)
    
local endX math.floor(chX 16) + 16
    local startZ 
math.floor(chZ 16)
    
local endZ math.floor(chZ 16) + 16

    
print(startX,endX,startZ,endZ)

    for 
startXendX do
        for 
0255 do
            for 
startZendZ do
                
local BlockType World:GetBlock(XYZ)
                if(
BlockType ~= 0then
                    local BlockMeta 
World:GetBlockMeta(XYZ)
                    print(
"Copy Block",X,Y,Z,"BlockID;"BlockType)
                    -- 
Test Copy to the next X Chunk
                    World
:SetBlock(X+16YZBlockTypeBlockMetafalse)
                
end
            end
        end
    end
end 




I doesnt find a function and hook in wiki.


RE: ReGen Chunk in selfmade World - xoft - 05-15-2017

In the Hooks section of the API documentation, there's the list of hooks Cuberite supports. I think you want the HOOK_PLAYER_BROKEN_BLOCK and HOOK_PLAYER_PLACED_BLOCK.
https://api.cuberite.org/#hooks

Copying the chunk one block at a time will be slow. Instead, use a cBlockArea to read the entire chunk in one API call and write it in another single API call.

Note, though, that the cBlockArea currently doesn't support block entities nor regular entities, so your plugin will have to process those separately.


RE: ReGen Chunk in selfmade World - moiko89 - 05-16-2017

(05-15-2017, 05:18 AM)xoft Wrote: In the Hooks section of the API documentation, there's the list of hooks Cuberite supports. I think you want the HOOK_PLAYER_BROKEN_BLOCK and HOOK_PLAYER_PLACED_BLOCK.
https://api.cuberite.org/#hooks

Copying the chunk one block at a time will be slow. Instead, use a cBlockArea to read the entire chunk in one API call and write it in another single API call.

Note, though, that the cBlockArea currently doesn't support block entities nor regular entities, so your plugin will have to process those separately.

Do you have an simple example for copy with cBlockArea?


RE: ReGen Chunk in selfmade World - xoft - 05-16-2017

The WorldEdit plugin has a //copy and //paste commands that basically do what you want to do.
Simply put, you need to create a cBlockArea object, Read data into it (from within a cWorld:ChunkStay() to make sure the chunks are loaded) and then Write() it to the destination, again in a cWorld:ChunkStay(). Note that it's a bad idea to call a ChunkStay from another world's ChunkStay handler, because that could result in a deadlock. Use cWorld:QueueTask on the second world to avoid the deadlock.
local ba = cBlockArea()
srcWorld:ChunkStay(chunkCoords, nil,
  function()
    ba:Read(srcWorld, ...)
    dstWorld:QueueTask(
      function()
        ba:Write(dstWorld, ...)
        ba:Clear()
      end
    )
  end
)



RE: ReGen Chunk in selfmade World - moiko89 - 05-17-2017

Hi,

function MyOnPlayerRightClick(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, CursorY, CursorZ) -- See API docs for parameters of all hooks

 local chunkx = math.floor(BlockX / 16)
 local chunkz = math.floor(BlockZ / 16)

 SourceWorld = cRoot:Get():GetWorld(Player:GetWorld():GetName() .. '_backup')
 DestWorld = Player:GetWorld()
 --print(backUpWorld:GetName())

 local ba = cBlockArea()


 local startX = math.floor(chunkx * 16)
 local endX = math.floor(chunkx * 16) + 15
 local startZ = math.floor(chunkz * 16)
 local endZ = math.floor(chunkz * 16) + 15

 local cubo = cCuboid(startX,1,startZ,endX,255,endZ)

 SourceWorld:ChunkStay({{chunkx, chunkz}}, nil,
  function()
    ba:Read(SourceWorld, cubo)
    DestWorld:QueueTask(
      function()
        ba:Write(DestWorld, startX, 2, startZ)
        ba:Clear()
      end
    )
  end
)

end

and my terminal says:

Code:
[20:56:44] cChunk::WriteBlockArea(): unsupported datatype request, can write only types + metas (0x3), requested 0x0. Ignoring.

Whats my fail?


RE: ReGen Chunk in selfmade World - xoft - 05-17-2017

That should work. For some reason it seems that the blockarea is not read from the source world (you should check for failures - it returns a boolean).
For troubleshooting, what does ba:GetDataValues() return after the Read() call?
Or it could be some weird API binding failure, Write() function mis-interpreting one of its parameters. Try using ba:Write(DestWorld, startX, 2, startZ, cBlockArea.baTypes + cBlockArea.baMetas)

Also, I forgot that there needs to be one more ChunkStay, for the DestWorld, inside the DestWorld:QueueTask()'s callback:
   ...
   DestWorld:QueueTask(
     function()
       DestWorld:ChunkStay({{chunkx, chunkz}}, nil,
         function()
           ba:Write(DestWorld, startX, 2, startZ)
           ba:Clear()
         end  -- ChunkStay callback
       )
     end  -- QueueTask callback
   )
   ...