diff --git a/gradle.properties b/gradle.properties index d5a3f651..17fa2a32 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ org.gradle.jvmargs=-Xmx1G loader_version=0.4.8+build.155 # Mod Properties - mod_version = 1.0.0+v190714 + mod_version = 1.0.0+v190721 maven_group = carpet archives_base_name = fabric-carpet diff --git a/src/main/java/carpet/commands/CameraModeCommand.java b/src/main/java/carpet/commands/CameraModeCommand.java index ab2af25f..1fb69827 100644 --- a/src/main/java/carpet/commands/CameraModeCommand.java +++ b/src/main/java/carpet/commands/CameraModeCommand.java @@ -4,11 +4,13 @@ import carpet.settings.CarpetSettings; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.minecraft.client.network.packet.EntityVelocityUpdateS2CPacket; +import net.minecraft.client.network.packet.RemoveEntityEffectS2CPacket; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.command.arguments.EntityArgumentType; -import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.effect.StatusEffects; import net.minecraft.entity.effect.StatusEffectInstance; +import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.world.GameMode; import static net.minecraft.server.command.CommandManager.argument; @@ -35,7 +37,7 @@ public class CameraModeCommand dispatcher.register(camera); dispatcher.register(survival); } - private static boolean iCanHasPermissions(ServerCommandSource source, PlayerEntity player) + private static boolean iCanHasPermissions(ServerCommandSource source, ServerPlayerEntity player) { try { @@ -46,19 +48,23 @@ public class CameraModeCommand return true; // shoudn't happen because server has all permissions anyways } } - private static int cameraMode(ServerCommandSource source, PlayerEntity player) + private static int cameraMode(ServerCommandSource source, ServerPlayerEntity player) { if (!(iCanHasPermissions(source, player))) return 0; player.setGameMode(GameMode.SPECTATOR); + player.addVelocity(0,0.1,0); + player.networkHandler.sendPacket(new EntityVelocityUpdateS2CPacket(player)); player.addPotionEffect(new StatusEffectInstance(StatusEffects.NIGHT_VISION, 999999, 0, false, false)); player.addPotionEffect(new StatusEffectInstance(StatusEffects.CONDUIT_POWER, 999999, 0, false, false)); return 1; } - private static int survivalMode(ServerCommandSource source, PlayerEntity player) + private static int survivalMode(ServerCommandSource source, ServerPlayerEntity player) { if (!(iCanHasPermissions(source, player))) return 0; player.setGameMode(GameMode.SURVIVAL); + player.networkHandler.sendPacket(new RemoveEntityEffectS2CPacket(player.getEntityId(), StatusEffects.NIGHT_VISION)); player.removePotionEffect(StatusEffects.NIGHT_VISION); + player.networkHandler.sendPacket(new RemoveEntityEffectS2CPacket(player.getEntityId(), StatusEffects.CONDUIT_POWER)); player.removePotionEffect(StatusEffects.CONDUIT_POWER); return 1; } diff --git a/src/main/java/carpet/mixins/ServerPlayNetworkHandler_scarpetEventsMixin.java b/src/main/java/carpet/mixins/ServerPlayNetworkHandler_scarpetEventsMixin.java index 37a3c9a5..aacf95ac 100644 --- a/src/main/java/carpet/mixins/ServerPlayNetworkHandler_scarpetEventsMixin.java +++ b/src/main/java/carpet/mixins/ServerPlayNetworkHandler_scarpetEventsMixin.java @@ -47,7 +47,8 @@ public class ServerPlayNetworkHandler_scarpetEventsMixin )) private void onClicked(PlayerActionC2SPacket packet, CallbackInfo ci) { - CarpetServer.scriptServer.events.onBlockClicked(player, packet.getPos(), packet.getDirection()); + if (packet.getAction() == PlayerActionC2SPacket.Action.START_DESTROY_BLOCK) + CarpetServer.scriptServer.events.onBlockClicked(player, packet.getPos(), packet.getDirection()); } @Inject(method = "onPlayerInteractBlock", at = @At( diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index 2b9b227e..523e1dd2 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -23,9 +23,14 @@ import carpet.utils.Messenger; import com.google.common.collect.Sets; import com.mojang.brigadier.StringReader; import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.minecraft.block.BarrierBlock; +import net.minecraft.block.BedrockBlock; import net.minecraft.block.Block; import net.minecraft.block.BlockPlacementEnvironment; import net.minecraft.block.BlockState; +import net.minecraft.block.CommandBlock; +import net.minecraft.block.JigsawBlock; +import net.minecraft.block.StructureBlock; import net.minecraft.block.entity.BlockEntity; import net.minecraft.client.network.packet.PlaySoundIdS2CPacket; import net.minecraft.command.arguments.ItemStackArgument; @@ -302,6 +307,46 @@ public class CarpetExpression } } + public boolean tryBreakBlock_copy_from_ServerPlayerInteractionManager(ServerPlayerEntity player, BlockPos blockPos_1) + { + //this could be done little better, by hooking up event handling not in try_break_block but wherever its called + // so we can safely call it here + // but that woudl do for now. + BlockState blockState_1 = player.world.getBlockState(blockPos_1); + if (!player.getMainHandStack().getItem().canMine(blockState_1, player.world, blockPos_1, player)) { + return false; + } else { + BlockEntity blockEntity_1 = player.world.getBlockEntity(blockPos_1); + Block block_1 = blockState_1.getBlock(); + if ((block_1 instanceof CommandBlock || block_1 instanceof StructureBlock || block_1 instanceof JigsawBlock) && !player.isCreativeLevelTwoOp()) { + player.world.updateListeners(blockPos_1, blockState_1, blockState_1, 3); + return false; + } else if (player.method_21701(player.world, blockPos_1, player.interactionManager.getGameMode())) { + return false; + } else { + block_1.onBreak(player.world, blockPos_1, blockState_1, player); + boolean boolean_1 = player.world.clearBlockState(blockPos_1, false); + if (boolean_1) { + block_1.onBroken(player.world, blockPos_1, blockState_1); + } + + if (player.isCreative()) { + return true; + } else { + ItemStack itemStack_1 = player.getMainHandStack(); + boolean boolean_2 = player.isUsingEffectiveTool(blockState_1); + itemStack_1.postMine(player.world, blockState_1, blockPos_1, player); + if (boolean_1 && boolean_2) { + ItemStack itemStack_2 = itemStack_1.isEmpty() ? ItemStack.EMPTY : itemStack_1.copy(); + block_1.afterBreak(player.world, player, blockPos_1, blockState_1, blockEntity_1, itemStack_2); + } + + return true; + } + } + } + } + /** *

Blocks / World API

*
@@ -368,11 +413,12 @@ public class CarpetExpression *

random_tick(pos)

*

Causes a random tick at position.

*

destroy(pos), destroy(pos, -1), destroy(pos, <N>)

- *

Destroys the block like it was harvest by a player. Add -1 for silk touch, and positive number for fortune level.

+ *

Destroys the block like it was mined by a player. Add -1 for silk touch, and positive number for fortune level. + * This function, unlike harvest, will affect all kinds of blocks

*

harvest(player, pos)

*

Causes a block to be harvested by a specified player entity. Honors player item enchantments, as well as damages the - * tool if applicable. If the entity is not a valid player, no block gets destroyed.

- * + * tool if applicable. If the entity is not a valid player, no block gets destroyed. If a player is not allowed to + * break that block, a block doesn't get destroyed either.

* *

Block and World querying

* @@ -385,6 +431,8 @@ public class CarpetExpression * pos(players()) => l(12.3, 45.6, 32.05) * pos(block('stone')) => Error: Cannot fetch position of an unrealized block * + *

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)

*

Returns property of block at pos, or specified by block argument. If a block doesn't * have that property, null value is returned. Returned values are always strings. It is expected from @@ -433,19 +481,19 @@ public class CarpetExpression *

blast_resistance(pos)

*

Numeric function, indicating blast_resistance of a block.

- *

top(type, x, z)

- *

Returns the Y value of the topmost block at given x, z coords, according to the + *

top(type, pos)

+ *

Returns the Y value of the topmost block at given x, z coords (y value of a block is not important), according to the * heightmap specified by type. Valid options are:

* *
-     * top('motion', x, z)  => 63
-     * top('ocean_floor', x, z)  => 41
+     * top('motion', x, y, z)  => 63
+     * top('ocean_floor', x, y, z)  => 41
      * 
*

loaded(pos)

*

Boolean function, true if the block is loaded. Normally scarpet doesn't check if operates on @@ -849,21 +897,19 @@ public class CarpetExpression if (!(entityValue instanceof EntityValue)) return (c_, t_) -> Value.FALSE; Entity e = ((EntityValue) entityValue).getEntity(); - if (!(e instanceof PlayerEntity)) + if (!(e instanceof ServerPlayerEntity)) return (c_, t_) -> Value.FALSE; - PlayerEntity player = (PlayerEntity)e; - + ServerPlayerEntity player = (ServerPlayerEntity)e; BlockValue.LocatorResult locator = BlockValue.fromParams(cc, lv, 1); - BlockState state = locator.block.getBlockState(); BlockPos where = locator.block.getPos(); - BlockEntity be = world.getBlockEntity(where); - world.clearBlockState(where, false); - ItemStack itemstack2 = player.getMainHandStack(); - itemstack2.postMine(player.world, state, where, player); - ItemStack itemstack1 = itemstack2.isEmpty() ? ItemStack.EMPTY : itemstack2.copy(); - state.getBlock().afterBreak(world, player, where, state, be, itemstack1); - world.playLevelEvent(null, 2001, where, Block.getRawIdFromState(state)); - return (c_, t_) -> Value.TRUE; + BlockState state = locator.block.getBlockState(); + Block block = state.getBlock(); + boolean success = false; + if (!((block instanceof BedrockBlock || block instanceof BarrierBlock) && player.interactionManager.isSurvivalLike())) + success = tryBreakBlock_copy_from_ServerPlayerInteractionManager(player, where); + if (success) + world.playLevelEvent(null, 2001, where, Block.getRawIdFromState(state)); + return success ? LazyValue.TRUE : LazyValue.FALSE; }); this.expr.addLazyFunction("place_item", -1, (c, t, lv) -> @@ -1336,6 +1382,11 @@ public class CarpetExpression *

Returns entities satisfying given vanilla entity selector. Most complex among all the methods of selecting * entities, but the most capable. Selectors are cached so should be as fast as other methods of selecting entities.

* + *

spawn(name, pos, nbt?)

+ *

Spawns and places an entity in world, like /summon vanilla command. + * Requires a position to spawn, and optional extra nbt data to merge with the entity. What makes it different from calling + * run('summon ...'), is the fact that you get the entity back as a return value, which is swell.

+ * *

Entity Manipulation

* *

Unlike with blocks, that use plethora of vastly different querying functions, entities are queried with @@ -1368,6 +1419,8 @@ public class CarpetExpression *

Respective entity coordinate

*

query(e,'pitch'), query(e,'yaw')

*

Pitch and Yaw or where entity is looking.

+ *

query(e,'look')

+ *

Returns a 3d vector where the entity is looking.

*

query(e,'motion')

*

Triple of entity motion vector, l(motion_x, motion_y, motion_z)

*

query(e,'motion_x'), query(e,'motion_y'), query(e,'motion_z')

@@ -1445,6 +1498,7 @@ public class CarpetExpression * *

query(e,'health')

*

Number indicating remaining entity health, or null if not applicable.

+ * *

query(e,'holds',slot?)

*

Returns triple of short name, stack count, and NBT of item held in slot. * Available options for slot are:

@@ -1462,7 +1516,14 @@ public class CarpetExpression *

query(e,'facing', order?)

*

Returns where the entity is facing. optional order (number from 0 to 5, and negative), indicating * primary directions where entity is looking at. From most prominent (order 0) to opposite (order 5, or -1)

- * + *

query(e,'trace', reach?, options?...)

+ *

Returns the result of ray tracing from entity perspective, indicating what it is looking at. Default reach is 4.5 + * blocks (5 for creative players), and by default it traces for blocks and entities, identical to player attack tracing action. + * This can be customized with options, use 'blocks' to trace for blocks only, 'liquids' to include liquid blocks + * as possible results, and 'entities' to trace entities as well.

+ *

Regardless of the options selected, the result could be null if nothing is in reach, entity, if look + * targets an antity, and block value if block is in reach. Tracing always hits blocks. Even if an entity tracing is requested + * and there is a block in the way - the block will be returned.

*

query(e,'nbt',path?)

*

Returns full NBT of the entity. If path is specified, it fetches only that portion of the NBT, * that corresponds to the path. For specification of path attribute, consult @@ -1497,8 +1558,7 @@ public class CarpetExpression *

modify(e, 'accelerate', x, y, z), modify(e, 'accelerate', l(x, y, z) )

*

Adds a vector to the motion vector. Most realistic way to apply a force to an entity.

*

modify(e, 'custom_name'), modify(e, 'custom_name', name )

- *

Sets a custom name for an entity. No argument sets it empty, not removes it. Vanilla doesn't allow removing - * of attributes.

+ *

Sets a custom name for an entity. Removes a custom name if the argument is null

*

modify(e, 'dismount')

*

Dismounts riding entity.

*

modify(e, 'mount', other)

@@ -1977,9 +2037,7 @@ public class CarpetExpression int y; int z; { - x = minx; - y = miny; - z = minz; + reset(); } @Override public boolean hasNext() @@ -2012,6 +2070,15 @@ public class CarpetExpression public void fatality() { // possibly return original x, y, z + super.fatality(); + } + + @Override + public void reset() + { + x = minx; + y = miny; + z = minz; } }; }); @@ -2066,10 +2133,10 @@ public class CarpetExpression { return (c_, t_) -> new LazyListValue() { - int curradius = 0; - int curpos = 0; + int curradius; + int curpos; { - + reset(); } @Override public boolean hasNext() @@ -2097,15 +2164,25 @@ public class CarpetExpression return block; } + + @Override + public void reset() + { + curradius = 0; + curpos = 0; + } }; } else { return (c_, t_) -> new LazyListValue() { - int curradius = 0; - int curpos = 0; - int curheight = -height; + int curradius; + int curpos; + int curheight; + { + reset(); + } @Override public boolean hasNext() { @@ -2142,6 +2219,14 @@ public class CarpetExpression } return block; } + + @Override + public void reset() + { + curradius = 0; + curpos = 0; + curheight = -height; + } }; } }); @@ -2170,6 +2255,10 @@ public class CarpetExpression *

particle_rect(name, pos, pos2, density?)

*

Renders a cuboid of particles between point pos to pos2 with supplied density.

*

System function

+ *

nbt(expr)

+ *

Treats the argument as a nbt serializable string and returns its nbt value. + * In case nbt is not in a correct nbt compound tag format, the execution of a script will stop with an error, + * whenever that tag is used.

*

print(expr)

*

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

@@ -2482,6 +2571,14 @@ public class CarpetExpression return (_cc, _tt) -> new NumericValue(finalTotal); }); + this.expr.addLazyFunction("nbt", 1, (c, t, lv) -> { + Value v = lv.get(0).evalValue(c); + if (v instanceof NBTSerializableValue) + return (cc, tt) -> v; + Value ret = new NBTSerializableValue(v.getString()); + return (cc, tt) -> ret; + }); + //"overridden" native call that prints to stderr this.expr.addLazyFunction("print", 1, (c, t, lv) -> { @@ -2775,4 +2872,90 @@ public class CarpetExpression { return "Yeah"; } + + /** + *

/script load / unload <module> (shared?), /script in <module> commands

+ *
+ *

load / unload commands allow for very conventient way of writing your code, providing it to the game + * and distribute with your worlds without the need of use of commandblocks. Just place your scarpet code in the /scripts + * folder of your world files and make sure it ends with .sc extension. The good thing about editing that + * code is that you can no only use normal editing without the need of marking of newlines, but you can also use + * comments in your code.

+ *

a comment is anything that starts with a double slash, and continues to the end of the line:

+ *
+     * foo = 1;
+     * //This is a comment
+     * bar = 2;
+     * // This never worked, so I commented it out
+     * // baz = foo()
+     * 
+ *

+ *

/script load/unload <module> (?shared)

+ *

Loading operation will load that script code from disk and execute it right away. You would probably use it to + * load some stored procedures to be used for later. To reload the module, just type /script load again. + * Reloading removes all the current global state (globals and functions) that were added later by the module.

+ *

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).

+ *

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 + * for each player independently. In shared mode - all global values and stored functions are shared among all players. + * To access specific player data with commandblocks, use /execute as (player) run script in (module) run ... + * To access global/server state, you need to disown the command from any player, so use a commandblock, or any arbitrary + * entity: /execute as @e[type=bat,limit=1] run script in (module) globals for instance. + *

+ *

/script in <module> ...

+ *

Allows to run normal /script commands in a specific module, like run, invoke,..., globals etc...

+ *
+ * @return . + */ + public static String loadScriptsFromFilesCommand() + { + return "Yeah"; + } + + /** + *

Scarpet events system

+ *
+ *

Provides the ability to execute specific function whenever an event occurs. The functions to be registered + * need to conform with the arguments to the event specification. When loading module functions, each function that + * starts with __on_... and has the required arguments, will be bound automatically. + * In case of player specific modules, all player action events will be directed to the appropriate player space, and + * all tick events will be executed in the global context, so its not a good idea to mix these two, so use either of these, + * or use commands to call tick events directly, or handle player specific data inside a module.

+ *

+ *

Event list

+ *

Here is a list of events that can be handled by scarpet. This list includes prefixes required by modules to + * autoload them, but you can add any function to any event if it had required parameters:

+ *
+     * __on_tick()         // can access blocks and entities in the overworld
+     * __on_tick_nether()  // can access blocks and entities in the nether
+     * __on_tick_ender()   // can access blocks and entities in the end
+     * // player specific callbacks
+     * __on_player_jumps(player)
+     * __on_player_deploys_elytra(player)
+     * __on_player_wakes_up(player)
+     * __on_player_rides(player, forward, strafe, jumping, sneaking)
+     * __on_player_uses_item(player, item_tuple, hand)
+     * __on_player_clicks_block(player, block, face)
+     * __on_player_right_clicks_block(player, item_tuple, hand, block, face, hitvec)
+     * __on_player_breaks_block(player, block)
+     * __on_player_interacts_with_entity(player, entity, hand)
+     * __on_player_attacks_entity(player, entity)
+     * __on_player_starts_sneaking(player)
+     * __on_player_stops_sneaking(player)
+     * __on_player_starts_sprinting(player)
+     * __on_player_stops_sprinting(player)
+     * 
+ *

/script event command

+ *

used to display current events and bounded functions. use add_to ro register new event, or remove_from + * to unbind a specific function from an event.

+ *
+ * @return . + */ + public static String gameEventsSystem() + { + return "Yeah"; + } } diff --git a/src/main/java/carpet/script/Expression.java b/src/main/java/carpet/script/Expression.java index 1f0720f2..dec37f55 100644 --- a/src/main/java/carpet/script/Expression.java +++ b/src/main/java/carpet/script/Expression.java @@ -12,6 +12,7 @@ import carpet.script.Fluff.SexFunction; import carpet.script.Fluff.TriFunction; import carpet.script.exception.ExpressionException; import carpet.script.exception.InternalExpressionException; +import carpet.script.value.AbstractListValue; import carpet.script.value.FunctionSignatureValue; import carpet.script.value.GlobalValue; import carpet.script.value.LazyListValue; @@ -63,7 +64,7 @@ import static java.lang.Math.min; * repository

* *

This specification is divided into two sections: this one is agnostic - * to any Minecraft related features and could function on its own, and {@see carpet.script.CarpetExpression} for + * to any Minecraft related features and could function on its own, and CarpetExpression for * Minecraft specific routines and world manipulation functions.

* *

Synopsis

@@ -74,7 +75,7 @@ import static java.lang.Math.min; *

or an overly complex example:

*
  * /script run
- *     block_check(x1, y1, z1, x2, y2, z2, block_to_check) ->
+ *     block_check(x1, y1, z1, x2, y2, z2, block_to_check) ->
  *     (
  *         l(minx, maxx) = sort(l(x1, x2));
  *         l(miny, maxy) = sort(l(y1, y2));
@@ -99,7 +100,7 @@ import static java.lang.Math.min;
  *         );
  *         total_count
  *     );
- *     check_area_around_closest_player_for_block(block_to_check) ->
+ *     check_area_around_closest_player_for_block(block_to_check) ->
  *     (
  *         closest_player = player();
  *         l(posx, posy, posz) = query(closest_player, 'pos');
@@ -1637,15 +1638,19 @@ public class Expression implements Cloneable
      *     range(20, 10, -2)  => [20, 18, 16, 14, 12]
      * 
* - *

get(list, index), element(list, index)(deprecated)

- *

Returns the value at index element from the list. - * use negative numbers to reach elements from the end of the list. get + *

get(value, address), element(value, address)(deprecated)

+ *

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

+ *

[Minecraft specific usecase]: In case value is of nbt type, uses addess as the 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

*
      *     get(l(range(10)), 5)  => 5
      *     get(l(range(10)), -1)  => 9
      *     get(l(range(10)), 10)  => 0
      *     get(l(range(10)), 93)  => 3
+     *     get(player() ~ 'nbt', 'Health') => 20 // inefficient way to get player health
      * 
* *

put(list, index, values ...), put(list, null, values ...)

@@ -1857,12 +1862,12 @@ public class Expression implements Cloneable return LazyListValue.range(from, to, step); }); - addBinaryFunction("get", (v1, v2) -> v1.getElementAt(v2)); + addBinaryFunction("get", Value::getElementAt); //Deprecated, use "get" instead addBinaryFunction("element", (v1, v2) -> { - if (v1 instanceof LazyListValue || !(v1 instanceof ListValue)) + if (!(v1 instanceof ListValue)) throw new InternalExpressionException("First argument of get should be a list"); List items = ((ListValue)v1).getItems(); long index = NumericValue.asNumber(v2).getLong(); @@ -1880,7 +1885,7 @@ public class Expression implements Cloneable throw new InternalExpressionException("put takes at least three arguments, a list, index, and values to insert at that index"); } Value list = lv.get(0); - if (list instanceof LazyListValue || !(list instanceof ListValue)) + if (!(list instanceof ListValue)) { throw new InternalExpressionException("First argument of element should be a list"); } @@ -1965,9 +1970,9 @@ public class Expression implements Cloneable Value rval= lv.get(0).evalValue(c); - if (!(rval instanceof ListValue)) + if (!(rval instanceof AbstractListValue)) throw new InternalExpressionException("First argument of map function should be a list or iterator"); - Iterator iterator = ((ListValue) rval).iterator(); + Iterator iterator = ((AbstractListValue) rval).iterator(); LazyValue expr = lv.get(1); LazyValue cond = null; if(lv.size() > 2) cond = lv.get(2); @@ -1991,12 +1996,12 @@ public class Expression implements Cloneable } next.boundVariable = var; } - ((ListValue) rval).fatality(); - LazyValue ret = (cc, tt) -> ListValue.wrap(result); + ((AbstractListValue) rval).fatality(); + Value ret = ListValue.wrap(result); //revering scope c.setVariable("_", _val); c.setVariable("_i", _iter); - return ret; + return (cc, tt) -> ret; }); // grep(list or num, expr, exit_expr) => list @@ -2010,9 +2015,9 @@ public class Expression implements Cloneable } Value rval= lv.get(0).evalValue(c); - if (!(rval instanceof ListValue)) + if (!(rval instanceof AbstractListValue)) throw new InternalExpressionException("First argument of filter function should be a list or iterator"); - Iterator iterator = ((ListValue) rval).iterator(); + Iterator iterator = ((AbstractListValue) rval).iterator(); LazyValue expr = lv.get(1); LazyValue cond = null; if(lv.size() > 2) cond = lv.get(2); @@ -2037,12 +2042,12 @@ public class Expression implements Cloneable } next.boundVariable = var; } - ((ListValue) rval).fatality(); - LazyValue ret = (cc, tt) -> ListValue.wrap(result); // might be a trap - lazy evaluation + ((AbstractListValue) rval).fatality(); + Value ret = ListValue.wrap(result); //revering scope c.setVariable("_", _val); c.setVariable("_i", _iter); - return ret; + return (cc, tt) -> ret; }); // first(list, expr) => elem or null @@ -2052,9 +2057,9 @@ public class Expression implements Cloneable { Value rval= lv.get(0).evalValue(c); - if (!(rval instanceof ListValue)) + if (!(rval instanceof AbstractListValue)) throw new InternalExpressionException("First argument of 'first' function should be a list or iterator"); - Iterator iterator = ((ListValue) rval).iterator(); + Iterator iterator = ((AbstractListValue) rval).iterator(); LazyValue expr = lv.get(1); //scoping LazyValue _val = c.getVariable("_"); @@ -2077,7 +2082,7 @@ public class Expression implements Cloneable next.boundVariable = var; } //revering scope - ((ListValue) rval).fatality(); + ((AbstractListValue) rval).fatality(); Value whyWontYouTrustMeJava = result; c.setVariable("_", _val); c.setVariable("_i", _iter); @@ -2090,9 +2095,9 @@ public class Expression implements Cloneable addLazyFunction("all", 2, (c, t, lv) -> { Value rval= lv.get(0).evalValue(c); - if (!(rval instanceof ListValue)) + if (!(rval instanceof AbstractListValue)) throw new InternalExpressionException("First argument of 'all' function should be a list or iterator"); - Iterator iterator = ((ListValue) rval).iterator(); + Iterator iterator = ((AbstractListValue) rval).iterator(); LazyValue expr = lv.get(1); //scoping LazyValue _val = c.getVariable("_"); @@ -2115,7 +2120,7 @@ public class Expression implements Cloneable next.boundVariable = var; } //revering scope - ((ListValue) rval).fatality(); + ((AbstractListValue) rval).fatality(); c.setVariable("_", _val); c.setVariable("_i", _iter); return result; @@ -2131,9 +2136,9 @@ public class Expression implements Cloneable throw new InternalExpressionException("Incorrect number of attributes for 'for', should be 2 or 3, not "+lv.size()); } Value rval= lv.get(0).evalValue(c); - if (!(rval instanceof ListValue)) + if (!(rval instanceof AbstractListValue)) throw new InternalExpressionException("Second argument of 'for' function should be a list or iterator"); - Iterator iterator = ((ListValue) rval).iterator(); + Iterator iterator = ((AbstractListValue) rval).iterator(); LazyValue expr = lv.get(1); LazyValue cond = null; if(lv.size() > 2) cond = lv.get(2); @@ -2160,7 +2165,7 @@ public class Expression implements Cloneable next.boundVariable = var; } //revering scope - ((ListValue) rval).fatality(); + ((AbstractListValue) rval).fatality(); c.setVariable("_", _val); c.setVariable("_i", _iter); long promiseWontChange = successCount; @@ -2178,9 +2183,9 @@ public class Expression implements Cloneable Value acc = lv.get(2).evalValue(c); Value rval= lv.get(0).evalValue(c); - if (!(rval instanceof ListValue)) + if (!(rval instanceof AbstractListValue)) throw new InternalExpressionException("First argument of 'reduce' should be a list or iterator"); - Iterator iterator = ((ListValue) rval).iterator(); + Iterator iterator = ((AbstractListValue) rval).iterator(); if (!iterator.hasNext()) { @@ -2204,7 +2209,7 @@ public class Expression implements Cloneable next.boundVariable = var; } //reverting scope - ((ListValue) rval).fatality(); + ((AbstractListValue) rval).fatality(); c.setVariable("_a", _acc); c.setVariable("_", _val); @@ -2219,6 +2224,10 @@ public class Expression implements Cloneable *

System functions

*
*

Type conversion functions

+ *

type(expr)

+ *

Returns the string value indicating type of the expression. Possible outcomes are + * null, number, string, list, iterator, as well as minecraft related concepts like + * block, entity, nbt

*

bool(expr)

*

Returns a boolean context of the expression. Note that there are no true/false values in * scarpet. true is alias of 1, and false is 0. Bool is also interpreting diff --git a/src/main/java/carpet/script/value/AbstractListValue.java b/src/main/java/carpet/script/value/AbstractListValue.java new file mode 100644 index 00000000..716b17b0 --- /dev/null +++ b/src/main/java/carpet/script/value/AbstractListValue.java @@ -0,0 +1,21 @@ +package carpet.script.value; + +import carpet.script.exception.InternalExpressionException; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.util.registry.Registry; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.stream.Collectors; + +import static java.lang.Math.abs; + +public abstract class AbstractListValue extends Value +{ + public abstract Iterator iterator(); + public void fatality() { } +} diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index 8ba290a6..0b5dab95 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -193,6 +193,10 @@ public class EntityValue extends Value put("has_tag", (e, a) -> new NumericValue(e.getScoreboardTags().contains(a.getString()))); put("yaw", (e, a)-> new NumericValue(e.yaw)); put("pitch", (e, a)-> new NumericValue(e.pitch)); + put("look", (e, a) -> { + Vec3d look = e.getRotationVector(); + return ListValue.of(new NumericValue(look.x),new NumericValue(look.y),new NumericValue(look.z)); + }); put("is_burning", (e, a) -> new NumericValue(e.isOnFire())); //put("fire", (e, a) -> new NumericValue(e.getFire())); needs mixing put("silent", (e, a)-> new NumericValue(e.isSilent())); diff --git a/src/main/java/carpet/script/value/FunctionSignatureValue.java b/src/main/java/carpet/script/value/FunctionSignatureValue.java index b54274ab..73976f6b 100644 --- a/src/main/java/carpet/script/value/FunctionSignatureValue.java +++ b/src/main/java/carpet/script/value/FunctionSignatureValue.java @@ -1,7 +1,6 @@ package carpet.script.value; import carpet.script.exception.ExpressionException; -import carpet.script.exception.InternalExpressionException; import java.util.List; @@ -23,12 +22,6 @@ public class FunctionSignatureValue extends Value throw new ExpressionException("Function "+identifier+" is not defined yet"); } - @Override - public String getTypeString() - { - throw new InternalExpressionException("How did you get here? Cannot get type of an internal struct."); - } - @Override public Value clone() { diff --git a/src/main/java/carpet/script/value/GlobalValue.java b/src/main/java/carpet/script/value/GlobalValue.java index fb2f3f71..47dcf994 100644 --- a/src/main/java/carpet/script/value/GlobalValue.java +++ b/src/main/java/carpet/script/value/GlobalValue.java @@ -1,7 +1,5 @@ package carpet.script.value; -import carpet.script.exception.InternalExpressionException; - public class GlobalValue extends Value { public GlobalValue(Value variable) @@ -21,10 +19,4 @@ public class GlobalValue extends Value { return false; } - - @Override - public String getTypeString() - { - throw new InternalExpressionException("How did you get here? Cannot get type of an internal struct."); - } } diff --git a/src/main/java/carpet/script/value/LazyListValue.java b/src/main/java/carpet/script/value/LazyListValue.java index accf40a5..016d6556 100644 --- a/src/main/java/carpet/script/value/LazyListValue.java +++ b/src/main/java/carpet/script/value/LazyListValue.java @@ -7,7 +7,7 @@ import java.util.Collections; import java.util.Iterator; import java.util.List; -public abstract class LazyListValue extends ListValue implements Iterator +public abstract class LazyListValue extends AbstractListValue implements Iterator { public static LazyListValue range(long from, long to, long step) { @@ -16,10 +16,12 @@ public abstract class LazyListValue extends ListValue implements Iterator { if (step == 0) throw new InternalExpressionException("range will never end with zero step"); - this.current = from; + this.start = from; + this.current = this.start; this.limit = to; this.stepp = step; } + private long start; private long current; private long limit; private long stepp; @@ -31,6 +33,12 @@ public abstract class LazyListValue extends ListValue implements Iterator return val; } + @Override + public void reset() + { + current = start; + } + @Override public boolean hasNext() { @@ -39,11 +47,6 @@ public abstract class LazyListValue extends ListValue implements Iterator }; } - public LazyListValue() - { - super(Collections.emptyList()); - } - @Override public String getString() { @@ -59,6 +62,10 @@ public abstract class LazyListValue extends ListValue implements Iterator public abstract Value next(); + @Override + public void fatality() {reset();} + public abstract void reset(); + @Override public Iterator iterator() {return this;} @@ -66,6 +73,7 @@ public abstract class LazyListValue extends ListValue implements Iterator { List result = new ArrayList<>(); this.forEachRemaining(result::add); + fatality(); return result; } @@ -83,14 +91,20 @@ public abstract class LazyListValue extends ListValue implements Iterator if (hasNext()) next(); else + { + fatality(); return ListValue.wrap(result); + } } for (i = (int)from; i < to; i++) { if (hasNext()) result.add(next()); else + { + fatality(); return ListValue.wrap(result); + } } return ListValue.wrap(result); } @@ -116,5 +130,19 @@ public abstract class LazyListValue extends ListValue implements Iterator { return "iterator"; } - + @Override + public Object clone() + { + Object copy; + try + { + copy = super.clone(); + } + catch (CloneNotSupportedException e) + { + throw new InternalExpressionException("cannot copy iterator"); + } + ((LazyListValue)copy).reset(); + return copy; + } } diff --git a/src/main/java/carpet/script/value/ListValue.java b/src/main/java/carpet/script/value/ListValue.java index f7ac3662..6f0b656c 100644 --- a/src/main/java/carpet/script/value/ListValue.java +++ b/src/main/java/carpet/script/value/ListValue.java @@ -2,7 +2,6 @@ package carpet.script.value; import carpet.script.exception.InternalExpressionException; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompoundTag; import net.minecraft.util.registry.Registry; import java.util.ArrayList; @@ -14,7 +13,7 @@ import java.util.stream.Collectors; import static java.lang.Math.abs; -public class ListValue extends Value +public class ListValue extends AbstractListValue { protected List items; @Override @@ -241,9 +240,6 @@ public class ListValue extends Value { return items.iterator(); } - public void fatality() - { - } public void extend(List subList) { @@ -331,7 +327,4 @@ public class ListValue extends Value { return "list"; } - - - } diff --git a/src/main/java/carpet/script/value/StringValue.java b/src/main/java/carpet/script/value/StringValue.java index 3db05b75..eba0cd16 100644 --- a/src/main/java/carpet/script/value/StringValue.java +++ b/src/main/java/carpet/script/value/StringValue.java @@ -28,6 +28,6 @@ public class StringValue extends Value @Override public String getTypeString() { - return "number"; + return "string"; } } diff --git a/src/main/java/carpet/script/value/Value.java b/src/main/java/carpet/script/value/Value.java index 35c94827..ce061449 100644 --- a/src/main/java/carpet/script/value/Value.java +++ b/src/main/java/carpet/script/value/Value.java @@ -178,5 +178,8 @@ public abstract class Value implements Comparable, Cloneable throw new InternalExpressionException("get element can only be obtained for lists and nbt values"); } - public abstract String getTypeString(); + public String getTypeString() + { + throw new InternalExpressionException("How did you get here? Cannot get type of an intenal type."); + } } diff --git a/src/main/java/carpet/settings/CarpetSettings.java b/src/main/java/carpet/settings/CarpetSettings.java index 842498e3..96767a49 100644 --- a/src/main/java/carpet/settings/CarpetSettings.java +++ b/src/main/java/carpet/settings/CarpetSettings.java @@ -26,7 +26,7 @@ import static carpet.settings.RuleCategory.SURVIVAL; public class CarpetSettings { - public static final String carpetVersion = "v190714"; + public static final String carpetVersion = "1.0.0-v190721"; public static final Logger LOG = LogManager.getLogger(); public static boolean skipGenerationChecks = false; public static boolean impendingFillSkipUpdates = false;