diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index 8dc34cb8..2ccfbb78 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -433,6 +433,14 @@ public class CarpetExpression * pos(players()) => l(12.3, 45.6, 32.05) * pos(block('stone')) => Error: Cannot fetch position of an unrealized block * + *

pos_offset(pos, direction, amount?)

+ *

Returns a coords triple that is offset in a specified direction by amount of blocks. + * The default offset amount is 1 block. To offset into opposite facing, use negative numbers for the amount. + *

+ *
+     *     pos_offset(block(0,5,0), 'up', 2)  => l(0,7,0)
+     *     pos_offset(l(0,5,0), 'up', -2 ) => l(0,3,0)
+     * 
*

block_properties(pos)

*

Returns a list of available block properties for a particular block. If a block has no properties, returns an empty list.

*

property(pos, name)

@@ -1087,6 +1095,13 @@ public class CarpetExpression * inventory_size(x,y,z) => 27 // chest * inventory_size(block(pos)) => 5 // hopper * + *

inventory_has_items(inventory)

+ *

Returns true, if the inventory is not empty, false if it is empty, and null, if its not an inventory.

+ *
+     *     inventory_has_items(player()) => true
+     *     inventory_has_items(x,y,z) => false // empty chest
+     *     inventory_has_items(block(pos)) => null // stone
+     * 
*

inventory_get(inventory, slot)

*

Returns the item in the corresponding inventory slot, or null if slot empty or inventory is invalid. * You can use negative numbers to indicate slots counted from 'the back'.

@@ -2427,11 +2442,22 @@ public class CarpetExpression *

print(expr)

*

Displays the result of the expression to the chat. Overrides default scarpet behaviour of * sending everyting to stderr.

+ *

logger(expr)

+ *

Prints the message to system logs, and not to chat.

*

run(expr)

*

Runs a command from the string result of the expr expression, and returns its success count

*

save()

*

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.

+ *

load_app_data(), load_app_data(file)

+ *

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 scripts + * floder.

+ *

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)

+ *

Stores the app data associated with the app from the world /scripts folder. With the file parameter + * saves immediately and with every call, without file parameter, it may take up to 10 seconds for the output + * file to sync preventing flickering in case this tag changes frequently. It will be synced when server closes.

*

tick_time()

*

Returns game tick counter. Can be used to run certain operations every n-th ticks, or to count in-game time

*

game_tick(mstime?)

@@ -3148,6 +3174,19 @@ public class CarpetExpression *

Loading a module, if it contains a __command() method, will attempt to registed a command with that * module name, and register all public (no underscore) functions available in the module as subcommands. It will also * bind specific events to the event system (check Events section for details).

+ *

If an app defines __config method, and that method returns a map, it will be used to apply custom + * settings for this app. Currently the following options are supported:

+ * *

Unloading a module removes all of its state from the game, disables commands, and removes bounded events

*

Scripts can be loaded in shared and player mode. Default is player, so all globals and stored functions are * individual for each player, meaning scripts don't need to worry about making sure they store some intermittent data diff --git a/src/main/java/carpet/script/Expression.java b/src/main/java/carpet/script/Expression.java index de69545f..572233fc 100644 --- a/src/main/java/carpet/script/Expression.java +++ b/src/main/java/carpet/script/Expression.java @@ -1090,12 +1090,14 @@ public class Expression implements Cloneable *

Get, Accessor Operator :

*

Operator version of the get(...) function to access elements of lists, maps, and potentially other * containers (i.e. NBTs). It is important to distinguish from ~ operator, which is a matching operator, - * which is expected to perform some extra computations to retrieve the result, while . should be + * which is expected to perform some extra computations to retrieve the result, while : should be * straightforward and immediate, and the source object should behave like a container and support full container * API, meaning get(...), put(...), delete(...), * and has(...) functions

- *

WARNING: Unlike for some languages, where item access operator can be an L-value, to assign new values to - * container elements, use put function instead, i.e. a:1='foo' won't work.

+ *

For certain operators and functions (get, put, delete, has, =, +=) objects can use : annotated + * fields as l-values, meaning construct like foo:0 = 5, would act like put(foo, 0, 5), + * rather than get(foo, 0) = 5, which would result in an error.

+ *

TODO: add more information about l-value behaviour.

* *

Matching Operator ~

*

This operator should be understood as 'matches', 'contains', 'is_in', @@ -2025,7 +2027,7 @@ public class Expression implements Cloneable *

Here is a list of operations that work on all types of containers: lists, maps, as well as other Minecraft * specific modifyable containers, like NBTs

* - *

get(container, address), ':' operator

+ *

get(container, address, ...), get(lvalue), ':' operator

*

Returns the value at address element from the value. * For lists it indicates an index, use negative numbers to reach elements from the end of the list. get * call will always be able to find the index. In case there is few items, it will loop over

@@ -2034,6 +2036,9 @@ public class Expression implements Cloneable * nbt path to query, * returning null, if path is not found, one value if there was one match, or list of values if result is a list. * Returned elements can be of numerical type, string texts, or another compound nbt tags

+ *

In case to simplify the access with nested objects, you can add chain of addresses to the arguments of + * get rather than calling it multiple times. get(get(foo,a),b) is equivalent to + * get(foo, a, b), or foo:a:b.

*
      *     get(l(range(10)), 5)  => 5
      *     get(l(range(10)), -1)  => 9
@@ -2045,17 +2050,24 @@ public class Expression implements Cloneable
      *     get(m( l('foo',2), l('bar',3), l('baz',4) ), 'bar')  => 3
      * 
* - *

has(container, address)

+ *

has(container, address, ...), has(lvalue)

*

Similar to get, but returns boolean value indicating if the given index / key / path is in the * container. Can be used to determine if get(...)==null means the element doesn't exist, or the stored value - * for this address is null, and is cheaper to run than get

+ * for this address is null, and is cheaper to run than get.

+ *

Like get, it can accept multiple addresses for chains in nested containers. In this case has(foo:a:b) + * is equivalent to has(get(foo,a), b) or has(foo, a, b)

* - *

delete(container, address)

+ *

delete(container, address, ...), delete(lvalue)

*

Removes specific entry from the container. For the lists - removes the element and shrinks it. For maps, it * removes the key from the map, and for nbt - removes content from a given path. For lists and maps returns previous * entry at the address, for nbt's - number of removed objects, with 0 indicating that the original value was unaffected.

+ *

Like with the get and has, delete can accept chained addresses, as well as + * l-value container access, removing the value + * from the leaf of the path provided, so delete(foo, a, b) is the same as delete(get(foo,a),b) + * or delete(foo:a:b)

+ *

Returns true, if container was changed, false, if it was left unchanged, and null if operation was invalid.

* - *

put(container, address, value), put(container, address, value, mode)

+ *

put(container, address, value), put(container, address, value, mode), put(lvalue, value)

*

Lists

*

Modifies the container by replacing the value under the address with the supplied value. * For lists, a valid index is required, but can be negative as well to indicate positions from the end of the list. @@ -2072,6 +2084,11 @@ public class Expression implements Cloneable * extending the list by this amount of items. Again use null address/index to point to the end of * the list * + *

Due to the extra mode parameter, there is no chaining for put, but you can still use l-value + * container access to indicate container and address, so put(foo, key, value) is the same as + * put(foo:key, value) or foo:key=value

+ *

Returns true, if container got modified, false otherwise, and null if operation was invalid.

+ * *

Maps

*

For maps there are no modes available (yet, seems there is no reason to). It replaces the value under the supplied * key (address), or sets it if not currently present.

diff --git a/src/main/java/carpet/settings/SettingsManager.java b/src/main/java/carpet/settings/SettingsManager.java index 349850d4..96467342 100644 --- a/src/main/java/carpet/settings/SettingsManager.java +++ b/src/main/java/carpet/settings/SettingsManager.java @@ -171,7 +171,7 @@ public class SettingsManager public void notifyPlayersCommandsChanged() { - if (server.getPlayerManager() == null) + if (server == null || server.getPlayerManager() == null) { return; }