Skip to content

Commit

Permalink
Add a 'delayed' argument to modifyblock
Browse files Browse the repository at this point in the history
Safe massive-area editing? Hell yes!
  • Loading branch information
mcmonkey4eva committed Nov 13, 2014
1 parent 2a707b8 commit 3e2cd71
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 48 deletions.
1 change: 0 additions & 1 deletion src/main/java/net/aufdemrand/denizen/objects/aH.java
Expand Up @@ -133,7 +133,6 @@ public Argument getPrefix() {


// TODO: REMOVE IN 1.0
@Deprecated
public boolean matches(String values) {
for (String value : StringUtils.split(values, ',')) {
if (CoreUtilities.toLowerCase(value.trim()).equals(lower_value))
Expand Down
Expand Up @@ -1706,7 +1706,7 @@ public void registerCoreMembers() {

// <--[command]
// @Name ModifyBlock
// @Syntax modifyblock [<location>|...] [<material>|...] (radius:<#>) (height:<#>) (depth:<#>) (no_physics/naturally)
// @Syntax modifyblock [<location>|...] [<material>|...] (radius:<#>) (height:<#>) (depth:<#>) (no_physics/naturally) (delayed)
// @Required 2
// @Stable stable
// @Short Modifies blocks.
Expand All @@ -1718,13 +1718,14 @@ public void registerCoreMembers() {
// physics taking over the modified blocks. This is useful for block types such as portals. This does NOT
// control physics for an extended period of time.
// Use 'naturally' when setting a block to air to break it naturally, meaning that it will drop items.
// Use 'delayed' to make the modifyblock slowly edit blocks at a time pace roughly equivalent to the server's limits.
// @Tags
// <l@location.block.material>
// @Usage
// TODO: Document Command Details
// -->
registerCoreMember(ModifyBlockCommand.class,
"MODIFYBLOCK", "modifyblock [<location>] [<material>|...] (radius:<#>) (height:<#>) (depth:<#>) (no_physics/naturally)", 2);
"MODIFYBLOCK", "modifyblock [<location>] [<material>|...] (radius:<#>) (height:<#>) (depth:<#>) (no_physics/naturally) (delayed)", 2);


// <--[command]
Expand Down
Expand Up @@ -31,6 +31,10 @@

public class ModifyBlockCommand extends AbstractCommand implements Listener {

public class IntHolder {
public int MyInteger = 0;
}

@Override
public void parseArgs(ScriptEntry scriptEntry)throws InvalidArgumentsException {

Expand Down Expand Up @@ -70,6 +74,9 @@ else if (arg.matches("no_physics"))
else if (arg.matches("naturally"))
scriptEntry.addObject("natural", new Element(true));

else if (arg.matches("delayed"))
scriptEntry.addObject("delayed", new Element(true));

else
arg.reportUnhandled();
}
Expand All @@ -87,89 +94,133 @@ else if (arg.matches("naturally"))
.defaultObject("height", new Element(0))
.defaultObject("depth", new Element(0))
.defaultObject("physics", new Element(true))
.defaultObject("natural", new Element(false));
.defaultObject("natural", new Element(false))
.defaultObject("delayed", new Element(false));

}


@Override
public void execute(ScriptEntry scriptEntry) throws CommandExecutionException {

dList materials = (dList) scriptEntry.getObject("materials");
List<dObject> locations = (List<dObject>) scriptEntry.getObject("locations");
Element physics = scriptEntry.getElement("physics");
Element natural = scriptEntry.getElement("natural");
Element radiusElement = scriptEntry.getElement("radius");
Element heightElement = scriptEntry.getElement("height");
Element depthElement = scriptEntry.getElement("depth");
List<dMaterial> materialList = materials.filter(dMaterial.class);
final dList materials = (dList) scriptEntry.getObject("materials");
final List<dObject> locations = (List<dObject>) scriptEntry.getObject("locations");
final Element physics = scriptEntry.getElement("physics");
final Element natural = scriptEntry.getElement("natural");
final Element delayed = scriptEntry.getElement("delayed");
final Element radiusElement = scriptEntry.getElement("radius");
final Element heightElement = scriptEntry.getElement("height");
final Element depthElement = scriptEntry.getElement("depth");
final List<dMaterial> materialList = materials.filter(dMaterial.class);

dB.report(scriptEntry, getName(), aH.debugList("locations", locations)
+ materials.debug()
+ physics.debug()
+ radiusElement.debug()
+ heightElement.debug()
+ depthElement.debug()
+ natural.debug());
+ natural.debug()
+ delayed.debug());

boolean doPhysics = physics.asBoolean();
boolean isNatural = natural.asBoolean();
int radius = radiusElement.asInt();
int height = heightElement.asInt();
int depth = depthElement.asInt();
final boolean doPhysics = physics.asBoolean();
final boolean isNatural = natural.asBoolean();
final int radius = radiusElement.asInt();
final int height = heightElement.asInt();
final int depth = depthElement.asInt();

no_physics = !doPhysics;
if (delayed.asBoolean()) {
final IntHolder myint = new IntHolder();
myint.MyInteger = Bukkit.getScheduler().scheduleSyncRepeatingTask(DenizenAPI.getCurrentInstance(), new Runnable() {
@Override
public void run() {
boolean was_static = preSetup(locations);
int index = 0;
long start = System.currentTimeMillis();
Location loc = (dLocation)locations.get(0);
while (locations.size() > 0) {
handleLocation((dLocation) locations.get(0), index, materialList, doPhysics, isNatural, radius, height, depth);
locations.remove(0);
if (System.currentTimeMillis() - start > 50) {
break;
}
}
postComplete(loc, was_static);
if (locations.size() == 0) {
Bukkit.getScheduler().cancelTask(myint.MyInteger);
}
}
}, 1, 1);
}
else {
boolean was_static = preSetup(locations);
Location loc = (dLocation)locations.get(0);
int index = 0;
for (dObject obj : locations) {
handleLocation((dLocation) obj, index, materialList, doPhysics, isNatural, radius, height, depth);
}
postComplete(loc, was_static);
}
}

boolean preSetup(List<dObject> locations) {
if (locations.size() == 0)
return false;
// Freeze the first world in the list.
CraftWorld craftWorld = (CraftWorld)((dLocation)locations.get(0)).getWorld();
boolean was_static = craftWorld.getHandle().isStatic;
if (no_physics)
craftWorld.getHandle().isStatic = true;
return was_static;
}

int index = 0;
for (dObject obj : locations) {
void postComplete(Location loc, boolean was_static) {
// Unfreeze the first world in the list.
CraftWorld craftWorld = (CraftWorld)loc.getWorld();
if (no_physics)
craftWorld.getHandle().isStatic = was_static;
no_physics = false;
}

dMaterial material = materialList.get(index % materialList.size());
index++;
dLocation location = (dLocation) obj;
World world = location.getWorld();
void handleLocation(dLocation location, int index, List<dMaterial> materialList, boolean doPhysics,
boolean isNatural, int radius, int height, int depth) {

location.setX(location.getBlockX());
location.setY(location.getBlockY());
location.setZ(location.getBlockZ());
setBlock(location, material, doPhysics, isNatural);
dMaterial material = materialList.get(index % materialList.size());
index++;
World world = location.getWorld();

if (radius != 0){
for (int x = 0; x < 2 * radius + 1; x++) {
for (int z = 0; z < 2 * radius + 1; z++) {
setBlock(new Location(world, location.getX() + x - radius, location.getY(), location.getZ() + z - radius), material, doPhysics, isNatural);
}
location.setX(location.getBlockX());
location.setY(location.getBlockY());
location.setZ(location.getBlockZ());
setBlock(location, material, doPhysics, isNatural);

if (radius != 0){
for (int x = 0; x < 2 * radius + 1; x++) {
for (int z = 0; z < 2 * radius + 1; z++) {
setBlock(new Location(world, location.getX() + x - radius, location.getY(), location.getZ() + z - radius), material, doPhysics, isNatural);
}
}
}

if (height != 0){
for (int x = 0; x < 2 * radius + 1; x++) {
for (int z = 0; z < 2 * radius + 1; z++) {
for (int y = 1; y < height + 1; y++) {
setBlock(new Location(world, location.getX() + x - radius, location.getY() + y, location.getZ() + z - radius), material, doPhysics, isNatural);
}
if (height != 0){
for (int x = 0; x < 2 * radius + 1; x++) {
for (int z = 0; z < 2 * radius + 1; z++) {
for (int y = 1; y < height + 1; y++) {
setBlock(new Location(world, location.getX() + x - radius, location.getY() + y, location.getZ() + z - radius), material, doPhysics, isNatural);
}
}
}
}

if (depth != 0){
for (int x = 0; x < 2 * radius + 1; x++) {
for (int z = 0; z < 2 * radius + 1; z++) {
for (int y = 1; y < depth + 1; y++) {
setBlock(new Location(world, location.getX() + x - radius, location.getY() - y, location.getZ() + z - radius), material, doPhysics, isNatural);
}
if (depth != 0){
for (int x = 0; x < 2 * radius + 1; x++) {
for (int z = 0; z < 2 * radius + 1; z++) {
for (int y = 1; y < depth + 1; y++) {
setBlock(new Location(world, location.getX() + x - radius, location.getY() - y, location.getZ() + z - radius), material, doPhysics, isNatural);
}
}
}
}
if (no_physics)
craftWorld.getHandle().isStatic = was_static;
no_physics = false;
}

void setBlock(Location location, dMaterial material, boolean physics, boolean natural) {
Expand Down

0 comments on commit 3e2cd71

Please sign in to comment.