Asynchronous Block Placement

  • Welcome to skUnity!

    Welcome to skUnity! This is a forum where members of the Skript community can communicate and interact. Skript Resource Creators can post their Resources for all to see and use.

    If you haven't done so already, feel free to join our official Discord server to expand your level of interaction with the comminuty!

    Now, what are you waiting for? Join the community now!

Pikachu

Supporter
Addon Developer
Jan 25, 2017
870
145
43
Here is a snippet that allows you to place blocks in a cuboid asynchronously (and therefore without lag, great for minigames and many other uses)
code_language.skript:
on script load:
  import "com.sk89q.worldedit.regions.CuboidRegion"
  import "com.sk89q.worldedit.Vector" as {WorldEditVector}
  import "com.sk89q.worldedit.EditSession"
  import "com.boydti.fawe.FaweAPI"
  import "com.boydti.fawe.util.EditSessionBuilder"
  import "com.sk89q.worldedit.blocks.BaseBlock"
  import "com.sk89q.worldedit.patterns.BlockChance"
  import "java.util.Arrays"
  import "com.sk89q.worldedit.patterns.RandomFillPattern"
  import "java.util.stream.Collectors"

function getRegion(pos1: location, pos2: location) :: object:
  loop 1 and 2:
    set {_vec::%loop-num%} to new {WorldEditVector}(x-loc of {_pos%loop-num%}, y-loc of {_pos%loop-num%} and z-loc of {_pos%loop-num%})
  return new {CuboidRegion}({_vec::*})

function getBaseBlock(block: itemtype) :: object:
  return new {BaseBlock}({_block}.getRandom().getTypeId() and {_block}.getRandom().getData().getData())

function getBlockChance(block: itemtype, chance: number) :: object:
  return new {BlockChance}(getBaseBlock({_block}) and {_chance})

function getWorld(world: world) :: object:
  return {FaweAPI}.getWorld("%{_world}%")

function getEditSession(world: world) :: object:
  return new {EditSessionBuilder}(getWorld({_world})).fastmode(true).build()

function setBlocks(pos1: location, pos2: location, block: object) :: boolean:
  set {_session} to getEditSession(world of {_pos1})
  set {_args::*} to getRegion({_pos1}, {_pos2}) and getBaseBlock({_block})
  if {_block} is a text:
    loop split {_block} at ",":
      set {_it::*} to join (split loop-value at "%%") with " " parsed as "%integer% %item%"
      if {_it::*} is set:
        add getBlockChance({_it::2}, {_it::1}) to {_c::*}
        delete {_it::*}
      else:
        return false
    set {_args::*} to getRegion({_pos1}, {_pos2})
    add new {RandomFillPattern}({Arrays}.stream([{_c::*} as (java type "%{BlockChance}%")]).collect({Collectors}.toList())) to {_args::*}
  {_session}.setBlocks({_args::*});
  {_session}.flushQueue();
  return true

Usage:
  • Basic:
    setBlocks({corner one}, {corner two}, dirt)

  • Patterns:
    setBlocks({corner one}, {corner two}, "50%%dirt,25%%air,25%%diamond ore")
Requires:
  • skript-mirror
  • Fast Async WorldEdit
 
Last edited:
  • Like
Reactions: KingAlterIV
Is there any way to count the blocks in progress?
Not as far as I know. If you can find a method for it in the FAWE api, I'll try to implement it. You can use skquery to get the total amount of blocks however that could cause a bit of lag if the region is large
 
  • Like
Reactions: glowgrew
For updated skript-mirror version
Tested on Skript Dev36 and skript-mirror 0.16.0
Code:
import:
    com.sk89q.worldedit.regions.CuboidRegion
    com.sk89q.worldedit.Vector as WorldEditVector
    com.sk89q.worldedit.EditSession
    com.boydti.fawe.FaweAPI
    com.boydti.fawe.util.EditSessionBuilder
    com.sk89q.worldedit.blocks.BaseBlock
    com.sk89q.worldedit.patterns.BlockChance
    java.util.Arrays
    com.sk89q.worldedit.patterns.RandomFillPattern
    java.util.stream.Collectors

function getRegion(pos1: location, pos2: location) :: object:
    loop 1 and 2:
        set {_vec::%loop-value%} to new WorldEditVector((x-coord of {_pos%loop-value%}), (y-coord of {_pos%loop-value%}) and (z-coord of {_pos%loop-value%}))
    return new CuboidRegion({_vec::*})

function getBaseBlock(block: itemtype) :: object:
    return new BaseBlock({_block}.getRandom().getTypeId() and {_block}.getRandom().getData().getData())

function getBlockChance(block: itemtype, chance: number) :: object:
    return new BlockChance(getBaseBlock({_block}) and {_chance})

function getWorld(world: world) :: object:
    return FaweAPI.getWorld("%{_world}%")

function getEditSession(world: world) :: object:
    return new EditSessionBuilder(getWorld({_world})).fastmode(true).build()

function setBlocks(pos1: location, pos2: location, block: object) :: boolean:
    set {_session} to getEditSession(world of {_pos1})
    set {_args::*} to getRegion({_pos1}, {_pos2}) and getBaseBlock({_block})
    if {_block} is a text:
        loop split {_block} at ",":
            set {_it::*} to join (split loop-value at "%%") with " " parsed as "%integer% %item%"
            if {_it::*} is set:
                add getBlockChance({_it::2}, {_it::1}) to {_c::*}
                delete {_it::*}
            else:
                return false
        set {_args::*} to getRegion({_pos1}, {_pos2})
        add new RandomFillPattern(Arrays.stream([{_c::*}]).collect(Collectors.toList())) to {_args::*}
    {_session}.setBlocks({_args::*})
    {_session}.flushQueue()
    return true