Merge pull request #57 from gnembon/scarpet_fixes

Scarpet fixes
This commit is contained in:
gnembon authored and GitHub committed 2019-07-21 16:59:08 -03:00
commit 2ba811bf48
14 files changed
+336 -103

No files matched your search

+1 -1
View File
@@ -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
@@ -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;
}
@@ -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(
+215 -32
View File
@@ -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;
}
}
}
}
/**
* <h1>Blocks / World API</h1>
* <div style="padding-left: 20px; border-radius: 5px 45px; border:1px solid grey;">
@@ -368,11 +413,12 @@ public class CarpetExpression
* <h3><code>random_tick(pos)</code></h3>
* <p>Causes a random tick at position.</p>
* <h3><code>destroy(pos), destroy(pos, -1), destroy(pos, &lt;N&gt;)</code></h3>
* <p>Destroys the block like it was harvest by a player. Add -1 for silk touch, and positive number for fortune level.</p>
* <p>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</p>
* <h3><code>harvest(player, pos)</code></h3>
* <p>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.</p>
*
* 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.</p>
*
* <h2>Block and World querying</h2>
*
@@ -385,6 +431,8 @@ public class CarpetExpression
* pos(players()) =&gt; l(12.3, 45.6, 32.05)
* pos(block('stone')) =&gt; Error: Cannot fetch position of an unrealized block
* </pre>
* <h3><code>block_properties(pos)</code></h3>
* <p>Returns a list of available block properties for a particular block. If a block has no properties, returns an empty list.</p>
* <h3><code>property(pos, name)</code></h3>
* <p>Returns property of block at <code>pos</code>, or specified by <code>block</code> argument. If a block doesn't
* have that property, <code>null</code> value is returned. Returned values are always strings. It is expected from
@@ -433,19 +481,19 @@ public class CarpetExpression
* <h3><code>blast_resistance(pos)</code></h3>
* <p>Numeric function, indicating blast_resistance of a block.</p>
* <h3><code>top(type, x, z)</code></h3>
* <p>Returns the Y value of the topmost block at given x, z coords, according to the
* <h3><code>top(type, pos)</code></h3>
* <p>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 <code>type</code>. Valid options are:</p>
* <ul>
* <li><code>light</code>: topmost light blocking block</li>
* <li><code>light</code>: topmost light blocking block (1.13 only)</li>
* <li><code>motion</code>: topmost motion blocking block</li>
* <li><code>terrain</code>: topmost motion blocking block except leaves</li>
* <li><code>ocean_floor</code>: topmost non-water block</li>
* <li><code>surface</code>: topmost surface block</li>
* </ul>
* <pre>
* top('motion', x, z) =&gt; 63
* top('ocean_floor', x, z) =&gt; 41
* top('motion', x, y, z) =&gt; 63
* top('ocean_floor', x, y, z) =&gt; 41
* </pre>
* <h3><code>loaded(pos)</code></h3>
* <p>Boolean function, true if the block is loaded. Normally <code>scarpet</code> 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
* <p>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.</p>
*
* <h3><code>spawn(name, pos, nbt?)</code></h3>
* <p>Spawns and places an entity in world, like <code>/summon</code> vanilla command.
* Requires a position to spawn, and optional extra nbt data to merge with the entity. What makes it different from calling
* <code>run('summon ...')</code>, is the fact that you get the entity back as a return value, which is swell.</p>
*
* <h2>Entity Manipulation</h2>
*
* <p>Unlike with blocks, that use plethora of vastly different querying functions, entities are queried with
@@ -1368,6 +1419,8 @@ public class CarpetExpression
* <p>Respective entity coordinate</p>
* <h3><code>query(e,'pitch'), query(e,'yaw')</code></h3>
* <p>Pitch and Yaw or where entity is looking.</p>
* <h3><code>query(e,'look')</code></h3>
* <p>Returns a 3d vector where the entity is looking.</p>
* <h3><code>query(e,'motion')</code></h3>
* <p>Triple of entity motion vector, <code>l(motion_x, motion_y, motion_z)</code></p>
* <h3><code>query(e,'motion_x'), query(e,'motion_y'), query(e,'motion_z')</code></h3>
@@ -1445,6 +1498,7 @@ public class CarpetExpression
* </pre>
* <h3><code>query(e,'health')</code></h3>
* <p>Number indicating remaining entity health, or <code>null</code> if not applicable.</p>
*
* <h3><code>query(e,'holds',slot?)</code></h3>
* <p>Returns triple of short name, stack count, and NBT of item held in <code>slot</code>.
* Available options for <code>slot</code> are:</p>
@@ -1462,7 +1516,14 @@ public class CarpetExpression
* <h3><code>query(e,'facing', order?)</code></h3>
* <p>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)</p>
*
* <h3><code>query(e,'trace', reach?, options?...)</code></h3>
* <p>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 <code>options</code>, use 'blocks' to trace for blocks only, 'liquids' to include liquid blocks
* as possible results, and 'entities' to trace entities as well.</p>
* <p>Regardless of the options selected, the result could be <code>null</code> 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.</p>
* <h3><code>query(e,'nbt',path?)</code></h3>
* <p>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 <code>path</code> attribute, consult
@@ -1497,8 +1558,7 @@ public class CarpetExpression
* <h3><code>modify(e, 'accelerate', x, y, z), modify(e, 'accelerate', l(x, y, z) )</code></h3>
* <p>Adds a vector to the motion vector. Most realistic way to apply a force to an entity.</p>
* <h3><code>modify(e, 'custom_name'), modify(e, 'custom_name', name )</code></h3>
* <p>Sets a custom name for an entity. No argument sets it empty, not removes it. Vanilla doesn't allow removing
* of attributes.</p>
* <p>Sets a custom name for an entity. Removes a custom name if the argument is <code>null</code></p>
* <h3><code>modify(e, 'dismount')</code></h3>
* <p>Dismounts riding entity.</p>
* <h3><code>modify(e, 'mount', other)</code></h3>
@@ -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
* <h3><code>particle_rect(name, pos, pos2, density?)</code></h3>
* <p>Renders a cuboid of particles between point <code>pos</code> to <code>pos2</code> with supplied density.</p>
* <h2>System function</h2>
* <h3><code>nbt(expr)</code></h3>
* <p>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.</p>
* <h3><code>print(expr)</code></h3>
* <p>Displays the result of the expression to the chat. Overrides default <code>scarpet</code> behaviour of
* sending everyting to stderr.</p>
@@ -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";
}
/**
* <h1><code>/script load / unload &lt;module&gt; (shared?)</code>, <code>/script in &lt;module&gt;</code> commands</h1>
* <div style="padding-left: 20px; border-radius: 5px 45px; border:1px solid grey;">
* <p><code>load / unload</code> 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 <code>.sc</code> 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.</p>
* <p> a comment is anything that starts with a double slash, and continues to the end of the line:</p>
* <pre>
* foo = 1;
* //This is a comment
* bar = 2;
* // This never worked, so I commented it out
* // baz = foo()
* </pre>
* <h2></h2>
* <h3><code>/script load/unload &lt;module&gt; (?shared) </code></h3>
* <p>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 <code>/script load</code> again.
* Reloading removes all the current global state (globals and functions) that were added later by the module. </p>
* <p>Loading a module, if it contains a <code>__command()</code> 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).</p>
* <p>Unloading a module removes all of its state from the game, disables commands, and removes bounded events</p>
* <p>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 <code>/execute as (player) run script in (module) run ... </code>
* To access global/server state, you need to disown the command from any player, so use a commandblock, or any arbitrary
* entity: <code>/execute as @e[type=bat,limit=1] run script in (module) globals</code> for instance.
* </p>
* <h3><code>/script in &lt;module&gt; ... </code></h3>
* <p>Allows to run normal /script commands in a specific module, like <code>run, invoke,..., globals</code> etc...</p>
* </div>
* @return .
*/
public static String loadScriptsFromFilesCommand()
{
return "Yeah";
}
/**
* <h1>Scarpet events system</h1>
* <div style="padding-left: 20px; border-radius: 5px 45px; border:1px solid grey;">
* <p>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 <code>__on_...</code> 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.</p>
* <h2></h2>
* <h3>Event list</h3>
* <p>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:</p>
* <pre>
* __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)
* </pre>
* <h3><code>/script event</code> command</h3>
* <p>used to display current events and bounded functions. use <code>add_to</code> ro register new event, or <code>remove_from</code>
* to unbind a specific function from an event.</p>
* </div>
* @return .
*/
public static String gameEventsSystem()
{
return "Yeah";
}
}
+40 -31
View File
@@ -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</a></p>
*
* <p>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.</p>
*
* <h1>Synopsis</h1>
@@ -74,7 +75,7 @@ import static java.lang.Math.min;
* <p>or an overly complex example:</p>
* <pre>
* /script run
* block_check(x1, y1, z1, x2, y2, z2, block_to_check) ->
* block_check(x1, y1, z1, x2, y2, z2, block_to_check) -&gt;
* (
* 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) -&gt;
* (
* closest_player = player();
* l(posx, posy, posz) = query(closest_player, 'pos');
@@ -1637,15 +1638,19 @@ public class Expression implements Cloneable
* range(20, 10, -2) =&gt; [20, 18, 16, 14, 12]
* </pre>
*
* <h3><code>get(list, index), element(list, index)(deprecated)</code></h3>
* <p>Returns the value at <code>index</code> element from the <code>list</code>.
* use negative numbers to reach elements from the end of the list. <code>get</code>
* <h3><code>get(value, address), element(value, address)(deprecated)</code></h3>
* <p>Returns the value at <code>address</code> element from the <code>value</code>.
* For lists it indicates an index, use negative numbers to reach elements from the end of the list. <code>get</code>
* call will always be able to find the index. In case there is few items, it will loop over </p>
* <p>[Minecraft specific usecase]: In case <code>value</code> is of <code>nbt</code> 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</p>
* <pre>
* get(l(range(10)), 5) =&gt; 5
* get(l(range(10)), -1) =&gt; 9
* get(l(range(10)), 10) =&gt; 0
* get(l(range(10)), 93) =&gt; 3
* get(player() ~ 'nbt', 'Health') =&gt; 20 // inefficient way to get player health
* </pre>
*
* <h3><code>put(list, index, values ...), put(list, null, values ...)</code></h3>
@@ -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<Value> 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<Value> iterator = ((ListValue) rval).iterator();
Iterator<Value> 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<Value> iterator = ((ListValue) rval).iterator();
Iterator<Value> 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<Value> iterator = ((ListValue) rval).iterator();
Iterator<Value> 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<Value> iterator = ((ListValue) rval).iterator();
Iterator<Value> 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<Value> iterator = ((ListValue) rval).iterator();
Iterator<Value> 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<Value> iterator = ((ListValue) rval).iterator();
Iterator<Value> 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
* <h1>System functions</h1>
* <div style="padding-left: 20px; border-radius: 5px 45px; border:1px solid grey;">
* <h2>Type conversion functions</h2>
* <h3><code>type(expr)</code></h3>
* <p>Returns the string value indicating type of the expression. Possible outcomes are
* <code>null, number, string, list, iterator</code>, as well as minecraft related concepts like
* <code>block, entity, nbt</code></p>
* <h3><code>bool(expr)</code></h3>
* <p>Returns a boolean context of the expression. Note that there are no true/false values in
* scarpet. <code>true</code> is alias of 1, and <code>false</code> is 0. Bool is also interpreting
@@ -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<Value> iterator();
public void fatality() { }
}
@@ -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()));
@@ -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()
{
@@ -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.");
}
}
@@ -7,7 +7,7 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.List;
public abstract class LazyListValue extends ListValue implements Iterator<Value>
public abstract class LazyListValue extends AbstractListValue implements Iterator<Value>
{
public static LazyListValue range(long from, long to, long step)
{
@@ -16,10 +16,12 @@ public abstract class LazyListValue extends ListValue implements Iterator<Value>
{
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<Value>
return val;
}
@Override
public void reset()
{
current = start;
}
@Override
public boolean hasNext()
{
@@ -39,11 +47,6 @@ public abstract class LazyListValue extends ListValue implements Iterator<Value>
};
}
public LazyListValue()
{
super(Collections.emptyList());
}
@Override
public String getString()
{
@@ -59,6 +62,10 @@ public abstract class LazyListValue extends ListValue implements Iterator<Value>
public abstract Value next();
@Override
public void fatality() {reset();}
public abstract void reset();
@Override
public Iterator<Value> iterator() {return this;}
@@ -66,6 +73,7 @@ public abstract class LazyListValue extends ListValue implements Iterator<Value>
{
List<Value> result = new ArrayList<>();
this.forEachRemaining(result::add);
fatality();
return result;
}
@@ -83,14 +91,20 @@ public abstract class LazyListValue extends ListValue implements Iterator<Value>
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<Value>
{
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;
}
}
@@ -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<Value> items;
@Override
@@ -241,9 +240,6 @@ public class ListValue extends Value
{
return items.iterator();
}
public void fatality()
{
}
public void extend(List<Value> subList)
{
@@ -331,7 +327,4 @@ public class ListValue extends Value
{
return "list";
}
}
@@ -28,6 +28,6 @@ public class StringValue extends Value
@Override
public String getTypeString()
{
return "number";
return "string";
}
}
+4 -1
View File
@@ -178,5 +178,8 @@ public abstract class Value implements Comparable<Value>, 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.");
}
}
@@ -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;