Merge branch 'master' into 1.16
# Conflicts: # src/main/java/carpet/CarpetSettings.java # src/main/java/carpet/script/CarpetScriptServer.java # src/main/java/carpet/script/bundled/Module.java
This commit is contained in:
commit
f29153c3d2
21 files changed
+601
-74
No files matched your search
+71
-12
@@ -3154,25 +3154,23 @@ Optional shared shape attributes:
|
|||||||
in the form of `0xRRGGBBAA`, with the default of `-1`, so white opaque, or `0xFFFFFFFF`.
|
in the form of `0xRRGGBBAA`, with the default of `-1`, so white opaque, or `0xFFFFFFFF`.
|
||||||
* `player` - name or player entity to send the shape to. If specified, the shapes will appear only for the specified
|
* `player` - name or player entity to send the shape to. If specified, the shapes will appear only for the specified
|
||||||
player, otherwise it will be send to all players in the dimension.
|
player, otherwise it will be send to all players in the dimension.
|
||||||
|
* `width` - line thickness, defaults to 2.0pt
|
||||||
|
* `fill` - color for the faces, defaults to no fill. Use `color` attribute format
|
||||||
|
* `follow` - entity, or player name. Shape will follow an entity instead of being static.
|
||||||
|
Follow attribute requires all positional arguments to be relative to the entity and disallow
|
||||||
|
of using entity or block as position markers. You must specify positions as a triple.
|
||||||
|
|
||||||
Available shapes:
|
Available shapes:
|
||||||
* `'line'` - draws a straight line between two points
|
* `'line'` - draws a straight line between two points
|
||||||
* Required attributes:
|
* Required attributes:
|
||||||
* `from` - triple coordinates, entity, or block value indicating one end of the line
|
* `from` - triple coordinates, entity, or block value indicating one end of the line
|
||||||
* `to` - other end of the line, same format as `from`
|
* `to` - other end of the line, same format as `from`
|
||||||
* Optional attributes:
|
|
||||||
* `width` - line thickness, defaults to 2.0pt
|
|
||||||
* `follow` - entity, or player name. Shape will follow an entity instead of being static.
|
|
||||||
Follow attribute requires all positional arguments to be relative to the entity and disallow
|
|
||||||
of using entity or block as position markers. You must specify positions as a triple.
|
|
||||||
|
|
||||||
* `'box'` - draws a box with corners in specified points
|
* `'box'` - draws a box with corners in specified points
|
||||||
* Required attributes:
|
* Required attributes:
|
||||||
* `from` - triple coordinates, entity, or block value indicating one corner of the box
|
* `from` - triple coordinates, entity, or block value indicating one corner of the box
|
||||||
* `to` - other corner, same format as `from`
|
* `to` - other corner, same format as `from`
|
||||||
* Optional attributes:
|
|
||||||
* `width` - mesh line thickness, defaults to 2.0pt
|
|
||||||
* `fill` - color for the box faces, defaults to no fill, use shared color attribute format
|
|
||||||
* `'sphere'` - draws a sphere
|
* `'sphere'` - draws a sphere
|
||||||
* Required attributes:
|
* Required attributes:
|
||||||
* `center` - center of the sphere
|
* `center` - center of the sphere
|
||||||
@@ -3180,7 +3178,6 @@ Available shapes:
|
|||||||
* Optional attributes:
|
* Optional attributes:
|
||||||
* `level` - level of details, or grid size. The more the denser your sphere. Default level of 0, means that the
|
* `level` - level of details, or grid size. The more the denser your sphere. Default level of 0, means that the
|
||||||
level of detail will be selected automatically based on radius.
|
level of detail will be selected automatically based on radius.
|
||||||
* `width` - line thickness
|
|
||||||
|
|
||||||
### `create_marker(text, pos, rotation?, block?)`
|
### `create_marker(text, pos, rotation?, block?)`
|
||||||
|
|
||||||
@@ -3269,6 +3266,63 @@ Example usages:
|
|||||||
|
|
||||||
Prints the message to system logs, and not to chat.
|
Prints the message to system logs, and not to chat.
|
||||||
|
|
||||||
|
### read_file(resource, type)
|
||||||
|
### delete_file(resource, type)
|
||||||
|
### write_file(resource, type, data, ...)
|
||||||
|
|
||||||
|
With the specified `resource` in the scripts folder, of a specific `type`, writes/appends `data` to it, reads its
|
||||||
|
content, or deletes the resource.
|
||||||
|
|
||||||
|
Resource is identified by a path to the file.
|
||||||
|
A path can contain letters, numbers and 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
|
||||||
|
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
|
||||||
|
resources is guaranteed to be isolated from other apps. Shared resources are... well, shared across all apes, meaning
|
||||||
|
they can eat of each others file, however all access to files is synchronized, and files are never left open, so
|
||||||
|
this should not lead to any access problems.
|
||||||
|
|
||||||
|
If the app's name is `'foo'`, the script location would
|
||||||
|
be `world/scripts/foo.sc`, app
|
||||||
|
specific data directory is under `world/scripts/foo.data/...`, and shared data space is under
|
||||||
|
`world/scripts/shared/...`.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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:
|
||||||
|
* `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
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
write_file('foo', 'shared_text, l('one', 'two'));
|
||||||
|
write_file('foo', 'shared_text', 'three\n', 'four\n');
|
||||||
|
write_file('foo', 'shared_raw', 'five\n', 'six\n');
|
||||||
|
|
||||||
|
read_file('foo', 'shared_text') => ['one', 'two', 'three', '', 'four', '', 'five', 'six']
|
||||||
|
</pre>
|
||||||
|
|
||||||
### `run(expr)`
|
### `run(expr)`
|
||||||
|
|
||||||
Runs a vanilla command from the string result of the `expr` and returns its success count
|
Runs a vanilla command from the string result of the `expr` and returns its success count
|
||||||
@@ -3283,7 +3337,10 @@ run('give @s stone 4') -> 1 // this operation was successful once
|
|||||||
Performs autosave, saves all chunks, player data, etc. Useful for programs where autosave is disabled due to
|
Performs autosave, saves all chunks, player data, etc. Useful for programs where autosave is disabled due to
|
||||||
performance reasons and saves the world only on demand.
|
performance reasons and saves the world only on demand.
|
||||||
|
|
||||||
### `load_app_data(), load_app_data(file), load_app_data(file, shared?)`
|
### `load_app_data()`
|
||||||
|
|
||||||
|
NOTE: usages with arguments, so `load_app_data(file)` and `load_app_data(file, shared?)` are deprecated.
|
||||||
|
Use `read_file` instead.
|
||||||
|
|
||||||
Loads the app data associated with the app from the world /scripts folder. Without argument returns the memory
|
Loads the app data associated with the app from the world /scripts folder. Without argument returns the memory
|
||||||
managed and buffered / throttled NBT tag. With a file name, reads explicitly a file with that name from the
|
managed and buffered / throttled NBT tag. With a file name, reads explicitly a file with that name from the
|
||||||
@@ -3291,7 +3348,7 @@ scripts folder that belongs exclusively to the app. if `shared` is true, the fil
|
|||||||
to the app anymore, but located in a shared app space.
|
to the app anymore, but located in a shared app space.
|
||||||
|
|
||||||
File descriptor can contain letters, numbers and folder separator: `'/'`. Any other characters are stripped
|
File descriptor can contain letters, numbers and folder separator: `'/'`. Any other characters are stripped
|
||||||
from the name before saving/loading. Empty descriptors are invalid.
|
from the name before saving/loading. Empty descriptors are invalid. Do not add file extensions to the descriptor
|
||||||
|
|
||||||
Function returns nbt value with the file content, or `null` if the file is missing or there were problems
|
Function returns nbt value with the file content, or `null` if the file is missing or there were problems
|
||||||
with retrieving the data.
|
with retrieving the data.
|
||||||
@@ -3305,7 +3362,9 @@ specific data directory is under `world/scripts/foo.data/bar/../baz.nbt`, and sh
|
|||||||
|
|
||||||
You can use app data to save non-vanilla information separately from the world and other scripts.
|
You can use app data to save non-vanilla information separately from the world and other scripts.
|
||||||
|
|
||||||
### `store_app_data(tag), store_app_data(tag, file), store_app_data(tag, file, shared?)`
|
### `store_app_data(tag)`
|
||||||
|
|
||||||
|
Note: `store_app_data(tag, file)` and `store_app_data(tag, file, shared?)` usages deprecated. Use `write_file` instead.
|
||||||
|
|
||||||
Stores the app data associated with the app from the world `/scripts` folder. With the `file` parameter saves
|
Stores the app data associated with the app from the world `/scripts` folder. With the `file` parameter saves
|
||||||
immediately and with every call to a specific file defined by the `file`, either in app space, or in the scripts
|
immediately and with every call to a specific file defined by the `file`, either in app space, or in the scripts
|
||||||
|
|||||||
@@ -172,6 +172,63 @@ Example usages:
|
|||||||
|
|
||||||
Prints the message to system logs, and not to chat.
|
Prints the message to system logs, and not to chat.
|
||||||
|
|
||||||
|
### read_file(resource, type)
|
||||||
|
### delete_file(resource, type)
|
||||||
|
### write_file(resource, type, data, ...)
|
||||||
|
|
||||||
|
With the specified `resource` in the scripts folder, of a specific `type`, writes/appends `data` to it, reads its
|
||||||
|
content, or deletes the resource.
|
||||||
|
|
||||||
|
Resource is identified by a path to the file.
|
||||||
|
A path can contain letters, numbers and 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
|
||||||
|
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
|
||||||
|
resources is guaranteed to be isolated from other apps. Shared resources are... well, shared across all apes, meaning
|
||||||
|
they can eat of each others file, however all access to files is synchronized, and files are never left open, so
|
||||||
|
this should not lead to any access problems.
|
||||||
|
|
||||||
|
If the app's name is `'foo'`, the script location would
|
||||||
|
be `world/scripts/foo.sc`, app
|
||||||
|
specific data directory is under `world/scripts/foo.data/...`, and shared data space is under
|
||||||
|
`world/scripts/shared/...`.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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:
|
||||||
|
* `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
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
write_file('foo', 'shared_text, l('one', 'two'));
|
||||||
|
write_file('foo', 'shared_text', 'three\n', 'four\n');
|
||||||
|
write_file('foo', 'shared_raw', 'five\n', 'six\n');
|
||||||
|
|
||||||
|
read_file('foo', 'shared_text') => ['one', 'two', 'three', '', 'four', '', 'five', 'six']
|
||||||
|
</pre>
|
||||||
|
|
||||||
### `run(expr)`
|
### `run(expr)`
|
||||||
|
|
||||||
Runs a vanilla command from the string result of the `expr` and returns its success count
|
Runs a vanilla command from the string result of the `expr` and returns its success count
|
||||||
@@ -186,7 +243,10 @@ run('give @s stone 4') -> 1 // this operation was successful once
|
|||||||
Performs autosave, saves all chunks, player data, etc. Useful for programs where autosave is disabled due to
|
Performs autosave, saves all chunks, player data, etc. Useful for programs where autosave is disabled due to
|
||||||
performance reasons and saves the world only on demand.
|
performance reasons and saves the world only on demand.
|
||||||
|
|
||||||
### `load_app_data(), load_app_data(file), load_app_data(file, shared?)`
|
### `load_app_data()`
|
||||||
|
|
||||||
|
NOTE: usages with arguments, so `load_app_data(file)` and `load_app_data(file, shared?)` are deprecated.
|
||||||
|
Use `read_file` instead.
|
||||||
|
|
||||||
Loads the app data associated with the app from the world /scripts folder. Without argument returns the memory
|
Loads the app data associated with the app from the world /scripts folder. Without argument returns the memory
|
||||||
managed and buffered / throttled NBT tag. With a file name, reads explicitly a file with that name from the
|
managed and buffered / throttled NBT tag. With a file name, reads explicitly a file with that name from the
|
||||||
@@ -194,7 +254,7 @@ scripts folder that belongs exclusively to the app. if `shared` is true, the fil
|
|||||||
to the app anymore, but located in a shared app space.
|
to the app anymore, but located in a shared app space.
|
||||||
|
|
||||||
File descriptor can contain letters, numbers and folder separator: `'/'`. Any other characters are stripped
|
File descriptor can contain letters, numbers and folder separator: `'/'`. Any other characters are stripped
|
||||||
from the name before saving/loading. Empty descriptors are invalid.
|
from the name before saving/loading. Empty descriptors are invalid. Do not add file extensions to the descriptor
|
||||||
|
|
||||||
Function returns nbt value with the file content, or `null` if the file is missing or there were problems
|
Function returns nbt value with the file content, or `null` if the file is missing or there were problems
|
||||||
with retrieving the data.
|
with retrieving the data.
|
||||||
@@ -208,7 +268,9 @@ specific data directory is under `world/scripts/foo.data/bar/../baz.nbt`, and sh
|
|||||||
|
|
||||||
You can use app data to save non-vanilla information separately from the world and other scripts.
|
You can use app data to save non-vanilla information separately from the world and other scripts.
|
||||||
|
|
||||||
### `store_app_data(tag), store_app_data(tag, file), store_app_data(tag, file, shared?)`
|
### `store_app_data(tag)`
|
||||||
|
|
||||||
|
Note: `store_app_data(tag, file)` and `store_app_data(tag, file, shared?)` usages deprecated. Use `write_file` instead.
|
||||||
|
|
||||||
Stores the app data associated with the app from the world `/scripts` folder. With the `file` parameter saves
|
Stores the app data associated with the app from the world `/scripts` folder. With the `file` parameter saves
|
||||||
immediately and with every call to a specific file defined by the `file`, either in app space, or in the scripts
|
immediately and with every call to a specific file defined by the `file`, either in app space, or in the scripts
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ public class CarpetServer // static for now - easier to handle all around the co
|
|||||||
if (sm != null) sm.attachServer(server);
|
if (sm != null) sm.attachServer(server);
|
||||||
e.onServerLoaded(server);
|
e.onServerLoaded(server);
|
||||||
});
|
});
|
||||||
scriptServer = new CarpetScriptServer();
|
scriptServer = new CarpetScriptServer(server);
|
||||||
scriptServer.loadAllWorldScripts();
|
scriptServer.loadAllWorldScripts();
|
||||||
MobAI.resetTrackers();
|
MobAI.resetTrackers();
|
||||||
LoggerRegistry.initLoggers();
|
LoggerRegistry.initLoggers();
|
||||||
|
|||||||
@@ -498,8 +498,8 @@ public class CarpetSettings
|
|||||||
if (server.isDedicated())
|
if (server.isDedicated())
|
||||||
{
|
{
|
||||||
int vd = (newValue >= 2)?newValue:((DedicatedServer) server).getProperties().viewDistance;
|
int vd = (newValue >= 2)?newValue:((DedicatedServer) server).getProperties().viewDistance;
|
||||||
if (vd != CarpetServer.minecraft_server.getPlayerManager().getViewDistance())
|
if (vd != server.getPlayerManager().getViewDistance())
|
||||||
CarpetServer.minecraft_server.getPlayerManager().setViewDistance(vd);
|
server.getPlayerManager().setViewDistance(vd);
|
||||||
return newValue;
|
return newValue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -546,6 +546,7 @@ public class CarpetSettings
|
|||||||
//must been some startup thing
|
//must been some startup thing
|
||||||
return newValue;
|
return newValue;
|
||||||
}
|
}
|
||||||
|
if (CarpetServer.minecraft_server == null) return newValue;
|
||||||
ServerWorld currentOverworld = CarpetServer.minecraft_server.getWorld(World.OVERWORLD); // OW
|
ServerWorld currentOverworld = CarpetServer.minecraft_server.getWorld(World.OVERWORLD); // OW
|
||||||
if (currentOverworld != null)
|
if (currentOverworld != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import net.minecraft.command.arguments.DimensionArgumentType;
|
|||||||
import net.minecraft.entity.SpawnGroup;
|
import net.minecraft.entity.SpawnGroup;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.server.command.ServerCommandSource;
|
import net.minecraft.server.command.ServerCommandSource;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
import net.minecraft.util.DyeColor;
|
import net.minecraft.util.DyeColor;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.registry.RegistryKey;
|
import net.minecraft.util.registry.RegistryKey;
|
||||||
@@ -197,7 +198,7 @@ public class SpawnCommand
|
|||||||
TickSpeed.tickrate_advance(null, 0, null, null);
|
TickSpeed.tickrate_advance(null, 0, null, null);
|
||||||
// tick warp given player
|
// tick warp given player
|
||||||
ServerCommandSource csource = null;
|
ServerCommandSource csource = null;
|
||||||
PlayerEntity player = null;
|
ServerPlayerEntity player = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
player = source.getPlayer();
|
player = source.getPlayer();
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import com.mojang.brigadier.CommandDispatcher;
|
|||||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
import net.minecraft.text.BaseText;
|
import net.minecraft.text.BaseText;
|
||||||
import net.minecraft.server.command.ServerCommandSource;
|
import net.minecraft.server.command.ServerCommandSource;
|
||||||
|
|
||||||
@@ -80,7 +81,7 @@ public class TickCommand
|
|||||||
|
|
||||||
private static int setWarp(ServerCommandSource source, int advance, String tail_command)
|
private static int setWarp(ServerCommandSource source, int advance, String tail_command)
|
||||||
{
|
{
|
||||||
PlayerEntity player = null;
|
ServerPlayerEntity player = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
player = source.getPlayer();
|
player = source.getPlayer();
|
||||||
|
|||||||
@@ -7,8 +7,10 @@ import java.util.ArrayList;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import carpet.logging.logHelpers.ExplosionLogHelper;
|
||||||
import carpet.mixins.ExplosionAccessor;
|
import carpet.mixins.ExplosionAccessor;
|
||||||
import carpet.CarpetSettings;
|
import carpet.CarpetSettings;
|
||||||
|
import carpet.mixins.ExplosionMixin;
|
||||||
import carpet.utils.Messenger;
|
import carpet.utils.Messenger;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import it.unimi.dsi.fastutil.objects.Object2DoubleOpenHashMap;
|
import it.unimi.dsi.fastutil.objects.Object2DoubleOpenHashMap;
|
||||||
@@ -51,6 +53,7 @@ public class OptimizedExplosion
|
|||||||
private static List<Entity> entitylist;
|
private static List<Entity> entitylist;
|
||||||
private static Vec3d vec3dmem;
|
private static Vec3d vec3dmem;
|
||||||
private static long tickmem;
|
private static long tickmem;
|
||||||
|
private static Vec3d vec3dZero = new Vec3d(0, 0, 0);
|
||||||
// For disabling the explosion particles and sound
|
// For disabling the explosion particles and sound
|
||||||
public static int explosionSound = 0;
|
public static int explosionSound = 0;
|
||||||
|
|
||||||
@@ -66,7 +69,7 @@ public class OptimizedExplosion
|
|||||||
private static ArrayList<Float> chances = new ArrayList<>();
|
private static ArrayList<Float> chances = new ArrayList<>();
|
||||||
private static BlockPos blastChanceLocation;
|
private static BlockPos blastChanceLocation;
|
||||||
|
|
||||||
public static void doExplosionA(Explosion e) {
|
public static void doExplosionA(Explosion e, ExplosionLogHelper eLogger) {
|
||||||
ExplosionAccessor eAccess = (ExplosionAccessor) e;
|
ExplosionAccessor eAccess = (ExplosionAccessor) e;
|
||||||
|
|
||||||
blastCalc(e);
|
blastCalc(e);
|
||||||
@@ -120,6 +123,9 @@ public class OptimizedExplosion
|
|||||||
entity.getX() == eAccess.getEntity().getX() &&
|
entity.getX() == eAccess.getEntity().getX() &&
|
||||||
entity.getY() == eAccess.getEntity().getY() &&
|
entity.getY() == eAccess.getEntity().getY() &&
|
||||||
entity.getZ() == eAccess.getEntity().getZ()) {
|
entity.getZ() == eAccess.getEntity().getZ()) {
|
||||||
|
if (eLogger != null) {
|
||||||
|
eLogger.onEntityImpacted(entity, new Vec3d(0,-0.9923437498509884d, 0));
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,6 +164,10 @@ public class OptimizedExplosion
|
|||||||
d11 = ProtectionEnchantment.transformExplosionKnockback((LivingEntity) entity, d10);
|
d11 = ProtectionEnchantment.transformExplosionKnockback((LivingEntity) entity, d10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (eLogger != null) {
|
||||||
|
eLogger.onEntityImpacted(entity, new Vec3d(d5 * d11, d7 * d11, d9 * d11));
|
||||||
|
}
|
||||||
|
|
||||||
entity.setVelocity(entity.getVelocity().add(d5 * d11, d7 * d11, d9 * d11));
|
entity.setVelocity(entity.getVelocity().add(d5 * d11, d7 * d11, d9 * d11));
|
||||||
|
|
||||||
if (entity instanceof PlayerEntity) {
|
if (entity instanceof PlayerEntity) {
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ import java.util.function.BiConsumer;
|
|||||||
import carpet.CarpetServer;
|
import carpet.CarpetServer;
|
||||||
import carpet.network.ServerNetworkHandler;
|
import carpet.network.ServerNetworkHandler;
|
||||||
import carpet.utils.Messenger;
|
import carpet.utils.Messenger;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.server.command.CommandManager;
|
import net.minecraft.server.command.CommandManager;
|
||||||
import net.minecraft.server.command.ServerCommandSource;
|
import net.minecraft.server.command.ServerCommandSource;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
import net.minecraft.text.BaseText;
|
import net.minecraft.text.BaseText;
|
||||||
|
|
||||||
public class TickSpeed
|
public class TickSpeed
|
||||||
@@ -21,7 +21,7 @@ public class TickSpeed
|
|||||||
public static long time_bias = 0;
|
public static long time_bias = 0;
|
||||||
public static long time_warp_start_time = 0;
|
public static long time_warp_start_time = 0;
|
||||||
public static long time_warp_scheduled_ticks = 0;
|
public static long time_warp_scheduled_ticks = 0;
|
||||||
public static PlayerEntity time_advancerer = null;
|
public static ServerPlayerEntity time_advancerer = null;
|
||||||
public static String tick_warp_callback = null;
|
public static String tick_warp_callback = null;
|
||||||
public static ServerCommandSource tick_warp_sender = null;
|
public static ServerCommandSource tick_warp_sender = null;
|
||||||
public static int player_active_timeout = 0;
|
public static int player_active_timeout = 0;
|
||||||
@@ -68,13 +68,14 @@ public class TickSpeed
|
|||||||
player_active_timeout = PLAYER_GRACE+ticks;
|
player_active_timeout = PLAYER_GRACE+ticks;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BaseText tickrate_advance(PlayerEntity player, int advance, String callback, ServerCommandSource source)
|
public static BaseText tickrate_advance(ServerPlayerEntity player, int advance, String callback, ServerCommandSource source)
|
||||||
{
|
{
|
||||||
if (0 == advance)
|
if (0 == advance)
|
||||||
{
|
{
|
||||||
tick_warp_callback = null;
|
tick_warp_callback = null;
|
||||||
tick_warp_sender = null;
|
if (source != tick_warp_sender) tick_warp_sender = null;
|
||||||
finish_time_warp();
|
finish_time_warp();
|
||||||
|
tick_warp_sender = null;
|
||||||
return Messenger.c("gi Warp interrupted");
|
return Messenger.c("gi Warp interrupted");
|
||||||
}
|
}
|
||||||
if (time_bias > 0)
|
if (time_bias > 0)
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ public class LoggerRegistry
|
|||||||
public static boolean __packets;
|
public static boolean __packets;
|
||||||
public static boolean __weather;
|
public static boolean __weather;
|
||||||
public static boolean __pathfinding;
|
public static boolean __pathfinding;
|
||||||
|
public static boolean __explosions;
|
||||||
|
|
||||||
public static void initLoggers()
|
public static void initLoggers()
|
||||||
{
|
{
|
||||||
@@ -52,6 +53,7 @@ public class LoggerRegistry
|
|||||||
registerLogger("packets", HUDLogger.stardardHUDLogger("packets", null, null));
|
registerLogger("packets", HUDLogger.stardardHUDLogger("packets", null, null));
|
||||||
registerLogger("counter",HUDLogger.stardardHUDLogger("counter","white", Arrays.stream(DyeColor.values()).map(Object::toString).toArray(String[]::new)));
|
registerLogger("counter",HUDLogger.stardardHUDLogger("counter","white", Arrays.stream(DyeColor.values()).map(Object::toString).toArray(String[]::new)));
|
||||||
registerLogger("mobcaps", HUDLogger.stardardHUDLogger("mobcaps", "dynamic",new String[]{"dynamic", "overworld", "nether","end"}));
|
registerLogger("mobcaps", HUDLogger.stardardHUDLogger("mobcaps", "dynamic",new String[]{"dynamic", "overworld", "nether","end"}));
|
||||||
|
registerLogger("explosions", HUDLogger.stardardLogger("explosions", "brief",new String[]{"brief", "full"}));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,156 @@
|
|||||||
|
package carpet.logging.logHelpers;
|
||||||
|
|
||||||
|
import carpet.logging.LoggerRegistry;
|
||||||
|
import carpet.utils.Messenger;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.EntityType;
|
||||||
|
import net.minecraft.text.BaseText;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
import net.minecraft.util.registry.Registry;
|
||||||
|
import net.minecraft.world.explosion.Explosion;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ExplosionLogHelper
|
||||||
|
{
|
||||||
|
private final boolean createFire;
|
||||||
|
private final Explosion.DestructionType blockDestructionType;
|
||||||
|
public final double x;
|
||||||
|
public final double y;
|
||||||
|
public final double z;
|
||||||
|
public final Entity entity;
|
||||||
|
private final float power;
|
||||||
|
private boolean affectBlocks = false;
|
||||||
|
private List<EntityChangedStatusWithCount> entityChangedStatusWithCount = Lists.newArrayList();
|
||||||
|
|
||||||
|
private static long lastGametime = 0;
|
||||||
|
private static int explosionCountInCurretGT = 0;
|
||||||
|
|
||||||
|
public ExplosionLogHelper(Entity entity, double x, double y, double z, float power, boolean createFire, Explosion.DestructionType blockDestructionType) {
|
||||||
|
this.entity = entity;
|
||||||
|
this.power = power;
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.z = z;
|
||||||
|
this.createFire = createFire;
|
||||||
|
this.blockDestructionType = blockDestructionType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAffectBlocks(boolean b)
|
||||||
|
{
|
||||||
|
affectBlocks = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onExplosionDone(long gametime)
|
||||||
|
{
|
||||||
|
BaseText timeDisplay;
|
||||||
|
if (!(lastGametime == gametime)){
|
||||||
|
explosionCountInCurretGT = 0;
|
||||||
|
lastGametime = gametime;
|
||||||
|
timeDisplay = Messenger.c("wb " + ">>>>>> CURRENT GAME TIME : ", "d " + gametime, "wb >>>>>>\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
timeDisplay = Messenger.s("");
|
||||||
|
}
|
||||||
|
explosionCountInCurretGT++;
|
||||||
|
LoggerRegistry.getLogger("explosions").log( (option) -> {
|
||||||
|
switch (option)
|
||||||
|
{
|
||||||
|
case "brief":
|
||||||
|
return new BaseText[]{Messenger.c(
|
||||||
|
timeDisplay, "gb EXPLOSION", "d #" + explosionCountInCurretGT,"gb -> ",
|
||||||
|
"w P: ", "d ",Messenger.dblt("l",x ,y ,z),
|
||||||
|
"w affectBlocks: ", "m " + this.affectBlocks
|
||||||
|
)};
|
||||||
|
case "full":
|
||||||
|
return new BaseText[]{Messenger.c(
|
||||||
|
timeDisplay, "gb EXPLOSION", "d #" + explosionCountInCurretGT,"gb -> ",
|
||||||
|
"w P: ", "d ",Messenger.dblt("l",x ,y ,z),
|
||||||
|
"w createFire: ", "m " + this.createFire,
|
||||||
|
"w power: ", "c " + this.power,
|
||||||
|
"w destructionType: ", "c " + this.blockDestructionType.name(),
|
||||||
|
"w affectBlocks: ", "m " + this.affectBlocks,
|
||||||
|
"b \n", ListToText()
|
||||||
|
)};
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onEntityImpacted(Entity entity, Vec3d deltaVelocity)
|
||||||
|
{
|
||||||
|
for (EntityChangedStatusWithCount e : entityChangedStatusWithCount)
|
||||||
|
{
|
||||||
|
if (e.checkIfEquals(entity, deltaVelocity))
|
||||||
|
{
|
||||||
|
e.count++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
entityChangedStatusWithCount.add(new EntityChangedStatusWithCount(entity.getPos(), entity.getType(), deltaVelocity));
|
||||||
|
}
|
||||||
|
|
||||||
|
public BaseText ListToText()
|
||||||
|
{
|
||||||
|
BaseText s = Messenger.s("Entities Impacted:\n");
|
||||||
|
for (EntityChangedStatusWithCount entityChanges : entityChangedStatusWithCount)
|
||||||
|
{
|
||||||
|
s.append(entityChanges.asText());
|
||||||
|
s.append("\n");
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class EntityChangedStatusWithCount
|
||||||
|
{
|
||||||
|
public final Vec3d entityPos;
|
||||||
|
public final EntityType entityType;
|
||||||
|
public final Vec3d deltaSpeed;
|
||||||
|
public int count;
|
||||||
|
public EntityChangedStatusWithCount(Vec3d entityPos, EntityType entityType, Vec3d deltaSpeed)
|
||||||
|
{
|
||||||
|
this.entityPos = entityPos;
|
||||||
|
this.entityType = entityType;
|
||||||
|
this.deltaSpeed = deltaSpeed;
|
||||||
|
this.count = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(EntityChangedStatusWithCount e)
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
e.entityType == this.entityType &&
|
||||||
|
e.deltaSpeed.equals(this.deltaSpeed) &&
|
||||||
|
e.entityPos.equals(this.entityPos)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean checkIfEquals(Entity e, Vec3d deltaSpeed)
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
e.getType() == this.entityType &&
|
||||||
|
deltaSpeed.equals(this.deltaSpeed) &&
|
||||||
|
e.getPos().equals(this.entityPos)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return String.format("{EntityType: %s, EntityPos: %s ,DeltaSpeed: %s}", entityType.getName().asString(), entityPos.toString(), deltaSpeed.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public BaseText asText()
|
||||||
|
{
|
||||||
|
return Messenger.c(
|
||||||
|
"m Entity(count="+ this.count +") of",
|
||||||
|
"l " + Registry.ENTITY_TYPE.getId(entityType), "g {",
|
||||||
|
"w P: ", "y ", Messenger.dblt("t", entityPos.x, entityPos.y, entityPos.z),
|
||||||
|
"w dV: ", "gbi " + (deltaSpeed.equals(new Vec3d(0,-0.9923437498509884d, 0)) ? "<TNTs-AT-SAME-SPOT>":""),"y ", Messenger.dblt("d", deltaSpeed.x, deltaSpeed.y, deltaSpeed.z),
|
||||||
|
"g }"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,9 +2,13 @@ package carpet.mixins;
|
|||||||
|
|
||||||
import carpet.helpers.OptimizedExplosion;
|
import carpet.helpers.OptimizedExplosion;
|
||||||
import carpet.CarpetSettings;
|
import carpet.CarpetSettings;
|
||||||
|
import carpet.logging.LoggerRegistry;
|
||||||
|
import carpet.logging.logHelpers.ExplosionLogHelper;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.block.Blocks;
|
import net.minecraft.block.Blocks;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraft.world.explosion.Explosion;
|
import net.minecraft.world.explosion.Explosion;
|
||||||
import org.spongepowered.asm.mixin.Final;
|
import org.spongepowered.asm.mixin.Final;
|
||||||
@@ -24,13 +28,17 @@ public abstract class ExplosionMixin
|
|||||||
@Final
|
@Final
|
||||||
private List<BlockPos> affectedBlocks;
|
private List<BlockPos> affectedBlocks;
|
||||||
|
|
||||||
|
@Shadow @Final private World world;
|
||||||
|
|
||||||
|
private ExplosionLogHelper eLogger;
|
||||||
|
|
||||||
@Inject(method = "collectBlocksAndDamageEntities", at = @At("HEAD"),
|
@Inject(method = "collectBlocksAndDamageEntities", at = @At("HEAD"),
|
||||||
cancellable = true)
|
cancellable = true)
|
||||||
private void onExplosionA(CallbackInfo ci)
|
private void onExplosionA(CallbackInfo ci)
|
||||||
{
|
{
|
||||||
if (CarpetSettings.optimizedTNT)
|
if (CarpetSettings.optimizedTNT)
|
||||||
{
|
{
|
||||||
OptimizedExplosion.doExplosionA((Explosion) (Object) this);
|
OptimizedExplosion.doExplosionA((Explosion) (Object) this, eLogger);
|
||||||
ci.cancel();
|
ci.cancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -39,6 +47,11 @@ public abstract class ExplosionMixin
|
|||||||
cancellable = true)
|
cancellable = true)
|
||||||
private void onExplosionB(boolean spawnParticles, CallbackInfo ci)
|
private void onExplosionB(boolean spawnParticles, CallbackInfo ci)
|
||||||
{
|
{
|
||||||
|
if (eLogger != null)
|
||||||
|
{
|
||||||
|
eLogger.setAffectBlocks( ! affectedBlocks.isEmpty());
|
||||||
|
eLogger.onExplosionDone(this.world.getTime());
|
||||||
|
}
|
||||||
if (CarpetSettings.explosionNoBlockDamage)
|
if (CarpetSettings.explosionNoBlockDamage)
|
||||||
{
|
{
|
||||||
affectedBlocks.clear();
|
affectedBlocks.clear();
|
||||||
@@ -58,4 +71,24 @@ public abstract class ExplosionMixin
|
|||||||
if (CarpetSettings.explosionNoBlockDamage) return Blocks.BEDROCK.getDefaultState();
|
if (CarpetSettings.explosionNoBlockDamage) return Blocks.BEDROCK.getDefaultState();
|
||||||
return world.getBlockState(pos);
|
return world.getBlockState(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Inject(method = "<init>(Lnet/minecraft/world/World;Lnet/minecraft/entity/Entity;DDDFZLnet/minecraft/world/explosion/Explosion$DestructionType;)V",
|
||||||
|
at = @At(value = "RETURN"))
|
||||||
|
private void onExplosionCreated(World world, Entity entity, double x, double y, double z, float power, boolean createFire, Explosion.DestructionType blockDestructionType, CallbackInfo ci)
|
||||||
|
{
|
||||||
|
if (LoggerRegistry.__explosions && ! world.isClient)
|
||||||
|
{
|
||||||
|
eLogger = new ExplosionLogHelper(entity, x, y, z, power, createFire, blockDestructionType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Redirect(method = "collectBlocksAndDamageEntities",
|
||||||
|
at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;setVelocity(Lnet/minecraft/util/math/Vec3d;)V"))
|
||||||
|
private void setVelocityAndUpdateLogging(Entity entity, Vec3d velocity)
|
||||||
|
{
|
||||||
|
if (eLogger != null) {
|
||||||
|
eLogger.onEntityImpacted(entity, velocity.subtract(entity.getVelocity()));
|
||||||
|
}
|
||||||
|
entity.setVelocity(velocity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -5,6 +5,7 @@ import carpet.fakes.PistonBlockEntityInterface;
|
|||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import net.minecraft.block.*;
|
import net.minecraft.block.*;
|
||||||
import net.minecraft.block.entity.BlockEntity;
|
import net.minecraft.block.entity.BlockEntity;
|
||||||
|
import net.minecraft.block.piston.PistonBehavior;
|
||||||
import net.minecraft.block.piston.PistonHandler;
|
import net.minecraft.block.piston.PistonHandler;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.Direction;
|
import net.minecraft.util.math.Direction;
|
||||||
@@ -62,6 +63,17 @@ public abstract class PistonBlock_movableTEMixin extends FacingBlock
|
|||||||
return !(CarpetSettings.movableBlockEntities && isPushableBlockEntity(block));
|
return !(CarpetSettings.movableBlockEntities && isPushableBlockEntity(block));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Redirect(method = "isMovable", at = @At(
|
||||||
|
value = "INVOKE",
|
||||||
|
target = "Lnet/minecraft/block/BlockState;getPistonBehavior()Lnet/minecraft/block/piston/PistonBehavior;"
|
||||||
|
))
|
||||||
|
private static PistonBehavior moveGrindstones(BlockState blockState)
|
||||||
|
{
|
||||||
|
if (CarpetSettings.movableBlockEntities && blockState.getBlock() == Blocks.GRINDSTONE) return PistonBehavior.NORMAL;
|
||||||
|
return blockState.getPistonBehavior();
|
||||||
|
}
|
||||||
|
|
||||||
@Inject(method = "move", at = @At(value = "INVOKE", shift = At.Shift.BEFORE,
|
@Inject(method = "move", at = @At(value = "INVOKE", shift = At.Shift.BEFORE,
|
||||||
target = "Ljava/util/List;size()I", ordinal = 4),locals = LocalCapture.CAPTURE_FAILHARD)
|
target = "Ljava/util/List;size()I", ordinal = 4),locals = LocalCapture.CAPTURE_FAILHARD)
|
||||||
private void onMove(World world_1, BlockPos blockPos_1, Direction direction_1, boolean boolean_1,
|
private void onMove(World world_1, BlockPos blockPos_1, Direction direction_1, boolean boolean_1,
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ public abstract class PlayerEntity_antiCheatDisabled
|
|||||||
@Inject(method = "checkFallFlying", at = @At("HEAD"), cancellable = true)
|
@Inject(method = "checkFallFlying", at = @At("HEAD"), cancellable = true)
|
||||||
private void allowDeploys(CallbackInfoReturnable<Boolean> cir)
|
private void allowDeploys(CallbackInfoReturnable<Boolean> cir)
|
||||||
{
|
{
|
||||||
if (CarpetSettings.antiCheatDisabled && CarpetServer.minecraft_server.isDedicated())
|
if (CarpetSettings.antiCheatDisabled && CarpetServer.minecraft_server != null && CarpetServer.minecraft_server.isDedicated())
|
||||||
{
|
{
|
||||||
ItemStack itemStack_1 = getEquippedStack(EquipmentSlot.CHEST);
|
ItemStack itemStack_1 = getEquippedStack(EquipmentSlot.CHEST);
|
||||||
if (itemStack_1.getItem() == Items.ELYTRA && ElytraItem.isUsable(itemStack_1)) {
|
if (itemStack_1.getItem() == Items.ELYTRA && ElytraItem.isUsable(itemStack_1)) {
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import carpet.script.value.Value;
|
|||||||
import carpet.utils.Messenger;
|
import carpet.utils.Messenger;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.entity.damage.DamageSource;
|
import net.minecraft.entity.damage.DamageSource;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.server.command.ServerCommandSource;
|
import net.minecraft.server.command.ServerCommandSource;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
@@ -53,6 +54,7 @@ import java.util.stream.Collectors;
|
|||||||
public class CarpetEventServer
|
public class CarpetEventServer
|
||||||
{
|
{
|
||||||
public final List<ScheduledCall> scheduledCalls = new LinkedList<>();
|
public final List<ScheduledCall> scheduledCalls = new LinkedList<>();
|
||||||
|
public final MinecraftServer server;
|
||||||
|
|
||||||
public static class Callback
|
public static class Callback
|
||||||
{
|
{
|
||||||
@@ -658,8 +660,9 @@ public class CarpetEventServer
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public CarpetEventServer()
|
public CarpetEventServer(MinecraftServer server)
|
||||||
{
|
{
|
||||||
|
this.server = server;
|
||||||
for (Event e: Event.values())
|
for (Event e: Event.values())
|
||||||
e.handler.callList.clear();
|
e.handler.callList.clear();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2489,6 +2489,18 @@ public class CarpetExpression
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String recognizeResource(Value value)
|
||||||
|
{
|
||||||
|
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())
|
||||||
|
{
|
||||||
|
throw new InternalExpressionException("Cannot use "+origfile+" as resource name - must have some letters and numbers");
|
||||||
|
}
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
private void API_AuxiliaryAspects()
|
private void API_AuxiliaryAspects()
|
||||||
{
|
{
|
||||||
this.expr.addLazyFunction("sound", -1, (c, t, lv) -> {
|
this.expr.addLazyFunction("sound", -1, (c, t, lv) -> {
|
||||||
@@ -2877,13 +2889,6 @@ public class CarpetExpression
|
|||||||
// implmenetation should dock the task on the main thread.
|
// implmenetation should dock the task on the main thread.
|
||||||
});
|
});
|
||||||
|
|
||||||
this.expr.addLazyFunction("logger", 1, (c, t, lv) ->
|
|
||||||
{
|
|
||||||
Value res = lv.get(0).evalValue(c);
|
|
||||||
CarpetSettings.LOG.error(res.getString());
|
|
||||||
return (_c, _t) -> res; // pass through for variables
|
|
||||||
});
|
|
||||||
|
|
||||||
this.expr.addLazyFunction("run", 1, (c, t, lv) -> {
|
this.expr.addLazyFunction("run", 1, (c, t, lv) -> {
|
||||||
BlockPos target = ((CarpetContext)c).origin;
|
BlockPos target = ((CarpetContext)c).origin;
|
||||||
Vec3d posf = new Vec3d((double)target.getX()+0.5D,(double)target.getY(),(double)target.getZ()+0.5D);
|
Vec3d posf = new Vec3d((double)target.getX()+0.5D,(double)target.getY(),(double)target.getZ()+0.5D);
|
||||||
@@ -3070,25 +3075,108 @@ public class CarpetExpression
|
|||||||
return (c_, t_) -> Value.TRUE;
|
return (c_, t_) -> Value.TRUE;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.expr.addLazyFunction("logger", 1, (c, t, lv) ->
|
||||||
|
{
|
||||||
|
Value res = lv.get(0).evalValue(c);
|
||||||
|
CarpetSettings.LOG.error(res.getString());
|
||||||
|
return (_c, _t) -> res; // pass through for variables
|
||||||
|
});
|
||||||
|
|
||||||
|
this.expr.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"))
|
||||||
|
{
|
||||||
|
Tag state = ((CarpetScriptHost)((CarpetContext)c).host).readFileTag(resource, shared);
|
||||||
|
if (state == null) return LazyValue.NULL;
|
||||||
|
retVal = new NBTSerializableValue(state);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
List<String> content = ((CarpetScriptHost) ((CarpetContext) c).host).readTextResource(resource, shared);
|
||||||
|
if (content == null) return LazyValue.NULL;
|
||||||
|
retVal = ListValue.wrap(content.stream().map(StringValue::new).collect(Collectors.toList()));
|
||||||
|
}
|
||||||
|
return (cc, tt) -> retVal;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.expr.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;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.expr.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);
|
||||||
|
boolean success;
|
||||||
|
if (type.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);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
List<String> data = new ArrayList<>();
|
||||||
|
if (lv.size()==3)
|
||||||
|
{
|
||||||
|
Value val = lv.get(2).evalValue(c);
|
||||||
|
if (val instanceof ListValue)
|
||||||
|
{
|
||||||
|
List<Value> lval = ((ListValue) val).getItems();
|
||||||
|
lval.forEach(v -> data.add(v.getString()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
data.add(val.getString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(int i = 2; i < lv.size(); i++)
|
||||||
|
{
|
||||||
|
data.add(lv.get(i).evalValue(c).getString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
success = ((CarpetScriptHost) ((CarpetContext) c).host).appendLogFile(resource, shared, type, data);
|
||||||
|
}
|
||||||
|
return success?LazyValue.TRUE:LazyValue.FALSE;
|
||||||
|
});
|
||||||
|
|
||||||
|
//write_file
|
||||||
|
|
||||||
this.expr.addLazyFunction("load_app_data", -1, (c, t, lv) ->
|
this.expr.addLazyFunction("load_app_data", -1, (c, t, lv) ->
|
||||||
{
|
{
|
||||||
String file = null;
|
String file = null;
|
||||||
boolean shared = false;
|
boolean shared = false;
|
||||||
if (lv.size()>0)
|
if (lv.size()>0)
|
||||||
{
|
{
|
||||||
String origfile = lv.get(0).evalValue(c).getString();
|
file = recognizeResource(lv.get(0).evalValue(c));
|
||||||
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())
|
|
||||||
{
|
|
||||||
throw new InternalExpressionException("Cannot use "+origfile+" as resource name - must have at least some letters and numbers");
|
|
||||||
}
|
|
||||||
if (lv.size() > 1)
|
if (lv.size() > 1)
|
||||||
{
|
{
|
||||||
shared = lv.get(1).evalValue(c).getBoolean();
|
shared = lv.get(1).evalValue(c).getBoolean();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Tag state = ((CarpetScriptHost)((CarpetContext)c).host).getGlobalState(file, shared);
|
Tag state = ((CarpetScriptHost)((CarpetContext)c).host).readFileTag(file, shared);
|
||||||
if (state == null)
|
if (state == null)
|
||||||
return (cc, tt) -> Value.NULL;
|
return (cc, tt) -> Value.NULL;
|
||||||
Value retVal = new NBTSerializableValue(state);
|
Value retVal = new NBTSerializableValue(state);
|
||||||
@@ -3104,13 +3192,7 @@ public class CarpetExpression
|
|||||||
boolean shared = false;
|
boolean shared = false;
|
||||||
if (lv.size()>1)
|
if (lv.size()>1)
|
||||||
{
|
{
|
||||||
String origfile = lv.get(1).evalValue(c).getString();
|
file = recognizeResource(lv.get(1).evalValue(c));
|
||||||
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())
|
|
||||||
{
|
|
||||||
throw new InternalExpressionException("Cannot use "+origfile+" as resource name - must have some letters and numbers");
|
|
||||||
}
|
|
||||||
if (lv.size() > 2)
|
if (lv.size() > 2)
|
||||||
{
|
{
|
||||||
shared = lv.get(2).evalValue(c).getBoolean();
|
shared = lv.get(2).evalValue(c).getBoolean();
|
||||||
@@ -3120,7 +3202,7 @@ public class CarpetExpression
|
|||||||
? (NBTSerializableValue) val
|
? (NBTSerializableValue) val
|
||||||
: new NBTSerializableValue(val.getString());
|
: new NBTSerializableValue(val.getString());
|
||||||
Tag tag = tagValue.getTag();
|
Tag tag = tagValue.getTag();
|
||||||
boolean success = ((CarpetScriptHost)((CarpetContext)c).host).setGlobalState(tag, file, shared);
|
boolean success = ((CarpetScriptHost)((CarpetContext)c).host).writeTagFile(tag, file, shared);
|
||||||
return success?LazyValue.TRUE:LazyValue.FALSE;
|
return success?LazyValue.TRUE:LazyValue.FALSE;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -323,7 +323,7 @@ public class CarpetScriptHost extends ScriptHost
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
callUDF(BlockPos.ORIGIN, CarpetServer.minecraft_server.getCommandSource(), closing, Collections.emptyList());
|
callUDF(BlockPos.ORIGIN, scriptServer.server.getCommandSource(), closing, Collections.emptyList());
|
||||||
}
|
}
|
||||||
catch (InvalidCallbackException ignored)
|
catch (InvalidCallbackException ignored)
|
||||||
{
|
{
|
||||||
@@ -334,8 +334,8 @@ public class CarpetScriptHost extends ScriptHost
|
|||||||
FunctionValue userClosing = value.getFunction("__on_close");
|
FunctionValue userClosing = value.getFunction("__on_close");
|
||||||
if (userClosing != null)
|
if (userClosing != null)
|
||||||
{
|
{
|
||||||
ServerPlayerEntity player = CarpetServer.minecraft_server.getPlayerManager().getPlayer(key);
|
ServerPlayerEntity player = scriptServer.server.getPlayerManager().getPlayer(key);
|
||||||
ServerCommandSource source = (player != null)?player.getCommandSource():CarpetServer.minecraft_server.getCommandSource();
|
ServerCommandSource source = (player != null)?player.getCommandSource():scriptServer.server.getCommandSource();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
((CarpetScriptHost) value).callUDF(BlockPos.ORIGIN, source, userClosing, Collections.emptyList());
|
((CarpetScriptHost) value).callUDF(BlockPos.ORIGIN, source, userClosing, Collections.emptyList());
|
||||||
@@ -347,7 +347,7 @@ public class CarpetScriptHost extends ScriptHost
|
|||||||
});
|
});
|
||||||
|
|
||||||
String markerName = CarpetExpression.MARKER_STRING+"_"+((getName()==null)?"":getName());
|
String markerName = CarpetExpression.MARKER_STRING+"_"+((getName()==null)?"":getName());
|
||||||
for (ServerWorld world : CarpetServer.minecraft_server.getWorlds())
|
for (ServerWorld world : scriptServer.server.getWorlds())
|
||||||
{
|
{
|
||||||
for (Entity e : world.getEntities(EntityType.ARMOR_STAND, (as) -> as.getScoreboardTags().contains(markerName)))
|
for (Entity e : world.getEntities(EntityType.ARMOR_STAND, (as) -> as.getScoreboardTags().contains(markerName)))
|
||||||
{
|
{
|
||||||
@@ -369,7 +369,7 @@ public class CarpetScriptHost extends ScriptHost
|
|||||||
return Module.getData(main, null, false);
|
return Module.getData(main, null, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Tag getGlobalState(String file, boolean isShared)
|
public Tag readFileTag(String file, boolean isShared)
|
||||||
{
|
{
|
||||||
if (getName() == null && !isShared) return null;
|
if (getName() == null && !isShared) return null;
|
||||||
if (file != null)
|
if (file != null)
|
||||||
@@ -379,7 +379,7 @@ public class CarpetScriptHost extends ScriptHost
|
|||||||
return ((CarpetScriptHost)parent).globalState;
|
return ((CarpetScriptHost)parent).globalState;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean setGlobalState(Tag tag, String file, boolean isShared)
|
public boolean writeTagFile(Tag tag, String file, boolean isShared)
|
||||||
{
|
{
|
||||||
if (getName() == null && !isShared) return false; // if belongs to an app, cannot be default host.
|
if (getName() == null && !isShared) return false; // if belongs to an app, cannot be default host.
|
||||||
|
|
||||||
@@ -398,6 +398,25 @@ public class CarpetScriptHost extends ScriptHost
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean removeResourceFile(String resource, boolean isShared, String type)
|
||||||
|
{
|
||||||
|
if (getName() == null && !isShared) return false; //
|
||||||
|
return Module.dropExistingFile(main, resource, type.equals("nbt")?"nbt":"txt", isShared);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean appendLogFile(String resource, boolean isShared, String type, List<String> data)
|
||||||
|
{
|
||||||
|
if (getName() == null && !isShared) return false; // if belongs to an app, cannot be default host.
|
||||||
|
return Module.appendToTextFile(main, resource, type, isShared, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> readTextResource(String resource, boolean isShared)
|
||||||
|
{
|
||||||
|
if (getName() == null && !isShared) return null; //
|
||||||
|
return Module.listFile(main, resource, "txt", isShared);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void tick()
|
public void tick()
|
||||||
{
|
{
|
||||||
if (this.saveTimeout > 0)
|
if (this.saveTimeout > 0)
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import static net.minecraft.server.command.CommandManager.literal;
|
|||||||
public class CarpetScriptServer
|
public class CarpetScriptServer
|
||||||
{
|
{
|
||||||
//make static for now, but will change that later:
|
//make static for now, but will change that later:
|
||||||
|
public final MinecraftServer server;
|
||||||
public CarpetScriptHost globalHost;
|
public CarpetScriptHost globalHost;
|
||||||
public Map<String, CarpetScriptHost> modules;
|
public Map<String, CarpetScriptHost> modules;
|
||||||
public long tickStart;
|
public long tickStart;
|
||||||
@@ -51,19 +52,20 @@ public class CarpetScriptServer
|
|||||||
add(new BundledModule("math", true));
|
add(new BundledModule("math", true));
|
||||||
}};
|
}};
|
||||||
|
|
||||||
public CarpetScriptServer()
|
public CarpetScriptServer(MinecraftServer server)
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void init()
|
private void init()
|
||||||
{
|
{
|
||||||
|
this.server = server;
|
||||||
ScriptHost.systemGlobals.clear();
|
ScriptHost.systemGlobals.clear();
|
||||||
events = new CarpetEventServer();
|
events = new CarpetEventServer(server);
|
||||||
modules = new HashMap<>();
|
modules = new HashMap<>();
|
||||||
tickStart = 0L;
|
tickStart = 0L;
|
||||||
stopAll = false;
|
stopAll = false;
|
||||||
holyMoly = CarpetServer.minecraft_server.getCommandManager().getDispatcher().getRoot().getChildren().stream().map(CommandNode::getName).collect(Collectors.toSet());
|
holyMoly = server.getCommandManager().getDispatcher().getRoot().getChildren().stream().map(CommandNode::getName).collect(Collectors.toSet());
|
||||||
globalHost = CarpetScriptHost.create(this, null, false, null);
|
globalHost = CarpetScriptHost.create(this, null, false, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,10 +73,10 @@ public class CarpetScriptServer
|
|||||||
{
|
{
|
||||||
if (CarpetSettings.scriptsAutoload)
|
if (CarpetSettings.scriptsAutoload)
|
||||||
{
|
{
|
||||||
Messenger.m(CarpetServer.minecraft_server.getCommandSource(), "Auto-loading world scarpet apps");
|
Messenger.m(server.getCommandSource(), "Auto-loading world scarpet apps");
|
||||||
for (String moduleName: listAvailableModules(false))
|
for (String moduleName: listAvailableModules(false))
|
||||||
{
|
{
|
||||||
addScriptHost(CarpetServer.minecraft_server.getCommandSource(), moduleName, true, true);
|
addScriptHost(server.getCommandSource(), moduleName, true, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,6 +85,8 @@ public class CarpetScriptServer
|
|||||||
public Module getModule(String name, boolean allowLibraries)
|
public Module getModule(String name, boolean allowLibraries)
|
||||||
{
|
{
|
||||||
File folder = CarpetServer.minecraft_server.getSavePath(WorldSavePath.ROOT).resolve("scripts").toFile();
|
File folder = CarpetServer.minecraft_server.getSavePath(WorldSavePath.ROOT).resolve("scripts").toFile();
|
||||||
|
File folder = server.getLevelStorage().resolveFile(
|
||||||
|
server.getLevelName(), "scripts");
|
||||||
File[] listOfFiles = folder.listFiles();
|
File[] listOfFiles = folder.listFiles();
|
||||||
if (listOfFiles != null)
|
if (listOfFiles != null)
|
||||||
for (File script : listOfFiles)
|
for (File script : listOfFiles)
|
||||||
@@ -117,6 +121,8 @@ public class CarpetScriptServer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
File folder = CarpetServer.minecraft_server.getSavePath(WorldSavePath.ROOT).resolve("scripts").toFile();
|
File folder = CarpetServer.minecraft_server.getSavePath(WorldSavePath.ROOT).resolve("scripts").toFile();
|
||||||
|
File folder = server.getLevelStorage().resolveFile(
|
||||||
|
server.getLevelName(), "scripts");
|
||||||
File[] listOfFiles = folder.listFiles();
|
File[] listOfFiles = folder.listFiles();
|
||||||
if (listOfFiles == null)
|
if (listOfFiles == null)
|
||||||
return moduleNames;
|
return moduleNames;
|
||||||
@@ -228,7 +234,7 @@ public class CarpetScriptServer
|
|||||||
})));
|
})));
|
||||||
}
|
}
|
||||||
Messenger.m(source, "gi "+hostName+" app loaded with /"+hostName+" command");
|
Messenger.m(source, "gi "+hostName+" app loaded with /"+hostName+" command");
|
||||||
CarpetServer.minecraft_server.getCommandManager().getDispatcher().register(command);
|
server.getCommandManager().getDispatcher().register(command);
|
||||||
CarpetServer.settingsManager.notifyPlayersCommandsChanged();
|
CarpetServer.settingsManager.notifyPlayersCommandsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -173,9 +173,9 @@ public class Tokenizer implements Iterator<Tokenizer.Token>
|
|||||||
}
|
}
|
||||||
else if (nextChar == 't')
|
else if (nextChar == 't')
|
||||||
{
|
{
|
||||||
throw new ExpressionException(context, this.expression, token,
|
//throw new ExpressionException(context, this.expression, token,
|
||||||
"Tab character is not supported");
|
// "Tab character is not supported");
|
||||||
//token.append('\t');
|
token.append('\t');
|
||||||
}
|
}
|
||||||
else if (nextChar == 'r')
|
else if (nextChar == 'r')
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,17 +1,24 @@
|
|||||||
package carpet.script.bundled;
|
package carpet.script.bundled;
|
||||||
|
|
||||||
import carpet.CarpetServer;
|
|
||||||
import net.minecraft.nbt.PositionTracker;
|
import net.minecraft.nbt.PositionTracker;
|
||||||
import net.minecraft.nbt.Tag;
|
import net.minecraft.nbt.Tag;
|
||||||
import net.minecraft.nbt.TagReaders;
|
import net.minecraft.nbt.TagReaders;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.BufferedWriter;
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.StandardOpenOption;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
public class FileModule extends Module
|
public class FileModule extends Module
|
||||||
@@ -96,4 +103,44 @@ public class FileModule extends Module
|
|||||||
if (!file.exists()) file_2.renameTo(file);
|
if (!file.exists()) file_2.renameTo(file);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean appendText(File filePath, boolean addNewLines, List<String> data)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
OutputStream out = Files.newOutputStream(filePath.toPath(), StandardOpenOption.APPEND, StandardOpenOption.CREATE);
|
||||||
|
try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, StandardCharsets.UTF_8)))
|
||||||
|
{
|
||||||
|
for (String line: data)
|
||||||
|
{
|
||||||
|
writer.append(line);
|
||||||
|
if (addNewLines) writer.newLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static List<String> listFileContent(File filePath)
|
||||||
|
{
|
||||||
|
try (BufferedReader reader = Files.newBufferedReader(filePath.toPath(), StandardCharsets.UTF_8)) {
|
||||||
|
List<String> result = new ArrayList<>();
|
||||||
|
for (;;) {
|
||||||
|
String line = reader.readLine();
|
||||||
|
if (line == null)
|
||||||
|
break;
|
||||||
|
result.add(line.replaceAll("[\n\r]+",""));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -6,15 +6,14 @@ import net.minecraft.util.WorldSavePath;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
|
import java.util.List;
|
||||||
import static carpet.script.bundled.FileModule.read;
|
|
||||||
import static carpet.script.bundled.FileModule.write;
|
|
||||||
|
|
||||||
public abstract class Module
|
public abstract class Module
|
||||||
{
|
{
|
||||||
public abstract String getName();
|
public abstract String getName();
|
||||||
public abstract String getCode();
|
public abstract String getCode();
|
||||||
public abstract boolean isLibrary();
|
public abstract boolean isLibrary();
|
||||||
|
public final static Object writeIOSync = new Object();
|
||||||
|
|
||||||
private static String getDescriptor(Module module, String file, boolean isShared)
|
private static String getDescriptor(Module module, String file, boolean isShared)
|
||||||
{
|
{
|
||||||
@@ -34,18 +33,52 @@ public abstract class Module
|
|||||||
|
|
||||||
public static Tag getData(Module module, String file, boolean isShared)
|
public static Tag getData(Module module, String file, boolean isShared)
|
||||||
{
|
{
|
||||||
|
File dataFile = resolveResource(module, file, "nbt", isShared);
|
||||||
|
if (dataFile == null) return null;
|
||||||
if (!isShared && (module == null || module.getName() == null)) return null;
|
if (!isShared && (module == null || module.getName() == null)) return null;
|
||||||
File dataFile = CarpetServer.minecraft_server.getSavePath(WorldSavePath.ROOT).resolve("scripts/"+getDescriptor(module, file, isShared)+".nbt").toFile();
|
File dataFile = CarpetServer.minecraft_server.getSavePath(WorldSavePath.ROOT).resolve("scripts/"+getDescriptor(module, file, isShared)+".nbt").toFile();
|
||||||
if (!Files.exists(dataFile.toPath()) || !(dataFile.isFile())) return null;
|
if (!Files.exists(dataFile.toPath()) || !(dataFile.isFile())) return null;
|
||||||
return read(dataFile);
|
synchronized (writeIOSync) { return FileModule.read(dataFile); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean saveData(Module module, String file, Tag globalState, boolean isShared)
|
public static boolean saveData(Module module, String file, Tag globalState, boolean isShared)
|
||||||
{
|
{
|
||||||
|
File dataFile = resolveResource(module, file, "nbt", isShared);
|
||||||
|
if (dataFile == null) return false;
|
||||||
if (!isShared && (module == null || module.getName() == null)) return false;
|
if (!isShared && (module == null || module.getName() == null)) return false;
|
||||||
File dataFile =CarpetServer.minecraft_server.getSavePath(WorldSavePath.ROOT).resolve("scripts/"+getDescriptor(module, file, isShared)+".nbt").toFile();
|
File dataFile =CarpetServer.minecraft_server.getSavePath(WorldSavePath.ROOT).resolve("scripts/"+getDescriptor(module, file, isShared)+".nbt").toFile();
|
||||||
if (!Files.exists(dataFile.toPath().getParent()) && !dataFile.getParentFile().mkdirs()) return false;
|
if (!Files.exists(dataFile.toPath().getParent()) && !dataFile.getParentFile().mkdirs()) return false;
|
||||||
return write(globalState, dataFile);
|
synchronized (writeIOSync) { return FileModule.write(globalState, dataFile); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean appendToTextFile(Module module, String resourceName, String type, boolean isShared, List<String> message)
|
||||||
|
{
|
||||||
|
File 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); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean dropExistingFile(Module module, String resourceName, String ext, boolean isShared)
|
||||||
|
{
|
||||||
|
File dataFile = resolveResource(module, resourceName, ext, isShared);
|
||||||
|
if (dataFile == null) return false;
|
||||||
|
synchronized (writeIOSync) { return dataFile.delete(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<String> listFile(Module module, String resourceName, String ext, boolean isShared)
|
||||||
|
{
|
||||||
|
File dataFile = resolveResource(module, resourceName, ext, isShared);
|
||||||
|
if (dataFile == null) return null;
|
||||||
|
if (!dataFile.exists()) return null;
|
||||||
|
synchronized (writeIOSync) { return FileModule.listFileContent(dataFile); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private static File resolveResource(Module module, String resourceName, String ext, boolean isShared)
|
||||||
|
{
|
||||||
|
if (!isShared && (module == null || module.getName() == null)) return null;
|
||||||
|
return CarpetServer.minecraft_server.getLevelStorage().resolveFile(
|
||||||
|
CarpetServer.minecraft_server.getLevelName(), "scripts/"+getDescriptor(module, resourceName, isShared)+"."+ext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -361,8 +361,7 @@ public class SettingsManager
|
|||||||
{
|
{
|
||||||
if (dispatcher.getRoot().getChildren().stream().anyMatch(node -> node.getName().equalsIgnoreCase(identifier)))
|
if (dispatcher.getRoot().getChildren().stream().anyMatch(node -> node.getName().equalsIgnoreCase(identifier)))
|
||||||
{
|
{
|
||||||
Messenger.print_server_message(CarpetServer.minecraft_server,
|
CarpetSettings.LOG.error("Failed to add settings command for " + identifier + ". It is masking previous command.");
|
||||||
Messenger.c("rb Failed to add settings command for " + identifier + ". It is masking previous command."));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user