24 files changed
+476
-89
No files matched your search
@@ -11,6 +11,8 @@ optional `mixer`. Default values for `volume`, `pitch` and `mixer` are `1.0`, `1
|
|||||||
Valid mixer options are `master`, `music`, `record`, `weather`, `block`, `hostile`,`neutral`, `player`, `ambient`
|
Valid mixer options are `master`, `music`, `record`, `weather`, `block`, `hostile`,`neutral`, `player`, `ambient`
|
||||||
and `voice`. `pos` can be either a block, triple of coords, or a list of thee numbers. Uses the same options as a
|
and `voice`. `pos` can be either a block, triple of coords, or a list of thee numbers. Uses the same options as a
|
||||||
corresponding `playsound` command.
|
corresponding `playsound` command.
|
||||||
|
|
||||||
|
Throws `unknown_sound` if sound doesn't exist.
|
||||||
|
|
||||||
## Particles
|
## Particles
|
||||||
|
|
||||||
@@ -21,12 +23,15 @@ of 0, and to all players nearby, but these options can be changed via optional a
|
|||||||
command on details on those options. Valid particle names are
|
command on details on those options. Valid particle names are
|
||||||
for example `'angry_villager', 'item diamond', 'block stone', 'dust 0.8 0.1 0.1 4'`.
|
for example `'angry_villager', 'item diamond', 'block stone', 'dust 0.8 0.1 0.1 4'`.
|
||||||
|
|
||||||
|
Throws `unknown_particle` if particle doesn't exist.
|
||||||
|
|
||||||
### `particle_line(name, pos, pos2, density?, player?)`
|
### `particle_line(name, pos, pos2, density?, player?)`
|
||||||
|
|
||||||
Renders a line of particles from point `pos` to `pos2` with supplied density (defaults to 1), which indicates how far
|
Renders a line of particles from point `pos` to `pos2` with supplied density (defaults to 1), which indicates how far
|
||||||
apart you would want particles to appear, so `0.1` means one every 10cm. If a player (or player name) is supplied, only
|
apart you would want particles to appear, so `0.1` means one every 10cm. If a player (or player name) is supplied, only
|
||||||
that player will receive particles.
|
that player will receive particles.
|
||||||
|
|
||||||
|
Throws `unknown_particle` if particle doesn't exist.
|
||||||
|
|
||||||
### `particle_box(name, pos, pos2, density?, player?)`
|
### `particle_box(name, pos, pos2, density?, player?)`
|
||||||
### `particle_rect` (deprecated)
|
### `particle_rect` (deprecated)
|
||||||
@@ -34,6 +39,8 @@ that player will receive particles.
|
|||||||
Renders a cuboid of particles between points `pos` and `pos2` with supplied density. If a player (or player name) is
|
Renders a cuboid of particles between points `pos` and `pos2` with supplied density. If a player (or player name) is
|
||||||
supplied, only that player will receive particles.
|
supplied, only that player will receive particles.
|
||||||
|
|
||||||
|
Throws `unknown_particle` if particle doesn't exist.
|
||||||
|
|
||||||
## Markers
|
## Markers
|
||||||
|
|
||||||
### `draw_shape(shape, duration, key?, value?, ... )`,
|
### `draw_shape(shape, duration, key?, value?, ... )`,
|
||||||
@@ -320,6 +327,10 @@ record to the file. Since files are closed after each write, sending multiple li
|
|||||||
write is beneficial for writing speed. To send multiple packs of data, either provide them flat or as a list in the
|
write is beneficial for writing speed. To send multiple packs of data, either provide them flat or as a list in the
|
||||||
third argument.
|
third argument.
|
||||||
|
|
||||||
|
Throws:
|
||||||
|
- `nbt_read_error`: When failed to read NBT file.
|
||||||
|
- `json_read_error`: When failed to read JSON file. The exception data will contain details about the problem.
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
write_file('foo', 'shared_text, ['one', 'two']);
|
write_file('foo', 'shared_text, ['one', 'two']);
|
||||||
write_file('foo', 'shared_text', 'three\n', 'four\n');
|
write_file('foo', 'shared_text', 'three\n', 'four\n');
|
||||||
@@ -371,6 +382,8 @@ 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.
|
||||||
|
|
||||||
|
Throws `nbt_read_error` if failed to read app data.
|
||||||
|
|
||||||
### `store_app_data(tag)`
|
### `store_app_data(tag)`
|
||||||
|
|
||||||
Note: `store_app_data(tag, file)` and `store_app_data(tag, file, shared?)` usages deprecated. Use `write_file` instead.
|
Note: `store_app_data(tag, file)` and `store_app_data(tag, file, shared?)` usages deprecated. Use `write_file` instead.
|
||||||
@@ -525,6 +538,8 @@ Evaluates the expression `expr` with different dimension execution context. `smt
|
|||||||
world-localized block, so not `block('stone')`, or a string representing a dimension like:
|
world-localized block, so not `block('stone')`, or a string representing a dimension like:
|
||||||
`'nether'`, `'the_nether'`, `'end'` or `'overworld'`, etc.
|
`'nether'`, `'the_nether'`, `'end'` or `'overworld'`, etc.
|
||||||
|
|
||||||
|
Throws `unknown_dimension` if provided dimension can't be found.
|
||||||
|
|
||||||
### `view_distance()`
|
### `view_distance()`
|
||||||
Returns the view distance of the server.
|
Returns the view distance of the server.
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ when it was used. Block values passed in various places like `scan` functions, e
|
|||||||
its properties are needed. This means that if the block at the location changes before its queried in the program this
|
its properties are needed. This means that if the block at the location changes before its queried in the program this
|
||||||
might result in getting the later state, which might not be desired. Consider the following example:
|
might result in getting the later state, which might not be desired. Consider the following example:
|
||||||
|
|
||||||
|
Throws `unknown_block` if provided input is not valid.
|
||||||
|
|
||||||
<pre>set(10,10,10,'stone');
|
<pre>set(10,10,10,'stone');
|
||||||
scan(10,10,10,0,0,0, b = _);
|
scan(10,10,10,0,0,0, b = _);
|
||||||
set(10,10,10,'air');
|
set(10,10,10,'air');
|
||||||
@@ -50,6 +52,8 @@ properties that the original source block may have contained.
|
|||||||
|
|
||||||
The returned value is either the block state that has been set, or `false` if block setting was skipped, or failed
|
The returned value is either the block state that has been set, or `false` if block setting was skipped, or failed
|
||||||
|
|
||||||
|
Throws `unknown_block` if provided block to set is not valid
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
set(0,5,0,'bedrock') => bedrock
|
set(0,5,0,'bedrock') => bedrock
|
||||||
set(l(0,5,0), 'bedrock') => bedrock
|
set(l(0,5,0), 'bedrock') => bedrock
|
||||||
@@ -128,6 +132,8 @@ but doesn't open chests / containers, so have no effect on interactive blocks, l
|
|||||||
Returns true if placement/use was
|
Returns true if placement/use was
|
||||||
successful, false otherwise.
|
successful, false otherwise.
|
||||||
|
|
||||||
|
Throws `unknown_item` if `item` doesn't exist
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
place_item('stone',x,y,z) // places a stone block on x,y,z block
|
place_item('stone',x,y,z) // places a stone block on x,y,z block
|
||||||
place_item('piston,x,y,z,'down') // places a piston facing down
|
place_item('piston,x,y,z,'down') // places a piston facing down
|
||||||
@@ -146,6 +152,8 @@ If type is `null`, POI at position is removed. In any case, previous POI is also
|
|||||||
Interestingly, `unemployed`, and `nitwit` are not used in the game, meaning, they could be used as permanent spatial
|
Interestingly, `unemployed`, and `nitwit` are not used in the game, meaning, they could be used as permanent spatial
|
||||||
markers for scarpet apps. `meeting` is the only one with increased max occupancy of 32.
|
markers for scarpet apps. `meeting` is the only one with increased max occupancy of 32.
|
||||||
|
|
||||||
|
Throws `unknown_poi` if the provided point of interest doesn't exist
|
||||||
|
|
||||||
### `set_biome(pos, biome_name, update=true)`
|
### `set_biome(pos, biome_name, update=true)`
|
||||||
|
|
||||||
Changes the biome at that block position. if update is specified and false, then chunk will not be refreshed
|
Changes the biome at that block position. if update is specified and false, then chunk will not be refreshed
|
||||||
@@ -156,6 +164,8 @@ is only effective if you set it at y=0, and affects the entire column of. In the
|
|||||||
specific Y coordinate of the biome you want to change, and it affects roughly 4x4x4 area (give or take some random
|
specific Y coordinate of the biome you want to change, and it affects roughly 4x4x4 area (give or take some random
|
||||||
noise).
|
noise).
|
||||||
|
|
||||||
|
Throws `unknown_biome` if the `biome_name` doesn't exist.
|
||||||
|
|
||||||
### `update(pos)`
|
### `update(pos)`
|
||||||
|
|
||||||
Causes a block update at position.
|
Causes a block update at position.
|
||||||
@@ -180,6 +190,8 @@ In item context, `true` means that breaking item has no nbt to use, `null` indic
|
|||||||
considered broken in process, and `nbt` type value, for a resulting NBT tag on a hypothetical tool. Its up to the
|
considered broken in process, and `nbt` type value, for a resulting NBT tag on a hypothetical tool. Its up to the
|
||||||
programmer to use that nbt to apply it where it belong
|
programmer to use that nbt to apply it where it belong
|
||||||
|
|
||||||
|
Throws `unknown_item` if `tool` doesn't exist.
|
||||||
|
|
||||||
Here is a sample code that can be used to mine blocks using items in player inventory, without using player context
|
Here is a sample code that can be used to mine blocks using items in player inventory, without using player context
|
||||||
for mining. Obviously, in this case the use of `harvest` would be much more applicable:
|
for mining. Obviously, in this case the use of `harvest` would be much more applicable:
|
||||||
|
|
||||||
@@ -271,6 +283,8 @@ back in state definition in various applications where block properties are requ
|
|||||||
|
|
||||||
`block_state` can also accept block names as input, returning block's default state.
|
`block_state` can also accept block names as input, returning block's default state.
|
||||||
|
|
||||||
|
Throws `unknown_block` if the provided input is not valid.
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
set(x,y,z,'iron_trapdoor','half','top'); block_state(x,y,z) => {waterlogged: false, half: top, open: false, ...}
|
set(x,y,z,'iron_trapdoor','half','top'); block_state(x,y,z) => {waterlogged: false, half: top, open: false, ...}
|
||||||
set(x,y,z,'iron_trapdoor','half','top'); block_state(x,y,z,'half') => top
|
set(x,y,z,'iron_trapdoor','half','top'); block_state(x,y,z,'half') => top
|
||||||
@@ -291,6 +305,8 @@ Without arguments, returns list of available tags, with block supplied (either b
|
|||||||
of tags the block belongs to, and if a tag is specified, returns `null` if tag is invalid, `false` if this block doesn't belong
|
of tags the block belongs to, and if a tag is specified, returns `null` if tag is invalid, `false` if this block doesn't belong
|
||||||
to this tag, and `true` if the block belongs to the tag.
|
to this tag, and `true` if the block belongs to the tag.
|
||||||
|
|
||||||
|
Throws `unknown_block` if `block` doesn't exist
|
||||||
|
|
||||||
### `block_data(pos)`
|
### `block_data(pos)`
|
||||||
|
|
||||||
Return NBT string associated with specific location, or null if the block does not carry block data. Can be currently
|
Return NBT string associated with specific location, or null if the block does not carry block data. Can be currently
|
||||||
@@ -325,9 +341,9 @@ poi(x,y,z,5) => [['nether_portal',0,[7,8,9]],['nether_portal',0,[7,9,9]]] // two
|
|||||||
|
|
||||||
Without arguments, returns the list of biomes in the world.
|
Without arguments, returns the list of biomes in the world.
|
||||||
|
|
||||||
With block, or name, returns the name of the biome in that position, or null, if provided biome is not valid.
|
With block, or name, returns the name of the biome in that position, or throws `'unknown_biome'` if provided biome or block are not valid.
|
||||||
|
|
||||||
With an optional feature, it returns value for the specified attribute for that biome. Available and querable features include:
|
With an optional feature, it returns value for the specified attribute for that biome. Available and queryable features include:
|
||||||
* `'top_material'`: unlocalized block representing the top surface material
|
* `'top_material'`: unlocalized block representing the top surface material
|
||||||
* `'under_material'`: unlocalized block representing what sits below topsoil
|
* `'under_material'`: unlocalized block representing what sits below topsoil
|
||||||
* `'category'`: the parent biome this biome is derived from. Possible values include:
|
* `'category'`: the parent biome this biome is derived from. Possible values include:
|
||||||
@@ -716,6 +732,7 @@ If structure is not specified, it will return a set of structure names that are
|
|||||||
as keys, and same type of map values as with a single structure call. An empty set or an empty map would indicate that nothing
|
as keys, and same type of map values as with a single structure call. An empty set or an empty map would indicate that nothing
|
||||||
should be generated there.
|
should be generated there.
|
||||||
|
|
||||||
|
Throws `unknown_structure` if structure doesn't exist.
|
||||||
|
|
||||||
### `structures(pos), structures(pos, structure_name)`
|
### `structures(pos), structures(pos, structure_name)`
|
||||||
|
|
||||||
@@ -749,6 +766,8 @@ structure starts.
|
|||||||
Requires a `Structure Variant` or `Standard Structure` name (see above). If standard name is used, the variant of the
|
Requires a `Structure Variant` or `Standard Structure` name (see above). If standard name is used, the variant of the
|
||||||
structure may depend on the biome, otherwise the default structure for this type will be generated.
|
structure may depend on the biome, otherwise the default structure for this type will be generated.
|
||||||
|
|
||||||
|
Throws `unknown_structure` if structure doesn't exist.
|
||||||
|
|
||||||
### `plop(pos, what)`
|
### `plop(pos, what)`
|
||||||
|
|
||||||
Plops a structure or a feature at a given `pos`, so block, triple position coordinates or a list of coordinates.
|
Plops a structure or a feature at a given `pos`, so block, triple position coordinates or a list of coordinates.
|
||||||
|
|||||||
@@ -28,14 +28,16 @@ an inventory, all API functions typically do nothing and return null.
|
|||||||
|
|
||||||
Most items returned are in the form of a triple of item name, count, and nbt or the extra data associated with an item.
|
Most items returned are in the form of a triple of item name, count, and nbt or the extra data associated with an item.
|
||||||
|
|
||||||
### item_list(tag?)
|
### `item_list(tag?)`
|
||||||
|
|
||||||
With no arguments, returns a list of all items in the game. With an item tag provided, list items matching the tag, or `null` if tag is not valid.
|
With no arguments, returns a list of all items in the game. With an item tag provided, list items matching the tag, or `null` if tag is not valid.
|
||||||
|
|
||||||
### item_tags(item, tag?)
|
### `item_tags(item, tag?)`
|
||||||
|
|
||||||
Returns list of tags the item belongs to, or, if tag is provided, `true` if an item maches the tag, `false` if it doesn't and `null` if that's not a valid tag
|
Returns list of tags the item belongs to, or, if tag is provided, `true` if an item maches the tag, `false` if it doesn't and `null` if that's not a valid tag
|
||||||
|
|
||||||
|
Throws `unknown_item` if item doesn't exist.
|
||||||
|
|
||||||
### `stack_limit(item)`
|
### `stack_limit(item)`
|
||||||
|
|
||||||
Returns number indicating what is the stack limit for the item. Its typically 1 (non-stackable), 16 (like buckets),
|
Returns number indicating what is the stack limit for the item. Its typically 1 (non-stackable), 16 (like buckets),
|
||||||
@@ -43,6 +45,8 @@ or 64 - rest. It is recommended to consult this, as other inventory API function
|
|||||||
it is up to the programmer to keep it at bay. As of 1.13, game checks for negative numbers and setting an item to
|
it is up to the programmer to keep it at bay. As of 1.13, game checks for negative numbers and setting an item to
|
||||||
negative is the same as empty.
|
negative is the same as empty.
|
||||||
|
|
||||||
|
Throws `unknown_item` if item doesn't exist.
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
stack_limit('wooden_axe') => 1
|
stack_limit('wooden_axe') => 1
|
||||||
stack_limit('ender_pearl') => 16
|
stack_limit('ender_pearl') => 16
|
||||||
@@ -53,6 +57,8 @@ stack_limit('stone') => 64
|
|||||||
|
|
||||||
Returns the string representing the category of a given item, like `building_blocks`, `combat`, or `tools`.
|
Returns the string representing the category of a given item, like `building_blocks`, `combat`, or `tools`.
|
||||||
|
|
||||||
|
Throws `unknown_item` if item doesn't exist.
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
item_category('wooden_axe') => tools
|
item_category('wooden_axe') => tools
|
||||||
item_category('ender_pearl') => misc
|
item_category('ender_pearl') => misc
|
||||||
@@ -175,6 +181,8 @@ while( (slot = inventory_find(p, 'diamond', slot)) != null, 41, drop_item(p, slo
|
|||||||
inventory_drop(x,y,z, 0) => 64 // removed and spawned in the world a full stack of items
|
inventory_drop(x,y,z, 0) => 64 // removed and spawned in the world a full stack of items
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
Throws `unknown_item` if item doesn't exist.
|
||||||
|
|
||||||
### `inventory_remove(inventory, item, amount?)`
|
### `inventory_remove(inventory, item, amount?)`
|
||||||
|
|
||||||
Removes amount (defaults to 1) of item from inventory. If the inventory doesn't have the defined amount, nothing
|
Removes amount (defaults to 1) of item from inventory. If the inventory doesn't have the defined amount, nothing
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ Adds a new objective to scoreboard. If `criterion` is not specified, assumes `'d
|
|||||||
If the objective already exists, changes the criterion of that objective and returns `false`. If the criterion was not specified but the objective already exists, returns the current criterion.
|
If the objective already exists, changes the criterion of that objective and returns `false`. If the criterion was not specified but the objective already exists, returns the current criterion.
|
||||||
If the objective was added, returns `true`. If nothing is affected, returns `null`
|
If the objective was added, returns `true`. If nothing is affected, returns `null`
|
||||||
|
|
||||||
|
Throws `unknown_criterion` if criterion doesn't exist.
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
scoreboard_add('counter')
|
scoreboard_add('counter')
|
||||||
scoreboard_add('lvl','level')
|
scoreboard_add('lvl','level')
|
||||||
|
|||||||
@@ -234,15 +234,73 @@ returns everywhere, but it would often lead to a messy code.
|
|||||||
|
|
||||||
It terminates entire program passing `expr` as the result of the program execution, or null if omitted.
|
It terminates entire program passing `expr` as the result of the program execution, or null if omitted.
|
||||||
|
|
||||||
### `try(expr, catch_expr(_)?) ... throw(value?)`
|
### `try(expr)` `try(expr, user_catch_expr)` `try(expr, type, catch_expr, type?, catch_expr?, ...)`
|
||||||
|
|
||||||
`try` function evaluates expression, and continues further unless `throw` function is called anywhere
|
`try` evaluates expression, allowing capturing exceptions that would be thrown inside `expr` statement. The exceptions can be
|
||||||
inside `expr`. In that case the `catch_expr` is evaluates with `_` set to the argument `throw` was called with.
|
thrown explicitly using `throw()` or internally by scarpet where code is correct but detects illegal state. The 2-argument form
|
||||||
This mechanic accepts skipping thrown value - it throws null instead, and catch expression - then try returns
|
catches only user-thrown exceptions and one argument call `try(expr)` is equivalent to `try(expr, null)`,
|
||||||
null as well This mechanism allows to terminate large portion of a convoluted call stack and continue program
|
or `try(expr, 'user_exception', null)`. If multiple `type-catch` pairs are defined, the execution terminates on the first
|
||||||
execution. There is only one level of exceptions currently in carpet, so if the inner function also defines
|
applicable type for the exception thrown. Therefore, even if the caught exception matches multiple filters, only
|
||||||
the `try` catchment area, it will received the exception first, but it can technically rethrow the value its
|
the first matching block will be executed.
|
||||||
getting for the outer scope. Unhandled throw acts like an exit statement.
|
|
||||||
|
Catch expressions are evaluated with
|
||||||
|
`_` set to the value associated with the exception and `_trace` set to contain details about point of error (token, and line and
|
||||||
|
column positions), call stack and local
|
||||||
|
variables at the time of failure. The `type` will catch any exception of that type and any subtype of this type.
|
||||||
|
|
||||||
|
|
||||||
|
You can use `try` mechanism to exit from large portion of a convoluted call stack and continue program execution, although catching
|
||||||
|
exceptions is typically much more expensive comparing to not throwing them.
|
||||||
|
|
||||||
|
The `try` function allows you to catch some scarpet exceptions for cases covering invalid data, like invalid
|
||||||
|
blocks, biomes, dimensions and other things, that may have been modified by datapacks, resourcepacks or other mods,
|
||||||
|
or when an error is outside of the programmers scope, such as problems when reading or decoding files.
|
||||||
|
|
||||||
|
This is the hierarchy of the exceptions that could be thrown/caught in the with the `try` function:
|
||||||
|
- `exception`: This is the base exception. Catching `'exception'` allows to catch everything that can be caught,
|
||||||
|
but like everywhere else, doing that sounds like a bad idea.
|
||||||
|
- `value_exception`: This is the parent for any exception that occurs due to an
|
||||||
|
incorrect argument value provided to a built-in function
|
||||||
|
- `unknown_item`, `unknown_block`, `unknown_biome`, `unknown_sound`, `unknown_particle`,
|
||||||
|
`unknown_poi_type`, `unknown_dimension`, `unknown_structure`, `unknown_criterion`: Specific
|
||||||
|
errors thrown when a specified internal name does not exist or is invalid.
|
||||||
|
- `io_exception`: This is the parent for any exception that occurs due to an error handling external data.
|
||||||
|
- `nbt_read_error`: Incorrect input NBT file.
|
||||||
|
- `json_read_error`: Incorrect input JSON data.
|
||||||
|
- `user_exception`: Exception thrown by default with `throw` function.
|
||||||
|
|
||||||
|
Synopsis:
|
||||||
|
<pre>
|
||||||
|
inner_call() ->
|
||||||
|
(
|
||||||
|
aaa = 'booyah';
|
||||||
|
try(
|
||||||
|
for (range(10), item_tags('stick'+_*'k'));
|
||||||
|
,
|
||||||
|
print(_trace) // not caught, only catching user_exceptions
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
outer_call() ->
|
||||||
|
(
|
||||||
|
try(
|
||||||
|
inner_call()
|
||||||
|
, 'exception', // catching everything
|
||||||
|
print(_trace)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
</pre>
|
||||||
|
Producing:
|
||||||
|
```
|
||||||
|
{stack: [[<app>, inner_call, 1, 14]], locals: {_a: 0, aaa: booyah, _: 1, _y: 0, _i: 1, _x: 0, _z: 0}, token: [item_tags, 5, 23]}
|
||||||
|
```
|
||||||
|
|
||||||
|
### `throw(value?)`, `throw(type, value)`, `throw(subtype, type, value)`
|
||||||
|
|
||||||
|
Throws an exception that can be caught in a `try` block (see above). If ran without arguments, it will throw a `user_exception`
|
||||||
|
passing `null` as the value to the `catch_expr`. With two arguments you can mimic any other exception type thrown in scarpet.
|
||||||
|
With 3 arguments, you can specify a custom exception acting as a `subtype` of a provided `type`, allowing to customize `try`
|
||||||
|
statements with custom exceptions.
|
||||||
|
|
||||||
### `if(cond, expr, cond?, expr?, ..., default?)`
|
### `if(cond, expr, cond?, expr?, ..., default?)`
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ _i
|
|||||||
_x
|
_x
|
||||||
_y
|
_y
|
||||||
_z
|
_z
|
||||||
|
_trace
|
||||||
euler
|
euler
|
||||||
false
|
false
|
||||||
null
|
null
|
||||||
|
|||||||
@@ -91,7 +91,7 @@
|
|||||||
</Keywords>
|
</Keywords>
|
||||||
<Keywords name="Keywords3">euler pi null true false</Keywords>
|
<Keywords name="Keywords3">euler pi null true false</Keywords>
|
||||||
<Keywords name="Keywords4">x y z p</Keywords>
|
<Keywords name="Keywords4">x y z p</Keywords>
|
||||||
<Keywords name="Keywords5">_ _i _a _x _y _z</Keywords>
|
<Keywords name="Keywords5">_ _i _a _x _y _z _trace</Keywords>
|
||||||
<Keywords name="Keywords6">global_</Keywords>
|
<Keywords name="Keywords6">global_</Keywords>
|
||||||
<Keywords name="Keywords7">
|
<Keywords name="Keywords7">
|
||||||
__command
|
__command
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ import carpet.script.exception.ExpressionException;
|
|||||||
import carpet.script.exception.InternalExpressionException;
|
import carpet.script.exception.InternalExpressionException;
|
||||||
import carpet.script.exception.ResolvedException;
|
import carpet.script.exception.ResolvedException;
|
||||||
import carpet.script.exception.ReturnStatement;
|
import carpet.script.exception.ReturnStatement;
|
||||||
import carpet.script.exception.ThrowStatement;
|
|
||||||
import carpet.script.language.Arithmetic;
|
import carpet.script.language.Arithmetic;
|
||||||
import carpet.script.language.ControlFlow;
|
import carpet.script.language.ControlFlow;
|
||||||
import carpet.script.language.DataStructures;
|
import carpet.script.language.DataStructures;
|
||||||
@@ -232,7 +231,7 @@ public class Expression
|
|||||||
if (exc instanceof ExitStatement)
|
if (exc instanceof ExitStatement)
|
||||||
return exc;
|
return exc;
|
||||||
if (exc instanceof InternalExpressionException)
|
if (exc instanceof InternalExpressionException)
|
||||||
return new ExpressionException(c, e, token, exc.getMessage(), ((InternalExpressionException) exc).stack);
|
return ((InternalExpressionException) exc).promote(c, e, token);
|
||||||
if (exc instanceof ArithmeticException)
|
if (exc instanceof ArithmeticException)
|
||||||
return new ExpressionException(c, e, token, "Your math is wrong, "+exc.getMessage());
|
return new ExpressionException(c, e, token, "Your math is wrong, "+exc.getMessage());
|
||||||
if (exc instanceof ResolvedException)
|
if (exc instanceof ResolvedException)
|
||||||
@@ -624,9 +623,9 @@ public class Expression
|
|||||||
{
|
{
|
||||||
return exprProvider.get().evalValue(c, expectedType);
|
return exprProvider.get().evalValue(c, expectedType);
|
||||||
}
|
}
|
||||||
catch (ContinueStatement | BreakStatement | ReturnStatement | ThrowStatement exc)
|
catch (ContinueStatement | BreakStatement | ReturnStatement exc)
|
||||||
{
|
{
|
||||||
throw new ExpressionException(c, this, "Control flow functions, like continue, break, throw or return, should only be used in loops, try blocks, and functions respectively.");
|
throw new ExpressionException(c, this, "Control flow functions, like continue, break or return, should only be used in loops, and functions respectively.");
|
||||||
}
|
}
|
||||||
catch (ExitStatement exit)
|
catch (ExitStatement exit)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -406,6 +406,7 @@ public class Tokenizer implements Iterator<Tokenizer.Token>
|
|||||||
public int pos;
|
public int pos;
|
||||||
public int linepos;
|
public int linepos;
|
||||||
public int lineno;
|
public int lineno;
|
||||||
|
public static final Token NONE = new Token();
|
||||||
public Token morphedInto(TokenType newType, String newSurface)
|
public Token morphedInto(TokenType newType, String newSurface)
|
||||||
{
|
{
|
||||||
Token created = new Token();
|
Token created = new Token();
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ import carpet.script.argument.FunctionArgument;
|
|||||||
import carpet.script.argument.Vector3Argument;
|
import carpet.script.argument.Vector3Argument;
|
||||||
import carpet.script.exception.ExitStatement;
|
import carpet.script.exception.ExitStatement;
|
||||||
import carpet.script.exception.InternalExpressionException;
|
import carpet.script.exception.InternalExpressionException;
|
||||||
|
import carpet.script.exception.ThrowStatement;
|
||||||
|
import carpet.script.exception.Throwables;
|
||||||
import carpet.script.utils.FixedCommandSource;
|
import carpet.script.utils.FixedCommandSource;
|
||||||
import carpet.script.utils.InputValidator;
|
import carpet.script.utils.InputValidator;
|
||||||
import carpet.script.utils.ScarpetJsonDeserializer;
|
import carpet.script.utils.ScarpetJsonDeserializer;
|
||||||
@@ -73,6 +75,7 @@ import net.minecraft.text.LiteralText;
|
|||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
import net.minecraft.util.InvalidIdentifierException;
|
import net.minecraft.util.InvalidIdentifierException;
|
||||||
|
import net.minecraft.util.crash.CrashException;
|
||||||
import net.minecraft.util.Util;
|
import net.minecraft.util.Util;
|
||||||
import net.minecraft.util.WorldSavePath;
|
import net.minecraft.util.WorldSavePath;
|
||||||
import net.minecraft.util.dynamic.RegistryOps;
|
import net.minecraft.util.dynamic.RegistryOps;
|
||||||
@@ -159,10 +162,11 @@ public class Auxiliary {
|
|||||||
{
|
{
|
||||||
expression.addLazyFunction("sound", -1, (c, t, lv) -> {
|
expression.addLazyFunction("sound", -1, (c, t, lv) -> {
|
||||||
CarpetContext cc = (CarpetContext)c;
|
CarpetContext cc = (CarpetContext)c;
|
||||||
Identifier soundName = new Identifier(lv.get(0).evalValue(c).getString());
|
String rawString = lv.get(0).evalValue(c).getString();
|
||||||
|
Identifier soundName = new Identifier(rawString);
|
||||||
Vector3Argument locator = Vector3Argument.findIn(cc, lv, 1);
|
Vector3Argument locator = Vector3Argument.findIn(cc, lv, 1);
|
||||||
if (Registry.SOUND_EVENT.get(soundName) == null)
|
if (Registry.SOUND_EVENT.get(soundName) == null)
|
||||||
throw new InternalExpressionException("No such sound: "+soundName.getPath());
|
throw new ThrowStatement(rawString, Throwables.UNKNOWN_SOUND);
|
||||||
float volume = 1.0F;
|
float volume = 1.0F;
|
||||||
float pitch = 1.0F;
|
float pitch = 1.0F;
|
||||||
SoundCategory mixer = SoundCategory.MASTER;
|
SoundCategory mixer = SoundCategory.MASTER;
|
||||||
@@ -852,7 +856,15 @@ public class Auxiliary {
|
|||||||
Value retVal;
|
Value retVal;
|
||||||
if (fdesc.getMiddle().equals("nbt"))
|
if (fdesc.getMiddle().equals("nbt"))
|
||||||
{
|
{
|
||||||
Tag state = ((CarpetScriptHost) c.host).readFileTag(fdesc.getLeft(), fdesc.getRight());
|
Tag state;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
state = ((CarpetScriptHost) c.host).readFileTag(fdesc.getLeft(), fdesc.getRight());
|
||||||
|
} catch (CrashException e)
|
||||||
|
{
|
||||||
|
throw new ThrowStatement((fdesc.getRight()?"shared/":"")+ fdesc.getLeft(), Throwables.NBT_READ);
|
||||||
|
}
|
||||||
|
|
||||||
if (state == null) return LazyValue.NULL;
|
if (state == null) return LazyValue.NULL;
|
||||||
retVal = new NBTSerializableValue(state);
|
retVal = new NBTSerializableValue(state);
|
||||||
}
|
}
|
||||||
@@ -865,10 +877,13 @@ public class Auxiliary {
|
|||||||
}
|
}
|
||||||
catch (JsonParseException e)
|
catch (JsonParseException e)
|
||||||
{
|
{
|
||||||
Throwable exception = e;
|
Throwable exc = e;
|
||||||
if(e.getCause() != null)
|
if(e.getCause() != null)
|
||||||
exception = e.getCause();
|
exc = e.getCause();
|
||||||
throw new InternalExpressionException("Failed to read JSON file: "+exception.getMessage());
|
throw new ThrowStatement(MapValue.wrap(ImmutableMap.of(
|
||||||
|
StringValue.of("error"), StringValue.of(exc.getMessage()),
|
||||||
|
StringValue.of("path"), StringValue.of((fdesc.getRight()?"shared/":"")+ fdesc.getLeft())
|
||||||
|
)), Throwables.JSON_READ);
|
||||||
}
|
}
|
||||||
Value parsedJson = GSON.fromJson(json, Value.class);
|
Value parsedJson = GSON.fromJson(json, Value.class);
|
||||||
if (parsedJson == null)
|
if (parsedJson == null)
|
||||||
@@ -956,7 +971,14 @@ public class Auxiliary {
|
|||||||
shared = lv.get(1).evalValue(c).getBoolean();
|
shared = lv.get(1).evalValue(c).getBoolean();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Tag state = ((CarpetScriptHost)((CarpetContext)c).host).readFileTag(file, shared);
|
Tag state;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
state = ((CarpetScriptHost)((CarpetContext)c).host).readFileTag(file, shared);
|
||||||
|
} catch (CrashException e)
|
||||||
|
{
|
||||||
|
throw new ThrowStatement("app data", Throwables.NBT_READ);
|
||||||
|
}
|
||||||
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);
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import carpet.script.CarpetContext;
|
|||||||
import carpet.script.Expression;
|
import carpet.script.Expression;
|
||||||
import carpet.script.LazyValue;
|
import carpet.script.LazyValue;
|
||||||
import carpet.script.exception.InternalExpressionException;
|
import carpet.script.exception.InternalExpressionException;
|
||||||
|
import carpet.script.exception.ThrowStatement;
|
||||||
|
import carpet.script.exception.Throwables;
|
||||||
import carpet.script.value.ListValue;
|
import carpet.script.value.ListValue;
|
||||||
import carpet.script.value.NBTSerializableValue;
|
import carpet.script.value.NBTSerializableValue;
|
||||||
import carpet.script.value.NullValue;
|
import carpet.script.value.NullValue;
|
||||||
@@ -119,14 +121,7 @@ public class Inventories {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
List<Recipe<?>> recipes;
|
List<Recipe<?>> recipes;
|
||||||
try
|
recipes = ((RecipeManagerInterface) cc.s.getMinecraftServer().getRecipeManager()).getAllMatching(type, new Identifier(recipeName));
|
||||||
{
|
|
||||||
recipes = ((RecipeManagerInterface) cc.s.getMinecraftServer().getRecipeManager()).getAllMatching(type, new Identifier(recipeName));
|
|
||||||
}
|
|
||||||
catch (InvalidIdentifierException ignored)
|
|
||||||
{
|
|
||||||
return LazyValue.NULL;
|
|
||||||
}
|
|
||||||
if (recipes.isEmpty())
|
if (recipes.isEmpty())
|
||||||
return LazyValue.NULL;
|
return LazyValue.NULL;
|
||||||
List<Value> recipesOutput = new ArrayList<>();
|
List<Value> recipesOutput = new ArrayList<>();
|
||||||
@@ -197,17 +192,9 @@ public class Inventories {
|
|||||||
{
|
{
|
||||||
String itemStr = lv.get(0).evalValue(c).getString();
|
String itemStr = lv.get(0).evalValue(c).getString();
|
||||||
Item item;
|
Item item;
|
||||||
try
|
Identifier id = new Identifier(itemStr);
|
||||||
{
|
item = Registry.ITEM.getOrEmpty(id).orElseThrow(() -> new ThrowStatement(itemStr, Throwables.UNKNOWN_ITEM));
|
||||||
Identifier id = new Identifier(itemStr);
|
|
||||||
item = Registry.ITEM.get(id);
|
|
||||||
if (item == Items.AIR && !id.getPath().equalsIgnoreCase("air"))
|
|
||||||
throw new InvalidIdentifierException("boo");
|
|
||||||
}
|
|
||||||
catch (InvalidIdentifierException ignored)
|
|
||||||
{
|
|
||||||
throw new InternalExpressionException("Incorrect item: "+itemStr);
|
|
||||||
}
|
|
||||||
if (!item.hasRecipeRemainder()) return LazyValue.NULL;
|
if (!item.hasRecipeRemainder()) return LazyValue.NULL;
|
||||||
Value ret = new StringValue(NBTSerializableValue.nameFromRegistryId(Registry.ITEM.getId(item.getRecipeRemainder())));
|
Value ret = new StringValue(NBTSerializableValue.nameFromRegistryId(Registry.ITEM.getId(item.getRecipeRemainder())));
|
||||||
return (_c, _t ) -> ret;
|
return (_c, _t ) -> ret;
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import carpet.script.CarpetContext;
|
|||||||
import carpet.script.Expression;
|
import carpet.script.Expression;
|
||||||
import carpet.script.LazyValue;
|
import carpet.script.LazyValue;
|
||||||
import carpet.script.exception.InternalExpressionException;
|
import carpet.script.exception.InternalExpressionException;
|
||||||
|
import carpet.script.exception.ThrowStatement;
|
||||||
|
import carpet.script.exception.Throwables;
|
||||||
import carpet.script.value.EntityValue;
|
import carpet.script.value.EntityValue;
|
||||||
import carpet.script.value.ListValue;
|
import carpet.script.value.ListValue;
|
||||||
import carpet.script.value.NullValue;
|
import carpet.script.value.NullValue;
|
||||||
@@ -131,7 +133,7 @@ public class Scoreboards {
|
|||||||
criterion = ScoreboardCriterion.createStatCriterion(critetionName).orElse(null);
|
criterion = ScoreboardCriterion.createStatCriterion(critetionName).orElse(null);
|
||||||
if (criterion==null)
|
if (criterion==null)
|
||||||
{
|
{
|
||||||
throw new InternalExpressionException("Unknown scoreboard criterion: "+critetionName);
|
throw new ThrowStatement(critetionName, Throwables.UNKNOWN_CRITERION);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ import carpet.script.LazyValue;
|
|||||||
import carpet.script.argument.BlockArgument;
|
import carpet.script.argument.BlockArgument;
|
||||||
import carpet.script.argument.Vector3Argument;
|
import carpet.script.argument.Vector3Argument;
|
||||||
import carpet.script.exception.InternalExpressionException;
|
import carpet.script.exception.InternalExpressionException;
|
||||||
|
import carpet.script.exception.ThrowStatement;
|
||||||
|
import carpet.script.exception.Throwables;
|
||||||
import carpet.script.utils.BiomeInfo;
|
import carpet.script.utils.BiomeInfo;
|
||||||
import carpet.script.utils.WorldTools;
|
import carpet.script.utils.WorldTools;
|
||||||
import carpet.script.value.BlockValue;
|
import carpet.script.value.BlockValue;
|
||||||
@@ -59,7 +61,6 @@ import net.minecraft.item.SwordItem;
|
|||||||
import net.minecraft.item.TridentItem;
|
import net.minecraft.item.TridentItem;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.nbt.Tag;
|
import net.minecraft.nbt.Tag;
|
||||||
import net.minecraft.server.MinecraftServer;
|
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
import net.minecraft.server.world.ChunkTicket;
|
import net.minecraft.server.world.ChunkTicket;
|
||||||
import net.minecraft.server.world.ChunkTicketType;
|
import net.minecraft.server.world.ChunkTicketType;
|
||||||
@@ -106,7 +107,6 @@ import java.util.Locale;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
@@ -336,8 +336,8 @@ public class WorldAccess {
|
|||||||
String poiType = lv.get(locator.offset+1).evalValue(c).getString().toLowerCase(Locale.ROOT);
|
String poiType = lv.get(locator.offset+1).evalValue(c).getString().toLowerCase(Locale.ROOT);
|
||||||
if (!"any".equals(poiType))
|
if (!"any".equals(poiType))
|
||||||
{
|
{
|
||||||
PointOfInterestType type = Registry.POINT_OF_INTEREST_TYPE.get(new Identifier(poiType));
|
PointOfInterestType type = Registry.POINT_OF_INTEREST_TYPE.getOrEmpty(new Identifier(poiType))
|
||||||
if (type == PointOfInterestType.UNEMPLOYED && !"unemployed".equals(poiType)) return LazyValue.NULL;
|
.orElseThrow(() -> new ThrowStatement(poiType, Throwables.UNKNOWN_POI));
|
||||||
condition = (tt) -> tt == type;
|
condition = (tt) -> tt == type;
|
||||||
}
|
}
|
||||||
if (locator.offset + 2 < lv.size())
|
if (locator.offset + 2 < lv.size())
|
||||||
@@ -391,9 +391,8 @@ public class WorldAccess {
|
|||||||
return LazyValue.FALSE;
|
return LazyValue.FALSE;
|
||||||
}
|
}
|
||||||
String poiTypeString = poi.getString().toLowerCase(Locale.ROOT);
|
String poiTypeString = poi.getString().toLowerCase(Locale.ROOT);
|
||||||
PointOfInterestType type = Registry.POINT_OF_INTEREST_TYPE.get(new Identifier(poiTypeString));
|
PointOfInterestType type = Registry.POINT_OF_INTEREST_TYPE.getOrEmpty(new Identifier(poiTypeString))
|
||||||
// solving lack of null with defaulted registries
|
.orElseThrow(() -> new ThrowStatement(poiTypeString, Throwables.UNKNOWN_POI));
|
||||||
if (type == PointOfInterestType.UNEMPLOYED && !"unemployed".equals(poiTypeString)) throw new InternalExpressionException("Unknown POI type: "+poiTypeString);
|
|
||||||
int occupancy = 0;
|
int occupancy = 0;
|
||||||
if (locator.offset + 1 < lv.size())
|
if (locator.offset + 1 < lv.size())
|
||||||
{
|
{
|
||||||
@@ -872,9 +871,8 @@ public class WorldAccess {
|
|||||||
{
|
{
|
||||||
playerBreak = true;
|
playerBreak = true;
|
||||||
String itemString = val.getString();
|
String itemString = val.getString();
|
||||||
item = Registry.ITEM.get(new Identifier(itemString));
|
item = Registry.ITEM.getOrEmpty(new Identifier(itemString))
|
||||||
if (item == Items.AIR && !itemString.equals("air"))
|
.orElseThrow(() -> new ThrowStatement(itemString, Throwables.UNKNOWN_ITEM));
|
||||||
throw new InternalExpressionException("Incorrect item: " + itemString);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CompoundTag tag = null;
|
CompoundTag tag = null;
|
||||||
@@ -1152,7 +1150,7 @@ public class WorldAccess {
|
|||||||
if (locator.replacement != null)
|
if (locator.replacement != null)
|
||||||
{
|
{
|
||||||
biome = world.getRegistryManager().get(Registry.BIOME_KEY).get(new Identifier(locator.replacement));
|
biome = world.getRegistryManager().get(Registry.BIOME_KEY).get(new Identifier(locator.replacement));
|
||||||
if (biome == null) return LazyValue.NULL;
|
if (biome == null) throw new ThrowStatement(locator.replacement, Throwables.UNKNOWN_BIOME) ;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1181,9 +1179,8 @@ public class WorldAccess {
|
|||||||
throw new InternalExpressionException("'set_biome' needs a biome name as an argument");
|
throw new InternalExpressionException("'set_biome' needs a biome name as an argument");
|
||||||
String biomeName = lv.get(locator.offset+0).evalValue(c).getString();
|
String biomeName = lv.get(locator.offset+0).evalValue(c).getString();
|
||||||
// from locatebiome command code
|
// from locatebiome command code
|
||||||
Biome biome = cc.s.getMinecraftServer().getRegistryManager().get(Registry.BIOME_KEY).get(new Identifier(biomeName));
|
Biome biome = cc.s.getMinecraftServer().getRegistryManager().get(Registry.BIOME_KEY).getOrEmpty(new Identifier(biomeName))
|
||||||
if (biome == null)
|
.orElseThrow(() -> new ThrowStatement(biomeName, Throwables.UNKNOWN_BIOME));
|
||||||
throw new InternalExpressionException("Unknown biome: "+biomeName);
|
|
||||||
boolean doImmediateUpdate = true;
|
boolean doImmediateUpdate = true;
|
||||||
if (lv.size() > locator.offset+1)
|
if (lv.size() > locator.offset+1)
|
||||||
{
|
{
|
||||||
@@ -1252,8 +1249,8 @@ public class WorldAccess {
|
|||||||
if (!(requested instanceof NullValue))
|
if (!(requested instanceof NullValue))
|
||||||
{
|
{
|
||||||
String reqString = requested.getString();
|
String reqString = requested.getString();
|
||||||
structure = Registry.STRUCTURE_FEATURE.get(new Identifier(reqString));
|
structure = Registry.STRUCTURE_FEATURE.getOrEmpty(new Identifier(reqString))
|
||||||
if (structure == null) throw new InternalExpressionException("Unknown structure: " + reqString);
|
.orElseThrow(() -> new ThrowStatement(reqString, Throwables.UNKNOWN_STRUCTURE));
|
||||||
}
|
}
|
||||||
if (lv.size() > locator.offset+1)
|
if (lv.size() > locator.offset+1)
|
||||||
{
|
{
|
||||||
@@ -1333,7 +1330,7 @@ public class WorldAccess {
|
|||||||
throw new InternalExpressionException("'set_structure requires at least position and a structure name");
|
throw new InternalExpressionException("'set_structure requires at least position and a structure name");
|
||||||
String structureName = lv.get(locator.offset).evalValue(c).getString().toLowerCase(Locale.ROOT);
|
String structureName = lv.get(locator.offset).evalValue(c).getString().toLowerCase(Locale.ROOT);
|
||||||
ConfiguredStructureFeature<?, ?> configuredStructure = FeatureGenerator.resolveConfiguredStructure(structureName, world, pos);
|
ConfiguredStructureFeature<?, ?> configuredStructure = FeatureGenerator.resolveConfiguredStructure(structureName, world, pos);
|
||||||
if (configuredStructure == null) throw new InternalExpressionException("Unknown structure: "+structureName);
|
if (configuredStructure == null) throw new ThrowStatement(structureName, Throwables.UNKNOWN_STRUCTURE);
|
||||||
// good 'ol pointer
|
// good 'ol pointer
|
||||||
Value[] result = new Value[]{Value.NULL};
|
Value[] result = new Value[]{Value.NULL};
|
||||||
// technically a world modification. Even if we could let it slide, we will still park it
|
// technically a world modification. Even if we could let it slide, we will still park it
|
||||||
|
|||||||
@@ -8,28 +8,44 @@ import carpet.script.value.FunctionValue;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
/* The expression evaluators exception class. */
|
/* The expression evaluators exception class. */
|
||||||
public class ExpressionException extends RuntimeException implements ResolvedException
|
public class ExpressionException extends RuntimeException implements ResolvedException
|
||||||
{
|
{
|
||||||
public final Context context;
|
public final Context context;
|
||||||
|
public final Tokenizer.Token token;
|
||||||
public final List<FunctionValue> stack = new ArrayList<>();
|
public final List<FunctionValue> stack = new ArrayList<>();
|
||||||
|
private final Supplier<String> lazyMessage;
|
||||||
|
private String cachedMessage = null;
|
||||||
|
|
||||||
public ExpressionException(Context c, Expression e, String message)
|
public ExpressionException(Context c, Expression e, String message)
|
||||||
{
|
{
|
||||||
super(makeMessage(c, e, null, message));
|
this(c, e, Tokenizer.Token.NONE, message);
|
||||||
context = c;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ExpressionException(Context c, Expression e, Tokenizer.Token t, String message)
|
public ExpressionException(Context c, Expression e, Tokenizer.Token t, String message)
|
||||||
{
|
{
|
||||||
super(makeMessage(c, e, t, message));
|
super("Error");
|
||||||
|
lazyMessage = () -> makeMessage(c, e, t, message);
|
||||||
|
token = t;
|
||||||
context = c;
|
context = c;
|
||||||
}
|
}
|
||||||
public ExpressionException(Context c, Expression e, Tokenizer.Token t, String message, List<FunctionValue> stack)
|
public ExpressionException(Context c, Expression e, Tokenizer.Token t, String message, List<FunctionValue> stack)
|
||||||
{
|
{
|
||||||
super(makeMessage(c, e, t, message));
|
super("Error");
|
||||||
this.stack.addAll(stack);
|
this.stack.addAll(stack);
|
||||||
|
lazyMessage = () -> makeMessage(c, e, t, message);
|
||||||
|
token = t;
|
||||||
|
context = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExpressionException(Context c, Expression e, Tokenizer.Token t, Supplier<String> messageSupplier, List<FunctionValue> stack)
|
||||||
|
{
|
||||||
|
super("Error");
|
||||||
|
this.stack.addAll(stack);
|
||||||
|
lazyMessage = () -> makeMessage(c, e, t, messageSupplier.get());
|
||||||
|
token = t;
|
||||||
context = c;
|
context = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,4 +84,13 @@ public class ExpressionException extends RuntimeException implements ResolvedExc
|
|||||||
}
|
}
|
||||||
return String.join("\n", errorMaker.apply(e, t, message));
|
return String.join("\n", errorMaker.apply(e, t, message));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMessage() {
|
||||||
|
if (cachedMessage == null)
|
||||||
|
{
|
||||||
|
cachedMessage = lazyMessage.get();
|
||||||
|
}
|
||||||
|
return cachedMessage;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,8 @@
|
|||||||
package carpet.script.exception;
|
package carpet.script.exception;
|
||||||
|
|
||||||
|
import carpet.script.Context;
|
||||||
|
import carpet.script.Expression;
|
||||||
|
import carpet.script.Tokenizer;
|
||||||
import carpet.script.value.FunctionValue;
|
import carpet.script.value.FunctionValue;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -13,4 +16,20 @@ public class InternalExpressionException extends RuntimeException
|
|||||||
{
|
{
|
||||||
super(message);
|
super(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Promotes this simple exception into one with context and extra information.
|
||||||
|
*
|
||||||
|
* <p>Provides a cleaner way of handling similar exceptions, in this case
|
||||||
|
* {@link InternalExpressionException} and {@link ThrowStatement}
|
||||||
|
* @param c Context
|
||||||
|
* @param e Expression
|
||||||
|
* @param token Token
|
||||||
|
* @return The new {@link ExpressionException} (or {@link ProcessedThrowStatement}),
|
||||||
|
* depending on the implementation.
|
||||||
|
*/
|
||||||
|
public ExpressionException promote(Context c, Expression e, Tokenizer.Token token)
|
||||||
|
{
|
||||||
|
return new ExpressionException(c, e, token, getMessage(), stack);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package carpet.script.exception;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import carpet.script.Context;
|
||||||
|
import carpet.script.Expression;
|
||||||
|
import carpet.script.Tokenizer.Token;
|
||||||
|
import carpet.script.value.FunctionValue;
|
||||||
|
import carpet.script.value.Value;
|
||||||
|
|
||||||
|
public class ProcessedThrowStatement extends ExpressionException {
|
||||||
|
public final Throwables thrownExceptionType;
|
||||||
|
public final Value data;
|
||||||
|
|
||||||
|
public ProcessedThrowStatement(Context c, Expression e, Token token, List<FunctionValue> stack, Throwables thrownExceptionType, Value data) {
|
||||||
|
super(c, e, token, () -> "Unhandled "+thrownExceptionType.getId()+" exception: "+data.getString(), stack);
|
||||||
|
this.thrownExceptionType = thrownExceptionType;
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,11 +1,54 @@
|
|||||||
package carpet.script.exception;
|
package carpet.script.exception;
|
||||||
|
|
||||||
|
import carpet.script.Context;
|
||||||
|
import carpet.script.Expression;
|
||||||
|
import carpet.script.Tokenizer.Token;
|
||||||
|
import carpet.script.value.StringValue;
|
||||||
import carpet.script.value.Value;
|
import carpet.script.value.Value;
|
||||||
|
|
||||||
public class ThrowStatement extends ExitStatement
|
public class ThrowStatement extends InternalExpressionException
|
||||||
{
|
{
|
||||||
public ThrowStatement(Value value)
|
private final Throwables type;
|
||||||
|
private final Value data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a throw exception from a value, and assigns it a specified message.
|
||||||
|
* <p>To be used when throwing from Scarpet's {@code throw} function
|
||||||
|
* @param data The value to pass
|
||||||
|
* @param type Exception type
|
||||||
|
*/
|
||||||
|
public ThrowStatement(Value data, Throwables type)
|
||||||
{
|
{
|
||||||
super(value);
|
super(type.getId());
|
||||||
|
this.data = data;
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ThrowStatement(Value data, Throwables parent, String subtype)
|
||||||
|
{
|
||||||
|
super(subtype);
|
||||||
|
this.data = data;
|
||||||
|
this.type = new Throwables(subtype, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a throw exception.<br>
|
||||||
|
* Conveniently creates a value from the {@code value} String
|
||||||
|
* to be used easily in Java code
|
||||||
|
* @param message The message to display when not handled
|
||||||
|
* @param type An {@link Throwables} containing the inheritance data
|
||||||
|
* for this exception. When throwing from Java,
|
||||||
|
* those exceptions should be pre-registered.
|
||||||
|
*/
|
||||||
|
public ThrowStatement(String message, Throwables type)
|
||||||
|
{
|
||||||
|
super(type.getId());
|
||||||
|
this.data = StringValue.of(message);
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ExpressionException promote(Context c, Expression e, Token token) {
|
||||||
|
return new ProcessedThrowStatement(c, e, token, stack, type, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
package carpet.script.exception;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class contains default Scarpet catchable types, as well as their inheritance and
|
||||||
|
* methods to check whether filters are compatible with those.
|
||||||
|
*/
|
||||||
|
public class Throwables {
|
||||||
|
private final String id;
|
||||||
|
private final Throwables parent;
|
||||||
|
|
||||||
|
private static final Map<String, Throwables> byId = new HashMap<>();
|
||||||
|
|
||||||
|
public static final Throwables THROWN_EXCEPTION_TYPE = register("exception", null);
|
||||||
|
public static final Throwables VALUE_EXCEPTION = register("value_exception", THROWN_EXCEPTION_TYPE);
|
||||||
|
public static final Throwables UNKNOWN_ITEM = register("unknown_item", VALUE_EXCEPTION);
|
||||||
|
public static final Throwables UNKNOWN_BLOCK = register("unknown_block", VALUE_EXCEPTION);
|
||||||
|
public static final Throwables UNKNOWN_BIOME = register("unknown_biome", VALUE_EXCEPTION);
|
||||||
|
public static final Throwables UNKNOWN_SOUND = register("unknown_sound", VALUE_EXCEPTION);
|
||||||
|
public static final Throwables UNKNOWN_PARTICLE = register("unknown_particle", VALUE_EXCEPTION);
|
||||||
|
public static final Throwables UNKNOWN_POI = register("unknown_poi", VALUE_EXCEPTION);
|
||||||
|
public static final Throwables UNKNOWN_DIMENSION = register("unknown_dimension", VALUE_EXCEPTION);
|
||||||
|
public static final Throwables UNKNOWN_STRUCTURE = register("unknown_structure", VALUE_EXCEPTION);
|
||||||
|
public static final Throwables UNKNOWN_CRITERION = register("unknown_criterion", VALUE_EXCEPTION);
|
||||||
|
public static final Throwables IO_EXCEPTION = register("io_exception", THROWN_EXCEPTION_TYPE);
|
||||||
|
public static final Throwables NBT_READ = register("nbt_read_error", IO_EXCEPTION);
|
||||||
|
public static final Throwables JSON_READ = register("json_read_error", IO_EXCEPTION);
|
||||||
|
public static final Throwables USER_DEFINED = register("user_exception", THROWN_EXCEPTION_TYPE);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an exception and registers it to be used as parent for
|
||||||
|
* user defined exceptions in Scarpet's throw function.
|
||||||
|
* <p>Scarpet exceptions should have a top-level parent being {@link Throwables#THROWN_EXCEPTION_TYPE}
|
||||||
|
* @param id The value for the exception as a {@link String}.
|
||||||
|
* @param parent The parent of the exception being created, or <code>null</code> if top-level
|
||||||
|
* @return The created exception
|
||||||
|
*/
|
||||||
|
public static Throwables register(String id, Throwables parent)
|
||||||
|
{
|
||||||
|
Throwables exc = new Throwables(id, parent);
|
||||||
|
byId.put(id, exc);
|
||||||
|
return exc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new exception.
|
||||||
|
* <p>Not suitable for creating exceptions that can't be caught.
|
||||||
|
* Use an {@link InternalExpressionException} for that
|
||||||
|
* @param id The exception's value as a {@link String}
|
||||||
|
*/
|
||||||
|
public Throwables(String id, Throwables parent)
|
||||||
|
{
|
||||||
|
this.id = id;
|
||||||
|
this.parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Throwables getTypeForException(String type)
|
||||||
|
{
|
||||||
|
Throwables properType = byId.get(type);
|
||||||
|
if (properType == null) throw new InternalExpressionException("Unknown exception type: "+type);
|
||||||
|
return properType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the given filter matches an instance of this exception, by checking equality
|
||||||
|
* with itself and possible parents.
|
||||||
|
* @param filter The type to check against
|
||||||
|
* @return Whether or not the given value matches this exception's hierarchy
|
||||||
|
*/
|
||||||
|
public boolean isRelevantFor(String filter)
|
||||||
|
{
|
||||||
|
return (id.equals(filter) || (parent != null && parent.isRelevantFor(filter)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isUserException()
|
||||||
|
{
|
||||||
|
return this == USER_DEFINED || parent == USER_DEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the throwable type
|
||||||
|
* @return The type of this exception
|
||||||
|
*/
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,8 +5,17 @@ import carpet.script.Expression;
|
|||||||
import carpet.script.LazyValue;
|
import carpet.script.LazyValue;
|
||||||
import carpet.script.exception.ExitStatement;
|
import carpet.script.exception.ExitStatement;
|
||||||
import carpet.script.exception.InternalExpressionException;
|
import carpet.script.exception.InternalExpressionException;
|
||||||
|
import carpet.script.exception.ProcessedThrowStatement;
|
||||||
import carpet.script.exception.ThrowStatement;
|
import carpet.script.exception.ThrowStatement;
|
||||||
|
import carpet.script.exception.Throwables;
|
||||||
|
import carpet.script.value.ListValue;
|
||||||
|
import carpet.script.value.MapValue;
|
||||||
|
import carpet.script.value.NumericValue;
|
||||||
|
import carpet.script.value.StringValue;
|
||||||
import carpet.script.value.Value;
|
import carpet.script.value.Value;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class ControlFlow {
|
public class ControlFlow {
|
||||||
public static void apply(Expression expression) // public just to get the javadoc right
|
public static void apply(Expression expression) // public just to get the javadoc right
|
||||||
@@ -42,26 +51,98 @@ public class ControlFlow {
|
|||||||
|
|
||||||
expression.addFunction("exit", (lv) -> { throw new ExitStatement(lv.size()==0?Value.NULL:lv.get(0)); });
|
expression.addFunction("exit", (lv) -> { throw new ExitStatement(lv.size()==0?Value.NULL:lv.get(0)); });
|
||||||
|
|
||||||
expression.addFunction("throw", (lv)-> {throw new ThrowStatement(lv.size()==0?Value.NULL:lv.get(0)); });
|
expression.addLazyFunction("throw", -1, (c, t, lv)->
|
||||||
|
{
|
||||||
|
switch (lv.size())
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
throw new ThrowStatement(Value.NULL, Throwables.USER_DEFINED);
|
||||||
|
case 1:
|
||||||
|
throw new ThrowStatement(lv.get(0).evalValue(c), Throwables.USER_DEFINED );
|
||||||
|
case 2:
|
||||||
|
throw new ThrowStatement(lv.get(1).evalValue(c), Throwables.getTypeForException(lv.get(0).evalValue(c).getString()));
|
||||||
|
case 3:
|
||||||
|
throw new ThrowStatement(lv.get(2).evalValue(c), Throwables.getTypeForException(lv.get(1).evalValue(c).getString()), lv.get(0).evalValue(c).getString());
|
||||||
|
default:
|
||||||
|
throw new InternalExpressionException("throw() can't accept more than 3 parameters");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
expression.addLazyFunction("try", -1, (c, t, lv) ->
|
expression.addLazyFunction("try", -1, (c, t, lv) ->
|
||||||
{
|
{
|
||||||
if (lv.size()==0)
|
if (lv.size()==0)
|
||||||
throw new InternalExpressionException("'try' needs at least an expression block");
|
throw new InternalExpressionException("'try' needs at least an expression block, and either a catch_epr, or a number of pairs of filters and catch_expr");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Value retval = lv.get(0).evalValue(c, t);
|
Value retval = lv.get(0).evalValue(c, t);
|
||||||
return (c_, t_) -> retval;
|
return (c_, t_) -> retval;
|
||||||
}
|
}
|
||||||
catch (ThrowStatement ret)
|
catch (ProcessedThrowStatement ret)
|
||||||
{
|
{
|
||||||
if (lv.size() == 1)
|
if (lv.size() == 1)
|
||||||
|
{
|
||||||
|
if (!ret.thrownExceptionType.isUserException())
|
||||||
|
throw ret;
|
||||||
return (c_, t_) -> Value.NULL;
|
return (c_, t_) -> Value.NULL;
|
||||||
|
}
|
||||||
|
if (lv.size() > 3 && lv.size() % 2 == 0)
|
||||||
|
{
|
||||||
|
throw new InternalExpressionException("Try-catch block needs the code to run, and either a catch expression for user thrown exceptions, or a number of pairs of filters and catch expressions");
|
||||||
|
}
|
||||||
|
|
||||||
|
Value val = null; // This is always assigned at some point, just the compiler doesn't know
|
||||||
|
|
||||||
LazyValue __ = c.getVariable("_");
|
LazyValue __ = c.getVariable("_");
|
||||||
c.setVariable("_", (__c, __t) -> ret.retval.reboundedTo("_"));
|
c.setVariable("_", (__c, __t) -> ret.data.reboundedTo("_"));
|
||||||
Value val = lv.get(1).evalValue(c, t);
|
LazyValue _trace = c.getVariable("_trace");
|
||||||
c.setVariable("_",__);
|
c.setVariable("_trace", (__c, __t) -> MapValue.wrap(ImmutableMap.of(
|
||||||
return (c_, t_) -> val;
|
StringValue.of("stack"), ListValue.wrap(ret.stack.stream().map(f -> ListValue.of(
|
||||||
|
StringValue.of(f.getModule().getName()),
|
||||||
|
StringValue.of(f.getString()),
|
||||||
|
NumericValue.of(f.getToken().lineno+1),
|
||||||
|
NumericValue.of(f.getToken().linepos+1)
|
||||||
|
)).collect(Collectors.toList())),
|
||||||
|
|
||||||
|
StringValue.of("locals"), MapValue.wrap(ret.context.variables.entrySet().stream().filter(e -> !e.getKey().equals("_trace")).collect(Collectors.toMap(
|
||||||
|
e -> StringValue.of(e.getKey()),
|
||||||
|
e -> e.getValue().evalValue(ret.context)
|
||||||
|
))),
|
||||||
|
StringValue.of("token"), ListValue.of(
|
||||||
|
StringValue.of(ret.token.surface),
|
||||||
|
NumericValue.of(ret.token.lineno+1),
|
||||||
|
NumericValue.of(ret.token.linepos+1)
|
||||||
|
)
|
||||||
|
)));
|
||||||
|
|
||||||
|
if (lv.size() == 2)
|
||||||
|
{
|
||||||
|
if (ret.thrownExceptionType.isUserException())
|
||||||
|
val = lv.get(1).evalValue(c, t);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int pointer = 1;
|
||||||
|
while (pointer < lv.size() -1)
|
||||||
|
{
|
||||||
|
if (ret.thrownExceptionType.isRelevantFor(lv.get(pointer).evalValue(c).getString()))
|
||||||
|
{
|
||||||
|
val = lv.get(pointer + 1).evalValue(c, t);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pointer += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.setVariable("_", __);
|
||||||
|
if (_trace != null)
|
||||||
|
c.setVariable("_trace", _trace);
|
||||||
|
else
|
||||||
|
c.delVariable("_trace");
|
||||||
|
if (val == null) // not handled
|
||||||
|
{
|
||||||
|
throw ret;
|
||||||
|
}
|
||||||
|
Value retval = val;
|
||||||
|
return (c_, t_) -> retval;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import carpet.CarpetSettings;
|
|||||||
import carpet.network.ServerNetworkHandler;
|
import carpet.network.ServerNetworkHandler;
|
||||||
import carpet.script.CarpetContext;
|
import carpet.script.CarpetContext;
|
||||||
import carpet.script.exception.InternalExpressionException;
|
import carpet.script.exception.InternalExpressionException;
|
||||||
|
import carpet.script.exception.ThrowStatement;
|
||||||
|
import carpet.script.exception.Throwables;
|
||||||
import carpet.script.language.Sys;
|
import carpet.script.language.Sys;
|
||||||
import carpet.script.value.BlockValue;
|
import carpet.script.value.BlockValue;
|
||||||
import carpet.script.value.EntityValue;
|
import carpet.script.value.EntityValue;
|
||||||
@@ -156,7 +158,7 @@ public class ShapeDispatcher
|
|||||||
}
|
}
|
||||||
catch (CommandSyntaxException e)
|
catch (CommandSyntaxException e)
|
||||||
{
|
{
|
||||||
throw new InternalExpressionException("No such particle: "+name);
|
throw new ThrowStatement(name, Throwables.UNKNOWN_PARTICLE);
|
||||||
}
|
}
|
||||||
particleCache.put(name, particle);
|
particleCache.put(name, particle);
|
||||||
return particle;
|
return particle;
|
||||||
|
|||||||
@@ -2,6 +2,9 @@ package carpet.script.value;
|
|||||||
|
|
||||||
import carpet.script.CarpetContext;
|
import carpet.script.CarpetContext;
|
||||||
import carpet.script.exception.InternalExpressionException;
|
import carpet.script.exception.InternalExpressionException;
|
||||||
|
import carpet.script.exception.ThrowStatement;
|
||||||
|
import carpet.script.exception.Throwables;
|
||||||
|
|
||||||
import com.mojang.brigadier.StringReader;
|
import com.mojang.brigadier.StringReader;
|
||||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
@@ -73,7 +76,7 @@ public class BlockValue extends Value
|
|||||||
catch (CommandSyntaxException ignored)
|
catch (CommandSyntaxException ignored)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
throw new InternalExpressionException("Cannot parse block: "+str);
|
throw new ThrowStatement(str, Throwables.UNKNOWN_BLOCK);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BlockPos locateBlockPos(CarpetContext c, int xpos, int ypos, int zpos)
|
public static BlockPos locateBlockPos(CarpetContext c, int xpos, int ypos, int zpos)
|
||||||
|
|||||||
@@ -215,7 +215,6 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction
|
|||||||
|
|
||||||
}
|
}
|
||||||
Value retVal;
|
Value retVal;
|
||||||
boolean rethrow = false;
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
retVal = body.evalValue(newFrame, type); // todo not sure if we need to propagete type / consider boolean context in defined functions - answer seems ye
|
retVal = body.evalValue(newFrame, type); // todo not sure if we need to propagete type / consider boolean context in defined functions - answer seems ye
|
||||||
@@ -228,15 +227,6 @@ public class FunctionValue extends Value implements Fluff.ILazyFunction
|
|||||||
{
|
{
|
||||||
retVal = returnStatement.retval;
|
retVal = returnStatement.retval;
|
||||||
}
|
}
|
||||||
catch (ThrowStatement throwStatement) // might not be really necessary
|
|
||||||
{
|
|
||||||
retVal = throwStatement.retval;
|
|
||||||
rethrow = true;
|
|
||||||
}
|
|
||||||
if (rethrow)
|
|
||||||
{
|
|
||||||
throw new ThrowStatement(retVal);
|
|
||||||
}
|
|
||||||
Value otherRetVal = retVal;
|
Value otherRetVal = retVal;
|
||||||
return (cc, tt) -> otherRetVal;
|
return (cc, tt) -> otherRetVal;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import carpet.fakes.InventoryBearerInterface;
|
|||||||
import carpet.script.CarpetContext;
|
import carpet.script.CarpetContext;
|
||||||
import carpet.script.LazyValue;
|
import carpet.script.LazyValue;
|
||||||
import carpet.script.exception.InternalExpressionException;
|
import carpet.script.exception.InternalExpressionException;
|
||||||
|
import carpet.script.exception.ThrowStatement;
|
||||||
|
import carpet.script.exception.Throwables;
|
||||||
import carpet.script.utils.EquipmentInventory;
|
import carpet.script.utils.EquipmentInventory;
|
||||||
import com.mojang.brigadier.StringReader;
|
import com.mojang.brigadier.StringReader;
|
||||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||||
@@ -297,7 +299,7 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
|
|||||||
}
|
}
|
||||||
catch (CommandSyntaxException e)
|
catch (CommandSyntaxException e)
|
||||||
{
|
{
|
||||||
throw new InternalExpressionException("Incorrect item: "+itemString);
|
throw new ThrowStatement(itemString, Throwables.UNKNOWN_ITEM);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package carpet.script.value;
|
|||||||
|
|
||||||
import carpet.fakes.BlockPredicateInterface;
|
import carpet.fakes.BlockPredicateInterface;
|
||||||
import carpet.script.exception.InternalExpressionException;
|
import carpet.script.exception.InternalExpressionException;
|
||||||
|
import carpet.script.exception.ThrowStatement;
|
||||||
|
import carpet.script.exception.Throwables;
|
||||||
import carpet.utils.BlockInfo;
|
import carpet.utils.BlockInfo;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.block.MaterialColor;
|
import net.minecraft.block.MaterialColor;
|
||||||
@@ -158,7 +160,7 @@ public class ValueConversions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (dim == null)
|
if (dim == null)
|
||||||
throw new InternalExpressionException("Incorrect dimension string: "+dimString);
|
throw new ThrowStatement(dimString, Throwables.UNKNOWN_DIMENSION);
|
||||||
return server.getWorld(dim);
|
return server.getWorld(dim);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user