code suggestions
This commit is contained in:
1 parent
238257f057
commit
e6158c1aab
5 files changed
+85
-17
No files matched your search
@@ -14,6 +14,8 @@ import com.mojang.brigadier.CommandDispatcher;
|
|||||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
import com.mojang.brigadier.context.CommandContext;
|
import com.mojang.brigadier.context.CommandContext;
|
||||||
|
import com.mojang.brigadier.suggestion.Suggestions;
|
||||||
|
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.block.pattern.CachedBlockPosition;
|
import net.minecraft.block.pattern.CachedBlockPosition;
|
||||||
import net.minecraft.command.arguments.BlockPosArgumentType;
|
import net.minecraft.command.arguments.BlockPosArgumentType;
|
||||||
@@ -31,6 +33,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
@@ -40,6 +43,31 @@ import static net.minecraft.server.command.CommandSource.suggestMatching;
|
|||||||
|
|
||||||
public class ScriptCommand
|
public class ScriptCommand
|
||||||
{
|
{
|
||||||
|
|
||||||
|
private static CompletableFuture<Suggestions> suggestCode(SuggestionsBuilder suggestionsBuilder) {
|
||||||
|
String previous = suggestionsBuilder.getRemaining().toLowerCase(Locale.ROOT);
|
||||||
|
int strlen = previous.length();
|
||||||
|
StringBuilder lastToken = new StringBuilder();
|
||||||
|
for (int idx = strlen-1; idx >=0; idx--)
|
||||||
|
{
|
||||||
|
char ch = previous.charAt(idx);
|
||||||
|
if (Character.isLetterOrDigit(ch) || ch == '_')
|
||||||
|
{
|
||||||
|
lastToken.append(ch);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (lastToken.length() == 0)
|
||||||
|
return suggestionsBuilder.buildFuture();
|
||||||
|
String prefix = lastToken.reverse().toString();
|
||||||
|
String previousString = previous.substring(0,previous.length()-prefix.length()) ;
|
||||||
|
ExpressionInspector.suggestFunctions(previousString, prefix).forEach(text -> suggestionsBuilder.suggest(previousString+text));
|
||||||
|
return suggestionsBuilder.buildFuture();
|
||||||
|
}
|
||||||
|
|
||||||
public static void register(CommandDispatcher<ServerCommandSource> dispatcher)
|
public static void register(CommandDispatcher<ServerCommandSource> dispatcher)
|
||||||
{
|
{
|
||||||
LiteralArgumentBuilder<ServerCommandSource> b = literal("globals").
|
LiteralArgumentBuilder<ServerCommandSource> b = literal("globals").
|
||||||
@@ -50,7 +78,7 @@ public class ScriptCommand
|
|||||||
executes( (cc) -> { CarpetServer.scriptServer.stopAll = false; return 1;});
|
executes( (cc) -> { CarpetServer.scriptServer.stopAll = false; return 1;});
|
||||||
LiteralArgumentBuilder<ServerCommandSource> l = literal("run").
|
LiteralArgumentBuilder<ServerCommandSource> l = literal("run").
|
||||||
requires((player) -> player.hasPermissionLevel(2)).
|
requires((player) -> player.hasPermissionLevel(2)).
|
||||||
then(argument("expr", StringArgumentType.greedyString()).
|
then(argument("expr", StringArgumentType.greedyString()).suggests((cc, bb) -> suggestCode(bb)).
|
||||||
executes((cc) -> compute(
|
executes((cc) -> compute(
|
||||||
cc,
|
cc,
|
||||||
StringArgumentType.getString(cc, "expr"))));
|
StringArgumentType.getString(cc, "expr"))));
|
||||||
@@ -113,6 +141,7 @@ public class ScriptCommand
|
|||||||
then(argument("from", BlockPosArgumentType.create()).
|
then(argument("from", BlockPosArgumentType.create()).
|
||||||
then(argument("to", BlockPosArgumentType.create()).
|
then(argument("to", BlockPosArgumentType.create()).
|
||||||
then(argument("expr", StringArgumentType.greedyString()).
|
then(argument("expr", StringArgumentType.greedyString()).
|
||||||
|
suggests((cc, bb) -> suggestCode(bb)).
|
||||||
executes( (cc) -> scriptScan(
|
executes( (cc) -> scriptScan(
|
||||||
cc,
|
cc,
|
||||||
BlockPosArgumentType.getBlockPos(cc, "origin"),
|
BlockPosArgumentType.getBlockPos(cc, "origin"),
|
||||||
|
|||||||
@@ -101,6 +101,7 @@ public class CarpetExpression
|
|||||||
private ServerCommandSource source;
|
private ServerCommandSource source;
|
||||||
private BlockPos origin;
|
private BlockPos origin;
|
||||||
private Expression expr;
|
private Expression expr;
|
||||||
|
Expression getExpr() {return expr;}
|
||||||
private static long tickStart = 0L;
|
private static long tickStart = 0L;
|
||||||
|
|
||||||
private static boolean stopAll = false;
|
private static boolean stopAll = false;
|
||||||
@@ -766,6 +767,8 @@ public class CarpetExpression
|
|||||||
|
|
||||||
this.expr.addLazyFunction("harvest", -1, (c, t, lv) ->
|
this.expr.addLazyFunction("harvest", -1, (c, t, lv) ->
|
||||||
{
|
{
|
||||||
|
if (lv.size()<2)
|
||||||
|
throw new InternalExpressionException("harvest takes at least 2 parameters: entity and block, or position, to harvest");
|
||||||
CarpetContext cc = (CarpetContext)c;
|
CarpetContext cc = (CarpetContext)c;
|
||||||
World world = cc.s.getWorld();
|
World world = cc.s.getWorld();
|
||||||
Value entityValue = lv.get(0).evalValue(cc);
|
Value entityValue = lv.get(0).evalValue(cc);
|
||||||
@@ -791,14 +794,12 @@ public class CarpetExpression
|
|||||||
|
|
||||||
this.expr.addLazyFunction("place_item", -1, (c, t, lv) ->
|
this.expr.addLazyFunction("place_item", -1, (c, t, lv) ->
|
||||||
{
|
{
|
||||||
|
if (lv.size()<2)
|
||||||
|
throw new InternalExpressionException("place_item takes at least 2 parameters: item and block, or position, to place onto");
|
||||||
CarpetContext cc = (CarpetContext) c;
|
CarpetContext cc = (CarpetContext) c;
|
||||||
String itemString = lv.get(0).evalValue(c).getString();
|
String itemString = lv.get(0).evalValue(c).getString();
|
||||||
BlockValue.VectorLocator locator = BlockValue.locateVec(cc, lv, 1);
|
BlockValue.VectorLocator locator = BlockValue.locateVec(cc, lv, 1);
|
||||||
ItemStackArgument stackArg = NBTSerializableValue.parseItem(itemString);
|
ItemStackArgument stackArg = NBTSerializableValue.parseItem(itemString);
|
||||||
if (stackArg == null)
|
|
||||||
{
|
|
||||||
throw new InternalExpressionException("unknown item: "+itemString);
|
|
||||||
}
|
|
||||||
BlockPos where = new BlockPos(locator.vec);
|
BlockPos where = new BlockPos(locator.vec);
|
||||||
String facing = "up";
|
String facing = "up";
|
||||||
if (lv.size() > locator.offset)
|
if (lv.size() > locator.offset)
|
||||||
@@ -876,6 +877,8 @@ public class CarpetExpression
|
|||||||
this.expr.addLazyFunction("inventory_get", -1, (c, t, lv) -> {
|
this.expr.addLazyFunction("inventory_get", -1, (c, t, lv) -> {
|
||||||
CarpetContext cc = (CarpetContext) c;
|
CarpetContext cc = (CarpetContext) c;
|
||||||
NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0);
|
NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0);
|
||||||
|
if (inventoryLocator == null)
|
||||||
|
return (_c, _t) -> Value.NULL;
|
||||||
if (lv.size() == inventoryLocator.offset)
|
if (lv.size() == inventoryLocator.offset)
|
||||||
{
|
{
|
||||||
List<Value> fullInventory = new ArrayList<>();
|
List<Value> fullInventory = new ArrayList<>();
|
||||||
@@ -897,6 +900,8 @@ public class CarpetExpression
|
|||||||
this.expr.addLazyFunction("inventory_drop", -1, (c, t, lv) -> {
|
this.expr.addLazyFunction("inventory_drop", -1, (c, t, lv) -> {
|
||||||
CarpetContext cc = (CarpetContext) c;
|
CarpetContext cc = (CarpetContext) c;
|
||||||
NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0);
|
NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0);
|
||||||
|
if (inventoryLocator == null)
|
||||||
|
return (_c, _t) -> Value.NULL;
|
||||||
if (lv.size() == inventoryLocator.offset)
|
if (lv.size() == inventoryLocator.offset)
|
||||||
throw new InternalExpressionException("slot number is required for inventory_drop");
|
throw new InternalExpressionException("slot number is required for inventory_drop");
|
||||||
int slot = (int)NumericValue.asNumber(lv.get(inventoryLocator.offset).evalValue(c)).getLong();
|
int slot = (int)NumericValue.asNumber(lv.get(inventoryLocator.offset).evalValue(c)).getLong();
|
||||||
@@ -947,16 +952,14 @@ public class CarpetExpression
|
|||||||
this.expr.addLazyFunction("inventory_find", -1, (c, t, lv) -> {
|
this.expr.addLazyFunction("inventory_find", -1, (c, t, lv) -> {
|
||||||
CarpetContext cc = (CarpetContext) c;
|
CarpetContext cc = (CarpetContext) c;
|
||||||
NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0);
|
NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0);
|
||||||
|
if (inventoryLocator == null)
|
||||||
|
return (_c, _t) -> Value.NULL;
|
||||||
ItemStackArgument itemArg = null;
|
ItemStackArgument itemArg = null;
|
||||||
if (lv.size() > inventoryLocator.offset)
|
if (lv.size() > inventoryLocator.offset)
|
||||||
{
|
{
|
||||||
Value secondArg = lv.get(inventoryLocator.offset+0).evalValue(c);
|
Value secondArg = lv.get(inventoryLocator.offset+0).evalValue(c);
|
||||||
if (!(secondArg instanceof NullValue))
|
if (!(secondArg instanceof NullValue))
|
||||||
{
|
|
||||||
itemArg = NBTSerializableValue.parseItem(secondArg.getString());
|
itemArg = NBTSerializableValue.parseItem(secondArg.getString());
|
||||||
if (itemArg == null)
|
|
||||||
throw new InternalExpressionException("Incorrect item format: "+secondArg.getString());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
int startIndex = 0;
|
int startIndex = 0;
|
||||||
if (lv.size() > inventoryLocator.offset+1)
|
if (lv.size() > inventoryLocator.offset+1)
|
||||||
@@ -980,7 +983,8 @@ public class CarpetExpression
|
|||||||
this.expr.addLazyFunction("inventory_set", -1, (c, t, lv) -> {
|
this.expr.addLazyFunction("inventory_set", -1, (c, t, lv) -> {
|
||||||
CarpetContext cc = (CarpetContext) c;
|
CarpetContext cc = (CarpetContext) c;
|
||||||
NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0);
|
NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0);
|
||||||
|
if (inventoryLocator == null)
|
||||||
|
return (_c, _t) -> Value.NULL;
|
||||||
if (lv.size() < inventoryLocator.offset+2)
|
if (lv.size() < inventoryLocator.offset+2)
|
||||||
throw new InternalExpressionException("inventory_set requires at least slot number and new stack size, and optional new item");
|
throw new InternalExpressionException("inventory_set requires at least slot number and new stack size, and optional new item");
|
||||||
int slot = (int) NumericValue.asNumber(lv.get(inventoryLocator.offset+0).evalValue(c)).getLong();
|
int slot = (int) NumericValue.asNumber(lv.get(inventoryLocator.offset+0).evalValue(c)).getLong();
|
||||||
@@ -1019,7 +1023,8 @@ public class CarpetExpression
|
|||||||
this.expr.addLazyFunction("inventory_remove", -1, (c, t, lv) -> {
|
this.expr.addLazyFunction("inventory_remove", -1, (c, t, lv) -> {
|
||||||
CarpetContext cc = (CarpetContext) c;
|
CarpetContext cc = (CarpetContext) c;
|
||||||
NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0);
|
NBTSerializableValue.InventoryLocator inventoryLocator = NBTSerializableValue.locateInventory(cc, lv, 0);
|
||||||
|
if (inventoryLocator == null)
|
||||||
|
return (_c, _t) -> Value.NULL;
|
||||||
if (lv.size() <= inventoryLocator.offset)
|
if (lv.size() <= inventoryLocator.offset)
|
||||||
throw new InternalExpressionException("inventory_set requires at least an item to be removed");
|
throw new InternalExpressionException("inventory_set requires at least an item to be removed");
|
||||||
ItemStackArgument searchItem = NBTSerializableValue.parseItem(lv.get(inventoryLocator.offset).evalValue(c).getString());
|
ItemStackArgument searchItem = NBTSerializableValue.parseItem(lv.get(inventoryLocator.offset).evalValue(c).getString());
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import java.util.List;
|
|||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.Stack;
|
import java.util.Stack;
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
@@ -350,6 +351,7 @@ public class Expression implements Cloneable
|
|||||||
boolean isAnOperator(String opname) { return operators.containsKey(opname) || operators.containsKey(opname+"u");}
|
boolean isAnOperator(String opname) { return operators.containsKey(opname) || operators.containsKey(opname+"u");}
|
||||||
|
|
||||||
private Map<String, ILazyFunction> functions = new HashMap<>();
|
private Map<String, ILazyFunction> functions = new HashMap<>();
|
||||||
|
Set<String> getFunctionNames() {return functions.keySet();}
|
||||||
|
|
||||||
//static final Map<String, UserDefinedFunction> globalFunctions = new HashMap<>();
|
//static final Map<String, UserDefinedFunction> globalFunctions = new HashMap<>();
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,13 @@
|
|||||||
package carpet.script;
|
package carpet.script;
|
||||||
|
|
||||||
|
import carpet.CarpetServer;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.TreeSet;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sole purpose of this package is to provide public access to package-private methods of Expression and CarpetExpression
|
* sole purpose of this package is to provide public access to package-private methods of Expression and CarpetExpression
|
||||||
@@ -17,4 +24,29 @@ public class ExpressionInspector
|
|||||||
{
|
{
|
||||||
return e.getName();
|
return e.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static TreeSet<String> scarpetFunctions;
|
||||||
|
private static TreeSet<String> APIFunctions;
|
||||||
|
static
|
||||||
|
{
|
||||||
|
Set<String> allFunctions = (new CarpetExpression("null", null, null)).getExpr().getFunctionNames();
|
||||||
|
scarpetFunctions = new TreeSet<>(new Expression("null").getFunctionNames());
|
||||||
|
APIFunctions = new TreeSet<>(allFunctions.stream().filter(s -> !scarpetFunctions.contains(s)).collect(Collectors.toSet()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<String> suggestFunctions(String previous, String prefix)
|
||||||
|
{
|
||||||
|
previous = previous.replace("\\'", "");
|
||||||
|
int quoteCount = StringUtils.countMatches(previous,'\'');
|
||||||
|
if (quoteCount % 2 == 1)
|
||||||
|
return Collections.emptyList();
|
||||||
|
int maxLen = prefix.length()<3 ? (prefix.length()*2+1) : 1234;
|
||||||
|
List<String> scarpetMatches = scarpetFunctions.stream().
|
||||||
|
filter(s -> s.startsWith(prefix) && s.length() <= maxLen).map(s -> s+"(").collect(Collectors.toList());
|
||||||
|
scarpetMatches.addAll(APIFunctions.stream().
|
||||||
|
filter(s -> s.startsWith(prefix) && s.length() <= maxLen).map(s -> s+"(").collect(Collectors.toList()));
|
||||||
|
scarpetMatches.addAll(CarpetServer.scriptServer.globalHost.globalVariables.keySet().stream().
|
||||||
|
filter(s -> s.startsWith(prefix)).collect(Collectors.toList()));
|
||||||
|
return scarpetMatches;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -51,7 +51,7 @@ public class NBTSerializableValue extends Value
|
|||||||
else if (e instanceof VillagerEntity) inv = ((VillagerEntity) e).getInventory();
|
else if (e instanceof VillagerEntity) inv = ((VillagerEntity) e).getInventory();
|
||||||
|
|
||||||
if (inv == null)
|
if (inv == null)
|
||||||
throw new InternalExpressionException("Entity " + e + " has no inventory");
|
return null;
|
||||||
|
|
||||||
return new InventoryLocator(e, e.getBlockPos(), inv, offset + 1);
|
return new InventoryLocator(e, e.getBlockPos(), inv, offset + 1);
|
||||||
}
|
}
|
||||||
@@ -59,10 +59,10 @@ public class NBTSerializableValue extends Value
|
|||||||
{
|
{
|
||||||
BlockPos pos = ((BlockValue) v1).getPos();
|
BlockPos pos = ((BlockValue) v1).getPos();
|
||||||
if (pos == null)
|
if (pos == null)
|
||||||
throw new InternalExpressionException("Block to acess inventory needs to be positioned in the world");
|
throw new InternalExpressionException("Block to access inventory needs to be positioned in the world");
|
||||||
inv = HopperBlockEntity.getInventoryAt(c.s.getWorld(), pos);
|
inv = HopperBlockEntity.getInventoryAt(c.s.getWorld(), pos);
|
||||||
if (inv == null)
|
if (inv == null)
|
||||||
throw new InternalExpressionException("Block at " + pos + " has no inventory");
|
return null;
|
||||||
return new InventoryLocator(pos, pos, inv, offset + 1);
|
return new InventoryLocator(pos, pos, inv, offset + 1);
|
||||||
}
|
}
|
||||||
else if (v1 instanceof ListValue)
|
else if (v1 instanceof ListValue)
|
||||||
@@ -74,7 +74,7 @@ public class NBTSerializableValue extends Value
|
|||||||
NumericValue.asNumber(args.get(2)).getDouble());
|
NumericValue.asNumber(args.get(2)).getDouble());
|
||||||
inv = HopperBlockEntity.getInventoryAt(c.s.getWorld(), pos);
|
inv = HopperBlockEntity.getInventoryAt(c.s.getWorld(), pos);
|
||||||
if (inv == null)
|
if (inv == null)
|
||||||
throw new InternalExpressionException("Block at " + pos + " has no inventory");
|
return null;
|
||||||
return new InventoryLocator(pos, pos, inv, offset + 1);
|
return new InventoryLocator(pos, pos, inv, offset + 1);
|
||||||
}
|
}
|
||||||
BlockPos pos = new BlockPos(
|
BlockPos pos = new BlockPos(
|
||||||
@@ -83,7 +83,7 @@ public class NBTSerializableValue extends Value
|
|||||||
NumericValue.asNumber(params.get(2 + offset).evalValue(c)).getDouble());
|
NumericValue.asNumber(params.get(2 + offset).evalValue(c)).getDouble());
|
||||||
inv = HopperBlockEntity.getInventoryAt(c.s.getWorld(), pos);
|
inv = HopperBlockEntity.getInventoryAt(c.s.getWorld(), pos);
|
||||||
if (inv == null)
|
if (inv == null)
|
||||||
throw new InternalExpressionException("Block at " + pos + " has no inventory");
|
return null;
|
||||||
return new InventoryLocator(pos, pos, inv, offset + 3);
|
return new InventoryLocator(pos, pos, inv, offset + 3);
|
||||||
}
|
}
|
||||||
catch (IndexOutOfBoundsException e)
|
catch (IndexOutOfBoundsException e)
|
||||||
@@ -109,7 +109,7 @@ public class NBTSerializableValue extends Value
|
|||||||
}
|
}
|
||||||
catch (CommandSyntaxException e)
|
catch (CommandSyntaxException e)
|
||||||
{
|
{
|
||||||
return null;
|
throw new InternalExpressionException("Incorrect item: "+itemString);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user