Merge branch 'master' into 1.17

This commit is contained in:
gnembon committed 2020-12-03 22:25:51 -04:00
commit 9d08c54324
13 files changed
+210 -108

No files matched your search

+23 -21
View File
@@ -3170,6 +3170,11 @@ Player's ping in milliseconds, or `null` if its not a player.
Player's permission level, or `null` if not applicable for this entity.
### `query(e, 'client_brand')`
Returns recognized type of client of the client connected. Possible results include `'vanilla'`, or `'carpet <version>'` where
version indicates the version of the connected carpet client.
### `query(e, 'effect', name?)`
Without extra arguments, it returns list of effect active on a living entity. Each entry is a triple of short
@@ -4566,13 +4571,15 @@ Available output types:
### `read_file(resource, type)`
### `delete_file(resource, type)`
### `write_file(resource, type, data, ...)`
### `list_files(resource, type)`
With the specified `resource` in the scripts folder, of a specific `type`, writes/appends `data` to it, reads its
content, or deletes the resource.
content, deletes the resource, or lists other files under this resource.
Resource is identified by a path to the file.
A path can contain letters, numbers, characters `-`, `+`, or `_`, and a folder separator: `'/'`. Any other characters are stripped
from the name. Empty descriptors are invalid. Do not add file extensions to the descriptor - extensions are inferred
from the name. Empty descriptors are invalid, except for `list_files` where it means the root folder.
Do not add file extensions to the descriptor - extensions are inferred
based on the `type` of the file.
Resources can be located in the app specific space, or a shared space for all the apps. Accessing of app-specific
@@ -4587,33 +4594,26 @@ specific data directory is under `world/scripts/foo.data/...`, and shared data s
The default no-name app, via `/script run` command can only save/load/read files from the shared space.
Functions return `null` if an error is encounter or no file is present (for read and delete operations). Returns `true`
for success writes and deletes, and requested data, based on the file type, for read operations.
Functions return `null` if an error is encounter or no file is present (for read, list and delete operations). Returns `true`
for success writes and deletes, and requested data, based on the file type, for read operations. It returns list of files
for folder listing.
NBT files can be written once as they an store one tag at a time. Consecutive writes will overwrite previous data.
Write operations to text files always result in appending to the existing file, so consecutive writes will increase
the size of the file and add data to it. Since files are closed after each write, sending multiple lines of data to
write is beneficial for writing speed. To send multiple packs of data, either provide them flat or as a list in the
third argument.
* `write_file('temp', 'text', 'foo', 'bar', 'baz')` or
* write_file('temp', 'text', l('foo', 'bar', 'baz'))
To log a single line of string
Supported values for resource `type` is:
Supported values for resource `type` are:
* `nbt` - NBT tag
* `text` - text resource with automatic newlines added
* `raw` - text resource without implied newlines
* `shared_nbt`, `shared_text`, `shared_raw` - shared versions of the above
* `folder` - for `list_files` only - indicting folder listing instead of files
* `shared_nbt`, `shared_text`, `shared_raw`, `shared_folder` - shared versions of the above
NBT files have extension `.nbt`, store one NBT tag, and return a NBT type value. Text files have `.txt` extension,
stores multiple lines of text and returns lists of all lines from the file. With `write_file`, multiple lines can be
sent to the file at once. The only difference between `raw` and `text` types are automatic newlines added after each
record to the file.
record to the file. Since files are closed after each write, sending multiple lines of data to
write is beneficial for writing speed. To send multiple packs of data, either provide them flat or as a list in the
third argument.
<pre>
write_file('foo', 'shared_text, l('one', 'two'));
write_file('foo', 'shared_text, ['one', 'two']);
write_file('foo', 'shared_text', 'three\n', 'four\n');
write_file('foo', 'shared_raw', 'five\n', 'six\n');
@@ -4791,7 +4791,6 @@ Available options in the scarpet app space:
* `game_version` - base version of the game
Server related properties
* `server_motd` - the motd of the server visible when joining
* `server_ip` - IP adress of the game hosted
* `server_whitelisted` - boolean indicating whether the access to the server is only for whitelisted players
@@ -4807,7 +4806,10 @@ Available options in the scarpet app space:
* `java_version` - version of Java
* `java_bits` - number indicating how many bits the Java has, 32 or 64
* `java_system_cpu_load` - current percentage of CPU used by the system
* `java_process_cpu_load` - current percentage of CPU used by JVM# `/script run` command
* `java_process_cpu_load` - current percentage of CPU used by JVM
Scarpet related properties
* `scarpet_version` - returns the version of the carpet your scarpet comes with.# `/script run` command
Primary way to input commands. The command executes in the context, position, and dimension of the executing player,
commandblock, etc... The command receives 4 variables, `x`, `y`, `z` and `p` indicating position and
+17 -20
View File
@@ -275,13 +275,15 @@ Available output types:
### `read_file(resource, type)`
### `delete_file(resource, type)`
### `write_file(resource, type, data, ...)`
### `list_files(resource, type)`
With the specified `resource` in the scripts folder, of a specific `type`, writes/appends `data` to it, reads its
content, or deletes the resource.
content, deletes the resource, or lists other files under this resource.
Resource is identified by a path to the file.
A path can contain letters, numbers, characters `-`, `+`, or `_`, and a folder separator: `'/'`. Any other characters are stripped
from the name. Empty descriptors are invalid. Do not add file extensions to the descriptor - extensions are inferred
from the name. Empty descriptors are invalid, except for `list_files` where it means the root folder.
Do not add file extensions to the descriptor - extensions are inferred
based on the `type` of the file.
Resources can be located in the app specific space, or a shared space for all the apps. Accessing of app-specific
@@ -296,33 +298,26 @@ specific data directory is under `world/scripts/foo.data/...`, and shared data s
The default no-name app, via `/script run` command can only save/load/read files from the shared space.
Functions return `null` if an error is encounter or no file is present (for read and delete operations). Returns `true`
for success writes and deletes, and requested data, based on the file type, for read operations.
Functions return `null` if an error is encounter or no file is present (for read, list and delete operations). Returns `true`
for success writes and deletes, and requested data, based on the file type, for read operations. It returns list of files
for folder listing.
NBT files can be written once as they an store one tag at a time. Consecutive writes will overwrite previous data.
Write operations to text files always result in appending to the existing file, so consecutive writes will increase
the size of the file and add data to it. Since files are closed after each write, sending multiple lines of data to
write is beneficial for writing speed. To send multiple packs of data, either provide them flat or as a list in the
third argument.
* `write_file('temp', 'text', 'foo', 'bar', 'baz')` or
* write_file('temp', 'text', l('foo', 'bar', 'baz'))
To log a single line of string
Supported values for resource `type` is:
Supported values for resource `type` are:
* `nbt` - NBT tag
* `text` - text resource with automatic newlines added
* `raw` - text resource without implied newlines
* `shared_nbt`, `shared_text`, `shared_raw` - shared versions of the above
* `folder` - for `list_files` only - indicting folder listing instead of files
* `shared_nbt`, `shared_text`, `shared_raw`, `shared_folder` - shared versions of the above
NBT files have extension `.nbt`, store one NBT tag, and return a NBT type value. Text files have `.txt` extension,
stores multiple lines of text and returns lists of all lines from the file. With `write_file`, multiple lines can be
sent to the file at once. The only difference between `raw` and `text` types are automatic newlines added after each
record to the file.
record to the file. Since files are closed after each write, sending multiple lines of data to
write is beneficial for writing speed. To send multiple packs of data, either provide them flat or as a list in the
third argument.
<pre>
write_file('foo', 'shared_text, l('one', 'two'));
write_file('foo', 'shared_text, ['one', 'two']);
write_file('foo', 'shared_text', 'three\n', 'four\n');
write_file('foo', 'shared_raw', 'five\n', 'six\n');
@@ -500,7 +495,6 @@ Available options in the scarpet app space:
* `game_version` - base version of the game
Server related properties
* `server_motd` - the motd of the server visible when joining
* `server_ip` - IP adress of the game hosted
* `server_whitelisted` - boolean indicating whether the access to the server is only for whitelisted players
@@ -517,3 +511,6 @@ Available options in the scarpet app space:
* `java_bits` - number indicating how many bits the Java has, 32 or 64
* `java_system_cpu_load` - current percentage of CPU used by the system
* `java_process_cpu_load` - current percentage of CPU used by JVM
Scarpet related properties
* `scarpet_version` - returns the version of the carpet your scarpet comes with.
+5
View File
@@ -366,6 +366,11 @@ Player's ping in milliseconds, or `null` if its not a player.
Player's permission level, or `null` if not applicable for this entity.
### `query(e, 'client_brand')`
Returns recognized type of client of the client connected. Possible results include `'vanilla'`, or `'carpet <version>'` where
version indicates the version of the connected carpet client.
### `query(e, 'effect', name?)`
Without extra arguments, it returns list of effect active on a living entity. Each entry is a triple of short
@@ -55,6 +55,7 @@ item_category
last_tick_times
light
liquid
list_files
load_app_data
loaded
loaded_status
@@ -82,7 +82,7 @@
plop harvest destroy schedule nbt draw_shape create_marker remove_all_markers
load_app_data store_app_data read_file write_file delete_file
load_app_data store_app_data read_file write_file delete_file list_files
escape_nbt parse_nbt encode_nbt tag_matches statistic
</Keywords>
<Keywords name="Keywords3">euler pi null true false</Keywords>
@@ -217,6 +217,13 @@ public class ServerNetworkHandler
}
public static String getPlayerStatus(ServerPlayerEntity player)
{
if (remoteCarpetPlayers.containsKey(player)) return "carpet "+remoteCarpetPlayers.get(player);
if (validCarpetPlayers.contains(player)) return "carpet "+CarpetSettings.carpetVersion;
return "vanilla";
}
private static class DataBuilder
{
private CompoundTag tag;
@@ -41,6 +41,7 @@ import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static java.lang.Math.max;
import static net.minecraft.server.command.CommandManager.literal;
@@ -673,6 +674,12 @@ public class CarpetScriptHost extends ScriptHost
return Module.listFile(main, resource, "txt", isShared);
}
public Stream<String> listFolder(String resource, String ext, boolean isShared)
{
if (getName() == null && !isShared) return null; //
return Module.listFolder(main, resource, ext, isShared);
}
public void tick()
{
@@ -137,7 +137,7 @@ public class CarpetScriptServer
Path folder = server.getSavePath(WorldSavePath.ROOT).resolve("scripts");
Files.createDirectories(folder);
Optional<Path>
scriptPath = Files.walk(folder)
scriptPath = Files.list(folder)
.filter(script ->
script.getFileName().toString().equalsIgnoreCase(name+".sc") ||
(allowLibraries && script.getFileName().toString().equalsIgnoreCase(name+".scl"))
@@ -149,7 +149,7 @@ public class CarpetScriptServer
{
Path globalFolder = FabricLoader.getInstance().getConfigDir().resolve("carpet/scripts");
Files.createDirectories(globalFolder);
scriptPath = Files.walk(globalFolder)
scriptPath = Files.list(globalFolder)
.filter(script -> script.getFileName().toString().equalsIgnoreCase(name + ".sc") ||
(allowLibraries && script.getFileName().toString().equalsIgnoreCase(name + ".scl")))
.findFirst();
+53 -33
View File
@@ -32,6 +32,7 @@ import carpet.script.value.StringValue;
import carpet.script.value.Value;
import carpet.script.value.ValueConversions;
import carpet.utils.Messenger;
import com.google.common.collect.ImmutableMap;
import net.minecraft.block.BlockState;
import net.minecraft.command.argument.EntityAnchorArgumentType;
import net.minecraft.entity.Entity;
@@ -50,7 +51,6 @@ import net.minecraft.particle.ParticleEffect;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.command.CommandOutput;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.server.network.ServerPlayNetworkHandler;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.sound.SoundCategory;
@@ -69,6 +69,7 @@ import net.minecraft.util.registry.DynamicRegistryManager;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.World;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.lang3.tuple.Triple;
import java.util.ArrayList;
import java.util.Arrays;
@@ -87,19 +88,39 @@ import static java.lang.Math.min;
public class Auxiliary {
public static final String MARKER_STRING = "__scarpet_marker";
private static final Map<String, SoundCategory> mixerMap = Arrays.stream(SoundCategory.values()).collect(Collectors.toMap(SoundCategory::getName, k -> k));
private static final Map<String, String> supportedTypes = ImmutableMap.of(
"raw", ".txt",
"text", ".txt",
"nbt", ".nbt",
"folder", "folder"
);
public static String recognizeResource(Value value)
public static String recognizeResource(Value value, boolean isFloder)
{
String origfile = value.getString();
String file = origfile.toLowerCase(Locale.ROOT).replaceAll("[^A-Za-z0-9\\-+_/]", "");
file = Arrays.stream(file.split("/+")).filter(s -> !s.isEmpty()).collect(Collectors.joining("/"));
if (file.isEmpty())
if (file.isEmpty() && !isFloder)
{
throw new InternalExpressionException("Cannot use "+origfile+" as resource name - must have some letters and numbers");
}
return file;
}
public static Triple<String, String, Boolean> getFileDescriptor(List<LazyValue> lv, Context c, boolean isFloder)
{
if (lv.size() < 2) throw new InternalExpressionException("File functions require path and type as first two arguments");
String resource = recognizeResource(lv.get(0).evalValue(c), isFloder);
String origtype = lv.get(1).evalValue(c).getString().toLowerCase(Locale.ROOT);
boolean shared = origtype.startsWith("shared_");
String type = shared ? origtype.substring(7) : origtype; //len(shared_)
if (!supportedTypes.containsKey(type))
throw new InternalExpressionException("Unsupported file type: "+origtype);
if (type.equals("folder") && !isFloder)
throw new InternalExpressionException("Folder types are no supported for this IO function");
return Triple.of(resource, type, shared);
}
public static void apply(Expression expression)
{
expression.addLazyFunction("sound", -1, (c, t, lv) -> {
@@ -785,23 +806,29 @@ public class Auxiliary {
return (_c, _t) -> res; // pass through for variables
});
expression.addLazyFunction("read_file", 2, (c, t, lv) -> {
String resource = recognizeResource(lv.get(0).evalValue(c));
String origtype = lv.get(1).evalValue(c).getString().toLowerCase(Locale.ROOT);
boolean shared = origtype.startsWith("shared_");
String type = shared ? origtype.substring(7) : origtype; //len(shared_)
if (!type.equals("raw") && !type.equals("text") && !type.equals("nbt"))
throw new InternalExpressionException("Unsupported file type: "+origtype);
Value retVal;
if (type.equals("nbt"))
expression.addLazyFunction("list_files", 2, (c, t, lv) ->
{
Tag state = ((CarpetScriptHost)((CarpetContext)c).host).readFileTag(resource, shared);
Triple<String, String, Boolean> fdesc = getFileDescriptor(lv, c, true);
Stream<String> files = ((CarpetScriptHost) c.host).listFolder(fdesc.getLeft(), supportedTypes.get(fdesc.getMiddle()), fdesc.getRight());
if (files == null) return LazyValue.NULL;
Value ret = ListValue.wrap(files.map(StringValue::of).collect(Collectors.toList()));
return (cc, tt) -> ret;
});
expression.addLazyFunction("read_file", 2, (c, t, lv) ->
{
Triple<String, String, Boolean> fdesc = getFileDescriptor(lv, c, false);
Value retVal;
if (fdesc.getMiddle().equals("nbt"))
{
Tag state = ((CarpetScriptHost) c.host).readFileTag(fdesc.getLeft(), fdesc.getRight());
if (state == null) return LazyValue.NULL;
retVal = new NBTSerializableValue(state);
}
else
{
List<String> content = ((CarpetScriptHost) ((CarpetContext) c).host).readTextResource(resource, shared);
List<String> content = ((CarpetScriptHost) c.host).readTextResource(fdesc.getLeft(), fdesc.getRight());
if (content == null) return LazyValue.NULL;
retVal = ListValue.wrap(content.stream().map(StringValue::new).collect(Collectors.toList()));
}
@@ -809,33 +836,26 @@ public class Auxiliary {
});
expression.addLazyFunction("delete_file", 2, (c, t, lv) -> {
String resource = recognizeResource(lv.get(0).evalValue(c));
String origtype = lv.get(1).evalValue(c).getString().toLowerCase(Locale.ROOT);
boolean shared = origtype.startsWith("shared_");
String type = shared ? origtype.substring(7) : origtype; //len(shared_)
if (!type.equals("raw") && !type.equals("text") && !type.equals("nbt"))
throw new InternalExpressionException("Unsupported file type: "+origtype);
boolean success = ((CarpetScriptHost)((CarpetContext)c).host).removeResourceFile(resource, shared, type);
return success?LazyValue.TRUE:LazyValue.FALSE;
Triple<String, String, Boolean> fdesc = getFileDescriptor(lv, c, false);
return ((CarpetScriptHost) c.host).removeResourceFile(fdesc.getLeft(), fdesc.getRight(), fdesc.getMiddle())
? LazyValue.TRUE
: LazyValue.FALSE;
});
expression.addLazyFunction("write_file", -1, (c, t, lv) -> {
if (lv.size() < 3) throw new InternalExpressionException("'write_file' requires three or more arguments");
String resource = recognizeResource(lv.get(0).evalValue(c));
String origtype = lv.get(1).evalValue(c).getString().toLowerCase(Locale.ROOT);
boolean shared = origtype.startsWith("shared_");
String type = shared ? origtype.substring(7) : origtype; //len(shared_)
if (!type.equals("raw") && !type.equals("text") && !type.equals("nbt"))
throw new InternalExpressionException("Unsupported file type: "+origtype);
Triple<String, String, Boolean> fdesc = getFileDescriptor(lv, c, false);
boolean success;
if (type.equals("nbt"))
if (fdesc.getMiddle().equals("nbt"))
{
Value val = lv.get(2).evalValue(c);
NBTSerializableValue tagValue = (val instanceof NBTSerializableValue)
? (NBTSerializableValue) val
: new NBTSerializableValue(val.getString());
Tag tag = tagValue.getTag();
success = ((CarpetScriptHost)((CarpetContext)c).host).writeTagFile(tag, resource, shared);
success = ((CarpetScriptHost) c.host).writeTagFile(tag, fdesc.getLeft(), fdesc.getRight());
}
else
{
@@ -860,7 +880,7 @@ public class Auxiliary {
data.add(lv.get(i).evalValue(c).getString());
}
}
success = ((CarpetScriptHost) ((CarpetContext) c).host).appendLogFile(resource, shared, type, data);
success = ((CarpetScriptHost) c.host).appendLogFile(fdesc.getLeft(), fdesc.getRight(), fdesc.getMiddle(), data);
}
return success?LazyValue.TRUE:LazyValue.FALSE;
});
@@ -874,7 +894,7 @@ public class Auxiliary {
if (lv.size()>0)
{
c.host.issueDeprecation("load_app_data(...) with arguments");
file = recognizeResource(lv.get(0).evalValue(c));
file = recognizeResource(lv.get(0).evalValue(c), false);
if (lv.size() > 1)
{
shared = lv.get(1).evalValue(c).getBoolean();
@@ -897,7 +917,7 @@ public class Auxiliary {
if (lv.size()>1)
{
c.host.issueDeprecation("store_app_data(...) with more than one argument");
file = recognizeResource(lv.get(1).evalValue(c));
file = recognizeResource(lv.get(1).evalValue(c), false);
if (lv.size() > 2)
{
shared = lv.get(2).evalValue(c).getBoolean();
@@ -1,5 +1,7 @@
package carpet.script.bundled;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtIo;
import net.minecraft.nbt.PositionTracker;
import net.minecraft.nbt.Tag;
import net.minecraft.nbt.TagReaders;
@@ -21,6 +23,7 @@ import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.stream.Stream;
public class FileModule extends Module
{
@@ -60,7 +63,20 @@ public class FileModule extends Module
}
//copied private method from net.minecraft.nbt.NbtIo.read()
// to read non-compound tags - these won't be compressed
public static Tag read(File file)
{
try
{
return NbtIo.readCompressed(file);
}
catch (IOException e)
{
try
{
return NbtIo.read(file);
}
catch (IOException ioException)
{
try (DataInputStream dataInput_1 = new DataInputStream(new FileInputStream(file)))
{
@@ -80,6 +96,8 @@ public class FileModule extends Module
}
return null;
}
}
}
//copied private method from net.minecraft.nbt.NbtIo.write() and client method safe_write
public static boolean write(Tag tag_1, File file)
@@ -87,6 +105,19 @@ public class FileModule extends Module
File file_2 = new File(file.getAbsolutePath() + "_tmp");
if (file_2.exists()) file_2.delete();
if (tag_1 instanceof CompoundTag)
{
try
{
NbtIo.writeCompressed((CompoundTag) tag_1, file_2);
}
catch (IOException e)
{
return false;
}
}
else
{
try (DataOutputStream dataOutputStream_1 = new DataOutputStream(new FileOutputStream(file_2)))
{
dataOutputStream_1.writeByte(tag_1.getType());
@@ -100,6 +131,7 @@ public class FileModule extends Module
{
return false;
}
}
if (file.exists()) file.delete();
if (!file.exists()) file_2.renameTo(file);
return true;
@@ -144,4 +176,18 @@ public class FileModule extends Module
return null;
}
}
public static Stream<Path> listFiles(Path dir, String ext)
{
boolean folderListing = ext.equals("folder");
try
{
return Files.list(dir).
filter(path -> folderListing?Files.isDirectory(path):path.toString().endsWith(ext));
}
catch (IOException ignored)
{
return null;
}
}
}
+37 -23
View File
@@ -3,10 +3,12 @@ package carpet.script.bundled;
import carpet.CarpetServer;
import net.minecraft.nbt.Tag;
import net.minecraft.util.WorldSavePath;
import org.apache.commons.io.FilenameUtils;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.stream.Stream;
public abstract class Module
{
@@ -19,61 +21,73 @@ public abstract class Module
{
if (isShared)
{
return "shared/"+file;
return file.isEmpty()?"shared":"shared/"+file;
}
else if (module != null && module.getName() != null) // appdata
if (module != null && module.getName() != null) // appdata
{
return module.getName()+".data"+(file==null?"":"/"+file);
return module.getName()+".data"+(file==null || file.isEmpty()?"":"/"+file);
}
else
{
throw new RuntimeException("Invalid file descriptor: "+file);
}
}
public static Tag getData(Module module, String file, boolean isShared)
{
File dataFile = resolveResource(module, file, "nbt", isShared);
Path dataFile = resolveResource(module, file, "nbt", isShared);
if (dataFile == null) return null;
if (!Files.exists(dataFile.toPath()) || !(dataFile.isFile())) return null;
synchronized (writeIOSync) { return FileModule.read(dataFile); }
if (!Files.exists(dataFile) || !(dataFile.toFile().isFile())) return null;
synchronized (writeIOSync) { return FileModule.read(dataFile.toFile()); }
}
public static boolean saveData(Module module, String file, Tag globalState, boolean isShared)
{
File dataFile = resolveResource(module, file, "nbt", isShared);
Path dataFile = resolveResource(module, file, "nbt", isShared);
if (dataFile == null) return false;
if (!Files.exists(dataFile.toPath().getParent()) && !dataFile.getParentFile().mkdirs()) return false;
synchronized (writeIOSync) { return FileModule.write(globalState, dataFile); }
if (!Files.exists(dataFile.getParent()) && !dataFile.toFile().getParentFile().mkdirs()) return false;
synchronized (writeIOSync) { return FileModule.write(globalState, dataFile.toFile()); }
}
public static boolean appendToTextFile(Module module, String resourceName, String type, boolean isShared, List<String> message)
{
File dataFile = resolveResource(module, resourceName, "txt", isShared);
Path dataFile = resolveResource(module, resourceName, "txt", isShared);
if (dataFile == null) return false;
if (!Files.exists(dataFile.toPath().getParent()) && !dataFile.getParentFile().mkdirs()) return false;
synchronized (writeIOSync) { return FileModule.appendText(dataFile, type.equals("text"), message); }
if (!Files.exists(dataFile.getParent()) && !dataFile.toFile().getParentFile().mkdirs()) return false;
synchronized (writeIOSync) { return FileModule.appendText(dataFile.toFile(), type.equals("text"), message); }
}
public static boolean dropExistingFile(Module module, String resourceName, String ext, boolean isShared)
{
File dataFile = resolveResource(module, resourceName, ext, isShared);
Path dataFile = resolveResource(module, resourceName, ext, isShared);
if (dataFile == null) return false;
synchronized (writeIOSync) { return dataFile.delete(); }
synchronized (writeIOSync) { return dataFile.toFile().delete(); }
}
public static List<String> listFile(Module module, String resourceName, String ext, boolean isShared)
{
File dataFile = resolveResource(module, resourceName, ext, isShared);
Path dataFile = resolveResource(module, resourceName, ext, isShared);
if (dataFile == null) return null;
if (!dataFile.exists()) return null;
synchronized (writeIOSync) { return FileModule.listFileContent(dataFile); }
if (!dataFile.toFile().exists()) return null;
synchronized (writeIOSync) { return FileModule.listFileContent(dataFile.toFile()); }
}
private static File resolveResource(Module module, String resourceName, String ext, boolean isShared)
public static Stream<String> listFolder(Module module, String resourceName, String ext, boolean isShared)
{
Path dir = resolveResource(module, resourceName, null, isShared);
if (dir == null) return null;
if (!Files.exists(dir)) return null;
Stream<Path> result;
synchronized (writeIOSync) { result = FileModule.listFiles(dir, ext); }
if (result == null) return null;
Path rootPath = resolveResource(module, "", null, isShared);
Stream<String> strings = result.map(p -> rootPath.relativize(p).toString().replaceAll("[\\\\/]","/"));
if (!ext.equals("folder"))
return strings.map(FilenameUtils::removeExtension);
return strings;
}
private static Path resolveResource(Module module, String resourceName, String ext, boolean isShared)
{
if (!isShared && (module == null || module.getName() == null)) return null;
return CarpetServer.minecraft_server.getSavePath(WorldSavePath.ROOT).resolve("scripts/"+getDescriptor(module, resourceName, isShared)+"."+ext).toFile();
return CarpetServer.minecraft_server.getSavePath(WorldSavePath.ROOT).resolve("scripts/"+getDescriptor(module, resourceName, isShared)+(ext==null?"":"."+ext));
}
@Override
@@ -1,6 +1,7 @@
package carpet.script.utils;
import carpet.CarpetServer;
import carpet.CarpetSettings;
import carpet.script.CarpetContext;
import carpet.script.CarpetScriptHost;
import carpet.script.value.ListValue;
@@ -123,14 +124,7 @@ public class SystemInfo {
});
return carpetRules;
});
put("scarpet_version", c -> StringValue.of(CarpetSettings.carpetVersion));
}};
public static Value get(String what, CarpetContext cc)
@@ -9,6 +9,7 @@ import carpet.fakes.MobEntityInterface;
import carpet.fakes.HungerManagerInterface;
import carpet.fakes.ServerPlayerInteractionManagerInterface;
import carpet.helpers.Tracer;
import carpet.network.ServerNetworkHandler;
import carpet.patches.EntityPlayerMPFake;
import carpet.script.CarpetContext;
import carpet.script.EntityEventsGroup;
@@ -594,6 +595,14 @@ public class EntityValue extends Value
return Value.NULL;
});
put("client_brand", (e, a) -> {
if (e instanceof ServerPlayerEntity)
{
return StringValue.of(ServerNetworkHandler.getPlayerStatus((ServerPlayerEntity) e));
}
return Value.NULL;
});
put("team", (e, a) -> e.getScoreboardTeam()==null?Value.NULL:new StringValue(e.getScoreboardTeam().getName()));
put("ping", (e, a) -> {