semi-auto cleanup
This commit is contained in:
1 parent
cad80f82c6
commit
8f61271606
99 files changed
+11463
-8007
No files matched your search
@@ -3,6 +3,7 @@ package carpet.script.argument;
|
||||
public abstract class Argument
|
||||
{
|
||||
public int offset;
|
||||
|
||||
protected Argument(int offset)
|
||||
{
|
||||
this.offset = offset;
|
||||
|
||||
@@ -7,48 +7,52 @@ import carpet.script.value.ListValue;
|
||||
import carpet.script.value.NumericValue;
|
||||
import carpet.script.value.StringValue;
|
||||
import carpet.script.value.Value;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
|
||||
public class BlockArgument extends Argument
|
||||
{
|
||||
public final BlockValue block;
|
||||
public final String replacement;
|
||||
private BlockArgument(BlockValue b, int o)
|
||||
|
||||
private BlockArgument(final BlockValue b, final int o)
|
||||
{
|
||||
super(o);
|
||||
block = b;
|
||||
replacement = null;
|
||||
}
|
||||
private BlockArgument(BlockValue b, int o, String replacement)
|
||||
|
||||
private BlockArgument(final BlockValue b, final int o, final String replacement)
|
||||
{
|
||||
super(o);
|
||||
block = b;
|
||||
this.replacement = replacement;
|
||||
}
|
||||
|
||||
public static BlockArgument findIn(CarpetContext c, List<Value> params, int offset)
|
||||
public static BlockArgument findIn(final CarpetContext c, final List<Value> params, final int offset)
|
||||
{
|
||||
return findIn(c, params,offset, false, false, false);
|
||||
return findIn(c, params, offset, false, false, false);
|
||||
}
|
||||
|
||||
public static BlockArgument findIn(CarpetContext c, List<Value> params, int offset, boolean acceptString)
|
||||
public static BlockArgument findIn(final CarpetContext c, final List<Value> params, final int offset, final boolean acceptString)
|
||||
{
|
||||
return findIn(c, params,offset, acceptString, false, false);
|
||||
return findIn(c, params, offset, acceptString, false, false);
|
||||
}
|
||||
|
||||
public static BlockArgument findIn(CarpetContext c, List<Value> params, int offset, boolean acceptString, boolean optional, boolean anyString)
|
||||
public static BlockArgument findIn(final CarpetContext c, final List<Value> params, final int offset, final boolean acceptString, final boolean optional, final boolean anyString)
|
||||
{
|
||||
return findIn(c, params.listIterator(offset), offset, acceptString, optional, anyString);
|
||||
}
|
||||
|
||||
public static BlockArgument findIn(CarpetContext c, Iterator<Value> params, int offset, boolean acceptString, boolean optional, boolean anyString)
|
||||
public static BlockArgument findIn(final CarpetContext c, final Iterator<Value> params, final int offset, final boolean acceptString, final boolean optional, final boolean anyString)
|
||||
{
|
||||
try
|
||||
{
|
||||
Value v1 = params.next();
|
||||
final Value v1 = params.next();
|
||||
//add conditional from string name
|
||||
if (optional && v1.isNull())
|
||||
{
|
||||
@@ -69,10 +73,10 @@ public class BlockArgument extends Argument
|
||||
final BlockPos pos = c.origin();
|
||||
if (v1 instanceof ListValue)
|
||||
{
|
||||
List<Value> args = ((ListValue) v1).getItems();
|
||||
int xpos = (int) NumericValue.asNumber(args.get(0)).getLong();
|
||||
int ypos = (int) NumericValue.asNumber(args.get(1)).getLong();
|
||||
int zpos = (int) NumericValue.asNumber(args.get(2)).getLong();
|
||||
final List<Value> args = ((ListValue) v1).getItems();
|
||||
final int xpos = (int) NumericValue.asNumber(args.get(0)).getLong();
|
||||
final int ypos = (int) NumericValue.asNumber(args.get(1)).getLong();
|
||||
final int zpos = (int) NumericValue.asNumber(args.get(2)).getLong();
|
||||
|
||||
return new BlockArgument(
|
||||
new BlockValue(
|
||||
@@ -82,9 +86,9 @@ public class BlockArgument extends Argument
|
||||
),
|
||||
1 + offset);
|
||||
}
|
||||
int xpos = (int) NumericValue.asNumber(v1).getLong();
|
||||
int ypos = (int) NumericValue.asNumber( params.next()).getLong();
|
||||
int zpos = (int) NumericValue.asNumber( params.next()).getLong();
|
||||
final int xpos = (int) NumericValue.asNumber(v1).getLong();
|
||||
final int ypos = (int) NumericValue.asNumber(params.next()).getLong();
|
||||
final int zpos = (int) NumericValue.asNumber(params.next()).getLong();
|
||||
return new BlockArgument(
|
||||
new BlockValue(
|
||||
null,
|
||||
@@ -100,13 +104,17 @@ public class BlockArgument extends Argument
|
||||
}
|
||||
}
|
||||
|
||||
private static InternalExpressionException handleError(boolean optional, boolean acceptString)
|
||||
private static InternalExpressionException handleError(final boolean optional, final boolean acceptString)
|
||||
{
|
||||
String message = "Block-type argument should be defined either by three coordinates (a triple or by three arguments), or a block value";
|
||||
if (acceptString)
|
||||
message+=", or a string with block description";
|
||||
{
|
||||
message += ", or a string with block description";
|
||||
}
|
||||
if (optional)
|
||||
message+=", or null";
|
||||
{
|
||||
message += ", or null";
|
||||
}
|
||||
return new InternalExpressionException(message);
|
||||
}
|
||||
|
||||
|
||||
@@ -59,14 +59,19 @@ public class FileArgument
|
||||
private FileSystem zfs;
|
||||
private Path zipPath;
|
||||
|
||||
public final static Object writeIOSync = new Object();
|
||||
public static final Object writeIOSync = new Object();
|
||||
|
||||
public void close() {
|
||||
if (zfs != null && zfs.isOpen()) {
|
||||
try {
|
||||
public void close()
|
||||
{
|
||||
if (zfs != null && zfs.isOpen())
|
||||
{
|
||||
try
|
||||
{
|
||||
zfs.close();
|
||||
} catch (IOException e) {
|
||||
throw new InternalExpressionException("Unable to close zip container: "+zipContainer);
|
||||
}
|
||||
catch (final IOException e)
|
||||
{
|
||||
throw new InternalExpressionException("Unable to close zip container: " + zipContainer);
|
||||
}
|
||||
zfs = null;
|
||||
}
|
||||
@@ -86,10 +91,10 @@ public class FileArgument
|
||||
|
||||
public static Map<String, Type> of = Arrays.stream(values()).collect(Collectors.toMap(t -> t.id, t -> t));
|
||||
|
||||
Type(String id, String extension)
|
||||
Type(final String id, final String extension)
|
||||
{
|
||||
this.id = id;
|
||||
this.extension = extension;
|
||||
this.id = id;
|
||||
this.extension = extension;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,7 +103,7 @@ public class FileArgument
|
||||
READ, CREATE, DELETE
|
||||
}
|
||||
|
||||
public FileArgument(String resource, Type type, String zipContainer, boolean isFolder, boolean isShared, Reason reason)
|
||||
public FileArgument(final String resource, final Type type, final String zipContainer, final boolean isFolder, final boolean isShared, final Reason reason)
|
||||
{
|
||||
this.resource = resource;
|
||||
this.type = type;
|
||||
@@ -111,48 +116,68 @@ public class FileArgument
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "path: "+resource+" zip: "+zipContainer+" type: "+type.id+" folder: "+isFolder+" shared: "+isShared+" reason: "+reason.toString();
|
||||
public String toString()
|
||||
{
|
||||
return "path: " + resource + " zip: " + zipContainer + " type: " + type.id + " folder: " + isFolder + " shared: " + isShared + " reason: " + reason.toString();
|
||||
}
|
||||
|
||||
public static FileArgument from(List<Value> lv, boolean isFolder, Reason reason)
|
||||
public static FileArgument from(final List<Value> lv, final boolean isFolder, final Reason reason)
|
||||
{
|
||||
if (lv.size() < 2) throw new InternalExpressionException("File functions require path and type as first two arguments");
|
||||
String origtype = lv.get(1).getString().toLowerCase(Locale.ROOT);
|
||||
boolean shared = origtype.startsWith("shared_");
|
||||
String typeString = shared ? origtype.substring(7) : origtype; //len(shared_)
|
||||
Type type = Type.of.get(typeString);
|
||||
Pair<String, String> resource = recognizeResource(lv.get(0).getString(), isFolder, type);
|
||||
if (type==null)
|
||||
throw new InternalExpressionException("Unsupported file type: "+origtype);
|
||||
if (type==Type.FOLDER && !isFolder)
|
||||
if (lv.size() < 2)
|
||||
{
|
||||
throw new InternalExpressionException("File functions require path and type as first two arguments");
|
||||
}
|
||||
final String origtype = lv.get(1).getString().toLowerCase(Locale.ROOT);
|
||||
final boolean shared = origtype.startsWith("shared_");
|
||||
final String typeString = shared ? origtype.substring(7) : origtype; //len(shared_)
|
||||
final Type type = Type.of.get(typeString);
|
||||
final Pair<String, String> resource = recognizeResource(lv.get(0).getString(), isFolder, type);
|
||||
if (type == null)
|
||||
{
|
||||
throw new InternalExpressionException("Unsupported file type: " + origtype);
|
||||
}
|
||||
if (type == Type.FOLDER && !isFolder)
|
||||
{
|
||||
throw new InternalExpressionException("Folder types are no supported for this IO function");
|
||||
return new FileArgument(resource.getLeft(), type,resource.getRight(), isFolder, shared, reason);
|
||||
}
|
||||
return new FileArgument(resource.getLeft(), type, resource.getRight(), isFolder, shared, reason);
|
||||
|
||||
}
|
||||
|
||||
public static FileArgument resourceFromPath(String path, Reason reason, boolean shared)
|
||||
public static FileArgument resourceFromPath(final String path, final Reason reason, final boolean shared)
|
||||
{
|
||||
Pair<String, String> resource = recognizeResource(path, false, Type.ANY);
|
||||
return new FileArgument(resource.getLeft(), Type.ANY,resource.getRight(), false, shared, reason);
|
||||
final Pair<String, String> resource = recognizeResource(path, false, Type.ANY);
|
||||
return new FileArgument(resource.getLeft(), Type.ANY, resource.getRight(), false, shared, reason);
|
||||
}
|
||||
|
||||
public static Pair<String,String> recognizeResource(String origfile, boolean isFolder, Type type)
|
||||
public static Pair<String, String> recognizeResource(final String origfile, final boolean isFolder, final Type type)
|
||||
{
|
||||
String[] pathElements = origfile.split("[/\\\\]+");
|
||||
List<String> path = new ArrayList<>();
|
||||
final String[] pathElements = origfile.split("[/\\\\]+");
|
||||
final List<String> path = new ArrayList<>();
|
||||
String zipPath = null;
|
||||
for (int i =0; i < pathElements.length; i++ )
|
||||
for (int i = 0; i < pathElements.length; i++)
|
||||
{
|
||||
String token = pathElements[i];
|
||||
boolean isZip = token.endsWith(".zip") && (isFolder || (i < pathElements.length-1));
|
||||
if (zipPath != null && isZip) throw new InternalExpressionException(token+" indicates zip access in an already zipped location "+zipPath);
|
||||
if (isZip) token = token.substring(0, token.length()-4);
|
||||
token = (type==Type.ANY && i == pathElements.length-1)? // sloppy really, but should work
|
||||
token.replaceAll("[^A-Za-z0-9\\-+_.]", ""):
|
||||
final boolean isZip = token.endsWith(".zip") && (isFolder || (i < pathElements.length - 1));
|
||||
if (zipPath != null && isZip)
|
||||
{
|
||||
throw new InternalExpressionException(token + " indicates zip access in an already zipped location " + zipPath);
|
||||
}
|
||||
if (isZip)
|
||||
{
|
||||
token = token.substring(0, token.length() - 4);
|
||||
}
|
||||
token = (type == Type.ANY && i == pathElements.length - 1) ? // sloppy really, but should work
|
||||
token.replaceAll("[^A-Za-z0-9\\-+_.]", "") :
|
||||
token.replaceAll("[^A-Za-z0-9\\-+_]", "");
|
||||
if (token.isEmpty()) continue;
|
||||
if (isZip) token = token + ".zip";
|
||||
if (token.isEmpty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (isZip)
|
||||
{
|
||||
token = token + ".zip";
|
||||
}
|
||||
path.add(token);
|
||||
if (isZip)
|
||||
{
|
||||
@@ -161,80 +186,106 @@ public class FileArgument
|
||||
}
|
||||
}
|
||||
if (path.isEmpty() && !isFolder)
|
||||
{
|
||||
throw new InternalExpressionException(
|
||||
"Cannot use "+origfile+" as resource name: indicated path is empty"+((zipPath==null)?"":" in zip container "+zipPath)
|
||||
"Cannot use " + origfile + " as resource name: indicated path is empty" + ((zipPath == null) ? "" : " in zip container " + zipPath)
|
||||
);
|
||||
}
|
||||
return Pair.of(String.join("/", path), zipPath);
|
||||
}
|
||||
|
||||
private Path resolve(String suffix)
|
||||
private Path resolve(final String suffix)
|
||||
{
|
||||
if (CarpetServer.minecraft_server == null)
|
||||
{
|
||||
throw new InternalExpressionException("Accessing world files without server running");
|
||||
return CarpetServer.minecraft_server.getWorldPath(LevelResource.ROOT).resolve("scripts/"+suffix);
|
||||
}
|
||||
return CarpetServer.minecraft_server.getWorldPath(LevelResource.ROOT).resolve("scripts/" + suffix);
|
||||
}
|
||||
|
||||
private Path toPath(Module module)
|
||||
private Path toPath(final Module module)
|
||||
{
|
||||
if (!isShared && module == null) return null;
|
||||
if (!isShared && module == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (zipContainer == null)
|
||||
return resolve(getDescriptor(module, resource)+(isFolder?"":type.extension));
|
||||
{
|
||||
return resolve(getDescriptor(module, resource) + (isFolder ? "" : type.extension));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (zfs == null)
|
||||
{
|
||||
Map<String, String> env = new HashMap<>();
|
||||
if (reason == Reason.CREATE) env.put("create", "true");
|
||||
zipPath = resolve(getDescriptor(module, zipContainer));
|
||||
if (!Files.exists(zipPath) && reason != Reason.CREATE) return null; // no zip file
|
||||
try {
|
||||
if (!Files.exists(zipPath.getParent())) Files.createDirectories(zipPath.getParent());
|
||||
zfs = FileSystems.newFileSystem(URI.create("jar:"+ zipPath.toUri().toString()), env);
|
||||
final Map<String, String> env = new HashMap<>();
|
||||
if (reason == Reason.CREATE)
|
||||
{
|
||||
env.put("create", "true");
|
||||
}
|
||||
catch (FileSystemNotFoundException | IOException e)
|
||||
zipPath = resolve(getDescriptor(module, zipContainer));
|
||||
if (!Files.exists(zipPath) && reason != Reason.CREATE)
|
||||
{
|
||||
return null; // no zip file
|
||||
}
|
||||
try
|
||||
{
|
||||
if (!Files.exists(zipPath.getParent()))
|
||||
{
|
||||
Files.createDirectories(zipPath.getParent());
|
||||
}
|
||||
zfs = FileSystems.newFileSystem(URI.create("jar:" + zipPath.toUri()), env);
|
||||
}
|
||||
catch (final FileSystemNotFoundException | IOException e)
|
||||
{
|
||||
CarpetScriptServer.LOG.warn("Exception when opening zip file", e);
|
||||
throw new ThrowStatement("Unable to open zip file: "+zipContainer, Throwables.IO_EXCEPTION);
|
||||
throw new ThrowStatement("Unable to open zip file: " + zipContainer, Throwables.IO_EXCEPTION);
|
||||
}
|
||||
}
|
||||
return zfs.getPath(resource+(isFolder?"/":type.extension));
|
||||
return zfs.getPath(resource + (isFolder ? "/" : type.extension));
|
||||
}
|
||||
}
|
||||
|
||||
private Path moduleRootPath(Module module)
|
||||
private Path moduleRootPath(final Module module)
|
||||
{
|
||||
if (!isShared && module == null) return null;
|
||||
return resolve(isShared?"shared":module.name()+".data");
|
||||
return !isShared && module == null
|
||||
? null
|
||||
: resolve(isShared ? "shared" : module.name() + ".data");
|
||||
}
|
||||
|
||||
public String getDisplayPath()
|
||||
{
|
||||
return (isShared?"shared/":"")+(zipContainer!=null?zipContainer+"/":"")+resource+type.extension;
|
||||
return (isShared ? "shared/" : "") + (zipContainer != null ? zipContainer + "/" : "") + resource + type.extension;
|
||||
}
|
||||
|
||||
private String getDescriptor(Module module, String res)
|
||||
private String getDescriptor(final Module module, final String res)
|
||||
{
|
||||
if (isShared)
|
||||
{
|
||||
return res.isEmpty()?"shared":"shared/"+res;
|
||||
return res.isEmpty() ? "shared" : "shared/" + res;
|
||||
}
|
||||
if (module != null) // appdata
|
||||
{
|
||||
return module.name()+".data"+(res==null || res.isEmpty()?"":"/"+res);
|
||||
return module.name() + ".data" + (res == null || res.isEmpty() ? "" : "/" + res);
|
||||
}
|
||||
throw new InternalExpressionException("Invalid file descriptor: "+res);
|
||||
throw new InternalExpressionException("Invalid file descriptor: " + res);
|
||||
}
|
||||
|
||||
|
||||
public boolean findPathAndApply(Module module, Consumer<Path> action)
|
||||
public boolean findPathAndApply(final Module module, final Consumer<Path> action)
|
||||
{
|
||||
try { synchronized (writeIOSync)
|
||||
try
|
||||
{
|
||||
Path dataFile = toPath(module);//, resourceName, supportedTypes.get(type), isShared);
|
||||
if (dataFile == null) return false;
|
||||
createPaths(dataFile);
|
||||
action.accept(dataFile);
|
||||
} }
|
||||
synchronized (writeIOSync)
|
||||
{
|
||||
final Path dataFile = toPath(module);//, resourceName, supportedTypes.get(type), isShared);
|
||||
if (dataFile == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
createPaths(dataFile);
|
||||
action.accept(dataFile);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
close();
|
||||
@@ -242,83 +293,109 @@ public class FileArgument
|
||||
return true;
|
||||
}
|
||||
|
||||
public Stream<Path> listFiles(Module module)
|
||||
public Stream<Path> listFiles(final Module module)
|
||||
{
|
||||
Path dir = toPath(module);
|
||||
if (dir == null || !Files.exists(dir)) return null;
|
||||
String ext = type.extension;
|
||||
final Path dir = toPath(module);
|
||||
if (dir == null || !Files.exists(dir))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
final String ext = type.extension;
|
||||
try
|
||||
{
|
||||
return Files.list(dir).filter(path -> (type==Type.FOLDER)
|
||||
?Files.isDirectory(path)
|
||||
:(Files.isRegularFile(path) && path.toString().endsWith(ext))
|
||||
return Files.list(dir).filter(path -> (type == Type.FOLDER)
|
||||
? Files.isDirectory(path)
|
||||
: (Files.isRegularFile(path) && path.toString().endsWith(ext))
|
||||
);
|
||||
}
|
||||
catch (IOException ignored)
|
||||
catch (final IOException ignored)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Stream<String> listFolder(Module module)
|
||||
public Stream<String> listFolder(final Module module)
|
||||
{
|
||||
Stream<String> strings;
|
||||
try (Stream<Path> result = listFiles(module)) { synchronized (writeIOSync)
|
||||
try (final Stream<Path> result = listFiles(module))
|
||||
{
|
||||
if (result == null) return null;
|
||||
Path rootPath = moduleRootPath(module);
|
||||
if (rootPath == null) return null;
|
||||
String zipComponent = (zipContainer != null) ? rootPath.relativize(zipPath).toString() : null;
|
||||
// need to evaluate the stream before exiting try-with-resources else there'll be no data to stream
|
||||
strings = (zipContainer == null)
|
||||
? result.map(p -> rootPath.relativize(p).toString().replaceAll("[\\\\/]+", "/")).toList().stream()
|
||||
: result.map(p -> (zipComponent + '/'+ p.toString()).replaceAll("[\\\\/]+", "/")).toList().stream();
|
||||
} }
|
||||
synchronized (writeIOSync)
|
||||
{
|
||||
if (result == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
final Path rootPath = moduleRootPath(module);
|
||||
if (rootPath == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
final String zipComponent = (zipContainer != null) ? rootPath.relativize(zipPath).toString() : null;
|
||||
// need to evaluate the stream before exiting try-with-resources else there'll be no data to stream
|
||||
strings = (zipContainer == null)
|
||||
? result.map(p -> rootPath.relativize(p).toString().replaceAll("[\\\\/]+", "/")).toList().stream()
|
||||
: result.map(p -> (zipComponent + '/' + p.toString()).replaceAll("[\\\\/]+", "/")).toList().stream();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
close();
|
||||
}
|
||||
if (type == Type.FOLDER)
|
||||
// java 8 paths are inconsistent. in java 16 they all should not have trailing slashes
|
||||
return strings.map(s -> s.endsWith("/")?s.substring(0, s.length()-1):s);
|
||||
return strings.map(FilenameUtils::removeExtension);
|
||||
// java 8 paths are inconsistent. in java 16 they all should not have trailing slashes
|
||||
return type == Type.FOLDER
|
||||
? strings.map(s -> s.endsWith("/") ? s.substring(0, s.length() - 1) : s)
|
||||
: strings.map(FilenameUtils::removeExtension);
|
||||
}
|
||||
|
||||
private void createPaths(Path file)
|
||||
private void createPaths(final Path file)
|
||||
{
|
||||
try {
|
||||
try
|
||||
{
|
||||
if ((zipContainer == null || file.getParent() != null) &&
|
||||
!Files.exists(file.getParent()) &&
|
||||
Files.createDirectories(file.getParent()) == null
|
||||
) throw new IOException();
|
||||
} catch (IOException e) {
|
||||
)
|
||||
{
|
||||
throw new IOException();
|
||||
}
|
||||
}
|
||||
catch (final IOException e)
|
||||
{
|
||||
CarpetScriptServer.LOG.warn("IOException when creating paths", e);
|
||||
throw new ThrowStatement("Unable to create paths for "+file.toString(), Throwables.IO_EXCEPTION);
|
||||
throw new ThrowStatement("Unable to create paths for " + file, Throwables.IO_EXCEPTION);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public boolean appendToTextFile(Module module, List<String> message)
|
||||
public boolean appendToTextFile(final Module module, final List<String> message)
|
||||
{
|
||||
try { synchronized (writeIOSync)
|
||||
try
|
||||
{
|
||||
Path dataFile = toPath(module);//, resourceName, supportedTypes.get(type), isShared);
|
||||
if (dataFile == null) return false;
|
||||
createPaths(dataFile);
|
||||
OutputStream out = Files.newOutputStream(dataFile, StandardOpenOption.APPEND, StandardOpenOption.CREATE);
|
||||
try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, StandardCharsets.UTF_8)))
|
||||
synchronized (writeIOSync)
|
||||
{
|
||||
for (String line: message)
|
||||
final Path dataFile = toPath(module);
|
||||
if (dataFile == null)
|
||||
{
|
||||
writer.append(line);
|
||||
if (type == Type.TEXT) writer.newLine();
|
||||
return false;
|
||||
}
|
||||
createPaths(dataFile);
|
||||
final OutputStream out = Files.newOutputStream(dataFile, StandardOpenOption.APPEND, StandardOpenOption.CREATE);
|
||||
try (final BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, StandardCharsets.UTF_8)))
|
||||
{
|
||||
for (final String line : message)
|
||||
{
|
||||
writer.append(line);
|
||||
if (type == Type.TEXT)
|
||||
{
|
||||
writer.newLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} }
|
||||
catch (IOException e)
|
||||
}
|
||||
catch (final IOException e)
|
||||
{
|
||||
CarpetScriptServer.LOG.warn("IOException when appending to text file", e);
|
||||
throw new ThrowStatement("Error when writing to the file: "+e, Throwables.IO_EXCEPTION);
|
||||
throw new ThrowStatement("Error when writing to the file: " + e, Throwables.IO_EXCEPTION);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -327,76 +404,91 @@ public class FileArgument
|
||||
return true;
|
||||
}
|
||||
|
||||
public Tag getNbtData(Module module) // aka getData
|
||||
public Tag getNbtData(final Module module) // aka getData
|
||||
{
|
||||
try { synchronized (writeIOSync) {
|
||||
Path dataFile = toPath(module);
|
||||
if (dataFile == null || !Files.exists(dataFile)) return null;
|
||||
return readTag(dataFile);
|
||||
} }
|
||||
finally {
|
||||
try
|
||||
{
|
||||
synchronized (writeIOSync)
|
||||
{
|
||||
final Path dataFile = toPath(module);
|
||||
if (dataFile == null || !Files.exists(dataFile))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return readTag(dataFile);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
//copied private method from net.minecraft.nbt.NbtIo.read()
|
||||
// to read non-compound tags - these won't be compressed
|
||||
public static Tag readTag(Path path)
|
||||
public static Tag readTag(final Path path)
|
||||
{
|
||||
try
|
||||
{
|
||||
return NbtIo.readCompressed(Files.newInputStream(path));
|
||||
}
|
||||
catch (IOException e)
|
||||
catch (final IOException e)
|
||||
{
|
||||
// Copy of NbtIo.read(File) because that's now client-side only
|
||||
if (!Files.exists(path))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
try (DataInputStream in = new DataInputStream(new BufferedInputStream(Files.newInputStream(path))))
|
||||
try (final DataInputStream in = new DataInputStream(new BufferedInputStream(Files.newInputStream(path))))
|
||||
{
|
||||
return NbtIo.read(in);
|
||||
}
|
||||
catch (IOException ioException)
|
||||
catch (final IOException ioException)
|
||||
{
|
||||
// not compressed compound tag neither uncompressed compound tag - trying any type of a tag
|
||||
try (DataInputStream dataInput_1 = new DataInputStream(new BufferedInputStream(Files.newInputStream(path))))
|
||||
try (final DataInputStream dataInputStream = new DataInputStream(new BufferedInputStream(Files.newInputStream(path))))
|
||||
{
|
||||
byte byte_1 = dataInput_1.readByte();
|
||||
if (byte_1 == 0)
|
||||
final byte b = dataInputStream.readByte();
|
||||
if (b == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
dataInput_1.readUTF();
|
||||
return TagTypes.getType(byte_1).load(dataInput_1, 0, NbtAccounter.UNLIMITED);
|
||||
dataInputStream.readUTF();
|
||||
return TagTypes.getType(b).load(dataInputStream, 0, NbtAccounter.UNLIMITED);
|
||||
}
|
||||
}
|
||||
catch (IOException secondIO)
|
||||
catch (final IOException secondIO)
|
||||
{
|
||||
CarpetScriptServer.LOG.warn("IOException when trying to read nbt file, something may have gone wrong with the fs", e);
|
||||
CarpetScriptServer.LOG.warn("", ioException);
|
||||
CarpetScriptServer.LOG.warn("", secondIO);
|
||||
throw new ThrowStatement("Not a valid NBT tag in "+path.toString(), Throwables.NBT_ERROR);
|
||||
throw new ThrowStatement("Not a valid NBT tag in " + path, Throwables.NBT_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ReportedException e)
|
||||
catch (final ReportedException e)
|
||||
{
|
||||
throw new ThrowStatement("Error when reading NBT file "+path.toString(), Throwables.NBT_ERROR);
|
||||
throw new ThrowStatement("Error when reading NBT file " + path.toString(), Throwables.NBT_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean saveNbtData(Module module, Tag tag) // aka saveData
|
||||
public boolean saveNbtData(final Module module, final Tag tag) // aka saveData
|
||||
{
|
||||
try { synchronized (writeIOSync) {
|
||||
Path dataFile = toPath(module);
|
||||
if (dataFile == null) return false;
|
||||
createPaths(dataFile);
|
||||
return writeTagDisk(tag, dataFile, zipContainer != null);
|
||||
} }
|
||||
try
|
||||
{
|
||||
synchronized (writeIOSync)
|
||||
{
|
||||
final Path dataFile = toPath(module);
|
||||
if (dataFile == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
createPaths(dataFile);
|
||||
return writeTagDisk(tag, dataFile, zipContainer != null);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
close();
|
||||
@@ -404,9 +496,9 @@ public class FileArgument
|
||||
}
|
||||
|
||||
//copied private method from net.minecraft.nbt.NbtIo.write() and client method safe_write
|
||||
public static boolean writeTagDisk(Tag tag_1, Path path, boolean zipped)
|
||||
public static boolean writeTagDisk(final Tag tag, Path path, final boolean zipped)
|
||||
{
|
||||
Path original = path;
|
||||
final Path original = path;
|
||||
try
|
||||
{
|
||||
if (!zipped)
|
||||
@@ -415,19 +507,19 @@ public class FileArgument
|
||||
Files.deleteIfExists(path);
|
||||
}
|
||||
|
||||
if (tag_1 instanceof CompoundTag)
|
||||
if (tag instanceof final CompoundTag cTag)
|
||||
{
|
||||
NbtIo.writeCompressed((CompoundTag) tag_1, Files.newOutputStream(path));
|
||||
NbtIo.writeCompressed(cTag, Files.newOutputStream(path));
|
||||
}
|
||||
else
|
||||
{
|
||||
try (DataOutputStream dataOutputStream_1 = new DataOutputStream(Files.newOutputStream(path)))
|
||||
try (final DataOutputStream dataOutputStream = new DataOutputStream(Files.newOutputStream(path)))
|
||||
{
|
||||
dataOutputStream_1.writeByte(tag_1.getId());
|
||||
if (tag_1.getId() != 0)
|
||||
dataOutputStream.writeByte(tag.getId());
|
||||
if (tag.getId() != 0)
|
||||
{
|
||||
dataOutputStream_1.writeUTF("");
|
||||
tag_1.write(dataOutputStream_1);
|
||||
dataOutputStream.writeUTF("");
|
||||
tag.write(dataOutputStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -438,26 +530,31 @@ public class FileArgument
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (IOException e)
|
||||
catch (final IOException e)
|
||||
{
|
||||
CarpetScriptServer.LOG.warn("IO Exception when writing nbt file", e);
|
||||
throw new ThrowStatement("Unable to write tag to "+original.toString(), Throwables.IO_EXCEPTION);
|
||||
throw new ThrowStatement("Unable to write tag to " + original, Throwables.IO_EXCEPTION);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean dropExistingFile(Module module)
|
||||
public boolean dropExistingFile(final Module module)
|
||||
{
|
||||
|
||||
try { synchronized (writeIOSync)
|
||||
try
|
||||
{
|
||||
Path dataFile = toPath(module);
|
||||
if (dataFile == null) return false;
|
||||
return Files.deleteIfExists(dataFile);
|
||||
} }
|
||||
catch (IOException e)
|
||||
synchronized (writeIOSync)
|
||||
{
|
||||
final Path dataFile = toPath(module);
|
||||
if (dataFile == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return Files.deleteIfExists(dataFile);
|
||||
}
|
||||
}
|
||||
catch (final IOException e)
|
||||
{
|
||||
CarpetScriptServer.LOG.warn("IOException when removing file", e);
|
||||
throw new ThrowStatement("Error while removing file: "+getDisplayPath(), Throwables.IO_EXCEPTION);
|
||||
throw new ThrowStatement("Error while removing file: " + getDisplayPath(), Throwables.IO_EXCEPTION);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -465,69 +562,95 @@ public class FileArgument
|
||||
}
|
||||
}
|
||||
|
||||
public List<String> listFile(Module module)
|
||||
public List<String> listFile(final Module module)
|
||||
{
|
||||
try { synchronized (writeIOSync) {
|
||||
Path dataFile = toPath(module);
|
||||
if (dataFile == null) return null;
|
||||
if (!Files.exists(dataFile)) return null;
|
||||
return listFileContent(dataFile);
|
||||
} }
|
||||
finally {
|
||||
try
|
||||
{
|
||||
synchronized (writeIOSync)
|
||||
{
|
||||
final Path dataFile = toPath(module);
|
||||
if (dataFile == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (!Files.exists(dataFile))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return listFileContent(dataFile);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
public static List<String> listFileContent(Path filePath)
|
||||
public static List<String> listFileContent(final Path filePath)
|
||||
{
|
||||
try (BufferedReader reader = Files.newBufferedReader(filePath, StandardCharsets.UTF_8)) {
|
||||
List<String> result = new ArrayList<>();
|
||||
for (;;) {
|
||||
String line = reader.readLine();
|
||||
try (final BufferedReader reader = Files.newBufferedReader(filePath, StandardCharsets.UTF_8))
|
||||
{
|
||||
final List<String> result = new ArrayList<>();
|
||||
for (; ; )
|
||||
{
|
||||
final String line = reader.readLine();
|
||||
if (line == null)
|
||||
{
|
||||
break;
|
||||
result.add(line.replaceAll("[\n\r]+",""));
|
||||
}
|
||||
result.add(line.replaceAll("[\n\r]+", ""));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
catch (IOException e)
|
||||
catch (final IOException e)
|
||||
{
|
||||
CarpetScriptServer.LOG.warn("IOException when reading text file", e);
|
||||
throw new ThrowStatement("Failed to read text file "+filePath.toString(), Throwables.IO_EXCEPTION);
|
||||
throw new ThrowStatement("Failed to read text file " + filePath, Throwables.IO_EXCEPTION);
|
||||
}
|
||||
}
|
||||
|
||||
public JsonElement readJsonFile(Module module) {
|
||||
try { synchronized (writeIOSync) {
|
||||
Path dataFile = toPath(module);
|
||||
if (dataFile == null || !Files.exists(dataFile)) return null;
|
||||
return readJsonContent(dataFile);
|
||||
} }
|
||||
finally {
|
||||
public JsonElement readJsonFile(final Module module)
|
||||
{
|
||||
try
|
||||
{
|
||||
synchronized (writeIOSync)
|
||||
{
|
||||
final Path dataFile = toPath(module);
|
||||
if (dataFile == null || !Files.exists(dataFile))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return readJsonContent(dataFile);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
public static JsonElement readJsonContent(Path filePath)
|
||||
public static JsonElement readJsonContent(final Path filePath)
|
||||
{
|
||||
try (BufferedReader reader = Files.newBufferedReader(filePath, StandardCharsets.UTF_8))
|
||||
try (final BufferedReader reader = Files.newBufferedReader(filePath, StandardCharsets.UTF_8))
|
||||
{
|
||||
return JsonParser.parseReader(reader);
|
||||
}
|
||||
catch (JsonParseException e)
|
||||
catch (final JsonParseException e)
|
||||
{
|
||||
Throwable exc = e;
|
||||
if(e.getCause() != null)
|
||||
if (e.getCause() != null)
|
||||
{
|
||||
exc = e.getCause();
|
||||
}
|
||||
throw new ThrowStatement(MapValue.wrap(Map.of(
|
||||
StringValue.of("error"), StringValue.of(exc.getMessage()),
|
||||
StringValue.of("path"), StringValue.of(filePath.toString())
|
||||
)), Throwables.JSON_ERROR);
|
||||
}
|
||||
catch (IOException e)
|
||||
catch (final IOException e)
|
||||
{
|
||||
CarpetScriptServer.LOG.warn("IOException when reading JSON file", e);
|
||||
throw new ThrowStatement("Failed to read json file content "+filePath.toString(), Throwables.IO_EXCEPTION);
|
||||
throw new ThrowStatement("Failed to read json file content " + filePath, Throwables.IO_EXCEPTION);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ public class FunctionArgument extends Argument
|
||||
public FunctionValue function;
|
||||
public List<Value> args;
|
||||
|
||||
private FunctionArgument(FunctionValue function, int offset, List<Value> args)
|
||||
private FunctionArgument(final FunctionValue function, final int offset, final List<Value> args)
|
||||
{
|
||||
super(offset);
|
||||
this.function = function;
|
||||
@@ -27,10 +27,10 @@ public class FunctionArgument extends Argument
|
||||
}
|
||||
|
||||
/**
|
||||
* @param c context
|
||||
* @param module module
|
||||
* @param params list of params
|
||||
* @param offset offset where to start looking for functional argument
|
||||
* @param c context
|
||||
* @param module module
|
||||
* @param params list of params
|
||||
* @param offset offset where to start looking for functional argument
|
||||
* @param allowNone none indicates no function present, otherwise it will croak
|
||||
* @param checkArgs whether the caller expects trailing parameters to fully resolve function argument list
|
||||
* if not - argument count check will not be performed and its up to the caller to verify
|
||||
@@ -38,63 +38,85 @@ public class FunctionArgument extends Argument
|
||||
* @return argument data
|
||||
*/
|
||||
public static FunctionArgument findIn(
|
||||
Context c,
|
||||
Module module,
|
||||
List<Value> params,
|
||||
int offset,
|
||||
boolean allowNone,
|
||||
boolean checkArgs)
|
||||
final Context c,
|
||||
final Module module,
|
||||
final List<Value> params,
|
||||
final int offset,
|
||||
final boolean allowNone,
|
||||
final boolean checkArgs)
|
||||
{
|
||||
Value functionValue = params.get(offset);
|
||||
if (functionValue.isNull())
|
||||
{
|
||||
if (allowNone) return new FunctionArgument(null, offset+1, Collections.emptyList());
|
||||
if (allowNone)
|
||||
{
|
||||
return new FunctionArgument(null, offset + 1, Collections.emptyList());
|
||||
}
|
||||
throw new InternalExpressionException("function argument cannot be null");
|
||||
}
|
||||
if (!(functionValue instanceof FunctionValue))
|
||||
{
|
||||
String name = functionValue.getString();
|
||||
final String name = functionValue.getString();
|
||||
functionValue = c.host.getAssertFunction(module, name);
|
||||
}
|
||||
FunctionValue fun = (FunctionValue)functionValue;
|
||||
int argsize = fun.getArguments().size();
|
||||
final FunctionValue fun = (FunctionValue) functionValue;
|
||||
final int argsize = fun.getArguments().size();
|
||||
if (checkArgs)
|
||||
{
|
||||
int extraargs = params.size() - argsize - offset - 1;
|
||||
final int extraargs = params.size() - argsize - offset - 1;
|
||||
if (extraargs < 0)
|
||||
{
|
||||
throw new InternalExpressionException("Function " + fun.getPrettyString() + " requires at least " + fun.getArguments().size() + " arguments");
|
||||
}
|
||||
if (extraargs > 0 && fun.getVarArgs() == null)
|
||||
{
|
||||
throw new InternalExpressionException("Function " + fun.getPrettyString() + " requires " + fun.getArguments().size() + " arguments");
|
||||
}
|
||||
}
|
||||
final List<Value> lvargs = new ArrayList<>();
|
||||
for (int i = offset + 1, mx = params.size(); i < mx; i++)
|
||||
{
|
||||
lvargs.add(params.get(i));
|
||||
}
|
||||
List<Value> lvargs = new ArrayList<>();
|
||||
for (int i = offset+1, mx = params.size(); i < mx; i++) lvargs.add(params.get(i));
|
||||
return new FunctionArgument(fun, offset + 1 + argsize, lvargs);
|
||||
}
|
||||
|
||||
public static FunctionArgument fromCommandSpec(ScriptHost host, Value funSpec) throws CommandSyntaxException {
|
||||
FunctionValue function;
|
||||
public static FunctionArgument fromCommandSpec(final ScriptHost host, Value funSpec) throws CommandSyntaxException
|
||||
{
|
||||
final FunctionValue function;
|
||||
List<Value> args = Collections.emptyList();
|
||||
if (!(funSpec instanceof ListValue))
|
||||
{
|
||||
funSpec = ListValue.of(funSpec);
|
||||
List<Value> params = ((ListValue) funSpec).getItems();
|
||||
if (params.isEmpty()) throw CommandArgument.error("Function has empty spec");
|
||||
Value first = params.get(0);
|
||||
}
|
||||
final List<Value> params = ((ListValue) funSpec).getItems();
|
||||
if (params.isEmpty())
|
||||
{
|
||||
throw CommandArgument.error("Function has empty spec");
|
||||
}
|
||||
final Value first = params.get(0);
|
||||
if (first instanceof FunctionValue)
|
||||
{
|
||||
function = (FunctionValue)first;
|
||||
function = (FunctionValue) first;
|
||||
}
|
||||
else
|
||||
{
|
||||
String name = first.getString();
|
||||
final String name = first.getString();
|
||||
function = host.getFunction(name);
|
||||
if (function == null) throw CommandArgument.error("Function "+name+" is not defined yet");
|
||||
if (function == null)
|
||||
{
|
||||
throw CommandArgument.error("Function " + name + " is not defined yet");
|
||||
}
|
||||
}
|
||||
if (params.size() > 1)
|
||||
{
|
||||
args = params.subList(1, params.size());
|
||||
}
|
||||
if (params.size() > 1) args = params.subList(1,params.size());
|
||||
|
||||
return new FunctionArgument(function, 0, args);
|
||||
}
|
||||
|
||||
public List<Value> checkedArgs() {
|
||||
public List<Value> checkedArgs()
|
||||
{
|
||||
function.checkArgs(args.size());
|
||||
return args;
|
||||
}
|
||||
|
||||
@@ -6,9 +6,11 @@ import carpet.script.value.EntityValue;
|
||||
import carpet.script.value.ListValue;
|
||||
import carpet.script.value.NumericValue;
|
||||
import carpet.script.value.Value;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
@@ -19,14 +21,16 @@ public class Vector3Argument extends Argument
|
||||
public final double pitch;
|
||||
public boolean fromBlock = false;
|
||||
public Entity entity = null;
|
||||
private Vector3Argument(Vec3 v, int o)
|
||||
|
||||
private Vector3Argument(final Vec3 v, final int o)
|
||||
{
|
||||
super(o);
|
||||
this.vec = v;
|
||||
this.yaw = 0.0D;
|
||||
this.pitch = 0.0D;
|
||||
}
|
||||
private Vector3Argument(Vec3 v, int o, double y, double p)
|
||||
|
||||
private Vector3Argument(final Vec3 v, final int o, final double y, final double p)
|
||||
{
|
||||
super(o);
|
||||
this.vec = v;
|
||||
@@ -40,52 +44,53 @@ public class Vector3Argument extends Argument
|
||||
return this;
|
||||
}
|
||||
|
||||
private Vector3Argument withEntity(Entity e)
|
||||
private Vector3Argument withEntity(final Entity e)
|
||||
{
|
||||
entity = e;
|
||||
return this;
|
||||
}
|
||||
|
||||
public static Vector3Argument findIn(List<Value> params, int offset)
|
||||
public static Vector3Argument findIn(final List<Value> params, final int offset)
|
||||
{
|
||||
return findIn(params, offset, false, false);
|
||||
}
|
||||
|
||||
public static Vector3Argument findIn(List<Value> params, int offset, boolean optionalDirection, boolean optionalEntity) {
|
||||
public static Vector3Argument findIn(final List<Value> params, final int offset, final boolean optionalDirection, final boolean optionalEntity)
|
||||
{
|
||||
return findIn(params.listIterator(offset), offset, optionalDirection, optionalEntity);
|
||||
}
|
||||
|
||||
public static Vector3Argument findIn(Iterator<Value> params, int offset, boolean optionalDirection, boolean optionalEntity)
|
||||
public static Vector3Argument findIn(final Iterator<Value> params, final int offset, final boolean optionalDirection, final boolean optionalEntity)
|
||||
{
|
||||
try
|
||||
{
|
||||
Value v1 = params.next();
|
||||
final Value v1 = params.next();
|
||||
if (v1 instanceof BlockValue)
|
||||
{
|
||||
return (new Vector3Argument(Vec3.atCenterOf(((BlockValue) v1).getPos()), 1+offset)).fromBlock();
|
||||
return (new Vector3Argument(Vec3.atCenterOf(((BlockValue) v1).getPos()), 1 + offset)).fromBlock();
|
||||
}
|
||||
if (optionalEntity && v1 instanceof EntityValue)
|
||||
{
|
||||
Entity e = ((EntityValue) v1).getEntity();
|
||||
return new Vector3Argument(e.position(), 1+offset).withEntity(e);
|
||||
final Entity e = ((EntityValue) v1).getEntity();
|
||||
return new Vector3Argument(e.position(), 1 + offset).withEntity(e);
|
||||
}
|
||||
if (v1 instanceof ListValue)
|
||||
{
|
||||
List<Value> args = ((ListValue) v1).getItems();
|
||||
Vec3 pos = new Vec3(
|
||||
final List<Value> args = ((ListValue) v1).getItems();
|
||||
final Vec3 pos = new Vec3(
|
||||
NumericValue.asNumber(args.get(0)).getDouble(),
|
||||
NumericValue.asNumber(args.get(1)).getDouble(),
|
||||
NumericValue.asNumber(args.get(2)).getDouble());
|
||||
double yaw = 0.0D;
|
||||
double pitch = 0.0D;
|
||||
if (args.size()>3 && optionalDirection)
|
||||
if (args.size() > 3 && optionalDirection)
|
||||
{
|
||||
yaw = NumericValue.asNumber(args.get(3)).getDouble();
|
||||
pitch = NumericValue.asNumber(args.get(4)).getDouble();
|
||||
}
|
||||
return new Vector3Argument(pos,offset+1, yaw, pitch);
|
||||
return new Vector3Argument(pos, offset + 1, yaw, pitch);
|
||||
}
|
||||
Vec3 pos = new Vec3(
|
||||
final Vec3 pos = new Vec3(
|
||||
NumericValue.asNumber(v1).getDouble(),
|
||||
NumericValue.asNumber(params.next()).getDouble(),
|
||||
NumericValue.asNumber(params.next()).getDouble());
|
||||
@@ -99,9 +104,9 @@ public class Vector3Argument extends Argument
|
||||
eatenLength = 5;
|
||||
}
|
||||
|
||||
return new Vector3Argument(pos, offset+eatenLength, yaw, pitch);
|
||||
return new Vector3Argument(pos, offset + eatenLength, yaw, pitch);
|
||||
}
|
||||
catch (IndexOutOfBoundsException | NoSuchElementException e)
|
||||
catch (final IndexOutOfBoundsException | NoSuchElementException e)
|
||||
{
|
||||
throw new InternalExpressionException("Position argument should be defined either by three coordinates (a triple or by three arguments), or a positioned block value");
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user