From 8d3b918441de93fba922858159b8bff6b918f947 Mon Sep 17 00:00:00 2001 From: Andrew Gazelka Date: Sun, 5 Mar 2017 19:57:57 -0600 Subject: [PATCH] Add option to limit //calc max execute time This fixes players abusing //calc by spamming it, causing more calculation threads be created than destroyed. --- build.gradle | 2 +- .../java/com/boydti/fawe/config/Settings.java | 3 ++ .../com/boydti/fawe/object/FaweLimit.java | 2 + .../worldedit/command/UtilityCommands.java | 39 ++++++++++--------- 4 files changed, 26 insertions(+), 20 deletions(-) diff --git a/build.gradle b/build.gradle index 71f2e49d..4f3849a4 100644 --- a/build.gradle +++ b/build.gradle @@ -28,7 +28,7 @@ ext { date = git.head().date.format("yy.MM.dd") revision = "-${git.head().abbreviatedId}" parents = git.head().parentIds; - index = -80; // Offset to mach CI + index = -81; // Offset to mach CI int major, minor, patch; major = minor = patch = 0; for (;parents != null && !parents.isEmpty();index++) { diff --git a/core/src/main/java/com/boydti/fawe/config/Settings.java b/core/src/main/java/com/boydti/fawe/config/Settings.java index 2c101516..0b404992 100644 --- a/core/src/main/java/com/boydti/fawe/config/Settings.java +++ b/core/src/main/java/com/boydti/fawe/config/Settings.java @@ -107,6 +107,8 @@ public class Settings extends Config { " - History on disk or memory will be deleted", }) public int MAX_HISTORY_MB = -1; + @Comment("Maximum time in milliseconds //calc can execute") + public int MAX_CALC_MS = 50; @Comment({ "Cinematic block placement:", " - Adds a delay to block placement (ms/block)", @@ -365,6 +367,7 @@ public class Settings extends Config { limit.MAX_FAILS = Math.max(limit.MAX_FAILS, newLimit.MAX_FAILS != -1 ? newLimit.MAX_FAILS : Integer.MAX_VALUE); limit.MAX_ITERATIONS = Math.max(limit.MAX_ITERATIONS, newLimit.MAX_ITERATIONS != -1 ? newLimit.MAX_ITERATIONS : Integer.MAX_VALUE); limit.MAX_HISTORY = Math.max(limit.MAX_HISTORY, newLimit.MAX_HISTORY_MB != -1 ? newLimit.MAX_HISTORY_MB : Integer.MAX_VALUE); + limit.MAX_CALC_MS = Math.max(limit.MAX_CALC_MS, newLimit.MAX_CALC_MS != -1 ? newLimit.MAX_CALC_MS : Integer.MAX_VALUE); limit.INVENTORY_MODE = Math.min(limit.INVENTORY_MODE, newLimit.INVENTORY_MODE); limit.SPEED_REDUCTION = Math.min(limit.SPEED_REDUCTION, newLimit.SPEED_REDUCTION); limit.FAST_PLACEMENT |= newLimit.FAST_PLACEMENT; diff --git a/core/src/main/java/com/boydti/fawe/object/FaweLimit.java b/core/src/main/java/com/boydti/fawe/object/FaweLimit.java index 5c6548ad..4252d36a 100644 --- a/core/src/main/java/com/boydti/fawe/object/FaweLimit.java +++ b/core/src/main/java/com/boydti/fawe/object/FaweLimit.java @@ -12,6 +12,7 @@ public class FaweLimit { public int MAX_BLOCKSTATES = 0; public int MAX_ENTITIES = 0; public int MAX_HISTORY = 0; + public int MAX_CALC_MS = 0; public int INVENTORY_MODE = Integer.MAX_VALUE; public int SPEED_REDUCTION = Integer.MAX_VALUE; public boolean FAST_PLACEMENT = false; @@ -55,6 +56,7 @@ public class FaweLimit { MAX.MAX_BLOCKSTATES = Integer.MAX_VALUE; MAX.MAX_ENTITIES = Integer.MAX_VALUE; MAX.MAX_HISTORY = Integer.MAX_VALUE; + MAX.MAX_CALC_MS = 50; MAX.FAST_PLACEMENT = true; } diff --git a/core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java b/core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java index 62ef6ee1..ac1a8f3c 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java @@ -20,19 +20,13 @@ package com.sk89q.worldedit.command; import com.boydti.fawe.config.BBC; +import com.boydti.fawe.object.FaweLimit; +import com.boydti.fawe.object.FawePlayer; import com.google.common.base.Joiner; import com.google.common.util.concurrent.AtomicDouble; -import com.sk89q.minecraft.util.commands.Command; -import com.sk89q.minecraft.util.commands.CommandContext; -import com.sk89q.minecraft.util.commands.CommandException; -import com.sk89q.minecraft.util.commands.CommandPermissions; -import com.sk89q.minecraft.util.commands.Logging; -import com.sk89q.worldedit.EditSession; -import com.sk89q.worldedit.LocalConfiguration; -import com.sk89q.worldedit.LocalSession; +import com.sk89q.minecraft.util.commands.*; +import com.sk89q.worldedit.*; import com.sk89q.worldedit.Vector; -import com.sk89q.worldedit.WorldEdit; -import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.command.util.CreatureButcher; import com.sk89q.worldedit.command.util.EntityRemover; @@ -64,17 +58,13 @@ import com.sk89q.worldedit.util.formatting.component.Code; import com.sk89q.worldedit.util.formatting.component.CommandListBox; import com.sk89q.worldedit.util.formatting.component.CommandUsageBox; import com.sk89q.worldedit.world.World; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Set; + +import java.util.*; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; - import static com.sk89q.minecraft.util.commands.Logging.LogMode.PLACEMENT; /** @@ -208,7 +198,7 @@ public class UtilityCommands { @CommandPermissions("worldedit.removeabove") @Logging(PLACEMENT) public void removeAbove(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException { - + int size = args.argsLength() > 0 ? Math.max(1, args.getInteger(0)) : 1; we.checkMaxRadius(size); World world = player.getWorld(); @@ -269,7 +259,7 @@ public class UtilityCommands { @CommandPermissions("worldedit.replacenear") @Logging(PLACEMENT) public void replaceNear(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException { - + int size = Math.max(1, args.getInteger(0)); int affected; Set from; @@ -524,6 +514,17 @@ public class UtilityCommands { @CommandPermissions("worldedit.calc") public void calc(final Actor actor, @Text String input) throws CommandException { try { + FaweLimit limit; + FawePlayer player = null; + if (actor != null) { + player = FawePlayer.wrap(actor); + } + if (player == null) { + limit = FaweLimit.MAX; + } else { + limit = player.getLimit(); + } + final Expression expression = Expression.compile(input); final AtomicDouble result = new AtomicDouble(Double.NaN); ExecutorService executor = Executors.newSingleThreadExecutor(); @@ -534,7 +535,7 @@ public class UtilityCommands { result.set(expression.evaluate()); return null; } - }), 10, TimeUnit.SECONDS); // Timeout of 10 minutes. + }), limit.MAX_CALC_MS, TimeUnit.MILLISECONDS); // Default timeout of 50 milliseconds to prevent abuse. } catch (InterruptedException e) { throw new RuntimeException(e); }